P-Adic numbers, basic: Difference between revisions
Content added Content deleted
m (Corrected a mistake in a comment.) |
m (Minor code improvement.) |
||
Line 63: | Line 63: | ||
public: |
public: |
||
// Create a p-adic number, with p = 'prime', from the given rational 'numerator' / 'denominator'. |
// Create a p-adic number, with p = 'prime', from the given rational 'numerator' / 'denominator'. |
||
p_adic(uint32_t prime, int32_t numerator, int32_t denominator) : prime(prime) { |
p_adic(const uint32_t& prime, int32_t numerator, int32_t denominator) : prime(prime) { |
||
if ( denominator == 0 ) { |
if ( denominator == 0 ) { |
||
std::invalid_argument("Denominator cannot be zero"); |
std::invalid_argument("Denominator cannot be zero"); |
||
Line 119: | Line 119: | ||
} |
} |
||
std::vector<uint32_t> this_digits = digits; |
|||
std::vector<uint32_t> other_digits = other.digits; |
|||
std::vector<uint32_t> result; |
std::vector<uint32_t> result; |
||
// Adjust the digits so that the p-adic points are aligned |
// Adjust the digits so that the p-adic points are aligned |
||
for ( int32_t i = 0; i < -order + other.order; ++i ) { |
for ( int32_t i = 0; i < -order + other.order; ++i ) { |
||
other_digits.insert(this_digits.begin(), 0); |
|||
} |
} |
||
for ( int32_t i = 0; i < -other.order + order; ++i ) { |
for ( int32_t i = 0; i < -other.order + order; ++i ) { |
||
this_digits.insert(this_digits.begin(), 0); |
|||
} |
} |
||
// Standard digit by digit addition |
// Standard digit by digit addition |
||
uint32_t carry = 0; |
uint32_t carry = 0; |
||
for ( uint32_t i = 0; i < std::min( |
for ( uint32_t i = 0; i < std::min(this_digits.size(), other_digits.size()); ++i ) { |
||
const uint32_t sum = |
const uint32_t sum = this_digits[i] + other_digits[i] + carry; |
||
const uint32_t remainder = sum % prime; |
const uint32_t remainder = sum % prime; |
||
carry = ( sum >= prime ) ? 1 : 0; |
carry = ( sum >= prime ) ? 1 : 0; |
||
result.emplace_back(remainder); |
result.emplace_back(remainder); |
||
} |
|||
// Reverse the changes made to the digits |
|||
for ( int32_t i = 0; i < -order + other.order; ++i ) { |
|||
other.digits.erase(digits.begin()); |
|||
} |
|||
for ( int32_t i = 0; i < -other.order + order; ++i ) { |
|||
digits.erase(digits.begin()); |
|||
} |
} |
||
Line 230: | Line 223: | ||
* 'order' < 0 shifts the vector 'order' places to the right. |
* 'order' < 0 shifts the vector 'order' places to the right. |
||
*/ |
*/ |
||
p_adic(uint32_t prime, std::vector<uint32_t> digits, int32_t order) |
p_adic(const uint32_t& prime, const std::vector<uint32_t>& digits, const int32_t& order) |
||
: prime(prime), digits(digits), order(order) { |
: prime(prime), digits(digits), order(order) { |
||
} |
} |
||
Line 244: | Line 237: | ||
// Return the multiplicative inverse of the given number modulo 'prime'. |
// Return the multiplicative inverse of the given number modulo 'prime'. |
||
uint32_t modulo_inverse(uint32_t number) { |
uint32_t modulo_inverse(const uint32_t& number) const { |
||
uint32_t inverse = 1; |
uint32_t inverse = 1; |
||
while ( ( inverse * number ) % prime != 1 ) { |
while ( ( inverse * number ) % prime != 1 ) { |
||
Line 253: | Line 246: | ||
// Return the given number modulo 'prime' in the range 0..'prime' - 1. |
// Return the given number modulo 'prime' in the range 0..'prime' - 1. |
||
int32_t modulo_prime(int64_t number) { |
int32_t modulo_prime(const int64_t& number) const { |
||
const int32_t div = static_cast<int32_t>(number % prime); |
const int32_t div = static_cast<int32_t>(number % prime); |
||
return ( div >= 0 ) ? div : div + prime; |
return ( div >= 0 ) ? div : div + prime; |
||
Line 266: | Line 259: | ||
// Return the given vector of base 'prime' integers converted to a decimal integer. |
// Return the given vector of base 'prime' integers converted to a decimal integer. |
||
uint32_t convert_to_decimal(std::vector<uint32_t> numbers) { |
uint32_t convert_to_decimal(const std::vector<uint32_t>& numbers) const { |
||
uint32_t decimal = 0; |
uint32_t decimal = 0; |
||
uint32_t multiple = 1; |
uint32_t multiple = 1; |
||
Line 277: | Line 270: | ||
// Return whether the given vector consists of all zeros. |
// Return whether the given vector consists of all zeros. |
||
bool all_zero_digits(std::vector<uint32_t> numbers) { |
bool all_zero_digits(const std::vector<uint32_t>& numbers) const { |
||
for ( uint32_t number : numbers ) { |
for ( uint32_t number : numbers ) { |
||
if ( number != 0 ) { |
if ( number != 0 ) { |
||
Line 287: | Line 280: | ||
// Return whether the given vector ends with multiple instances of the given number. |
// Return whether the given vector ends with multiple instances of the given number. |
||
bool ends_with(std::vector<uint32_t> numbers, uint32_t number) { |
bool ends_with(const std::vector<uint32_t>& numbers, const uint32_t& number) const { |
||
for ( uint64_t i = numbers.size() - 1; i >= numbers.size() - PRECISION / 2; --i ) { |
for ( uint64_t i = numbers.size() - 1; i >= numbers.size() - PRECISION / 2; --i ) { |
||
if ( numbers[i] != number ) { |
if ( numbers[i] != number ) { |