pub fn number_theoretic_transformation<T, M>(
        f: &[ModInt<T, M>],
        zeta: ModInt<T, M>,
    ) -> Vec<ModInt<T, M>>
    where
        M: StaticModulus<T>,
        T: NumAssignOps + PrimInt + Unsigned,
    {
        // bit-reversal
        let bit_colength = f.len().leading_zeros() + 1;
        let mut f_rev: Vec<ModInt<T, M>> = vec![ModInt::new(T::zero()); f.len()];
        for i in 0..f.len() {
            f_rev[i.reverse_bits() >> bit_colength] = f[i];
        }
        sub(&mut f_rev, zeta);
        return f_rev;
        fn sub<T, M>(f: &mut [ModInt<T, M>], zeta: ModInt<T, M>)
        where
            M: StaticModulus<T>,
            T: NumAssignOps + PrimInt + Unsigned,
        {
            let n = f.len();
            if n == 1 {
                return;
            }
            sub(&mut f[..n / 2], zeta * zeta);
            sub(&mut f[n / 2..], zeta * zeta);
            let mut pow_zeta = ModInt::new(T::one());
            for i in 0..n / 2 {
                let g0 = f[i];
                let g1 = f[i + n / 2];
                f[i] = g0 + pow_zeta * g1;
                f[i + n / 2] = g0 - pow_zeta * g1;
                pow_zeta = pow_zeta * zeta;
            }
        }
    }
// Number-theoretic transformation
// The length of f must be a power of 2
// and zeta must be a primitive f.len()-th root of unity
// The inverse can be calculated by doing the same
// with the original zeta's inverse as zeta
// and dividing by f.len()
Number-theoretic transformation
The length of f must be a power of 2
and zeta must be a primitive f.len()-th root of unity
The inverse can be calculated by doing the same
with the original zeta's inverse as zeta
and dividing by f.len()
Number - theoretic transformation The length of f must be a power of 2 and zeta must be a primitive f . len () - th root of unity The inverse can be calculated by doing the same with the original zeta ' s inverse as zeta and dividing by f . len ()
pub fn number_theoretic_transformation<T, M>(
        f: &[ModInt<T, M>],
        zeta: ModInt<T, M>,
    ) -> Vec<ModInt<T, M>>
    where
        M: StaticModulus<T>,
        T: NumAssignOps + PrimInt + Unsigned,
    {
        // bit-reversal
        let bit_colength = f.len().leading_zeros() + 1;
        let mut f_rev: Vec<ModInt<T, M>> = vec![ModInt::new(T::zero()); f.len()];
        for i in 0..f.len() {
            f_rev[i.reverse_bits() >> bit_colength] = f[i];
        }
        sub(&mut f_rev, zeta);
        return f_rev;
        fn sub<T, M>(f: &mut [ModInt<T, M>], zeta: ModInt<T, M>)
        where
            M: StaticModulus<T>,
            T: NumAssignOps + PrimInt + Unsigned,
        {
            let n = f.len();
            if n == 1 {
                return;
            }
            sub(&mut f[..n / 2], zeta * zeta);
            sub(&mut f[n / 2..], zeta * zeta);
            let mut pow_zeta = ModInt::new(T::one());
            for i in 0..n / 2 {
                let g0 = f[i];
                let g1 = f[i + n / 2];
                f[i] = g0 + pow_zeta * g1;
                f[i + n / 2] = g0 - pow_zeta * g1;
                pow_zeta = pow_zeta * zeta;
            }
        }
    }
pub fn number_theoretic_transformation < T , M > ( f : & [ ModInt < T , M > ] , zeta : ModInt < T , M > , ) -> Vec < ModInt < T , M > > where M : StaticModulus < T > , T : NumAssignOps + PrimInt + Unsigned , { // bit-reversal let bit_colength = f . len ( ) . leading_zeros ( ) + 1 ; let mut f_rev : Vec < ModInt < T , M > > = vec ! [ ModInt new ( T zero ( ) ) f len ( ) ] ; for i in 0 .. f . len ( ) { f_rev [ i . reverse_bits ( ) >> bit_colength ] = f [ i ] ; } sub ( & mut f_rev , zeta ) ; return f_rev ; fn sub < T , M > ( f : & mut [ ModInt < T , M > ] , zeta : ModInt < T , M > ) where M : StaticModulus < T > , T : NumAssignOps + PrimInt + Unsigned , { let n = f . len ( ) ; if n == 1 { return ; } sub ( & mut f [ .. n / 2 ] , zeta * zeta ) ; sub ( & mut f [ n / 2 .. ] , zeta * zeta ) ; let mut pow_zeta = ModInt :: new ( T :: one ( ) ) ; for i in 0 .. n / 2 { let g0 = f [ i ] ; let g1 = f [ i + n / 2 ] ; f [ i ] = g0 + pow_zeta * g1 ; f [ i + n / 2 ] = g0 - pow_zeta * g1 ; pow_zeta = pow_zeta * zeta ; } } }
Number-theoretic transformation
The length of f must be a power of 2
and zeta must be a primitive f.len()-th root of unity
The inverse can be calculated by doing the same
with the original zeta's inverse as zeta
and dividing by f.len()
Number - theoretic transformation The length of f must be a power of 2 and zeta must be a primitive f . len () - th root of unity The inverse can be calculated by doing the same with the original zeta ' s inverse as zeta and dividing by f . len ()
f
&[ModInt<T, M>]
zeta
ModInt<T, M>
f
&[ModInt<T, M>]
zeta
ModInt<T, M>