BigUInt BigUInt::operator /(const BigUInt& operand2) const { int result_bits = significant_bit_count(); int operand2_bits = operand2.significant_bit_count(); if (operand2_bits == 0) { throw invalid_argument("operand2 must be positive"); } if (operand2_bits > result_bits) { BigUInt zero(result_bits); return zero; } BigUInt result(result_bits); BigUInt remainder(result_bits); MemoryPool pool; int uint64_count = divide_round_up(result_bits, bits_per_uint64); if (uint64_count > operand2.uint64_count()) { BigUInt operand2resized(result_bits); operand2resized = operand2; divide_uint_uint(value_, operand2resized.pointer(), uint64_count, result.pointer(), remainder.pointer(), pool); } else { divide_uint_uint(value_, operand2.pointer(), uint64_count, result.pointer(), remainder.pointer(), pool); } return result; }
BigUInt BigUInt::operator *(const BigUInt& operand2) const { int result_bits = significant_bit_count() + operand2.significant_bit_count(); BigUInt result(result_bits); multiply_uint_uint(value_, uint64_count(), operand2.pointer(), operand2.uint64_count(), result.uint64_count(), result.pointer()); return result; }
BigUInt BigUInt::operator +(const BigUInt& operand2) const { int result_bits = max(significant_bit_count(), operand2.significant_bit_count()) + 1; BigUInt result(result_bits); add_uint_uint(value_, uint64_count(), operand2.pointer(), operand2.uint64_count(), false, result.uint64_count(), result.pointer()); return result; }
ChooserPoly ChooserEvaluator::multiply_plain(const ChooserPoly &operand, int plain_max_coeff_count, const BigUInt &plain_max_abs_value) { if (operand.max_coeff_count_ <= 0 || operand.comp_ == nullptr) { throw invalid_argument("operand is not correctly initialized"); } if (plain_max_coeff_count <= 0) { throw invalid_argument("plain_max_coeff_count must be positive"); } if (plain_max_abs_value.is_zero()) { return ChooserPoly(1, 0, new MultiplyPlainComputation(*operand.comp_, plain_max_coeff_count, plain_max_abs_value)); } if (operand.max_abs_value_.is_zero()) { return ChooserPoly(1, 0, new MultiplyPlainComputation(*operand.comp_, plain_max_coeff_count, plain_max_abs_value)); } uint64_t growth_factor = min(operand.max_coeff_count_, plain_max_coeff_count); int prod_bit_count = operand.max_abs_value_.significant_bit_count() + plain_max_abs_value.significant_bit_count() + get_significant_bit_count(growth_factor) + 1; int prod_uint64_count = divide_round_up(prod_bit_count, bits_per_uint64); Pointer prod_max_abs_value(allocate_zero_uint(prod_uint64_count, pool_)); ConstPointer wide_operand_max_abs_value(duplicate_uint_if_needed(operand.max_abs_value_.pointer(), operand.max_abs_value_.uint64_count(), prod_uint64_count, false, pool_)); multiply_uint_uint(&growth_factor, 1, plain_max_abs_value.pointer(), plain_max_abs_value.uint64_count(), prod_uint64_count, prod_max_abs_value.get()); ConstPointer temp_pointer(duplicate_uint_if_needed(prod_max_abs_value.get(), prod_uint64_count, prod_uint64_count, true, pool_)); multiply_uint_uint(wide_operand_max_abs_value.get(), prod_uint64_count, temp_pointer.get(), prod_uint64_count, prod_uint64_count, prod_max_abs_value.get()); return ChooserPoly(operand.max_coeff_count_ + plain_max_coeff_count - 1, BigUInt(prod_bit_count, prod_max_abs_value.get()), new MultiplyPlainComputation(*operand.comp_, plain_max_coeff_count, plain_max_abs_value)); }
BigUInt BigUInt::operator -(const BigUInt& operand2) const { int result_bits = max(bit_count_, operand2.bit_count()); BigUInt result(result_bits); sub_uint_uint(value_, uint64_count(), operand2.pointer(), operand2.uint64_count(), false, result.uint64_count(), result.pointer()); filter_highbits_uint(result.pointer(), result.uint64_count(), result_bits); return result; }
BigUInt BigUInt::operator |(const BigUInt& operand2) const { int result_bits = max(bit_count_, operand2.bit_count()); BigUInt result(result_bits); int uint64_count = result.uint64_count(); if (uint64_count != this->uint64_count()) { result = *this; or_uint_uint(result.pointer(), operand2.pointer(), uint64_count, result.pointer()); } else if (uint64_count != operand2.uint64_count()) { result = operand2; or_uint_uint(result.pointer(), value_, uint64_count, result.pointer()); } else { or_uint_uint(value_, operand2.pointer(), uint64_count, result.pointer()); } return result; }
BigUInt BigUInt::operator %(const BigUInt& operand2) const { if (operand2.is_zero()) { throw invalid_argument("operand2 must be positive"); } MemoryPool pool; Modulus modulus(operand2.pointer(), operand2.uint64_count(), pool); int result_bits = significant_bit_count(); BigUInt result(result_bits); result = *this; int uint64_count = divide_round_up(result_bits, bits_per_uint64); modulo_uint_inplace(result.pointer(), uint64_count, modulus, pool); return result; }