use crate::algos::cbrt;
use crate::int::types::traits::BigInt;
use crate::int::types::compute_limbs::{ComputeLimbs, Limbs};
use crate::int::types::Int;
use crate::support::rounding::RoundingMode;
#[derive(Clone, Copy, PartialEq, Eq)]
enum Algorithm {
Newton,
MgDivide,
#[allow(dead_code)]
Native,
#[allow(dead_code)]
NewtonWithTableSeed,
#[allow(dead_code)]
Schoolbook,
}
#[derive(Clone, Copy)]
enum Select<const N: usize> {
ByAlgorithm(Algorithm),
#[allow(dead_code)]
ByValue(fn(&Int<N>) -> Algorithm),
}
const fn select<const N: usize, const SCALE: u32>() -> Select<N> {
match (N, SCALE) {
(1, _) => Select::ByAlgorithm(Algorithm::MgDivide),
(2, _) => Select::ByAlgorithm(Algorithm::MgDivide),
(3, _) | (4, _) => Select::ByAlgorithm(Algorithm::Native),
(6, s) if s >= 48 => Select::ByAlgorithm(Algorithm::Native), (8, s) if s >= 64 => Select::ByAlgorithm(Algorithm::Native), (12, s) if s >= 96 => Select::ByAlgorithm(Algorithm::Native), (16, s) if s >= 128 => Select::ByAlgorithm(Algorithm::Native), (24, s) if s >= 192 => Select::ByAlgorithm(Algorithm::Native), (32, s) if s >= 256 => Select::ByAlgorithm(Algorithm::Native), (48, s) if s >= 384 => Select::ByAlgorithm(Algorithm::Native), (64, s) if s >= 512 => Select::ByAlgorithm(Algorithm::Native), _ => Select::ByAlgorithm(Algorithm::Newton),
}
}
#[inline]
#[must_use]
pub(crate) fn dispatch<const N: usize, const SCALE: u32>(raw: Int<N>, mode: RoundingMode) -> Int<N>
where
Limbs<N>: ComputeLimbs,
{
if raw == Int::<N>::ZERO {
return Int::<N>::ZERO;
}
let algo = match const { select::<N, SCALE>() } {
Select::ByAlgorithm(a) => a,
Select::ByValue(f) => f(&raw),
};
match algo {
Algorithm::Newton => cbrt::cbrt_newton::cbrt_newton::<N>(raw, SCALE, mode),
Algorithm::MgDivide => {
cbrt::cbrt_mg_divide::cbrt_mg_divide(raw.resize_to::<Int<2>>(), SCALE, mode)
.resize_to::<Int<N>>()
}
Algorithm::Native => match N {
3 => cbrt::cbrt_native_fast::cbrt_native_fast_a::<N, 9>(raw, const { Int::<9>::TEN.pow(2 * SCALE) }, mode),
4 => cbrt::cbrt_native_fast::cbrt_native_fast_a::<N, 12>(raw, const { Int::<12>::TEN.pow(2 * SCALE) }, mode),
6 => cbrt::cbrt_native_fast::cbrt_native_fast_a::<N, 18>(raw, const { Int::<18>::TEN.pow(2 * SCALE) }, mode),
8 => cbrt::cbrt_native_fast::cbrt_native_fast_a::<N, 24>(raw, const { Int::<24>::TEN.pow(2 * SCALE) }, mode),
12 => cbrt::cbrt_native_fast::cbrt_native_fast_a::<N, 36>(raw, const { Int::<36>::TEN.pow(2 * SCALE) }, mode),
16 => cbrt::cbrt_native_fast::cbrt_native_fast_a::<N, 48>(raw, const { Int::<48>::TEN.pow(2 * SCALE) }, mode),
24 => cbrt::cbrt_native_fast::cbrt_native_fast_a::<N, 72>(raw, const { Int::<72>::TEN.pow(2 * SCALE) }, mode),
32 => cbrt::cbrt_native_fast::cbrt_native_fast_a::<N, 96>(raw, const { Int::<96>::TEN.pow(2 * SCALE) }, mode),
48 => cbrt::cbrt_native_fast::cbrt_native_fast_a::<N, 144>(raw, const { Int::<144>::TEN.pow(2 * SCALE) }, mode),
64 => cbrt::cbrt_native_fast::cbrt_native_fast_a::<N, 192>(raw, const { Int::<192>::TEN.pow(2 * SCALE) }, mode),
_ => cbrt::cbrt_newton::cbrt_newton::<N>(raw, SCALE, mode),
},
Algorithm::NewtonWithTableSeed => {
cbrt::cbrt_newton_with_table_seed::cbrt_newton_with_table_seed(
raw.resize_to::<Int<3>>(),
mode,
)
.resize_to::<Int<N>>()
}
Algorithm::Schoolbook => cbrt::cbrt_newton::cbrt_newton::<N>(raw, SCALE, mode),
}
}