static void produce_digits_low( limb_type *limbs, std::size_t limb_cnt, fp_value_t<T> const &val, int32_t exp10, int32_t denom_shift, uint8_t *m_out, std::size_t &m_len, int32_t &exp_out ) { auto num(limbs); auto bound(limbs + limb_cnt); bool in_range(false); if (Pow2) { in_range = compare_sum_pow2<true>( num, bound, denom_shift, limb_cnt ) >= 0; } else { if (val.m & 1) in_range = compare_sum_pow2<false>( num, bound, denom_shift, limb_cnt ) > 0; else in_range = compare_sum_pow2<false>( num, bound, denom_shift, limb_cnt ) >= 0; } if (in_range) ++exp10; else { multiply_10(num, limb_cnt); multiply_10(bound, limb_cnt); } m_len = 0; while (true) { limb_type digit(mod_pow2(num, limb_cnt, denom_shift)); int bd_test(0); if (Pow2) { bd_test |= compare( num, bound, limb_cnt ) <= 0 ? 1 : 0; bd_test |= compare_sum_pow2<true>( num, bound, denom_shift, limb_cnt ) >= 0 ? 2 : 0; } else { if (val.m & 1) { bd_test |= compare( num, bound, limb_cnt ) < 0 ? 1 : 0; bd_test |= compare_sum_pow2<false>( num, bound, denom_shift, limb_cnt ) > 0 ? 2 : 0; } else { bd_test |= compare( num, bound, limb_cnt ) <= 0 ? 1 : 0; bd_test |= compare_sum_pow2<false>( num, bound, denom_shift, limb_cnt ) >= 0 ? 2 : 0; } } switch (bd_test) { case 0: m_out[m_len / 2] = m_len & 1 ? m_out[m_len / 2] | (digit << 4) : digit; ++m_len; multiply_10(num, limb_cnt); multiply_10(bound, limb_cnt); break; case 1: m_out[m_len / 2] = m_len & 1 ? m_out[m_len / 2] | (digit << 4) : digit; ++m_len; exp_out = exp10 - m_len; return; case 2: ++digit; m_out[m_len / 2] = m_len & 1 ? m_out[m_len / 2] | (digit << 4) : digit; ++m_len; exp_out = exp10 - m_len; return; case 3: bd_test = compare_sum_pow2<false>( num, num, denom_shift, limb_cnt ); if ((bd_test > 0) || (!bd_test && (digit & 1))) ++digit; m_out[m_len / 2] = m_len & 1 ? m_out[m_len / 2] | (digit << 4) : digit; ++m_len; exp_out = exp10 - m_len; return; } } }
ll mod_pow2(ll x, ll n, ll mod){ if (n==0) return 1; ll res = mod_pow2(x* x % mod, n / 2, mod); if (n&1) res = res*x % mod; return res; }