use crate::Tmr;
use super::Final;
use std::cell::RefCell;
use std::convert::TryInto;
use std::sync::Arc;
const N_POWERS: usize = Tmr::TWO_TWO_N.len();
thread_local! {
static TWO_TWO_N: RefCell<Option<[Arc<Final>; N_POWERS]>> = const { RefCell::new(None) };
}
fn initialize(write: &mut Option<[Arc<Final>; N_POWERS]>) {
let one = Final::unit();
let mut powers = Vec::with_capacity(N_POWERS);
let mut power = Final::sum(Arc::clone(&one), one);
powers.push(Arc::clone(&power));
for _ in 1..N_POWERS {
power = Final::product(Arc::clone(&power), power);
powers.push(Arc::clone(&power));
}
let powers: [Arc<Final>; N_POWERS] = powers.try_into().unwrap();
*write = Some(powers);
}
pub fn nth_power_of_2(n: usize) -> Arc<Final> {
TWO_TWO_N.with(|arr| {
if arr.borrow().is_none() {
initialize(&mut arr.borrow_mut());
}
debug_assert!(arr.borrow().is_some());
Arc::clone(&arr.borrow().as_ref().unwrap()[n])
})
}