P-Adic numbers, basic: Difference between revisions
Content added Content deleted
m (Improved coding.) |
m (Improved code.) |
||
Line 93: | Line 93: | ||
class P_adic { |
class P_adic { |
||
public: |
public: |
||
// Create a |
// Create a P_adic number, with p = 'prime', from the given rational 'numerator' / 'denominator'. |
||
P_adic(const 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"); |
throw std::invalid_argument("Denominator cannot be zero"); |
||
} |
} |
||
Line 103: | Line 103: | ||
// Process rational zero |
// Process rational zero |
||
if ( numerator == 0 ) { |
if ( numerator == 0 ) { |
||
⚫ | |||
order = ORDER_MAX; |
order = ORDER_MAX; |
||
return; |
return; |
||
} |
} |
||
// Remove multiples of 'prime' and adjust the order of the |
// Remove multiples of 'prime' and adjust the order of the P_adic number accordingly |
||
while ( modulo_prime(numerator) == 0 ) { |
while ( modulo_prime(numerator) == 0 ) { |
||
numerator /= static_cast<int32_t>(prime); |
numerator /= static_cast<int32_t>(prime); |
||
Line 118: | Line 119: | ||
} |
} |
||
// Standard calculation of |
// Standard calculation of P_adic digits |
||
const uint64_t inverse = modulo_inverse(denominator); |
const uint64_t inverse = modulo_inverse(denominator); |
||
while ( digits.size() < DIGITS_SIZE ) { |
while ( digits.size() < DIGITS_SIZE ) { |
||
Line 141: | Line 142: | ||
} |
} |
||
// Return the sum of this |
// Return the sum of this P_adic number with the given P_adic number. |
||
P_adic add(P_adic other) { |
P_adic add(P_adic other) { |
||
if ( prime != other.prime ) { |
if ( prime != other.prime ) { |
||
std::invalid_argument("Cannot add p-adic's with different primes"); |
throw std::invalid_argument("Cannot add p-adic's with different primes"); |
||
} |
} |
||
Line 151: | Line 152: | ||
std::vector<uint32_t> result; |
std::vector<uint32_t> result; |
||
// Adjust the digits so that the |
// 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(other_digits.begin(), 0); |
other_digits.insert(other_digits.begin(), 0); |
||
Line 172: | Line 173: | ||
} |
} |
||
// Return the Rational representation of this |
// Return the Rational representation of this P_adic number. |
||
Rational convert_to_rational() { |
Rational convert_to_rational() { |
||
std::vector<uint32_t> numbers = digits; |
std::vector<uint32_t> numbers = digits; |
||
Line 227: | Line 228: | ||
} |
} |
||
// Return a string representation of this |
// Return a string representation of this P_adic number. |
||
std::string to_string() { |
std::string to_string() { |
||
if ( digits.empty() ) { |
|||
⚫ | |||
⚫ | |||
std::vector<uint32_t> numbers = digits; |
std::vector<uint32_t> numbers = digits; |
||
pad_with_zeros(numbers); |
pad_with_zeros(numbers); |
||
Line 244: | Line 241: | ||
for ( int32_t i = 0; i < order; ++i ) { |
for ( int32_t i = 0; i < order; ++i ) { |
||
result += "0"; |
result += "0"; |
||
⚫ | |||
} |
} |
||
Line 250: | Line 246: | ||
} else { |
} else { |
||
result.insert(result.length() + order, "."); |
result.insert(result.length() + order, "."); |
||
result = "0" + result; |
|||
while ( result[result.length() - 1] == '0' ) { |
|||
⚫ | |||
⚫ | |||
} |
} |
||
return " ..." + result.substr(result.length() - PRECISION - 1); |
|||
return " ..." + result.substr(surplus, result.length() - surplus); |
|||
} |
} |
||
private: |
private: |
||
/** |
/** |
||
* Create a |
* Create a P_adic, with p = 'prime', directly from a vector of digits. |
||
* |
* |
||
* |
* For example: with 'order' = 0, the vector [1, 2, 3, 4, 5] creates the p-adic ...54321.0, |
||
* 'order' > 0 shifts the vector 'order' places to the left and |
* 'order' > 0 shifts the vector 'order' places to the left and |
||
* 'order' < 0 shifts the vector 'order' places to the right. |
* 'order' < 0 shifts the vector 'order' places to the right. |
||
Line 269: | Line 267: | ||
} |
} |
||
// Transform the given vector of digits representing a |
// Transform the given vector of digits representing a P_adic number |
||
// into a vector which represents the negation of the |
// into a vector which represents the negation of the P_adic number. |
||
void negate_digits(std::vector<uint32_t> numbers) { |
void negate_digits(std::vector<uint32_t>& numbers) { |
||
numbers[0] = ( |
numbers[0] = modulo_prime(prime - numbers[0]); |
||
for ( uint64_t i = 1; i < numbers.size(); ++i ) { |
for ( uint64_t i = 1; i < numbers.size(); ++i ) { |
||
numbers[i] = prime - 1 - numbers[i]; |
numbers[i] = prime - 1 - numbers[i]; |
||
Line 294: | Line 292: | ||
// The given vector is padded on the right by zeros up to a maximum length of 'DIGITS_SIZE'. |
// The given vector is padded on the right by zeros up to a maximum length of 'DIGITS_SIZE'. |
||
void pad_with_zeros(std::vector<uint32_t> vector) { |
void pad_with_zeros(std::vector<uint32_t>& vector) { |
||
while ( vector.size() < DIGITS_SIZE ) { |
while ( vector.size() < DIGITS_SIZE ) { |
||
vector.emplace_back(0); |
vector.emplace_back(0); |
||
Line 366: | Line 364: | ||
{{ out }} |
{{ out }} |
||
<pre> |
<pre> |
||
3-adic numbers: |
|||
-2 / 87 => ... |
-2 / 87 => ...101020111222001212021110002210102011122.2 |
||
4 / 97 => ... |
4 / 97 => ...022220111100202001010001200002111122021.0 |
||
sum => ... |
sum => ...201011000022210220101111202212220210220.2 |
||
Rational = 154 / 8439 |
Rational = 154 / 8439 |
||
7-adic numbers: |
7-adic numbers: |
||
5 / 8 => ... |
5 / 8 => ...424242424242424242424242424242424242425.0 |
||
353 / 30809 => ... |
353 / 30809 => ...560462505550343461155520004023663643455.0 |
||
sum => ... |
sum => ...315035233123101033613062431266421216213.0 |
||
Rational = 156869 / 246472 |
Rational = 156869 / 246472 |
||
</pre> |
</pre> |