Exemplo n.º 1
0
	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;
			}
		}
	}
Exemplo n.º 2
0
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;
}