static inline AA1 case_1(AA1 & x, int32_t sn, const AA1 & n) { typedef typename meta::scalar_of<AA1>::type sA1; /* Power series expansion */ AA1 eqzx = is_eqz(x); x = seladd(is_eqz(x), x, One<A1>()); //loop is infinite for x == 0 sA1 psi1 = Zero<sA1>(); for( int32_t i=sn-1; i; --i ) psi1 += rec((sA1)i); AA1 psi = -Euler<A1>()-nt2::log(x)+splat<A1>(psi1); AA1 t; AA1 z = -x; AA1 xk = Zero<A1>(); AA1 yk = One<A1>(); AA1 pk = One<A1>() - n; AA1 ans = ( sn == 1 ) ? Zero<A1>() : rec(pk); do { xk += One<AA1>(); yk *= z/xk; pk += One<AA1>(); ans = seladd(is_nez(pk), ans, yk/pk); t = select(is_nez(ans), nt2::abs(yk/ans), One<AA1>()); } while( nt2::bitwise_any(gt(t, Halfeps<A1>()))); return seladd(eqzx,(nt2::powi(z, sn-1) * psi / nt2::gamma(n)) - ans, Inf<A1>()); //TO DO pow->powi and gamma splatted from scalar or mere factorial call }
static inline A0 cosa(const A0& a0) { static const sint_type de = sizeof(sint_type)*8-1; // size in bits of the scalar types minus one if (is_invalid(a0)) return Nan<A0>(); //Nan or Inf input A0 x = nt2::abs(a0); if (redu_t::replacement_needed(x)) { return redu_t::cos_replacement(a0); } else { A0 xr = Nan<A0>(), xc; int_type n = redu_t::reduce(x, xr, xc); int_type swap_bit = n&One<int_type>(); int_type sign_bit = shli(b_xor(swap_bit, (n&2)>>1), de); A0 z = sqr(xr); if (is_nez(swap_bit)) { z = eval_t::sin_eval(z, xr, xc); } else { z = eval_t::cos_eval(z, xr, xc); } return b_xor(z,sign_bit); } }
static inline void sincosa(const A0& a0, A0& s, A0& c) { if (is_invalid(a0)) { s = c = Nan<A0>(); return; } A0 x = nt2::abs(a0); if (redu_t::replacement_needed(x)) { redu_t::sincos_replacement(a0, s, c); } else { static const sint_type de = sizeof(sint_type)*8-1; A0 xr, xc; int_type n = redu_t::reduce(x, xr, xc); int_type swap_bit = n&One<int_type>(); A0 z = sqr(xr); int_type cos_sign_bit = shli(b_xor(swap_bit, (n&Two<int_type>())>>1), de); A0 sin_sign_bit = b_xor(bitofsign(a0), shli(n&Two<int_type>(), de-1)); if (is_nez(swap_bit)) { c = eval_t::sin_eval(z, xr, xc); s = eval_t::cos_eval(z, xr, xc); } else { c = eval_t::cos_eval(z, xr, xc); s = eval_t::sin_eval(z, xr, xc); } c = b_xor(c,cos_sign_bit); s = b_xor(s,sin_sign_bit); } }
static inline A0 sincosa(const A0& a0, A0& c, const regular&) { A0 s; if (is_invalid(a0)) { c = Nan<A0>(); return c; } const A0 x = nt2::abs(a0); static const sint_type de = sizeof(sint_type)*8-1; A0 xr, xc; const int_type n = redu_t::reduce(x, xr, xc); const int_type swap_bit = n&One<int_type>(); const A0 z = sqr(xr); const int_type cos_sign_bit = shli(b_xor(swap_bit, (n&Two<int_type>())>>1), de); const A0 sin_sign_bit = b_xor(bitofsign(a0), shli(n&Two<int_type>(), de-1)); if (is_nez(swap_bit)) { c = eval_t::sin_eval(z, xr, xc); s = eval_t::cos_eval(z, xr, xc); } else { c = eval_t::cos_eval(z, xr, xc); s = eval_t::sin_eval(z, xr, xc); } c = b_xor(c,cos_sign_bit); return b_xor(s,sin_sign_bit); }
static inline AA1 case_2(const AA1 & x, int32_t /*sn*/, const AA1 & n) { typedef typename meta::scalar_of<AA1>::type sAA1; int32_t sk = 1; AA1 t; AA1 pkm2 = One<AA1>(); AA1 qkm2 = x; AA1 pkm1 = One<AA1>(); AA1 qkm1 = x + n; AA1 ans = pkm1/qkm1; do { AA1 test = is_nez(splat<AA1>(is_odd(++sk))); AA1 k_2 = splat<AA1>(sk >> 1); AA1 yk = sel(test, One<AA1>(), x); AA1 xk = seladd(test, k_2, n); AA1 pk = pkm1 * yk + pkm2 * xk; AA1 qk = qkm1 * yk + qkm2 * xk; AA1 r = pk/qk; test = is_nez(qk); t = sel(test,nt2::abs((ans-r)/r),One<AA1>()); ans = sel(test, r, ans); pkm2 = pkm1; pkm1 = pk; qkm2 = qkm1; qkm1 = qk; test = gt(nt2::abs(pk), Expnibig<AA1>()); AA1 fac = sel(test, Halfeps<AA1>(), One<AA1>()); pkm2 *= fac; pkm1 *= fac; qkm2 *= fac; qkm1 *= fac; } while( nt2::bitwise_any(gt(t, Halfeps<AA1>())) ); return ans*nt2::exp(-x); }
namespace nt2 { namespace functors { // no special validate for majority ///////////////////////////////////////////////////////////////////////////// // Compute majority(const A0& a0, const A0& a1, const A0& a2) ///////////////////////////////////////////////////////////////////////////// template<class Extension,class Info> struct call<majority_, tag::simd_(tag::arithmetic_,Extension),Info> { template<class Sig> struct result; template<class This,class A0> struct result<This(A0,A0,A0)> : meta::strip<A0>{};// NT2_FUNCTOR_CALL(3) { A0 aa0 = is_nez(a0); A0 aa1 = is_nez(a1); A0 aa2 = is_nez(a2); return b_or(b_or(b_and(aa0, aa1),b_and(aa1, aa2)),b_and(aa2, aa0)); } }; } } #endif
namespace nt2 { namespace ext { template<class X, class Dummy> struct call<tag::gcd_(tag::simd_<tag::arithmetic_, X> , tag::simd_<tag::arithmetic_, X> ), tag::cpu_, Dummy> : callable { template<class Sig> struct result; template<class This,class A0> struct result<This(A0,A0)> : meta::strip<A0>{}; NT2_FUNCTOR_CALL(2) { A0 a = a0, b = a1; A0 t= is_nez(b); while (nt2::any(t)) { A0 r = t&rem(a, b); a = sel(t, b, a); b = r; t= is_nez(b); } return a; } }; } } ///////////////////////////////////////////////////////////////////////////// // Implementation when type A0 is real_ /////////////////////////////////////////////////////////////////////////////
static inline logic cot_invalid(const A0& x) { return /*is_invalid(x)|*/(is_nez(x)&is_flint(x)); }
namespace nt2 { namespace ext { template<class X, class Dummy> struct call<tag::negate_(tag::simd_<tag::arithmetic_, X> , tag::simd_<tag::arithmetic_, X> ), tag::cpu_, Dummy> : callable { template<class Sig> struct result; template<class This,class A0> struct result<This(A0,A0)> : meta::strip<A0>{};// NT2_FUNCTOR_CALL(2) { return sel(is_ltz(a1),-a0,is_nez(a1)&a0); } }; } } ///////////////////////////////////////////////////////////////////////////// // Implementation when type A0 is unsigned ///////////////////////////////////////////////////////////////////////////// NT2_REGISTER_DISPATCH(tag::negate_, tag::cpu_, (A0)(X), ((simd_<unsigned_<A0>,X>)) ((simd_<unsigned_<A0>,X>)) ); namespace nt2 { namespace ext {
); namespace nt2 { namespace ext { template<class X, class Dummy> struct call<tag::negation_(tag::simd_<tag::arithmetic_, X> , tag::simd_<tag::arithmetic_, X> ), tag::cpu_, Dummy> : callable { template<class Sig> struct result; template<class This,class A0> struct result<This(A0,A0)> : meta::strip<A0>{};// NT2_FUNCTOR_CALL(2) { return sel(is_ltz(a1),-a0,b_and(is_nez(a1), a0)); } }; } } ///////////////////////////////////////////////////////////////////////////// // Implementation when type A0 is unsigned ///////////////////////////////////////////////////////////////////////////// NT2_REGISTER_DISPATCH(tag::negation_, tag::cpu_, (A0)(X), ((simd_<unsigned_<A0>,X>)) ((simd_<unsigned_<A0>,X>)) ); namespace nt2 { namespace ext {