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 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(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 ) {
digits.assign(DIGITS_SIZE, 0);
order = ORDER_MAX;
order = ORDER_MAX;
return;
return;
}
}


// Remove multiples of 'prime' and adjust the order of the P-adic number accordingly
// 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 P-adic digits
// 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 P-adic number with the given P-adic number.
// 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 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(other_digits.begin(), 0);
other_digits.insert(other_digits.begin(), 0);
Line 172: Line 173:
}
}


// Return the Rational representation of this P-adic number.
// 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 p-adic.
// Return a string representation of this P_adic number.
std::string to_string() {
std::string to_string() {
if ( digits.empty() ) {
digits.assign(DIGITS_SIZE, 0);
}

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";
result.erase(result.begin());
}
}


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' ) {
result = result.substr(0, result.length() - 1);
}
}
}


const uint32_t surplus = DIGITS_SIZE - PRECISION;
return " ..." + result.substr(result.length() - PRECISION - 1);
return " ..." + result.substr(surplus, result.length() - surplus);
}
}


private:
private:
/**
/**
* Create a P-adic, with p = 'prime', directly from a vector of digits.
* Create a P_adic, with p = 'prime', directly from a vector of digits.
*
*
* With 'order' = 0, the vector [1, 2, 3, 4, 5] creates the p-adic ...54321.0
* 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 p-adic number
// Transform the given vector of digits representing a P_adic number
// into a vector which represents the negation of the p-adic number.
// 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] = ( prime - numbers[0] ) % prime;
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:
3-adic numbers:
-2 / 87 => ...2101020111222001212021110002210102011122.2
-2 / 87 => ...101020111222001212021110002210102011122.2
4 / 97 => ...1022220111100202001010001200002111122021.0
4 / 97 => ...022220111100202001010001200002111122021.0
sum => ...0201011000022210220101111202212220210220.2
sum => ...201011000022210220101111202212220210220.2
Rational = 154 / 8439
Rational = 154 / 8439


7-adic numbers:
7-adic numbers:
5 / 8 => ...2424242424242424242424242424242424242425.0
5 / 8 => ...424242424242424242424242424242424242425.0
353 / 30809 => ...1560462505550343461155520004023663643455.0
353 / 30809 => ...560462505550343461155520004023663643455.0
sum => ...4315035233123101033613062431266421216213.0
sum => ...315035233123101033613062431266421216213.0
Rational = 156869 / 246472
Rational = 156869 / 246472
</pre>
</pre>