Data update
This commit is contained in:
parent
72eb4943cb
commit
4d5544505c
2347 changed files with 62432 additions and 16731 deletions
|
|
@ -47,4 +47,3 @@ set the shortest prime-exponent combinations that allow valid reconstruction.
|
|||
|
||||
__TOC__
|
||||
|
||||
|
||||
|
|
|
|||
402
Task/P-Adic-numbers-basic/C-sharp/p-adic-numbers-basic.cs
Normal file
402
Task/P-Adic-numbers-basic/C-sharp/p-adic-numbers-basic.cs
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
public static class PAdicNumbersBasic
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("3-adic numbers:");
|
||||
Padic padicOne = new Padic(3, -5, 9);
|
||||
Console.WriteLine("-5 / 9 => " + padicOne);
|
||||
Padic padicTwo = new Padic(3, 47, 12);
|
||||
Console.WriteLine("47 / 12 => " + padicTwo);
|
||||
|
||||
Padic sum = padicOne.Add(padicTwo);
|
||||
Console.WriteLine("sum => " + sum);
|
||||
Console.WriteLine("Rational = " + sum.ConvertToRational());
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine("7-adic numbers:");
|
||||
padicOne = new Padic(7, 5, 8);
|
||||
Console.WriteLine("5 / 8 => " + padicOne);
|
||||
padicTwo = new Padic(7, 353, 30809);
|
||||
Console.WriteLine("353 / 30809 => " + padicTwo);
|
||||
|
||||
sum = padicOne.Add(padicTwo);
|
||||
Console.WriteLine("sum => " + sum);
|
||||
Console.WriteLine("Rational = " + sum.ConvertToRational());
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Padic
|
||||
{
|
||||
/**
|
||||
* Create a p-adic, with p = aPrime, from the given rational 'aNumerator' / 'aDenominator'.
|
||||
*/
|
||||
public Padic(int aPrime, int aNumerator, int aDenominator)
|
||||
{
|
||||
if (aDenominator == 0)
|
||||
{
|
||||
throw new ArgumentException("Denominator cannot be zero");
|
||||
}
|
||||
|
||||
prime = aPrime;
|
||||
digits = new List<int>(DIGITS_SIZE);
|
||||
order = 0;
|
||||
|
||||
// Process rational zero
|
||||
if (aNumerator == 0)
|
||||
{
|
||||
order = MAX_ORDER;
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove multiples of 'prime' and adjust the order of the p-adic number accordingly
|
||||
while (FloorMod(aNumerator, prime) == 0)
|
||||
{
|
||||
aNumerator /= prime;
|
||||
order += 1;
|
||||
}
|
||||
|
||||
while (FloorMod(aDenominator, prime) == 0)
|
||||
{
|
||||
aDenominator /= prime;
|
||||
order -= 1;
|
||||
}
|
||||
|
||||
// Standard calculation of p-adic digits
|
||||
long inverse = ModuloInverse(aDenominator);
|
||||
while (digits.Count < DIGITS_SIZE)
|
||||
{
|
||||
int digit = FloorMod((int)(aNumerator * inverse), prime);
|
||||
digits.Add(digit);
|
||||
|
||||
aNumerator -= digit * aDenominator;
|
||||
|
||||
if (aNumerator != 0)
|
||||
{
|
||||
// The denominator is not a power of a prime
|
||||
int count = 0;
|
||||
while (FloorMod(aNumerator, prime) == 0)
|
||||
{
|
||||
aNumerator /= prime;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
for (int i = count; i > 1; i--)
|
||||
{
|
||||
digits.Add(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sum of this p-adic number and the given p-adic number.
|
||||
*/
|
||||
public Padic Add(Padic aOther)
|
||||
{
|
||||
if (prime != aOther.prime)
|
||||
{
|
||||
throw new ArgumentException("Cannot add p-adic's with different primes");
|
||||
}
|
||||
|
||||
List<int> result = new List<int>();
|
||||
|
||||
// Adjust the digits so that the p-adic points are aligned
|
||||
for (int i = 0; i < -order + aOther.order; i++)
|
||||
{
|
||||
aOther.digits.Insert(0, 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < -aOther.order + order; i++)
|
||||
{
|
||||
digits.Insert(0, 0);
|
||||
}
|
||||
|
||||
// Standard digit by digit addition
|
||||
int carry = 0;
|
||||
for (int i = 0; i < Math.Min(digits.Count, aOther.digits.Count); i++)
|
||||
{
|
||||
int sum = digits[i] + aOther.digits[i] + carry;
|
||||
int remainder = FloorMod(sum, prime);
|
||||
carry = (sum >= prime) ? 1 : 0;
|
||||
result.Add(remainder);
|
||||
}
|
||||
|
||||
// Reverse the changes made to the digits
|
||||
for (int i = 0; i < -order + aOther.order; i++)
|
||||
{
|
||||
aOther.digits.RemoveAt(0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < -aOther.order + order; i++)
|
||||
{
|
||||
digits.RemoveAt(0);
|
||||
}
|
||||
|
||||
return new Padic(prime, result, AllZeroDigits(result) ? MAX_ORDER : Math.Min(order, aOther.order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Rational representation of this p-adic number.
|
||||
*/
|
||||
public Rational ConvertToRational()
|
||||
{
|
||||
List<int> numbers = new List<int>(digits);
|
||||
|
||||
// Zero
|
||||
if (numbers.Count == 0 || AllZeroDigits(numbers))
|
||||
{
|
||||
return new Rational(0, 1);
|
||||
}
|
||||
|
||||
// Positive integer
|
||||
if (order >= 0 && EndsWith(numbers, 0))
|
||||
{
|
||||
for (int i = 0; i < order; i++)
|
||||
{
|
||||
numbers.Insert(0, 0);
|
||||
}
|
||||
|
||||
return new Rational(ConvertToDecimal(numbers), 1);
|
||||
}
|
||||
|
||||
// Negative integer
|
||||
if (order >= 0 && EndsWith(numbers, prime - 1))
|
||||
{
|
||||
NegateList(numbers);
|
||||
for (int i = 0; i < order; i++)
|
||||
{
|
||||
numbers.Insert(0, 0);
|
||||
}
|
||||
|
||||
return new Rational(-ConvertToDecimal(numbers), 1);
|
||||
}
|
||||
|
||||
// Rational
|
||||
Padic sum = new Padic(prime, new List<int>(digits), order);
|
||||
Padic self = new Padic(prime, new List<int>(digits), order);
|
||||
int denominator = 1;
|
||||
do
|
||||
{
|
||||
sum = sum.Add(self);
|
||||
denominator += 1;
|
||||
} while (!(EndsWith(sum.digits, 0) || EndsWith(sum.digits, prime - 1)));
|
||||
|
||||
bool negative = EndsWith(sum.digits, prime - 1);
|
||||
if (negative)
|
||||
{
|
||||
NegateList(sum.digits);
|
||||
}
|
||||
|
||||
int numerator = negative ? -ConvertToDecimal(sum.digits) : ConvertToDecimal(sum.digits);
|
||||
|
||||
if (order > 0)
|
||||
{
|
||||
numerator *= (int)Math.Pow(prime, order);
|
||||
}
|
||||
|
||||
if (order < 0)
|
||||
{
|
||||
denominator *= (int)Math.Pow(prime, -order);
|
||||
}
|
||||
|
||||
return new Rational(numerator, denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representation of this p-adic.
|
||||
*/
|
||||
public override string ToString()
|
||||
{
|
||||
List<int> numbers = new List<int>(digits);
|
||||
PadWithZeros(numbers);
|
||||
numbers.Reverse();
|
||||
string numberString = string.Join("", numbers.Select(n => n.ToString()));
|
||||
StringBuilder builder = new StringBuilder(numberString);
|
||||
|
||||
if (order >= 0)
|
||||
{
|
||||
for (int i = 0; i < order; i++)
|
||||
{
|
||||
builder.Append("0");
|
||||
}
|
||||
|
||||
builder.Append(".0");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Insert(builder.Length + order, ".");
|
||||
|
||||
while (builder.ToString().EndsWith("0"))
|
||||
{
|
||||
builder.Remove(builder.Length - 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return " ..." + builder.ToString().Substring(builder.Length - PRECISION - 1);
|
||||
}
|
||||
|
||||
// PRIVATE //
|
||||
|
||||
/**
|
||||
* Create a p-adic, with p = 'aPrime', directly from a list of digits.
|
||||
*
|
||||
* With 'aOrder' = 0, the list [1, 2, 3, 4, 5] creates the p-adic ...54321.0
|
||||
* 'aOrder' > 0 shifts the list 'aOrder' places to the left and
|
||||
* 'aOrder' < 0 shifts the list 'aOrder' places to the right.
|
||||
*/
|
||||
private Padic(int aPrime, List<int> aDigits, int aOrder)
|
||||
{
|
||||
prime = aPrime;
|
||||
digits = new List<int>(aDigits);
|
||||
order = aOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the multiplicative inverse of the given decimal number modulo 'prime'.
|
||||
*/
|
||||
private int ModuloInverse(int aNumber)
|
||||
{
|
||||
int inverse = 1;
|
||||
while (FloorMod(inverse * aNumber, prime) != 1)
|
||||
{
|
||||
inverse += 1;
|
||||
}
|
||||
|
||||
return inverse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the given list of digits representing a p-adic number
|
||||
* into a list which represents the negation of the p-adic number.
|
||||
*/
|
||||
private void NegateList(List<int> aDigits)
|
||||
{
|
||||
aDigits[0] = FloorMod(prime - aDigits[0], prime);
|
||||
for (int i = 1; i < aDigits.Count; i++)
|
||||
{
|
||||
aDigits[i] = prime - 1 - aDigits[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the given list of base 'prime' integers converted to a decimal integer.
|
||||
*/
|
||||
private int ConvertToDecimal(List<int> aNumbers)
|
||||
{
|
||||
int decimal_value = 0;
|
||||
int multiple = 1;
|
||||
foreach (int number in aNumbers)
|
||||
{
|
||||
decimal_value += number * multiple;
|
||||
multiple *= prime;
|
||||
}
|
||||
|
||||
return decimal_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given list consists of all zeros.
|
||||
*/
|
||||
private static bool AllZeroDigits(List<int> aList)
|
||||
{
|
||||
return aList.All(i => i == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The given list is padded on the right by zeros up to a maximum length of 'PRECISION'.
|
||||
*/
|
||||
private static void PadWithZeros(List<int> aList)
|
||||
{
|
||||
while (aList.Count < DIGITS_SIZE)
|
||||
{
|
||||
aList.Add(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given list ends with multiple instances of the given number.
|
||||
*/
|
||||
private static bool EndsWith(List<int> aDigits, int aDigit)
|
||||
{
|
||||
for (int i = aDigits.Count - 1; i >= aDigits.Count - PRECISION / 2; i--)
|
||||
{
|
||||
if (aDigits[i] != aDigit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* C# implementation of Java's Math.floorMod
|
||||
*/
|
||||
private static int FloorMod(int x, int y)
|
||||
{
|
||||
int r = x % y;
|
||||
// If the signs are different and modulo not zero, adjust result
|
||||
if ((x ^ y) < 0 && r != 0)
|
||||
{
|
||||
r += y;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public class Rational
|
||||
{
|
||||
private int numerator;
|
||||
private int denominator;
|
||||
|
||||
public Rational(int aNumerator, int aDenominator)
|
||||
{
|
||||
if (aDenominator < 0)
|
||||
{
|
||||
numerator = -aNumerator;
|
||||
denominator = -aDenominator;
|
||||
}
|
||||
else
|
||||
{
|
||||
numerator = aNumerator;
|
||||
denominator = aDenominator;
|
||||
}
|
||||
|
||||
if (aNumerator == 0)
|
||||
{
|
||||
denominator = 1;
|
||||
}
|
||||
|
||||
int gcd = GCD(numerator, denominator);
|
||||
numerator /= gcd;
|
||||
denominator /= gcd;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return numerator + " / " + denominator;
|
||||
}
|
||||
|
||||
private int GCD(int aOne, int aTwo)
|
||||
{
|
||||
if (aTwo == 0)
|
||||
{
|
||||
return Math.Abs(aOne);
|
||||
}
|
||||
return GCD(aTwo, FloorMod(aOne, aTwo));
|
||||
}
|
||||
}
|
||||
|
||||
private List<int> digits;
|
||||
private int order;
|
||||
|
||||
private readonly int prime;
|
||||
|
||||
private const int MAX_ORDER = 1000;
|
||||
private const int PRECISION = 40;
|
||||
private const int DIGITS_SIZE = PRECISION + 5;
|
||||
}
|
||||
310
Task/P-Adic-numbers-basic/JavaScript/p-adic-numbers-basic.js
Normal file
310
Task/P-Adic-numbers-basic/JavaScript/p-adic-numbers-basic.js
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
// Rational class for rational number representation
|
||||
class Rational {
|
||||
constructor(numerator, denominator) {
|
||||
if (denominator < 0) {
|
||||
this.numerator = -numerator;
|
||||
this.denominator = -denominator;
|
||||
} else {
|
||||
this.numerator = numerator;
|
||||
this.denominator = denominator;
|
||||
}
|
||||
|
||||
if (numerator === 0) {
|
||||
this.denominator = 1;
|
||||
}
|
||||
|
||||
const divisor = this.gcd(Math.abs(this.numerator), this.denominator);
|
||||
this.numerator = Math.floor(this.numerator / divisor);
|
||||
this.denominator = Math.floor(this.denominator / divisor);
|
||||
}
|
||||
|
||||
gcd(a, b) {
|
||||
while (b !== 0) {
|
||||
const temp = b;
|
||||
b = a % b;
|
||||
a = temp;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `${this.numerator} / ${this.denominator}`;
|
||||
}
|
||||
}
|
||||
|
||||
// P_adic class for p-adic number representation
|
||||
class P_adic {
|
||||
static PRECISION = 40;
|
||||
static ORDER_MAX = 1000;
|
||||
static DIGITS_SIZE = P_adic.PRECISION + 5;
|
||||
|
||||
// Create a P_adic number with p = 'prime', from the given rational 'numerator' / 'denominator'
|
||||
constructor(prime, numerator, denominator, digits = null, order = null) {
|
||||
this.prime = prime;
|
||||
|
||||
// If digits and order are provided, use them directly (for internal use)
|
||||
if (digits !== null && order !== null) {
|
||||
this.digits = digits;
|
||||
this.order = order;
|
||||
return;
|
||||
}
|
||||
|
||||
if (denominator === 0) {
|
||||
throw new Error("Denominator cannot be zero");
|
||||
}
|
||||
|
||||
this.order = 0;
|
||||
|
||||
// Process rational zero
|
||||
if (numerator === 0) {
|
||||
this.digits = Array(P_adic.DIGITS_SIZE).fill(0);
|
||||
this.order = P_adic.ORDER_MAX;
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove multiples of 'prime' and adjust the order of the P_adic number accordingly
|
||||
while (this.moduloPrime(numerator) === 0) {
|
||||
numerator = Math.floor(numerator / prime);
|
||||
this.order += 1;
|
||||
}
|
||||
|
||||
while (this.moduloPrime(denominator) === 0) {
|
||||
denominator = Math.floor(denominator / prime);
|
||||
this.order -= 1;
|
||||
}
|
||||
|
||||
// Standard calculation of P_adic digits
|
||||
const inverse = this.moduloInverse(denominator);
|
||||
this.digits = [];
|
||||
|
||||
while (this.digits.length < P_adic.DIGITS_SIZE) {
|
||||
const digit = this.moduloPrime(numerator * inverse);
|
||||
this.digits.push(digit);
|
||||
|
||||
numerator -= digit * denominator;
|
||||
|
||||
if (numerator !== 0) {
|
||||
// The denominator is not a power of a prime
|
||||
let count = 0;
|
||||
while (this.moduloPrime(numerator) === 0) {
|
||||
numerator = Math.floor(numerator / prime);
|
||||
count += 1;
|
||||
}
|
||||
|
||||
for (let i = count; i > 1; --i) {
|
||||
this.digits.push(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the sum of this P_adic number with the given P_adic number
|
||||
add(other) {
|
||||
if (this.prime !== other.prime) {
|
||||
throw new Error("Cannot add p-adic's with different primes");
|
||||
}
|
||||
|
||||
let this_digits = [...this.digits];
|
||||
let other_digits = [...other.digits];
|
||||
let result = [];
|
||||
|
||||
// Adjust the digits so that the P_adic points are aligned
|
||||
for (let i = 0; i < -this.order + other.order; ++i) {
|
||||
other_digits.unshift(0);
|
||||
}
|
||||
|
||||
for (let i = 0; i < -other.order + this.order; ++i) {
|
||||
this_digits.unshift(0);
|
||||
}
|
||||
|
||||
// Standard digit by digit addition
|
||||
let carry = 0;
|
||||
for (let i = 0; i < Math.min(this_digits.length, other_digits.length); ++i) {
|
||||
const sum = this_digits[i] + other_digits[i] + carry;
|
||||
const remainder = sum % this.prime;
|
||||
carry = (sum >= this.prime) ? 1 : 0;
|
||||
result.push(remainder);
|
||||
}
|
||||
|
||||
return new P_adic(
|
||||
this.prime,
|
||||
null,
|
||||
null,
|
||||
result,
|
||||
this.allZeroDigits(result) ? P_adic.ORDER_MAX : Math.min(this.order, other.order)
|
||||
);
|
||||
}
|
||||
|
||||
// Return the Rational representation of this P_adic number
|
||||
convertToRational() {
|
||||
let numbers = [...this.digits];
|
||||
|
||||
// Zero
|
||||
if (numbers.length === 0 || this.allZeroDigits(numbers)) {
|
||||
return new Rational(0, 1);
|
||||
}
|
||||
|
||||
// Positive integer
|
||||
if (this.order >= 0 && this.endsWith(numbers, 0)) {
|
||||
for (let i = 0; i < this.order; ++i) {
|
||||
numbers.unshift(0);
|
||||
}
|
||||
|
||||
return new Rational(this.convertToDecimal(numbers), 1);
|
||||
}
|
||||
|
||||
// Negative integer
|
||||
if (this.order >= 0 && this.endsWith(numbers, this.prime - 1)) {
|
||||
this.negateDigits(numbers);
|
||||
for (let i = 0; i < this.order; ++i) {
|
||||
numbers.unshift(0);
|
||||
}
|
||||
|
||||
return new Rational(-this.convertToDecimal(numbers), 1);
|
||||
}
|
||||
|
||||
// Rational
|
||||
const copy = new P_adic(this.prime, null, null, [...this.digits], this.order);
|
||||
let sum = new P_adic(this.prime, null, null, [...this.digits], this.order);
|
||||
let denominator = 1;
|
||||
|
||||
do {
|
||||
sum = sum.add(copy);
|
||||
denominator += 1;
|
||||
} while (!(this.endsWith(sum.digits, 0) || this.endsWith(sum.digits, this.prime - 1)));
|
||||
|
||||
const negative = this.endsWith(sum.digits, this.prime - 1);
|
||||
if (negative) {
|
||||
this.negateDigits(sum.digits);
|
||||
}
|
||||
|
||||
let numerator = negative ? -this.convertToDecimal(sum.digits) : this.convertToDecimal(sum.digits);
|
||||
|
||||
if (this.order > 0) {
|
||||
numerator *= Math.pow(this.prime, this.order);
|
||||
}
|
||||
|
||||
if (this.order < 0) {
|
||||
denominator *= Math.pow(this.prime, -this.order);
|
||||
}
|
||||
|
||||
return new Rational(numerator, denominator);
|
||||
}
|
||||
|
||||
// Return a string representation of this P_adic number
|
||||
toString() {
|
||||
let numbers = [...this.digits];
|
||||
this.padWithZeros(numbers);
|
||||
|
||||
let result = "";
|
||||
for (let i = numbers.length - 1; i >= 0; --i) {
|
||||
result += this.digits[i].toString();
|
||||
}
|
||||
|
||||
if (this.order >= 0) {
|
||||
for (let i = 0; i < this.order; ++i) {
|
||||
result += "0";
|
||||
}
|
||||
|
||||
result += ".0";
|
||||
} else {
|
||||
result = result.slice(0, result.length + this.order) + "." + result.slice(result.length + this.order);
|
||||
|
||||
while (result[result.length - 1] === '0') {
|
||||
result = result.substring(0, result.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return " ..." + result.substring(result.length - P_adic.PRECISION - 1);
|
||||
}
|
||||
|
||||
// Transform the given array of digits representing a P_adic number
|
||||
// into an array which represents the negation of the P_adic number
|
||||
negateDigits(numbers) {
|
||||
numbers[0] = this.moduloPrime(this.prime - numbers[0]);
|
||||
for (let i = 1; i < numbers.length; ++i) {
|
||||
numbers[i] = this.prime - 1 - numbers[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Return the multiplicative inverse of the given number modulo 'prime'
|
||||
moduloInverse(number) {
|
||||
let inverse = 1;
|
||||
while (this.moduloPrime(inverse * number) !== 1) {
|
||||
inverse += 1;
|
||||
}
|
||||
return inverse;
|
||||
}
|
||||
|
||||
// Return the given number modulo 'prime' in the range 0...'prime' - 1
|
||||
moduloPrime(number) {
|
||||
const div = number % this.prime;
|
||||
return (div >= 0) ? div : div + this.prime;
|
||||
}
|
||||
|
||||
// The given array is padded on the right by zeros up to a maximum length of 'DIGITS_SIZE'
|
||||
padWithZeros(array) {
|
||||
while (array.length < P_adic.DIGITS_SIZE) {
|
||||
array.push(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the given array of base 'prime' integers converted to a decimal integer
|
||||
convertToDecimal(numbers) {
|
||||
let decimal = 0;
|
||||
let multiple = 1;
|
||||
for (const number of numbers) {
|
||||
decimal += number * multiple;
|
||||
multiple *= this.prime;
|
||||
}
|
||||
return decimal;
|
||||
}
|
||||
|
||||
// Return whether the given array consists of all zeros
|
||||
allZeroDigits(numbers) {
|
||||
for (const number of numbers) {
|
||||
if (number !== 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return whether the given array ends with multiple instances of the given number
|
||||
endsWith(numbers, number) {
|
||||
for (let i = numbers.length - 1; i >= numbers.length - P_adic.PRECISION / 2; --i) {
|
||||
if (numbers[i] !== number) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Main function equivalent
|
||||
function main() {
|
||||
console.log("3-adic numbers:");
|
||||
let padic_one = new P_adic(3, -2, 87);
|
||||
console.log("-2 / 87 => " + padic_one.toString());
|
||||
let padic_two = new P_adic(3, 4, 97);
|
||||
console.log("4 / 97 => " + padic_two.toString());
|
||||
|
||||
let sum = padic_one.add(padic_two);
|
||||
console.log("sum => " + sum.toString());
|
||||
console.log("Rational = " + sum.convertToRational().toString());
|
||||
console.log();
|
||||
|
||||
console.log("7-adic numbers:");
|
||||
padic_one = new P_adic(7, 5, 8);
|
||||
console.log("5 / 8 => " + padic_one.toString());
|
||||
padic_two = new P_adic(7, 353, 30809);
|
||||
console.log("353 / 30809 => " + padic_two.toString());
|
||||
|
||||
sum = padic_one.add(padic_two);
|
||||
console.log("sum => " + sum.toString());
|
||||
console.log("Rational = " + sum.convertToRational().toString());
|
||||
console.log();
|
||||
}
|
||||
|
||||
// Run the main function
|
||||
main();
|
||||
391
Task/P-Adic-numbers-basic/Rust/p-adic-numbers-basic.rs
Normal file
391
Task/P-Adic-numbers-basic/Rust/p-adic-numbers-basic.rs
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
use std::cmp;
|
||||
use std::sync::atomic::{AtomicI32, Ordering};
|
||||
use std::cell::UnsafeCell;
|
||||
|
||||
// constants
|
||||
const EMX: i32 = 64; // exponent maximum (if indexing starts at -EMX)
|
||||
const DMX: i32 = 100000; // approximation loop maximum
|
||||
const AMX: i32 = 1048576; // argument maximum
|
||||
const PMAX: i32 = 32749; // prime maximum
|
||||
|
||||
// Using atomics for the global variables
|
||||
static P1: AtomicI32 = AtomicI32::new(0);
|
||||
static P: AtomicI32 = AtomicI32::new(7); // default prime
|
||||
static K: AtomicI32 = AtomicI32::new(11); // precision
|
||||
|
||||
fn abs(a: i32) -> i32 {
|
||||
if a >= 0 {
|
||||
a
|
||||
} else {
|
||||
-a
|
||||
}
|
||||
}
|
||||
|
||||
fn min(a: i32, b: i32) -> i32 {
|
||||
if a < b {
|
||||
a
|
||||
} else {
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
struct Ratio {
|
||||
a: i32,
|
||||
b: i32,
|
||||
}
|
||||
|
||||
struct Padic {
|
||||
v: i32,
|
||||
d: [i32; 2 * EMX as usize], // add EMX to index to be consistent with FB
|
||||
}
|
||||
|
||||
impl Padic {
|
||||
// Create a new Padic with default values
|
||||
fn new() -> Self {
|
||||
Padic {
|
||||
v: 0,
|
||||
d: [0; 2 * EMX as usize],
|
||||
}
|
||||
}
|
||||
|
||||
// (re)initialize receiver from Ratio, set 'sw' to print
|
||||
fn r2pa(&mut self, q: Ratio, sw: i32) -> i32 {
|
||||
let mut a = q.a;
|
||||
let mut b = q.b;
|
||||
if b == 0 {
|
||||
return 1;
|
||||
}
|
||||
if b < 0 {
|
||||
b = -b;
|
||||
a = -a;
|
||||
}
|
||||
if abs(a) > AMX || b > AMX {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let p_val = P.load(Ordering::Relaxed);
|
||||
if p_val < 2 || K.load(Ordering::Relaxed) < 1 {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set P to minimum of P and PMAX
|
||||
let p_val = cmp::min(p_val, PMAX);
|
||||
P.store(p_val, Ordering::Relaxed);
|
||||
|
||||
// Set K to minimum of K and EMX-1
|
||||
let k_val = cmp::min(K.load(Ordering::Relaxed), EMX - 1);
|
||||
K.store(k_val, Ordering::Relaxed);
|
||||
|
||||
if sw != 0 {
|
||||
println!("{}/{} + ", a, b); // numerator, denominator
|
||||
println!("0({}^{})", p_val, k_val); // prime, precision
|
||||
}
|
||||
|
||||
// (re)initialize
|
||||
self.v = 0;
|
||||
P1.store(p_val - 1, Ordering::Relaxed);
|
||||
self.d = [0; 2 * EMX as usize];
|
||||
|
||||
if a == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
let p1_val = P1.load(Ordering::Relaxed);
|
||||
|
||||
// find -exponent of p in b
|
||||
while b % p_val == 0 {
|
||||
b = b / p_val;
|
||||
i -= 1;
|
||||
}
|
||||
|
||||
let mut s = 0;
|
||||
let r = b % p_val;
|
||||
|
||||
// modular inverse for small p
|
||||
let mut b1 = 1;
|
||||
while b1 <= p1_val {
|
||||
s += r;
|
||||
if s > p1_val {
|
||||
s -= p_val;
|
||||
}
|
||||
if s == 1 {
|
||||
break;
|
||||
}
|
||||
b1 += 1;
|
||||
}
|
||||
|
||||
if b1 == p_val {
|
||||
println!("r2pa: impossible inverse mod");
|
||||
return -1;
|
||||
}
|
||||
|
||||
self.v = EMX;
|
||||
|
||||
loop {
|
||||
// find exponent of P in a
|
||||
while a % p_val == 0 {
|
||||
a = a / p_val;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// valuation
|
||||
if self.v == EMX {
|
||||
self.v = i;
|
||||
}
|
||||
|
||||
// upper bound
|
||||
if i >= EMX {
|
||||
break;
|
||||
}
|
||||
|
||||
// check precision
|
||||
if (i - self.v) > k_val {
|
||||
break;
|
||||
}
|
||||
|
||||
// next digit
|
||||
self.d[(i + EMX) as usize] = a * b1 % p_val;
|
||||
if self.d[(i + EMX) as usize] < 0 {
|
||||
self.d[(i + EMX) as usize] += p_val;
|
||||
}
|
||||
|
||||
// remainder - digit * divisor
|
||||
a -= self.d[(i + EMX) as usize] * b;
|
||||
if a == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
// Horner's rule
|
||||
fn dsum(&self) -> i32 {
|
||||
let t = cmp::min(self.v, 0);
|
||||
let mut s = 0;
|
||||
let p_val = P.load(Ordering::Relaxed);
|
||||
let k_val = K.load(Ordering::Relaxed);
|
||||
|
||||
for i in (t..=k_val - 1 + t).rev() {
|
||||
let r = s;
|
||||
s *= p_val;
|
||||
if r != 0 && (s / r - p_val != 0) {
|
||||
// overflow
|
||||
s = -1;
|
||||
break;
|
||||
}
|
||||
s += self.d[(i + EMX) as usize];
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
// add b to receiver
|
||||
fn add(&self, b: &Padic) -> Padic {
|
||||
let mut c = 0;
|
||||
let mut r = Padic::new();
|
||||
r.v = cmp::min(self.v, b.v);
|
||||
let p_val = P.load(Ordering::Relaxed);
|
||||
let p1_val = P1.load(Ordering::Relaxed);
|
||||
let k_val = K.load(Ordering::Relaxed);
|
||||
|
||||
for i in r.v..=k_val + r.v {
|
||||
c += self.d[(i + EMX) as usize] + b.d[(i + EMX) as usize];
|
||||
if c > p1_val {
|
||||
r.d[(i + EMX) as usize] = c - p_val;
|
||||
c = 1;
|
||||
} else {
|
||||
r.d[(i + EMX) as usize] = c;
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
r
|
||||
}
|
||||
|
||||
// complement of receiver
|
||||
fn cmpt(&self) -> Padic {
|
||||
let mut c = 1;
|
||||
let mut r = Padic::new();
|
||||
r.v = self.v;
|
||||
let p_val = P.load(Ordering::Relaxed);
|
||||
let p1_val = P1.load(Ordering::Relaxed);
|
||||
let k_val = K.load(Ordering::Relaxed);
|
||||
|
||||
for i in self.v..=k_val + self.v {
|
||||
c += p1_val - self.d[(i + EMX) as usize];
|
||||
if c > p1_val {
|
||||
r.d[(i + EMX) as usize] = c - p_val;
|
||||
c = 1;
|
||||
} else {
|
||||
r.d[(i + EMX) as usize] = c;
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
r
|
||||
}
|
||||
|
||||
// rational reconstruction
|
||||
fn crat(&self) {
|
||||
let mut fl = false;
|
||||
let mut s = self.clone();
|
||||
let mut j = 0;
|
||||
let mut i = 1;
|
||||
let p_val = P.load(Ordering::Relaxed);
|
||||
let p1_val = P1.load(Ordering::Relaxed);
|
||||
let k_val = K.load(Ordering::Relaxed);
|
||||
|
||||
// denominator count
|
||||
while i <= DMX {
|
||||
// check for integer
|
||||
j = k_val - 1 + self.v;
|
||||
while j >= self.v {
|
||||
if s.d[(j + EMX) as usize] != 0 {
|
||||
break;
|
||||
}
|
||||
j -= 1;
|
||||
}
|
||||
fl = ((j - self.v) * 2) < k_val;
|
||||
if fl {
|
||||
fl = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// check negative integer
|
||||
j = k_val - 1 + self.v;
|
||||
while j >= self.v {
|
||||
if p1_val - s.d[(j + EMX) as usize] != 0 {
|
||||
break;
|
||||
}
|
||||
j -= 1;
|
||||
}
|
||||
fl = ((j - self.v) * 2) < k_val;
|
||||
if fl {
|
||||
break;
|
||||
}
|
||||
|
||||
// repeatedly add self to s
|
||||
s = s.add(self);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if fl {
|
||||
s = s.cmpt();
|
||||
}
|
||||
|
||||
// numerator: weighted digit sum
|
||||
let x = s.dsum();
|
||||
let mut y = i;
|
||||
|
||||
if x < 0 || y > DMX {
|
||||
println!("{} {}", x, y);
|
||||
println!("crat: fail");
|
||||
} else {
|
||||
// negative powers
|
||||
let mut i = self.v;
|
||||
while i <= -1 {
|
||||
y *= p_val;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// negative rational
|
||||
let final_x = if fl { -x } else { x };
|
||||
print!("{}", final_x);
|
||||
if y > 1 {
|
||||
print!("/{}", y);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
// print expansion
|
||||
fn printf(&self, sw: i32) {
|
||||
let t = cmp::min(self.v, 0);
|
||||
let k_val = K.load(Ordering::Relaxed);
|
||||
|
||||
for i in (t..=k_val - 1 + t).rev() {
|
||||
print!("{}", self.d[(i + EMX) as usize]);
|
||||
if i == 0 && self.v < 0 {
|
||||
print!(".");
|
||||
}
|
||||
print!(" ");
|
||||
}
|
||||
println!();
|
||||
// rational approximation
|
||||
if sw != 0 {
|
||||
self.crat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement the Clone trait for Padic
|
||||
impl Clone for Padic {
|
||||
fn clone(&self) -> Self {
|
||||
Padic {
|
||||
v: self.v,
|
||||
d: self.d,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let data = vec![
|
||||
/* rational reconstruction depends on the precision
|
||||
until the dsum-loop overflows */
|
||||
vec![2, 1, 2, 4, 1, 1],
|
||||
vec![4, 1, 2, 4, 3, 1],
|
||||
vec![4, 1, 2, 5, 3, 1],
|
||||
vec![4, 9, 5, 4, 8, 9],
|
||||
vec![26, 25, 5, 4, -109, 125],
|
||||
vec![49, 2, 7, 6, -4851, 2],
|
||||
vec![-9, 5, 3, 8, 27, 7],
|
||||
vec![5, 19, 2, 12, -101, 384],
|
||||
/* two decadic pairs */
|
||||
vec![2, 7, 10, 7, -1, 7],
|
||||
vec![34, 21, 10, 9, -39034, 791],
|
||||
/* familiar digits */
|
||||
vec![11, 4, 2, 43, 679001, 207],
|
||||
vec![-8, 9, 23, 9, 302113, 92],
|
||||
vec![-22, 7, 3, 23, 46071, 379],
|
||||
vec![-22, 7, 32749, 3, 46071, 379],
|
||||
vec![35, 61, 5, 20, 9400, 109],
|
||||
vec![-101, 109, 61, 7, 583376, 6649],
|
||||
vec![-25, 26, 7, 13, 5571, 137],
|
||||
vec![1, 4, 7, 11, 9263, 2837],
|
||||
vec![122, 407, 7, 11, -517, 1477],
|
||||
/* more subtle */
|
||||
vec![5, 8, 7, 11, 353, 30809],
|
||||
];
|
||||
|
||||
let mut sw = 0;
|
||||
let mut a = Padic::new();
|
||||
let mut b = Padic::new();
|
||||
|
||||
for d in data {
|
||||
let q = Ratio { a: d[0], b: d[1] };
|
||||
|
||||
P.store(d[2], Ordering::Relaxed);
|
||||
K.store(d[3], Ordering::Relaxed);
|
||||
|
||||
sw = a.r2pa(q, 1);
|
||||
if sw == 1 {
|
||||
break;
|
||||
}
|
||||
a.printf(0);
|
||||
|
||||
let q_b = Ratio { a: d[4], b: d[5] };
|
||||
sw = sw | b.r2pa(q_b, 1);
|
||||
if sw == 1 {
|
||||
break;
|
||||
}
|
||||
|
||||
if sw == 0 {
|
||||
b.printf(0);
|
||||
let c = a.add(&b);
|
||||
println!("+ =");
|
||||
c.printf(1);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
357
Task/P-Adic-numbers-basic/Zig/p-adic-numbers-basic.zig
Normal file
357
Task/P-Adic-numbers-basic/Zig/p-adic-numbers-basic.zig
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
const std = @import("std");
|
||||
const math = std.math;
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
const print = std.debug.print;
|
||||
|
||||
// Constants
|
||||
const EMX: i32 = 64; // exponent maximum (if indexing starts at -EMX)
|
||||
const DMX: i32 = 100000; // approximation loop maximum
|
||||
const AMX: i32 = 1048576; // argument maximum
|
||||
const PMAX: i32 = 32749; // prime maximum
|
||||
|
||||
// Global variables
|
||||
var P1: i32 = 0;
|
||||
var P: i32 = 7; // default prime
|
||||
var K: i32 = 11; // precision
|
||||
|
||||
// Helper functions
|
||||
fn abs(a: i32) i32 {
|
||||
return if (a >= 0) a else -a;
|
||||
}
|
||||
|
||||
fn min(a: i32, b: i32) i32 {
|
||||
return if (a < b) a else b;
|
||||
}
|
||||
|
||||
const Ratio = struct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
};
|
||||
|
||||
const Padic = struct {
|
||||
v: i32,
|
||||
d: [2 * EMX]i32, // add EMX to index to be consistent
|
||||
|
||||
// Create a new Padic with default values
|
||||
fn new() Padic {
|
||||
return Padic{
|
||||
.v = 0,
|
||||
.d = [_]i32{0} ** (2 * EMX),
|
||||
};
|
||||
}
|
||||
|
||||
// (re)initialize receiver from Ratio, set 'sw' to print
|
||||
fn r2pa(self: *Padic, q: Ratio, sw: i32) i32 {
|
||||
var a = q.a;
|
||||
var b = q.b;
|
||||
if (b == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (b < 0) {
|
||||
b = -b;
|
||||
a = -a;
|
||||
}
|
||||
if (abs(a) > AMX or b > AMX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (P < 2 or K < 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set P to minimum of P and PMAX
|
||||
P = @min(P, PMAX);
|
||||
|
||||
// Set K to minimum of K and EMX-1
|
||||
K = @min(K, EMX - 1);
|
||||
|
||||
if (sw != 0) {
|
||||
print("{d}/{d} + \n", .{a, b}); // numerator, denominator
|
||||
print("0({d}^{d})\n", .{P, K}); // prime, precision
|
||||
}
|
||||
|
||||
// (re)initialize
|
||||
self.v = 0;
|
||||
P1 = P - 1;
|
||||
// std.mem.set(i32, &self.d, 0);
|
||||
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var i: i32 = 0;
|
||||
|
||||
// find -exponent of p in b
|
||||
while ( @rem(b, P) == 0) {
|
||||
b = @divTrunc(b, P);
|
||||
i -= 1;
|
||||
}
|
||||
|
||||
var s: i32 = 0;
|
||||
const r = @rem(b, P);
|
||||
|
||||
// modular inverse for small p
|
||||
var b1: i32 = 1;
|
||||
while (b1 <= P1) {
|
||||
s += r;
|
||||
if (s > P1) {
|
||||
s -= P;
|
||||
}
|
||||
if (s == 1) {
|
||||
break;
|
||||
}
|
||||
b1 += 1;
|
||||
}
|
||||
|
||||
if (b1 == P) {
|
||||
print("r2pa: impossible inverse mod\n", .{});
|
||||
return -1;
|
||||
}
|
||||
|
||||
self.v = EMX;
|
||||
|
||||
while (true) {
|
||||
// find exponent of P in a
|
||||
while ( @rem(a, P)==0) {
|
||||
a = @divTrunc(a, P);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// valuation
|
||||
if (self.v == EMX) {
|
||||
self.v = i;
|
||||
}
|
||||
|
||||
// upper bound
|
||||
if (i >= EMX) {
|
||||
break;
|
||||
}
|
||||
|
||||
// check precision
|
||||
if ((i - self.v) > K) {
|
||||
break;
|
||||
}
|
||||
|
||||
// next digit
|
||||
self.d[@intCast(i + EMX)] = @mod(a * b1, P);
|
||||
if (self.d[@intCast(i + EMX)] < 0) {
|
||||
self.d[@intCast(i + EMX)] += P;
|
||||
}
|
||||
|
||||
// remainder - digit * divisor
|
||||
a -= self.d[@intCast(i + EMX)] * b;
|
||||
if (a == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Horner's rule
|
||||
fn dsum(self: *const Padic) i32 {
|
||||
const t = @min(self.v, 0);
|
||||
var s: i32 = 0;
|
||||
|
||||
var i = K - 1 + t;
|
||||
while (i >= t) : (i -= 1) {
|
||||
const r = s;
|
||||
s *= P;
|
||||
if (r != 0 and (@divTrunc(s, r) - P != 0)) {
|
||||
// overflow
|
||||
s = -1;
|
||||
break;
|
||||
}
|
||||
s += self.d[@intCast(i + EMX)];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// add b to receiver
|
||||
fn add(self: *const Padic, b: *const Padic) Padic {
|
||||
var c: i32 = 0;
|
||||
var r = Padic.new();
|
||||
r.v = @min(self.v, b.v);
|
||||
|
||||
var i: i32 = r.v;
|
||||
while (i <= K + r.v) : (i += 1) {
|
||||
c += self.d[@intCast(i + EMX)] + b.d[@intCast(i + EMX)];
|
||||
if (c > P1) {
|
||||
r.d[@intCast(i + EMX)] = c - P;
|
||||
c = 1;
|
||||
} else {
|
||||
r.d[@intCast(i + EMX)] = c;
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// complement of receiver
|
||||
fn cmpt(self: *const Padic) Padic {
|
||||
var c: i32 = 1;
|
||||
var r = Padic.new();
|
||||
r.v = self.v;
|
||||
|
||||
var i: i32 = self.v;
|
||||
while (i <= K + self.v) : (i += 1) {
|
||||
c += P1 - self.d[@intCast(i + EMX)];
|
||||
if (c > P1) {
|
||||
r.d[@intCast(i + EMX)] = c - P;
|
||||
c = 1;
|
||||
} else {
|
||||
r.d[@intCast(i + EMX)] = c;
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// rational reconstruction
|
||||
fn crat(self: *const Padic) void {
|
||||
var fl = false;
|
||||
var s = self.*;
|
||||
var j: i32 = 0;
|
||||
var i: i32 = 1;
|
||||
|
||||
// denominator count
|
||||
while (i <= DMX) : (i += 1) {
|
||||
// check for integer
|
||||
j = K - 1 + self.v;
|
||||
while (j >= self.v) : (j -= 1) {
|
||||
if (s.d[@intCast(j + EMX)] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
fl = ((j - self.v) * 2) < K;
|
||||
if (fl) {
|
||||
fl = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// check negative integer
|
||||
j = K - 1 + self.v;
|
||||
while (j >= self.v) : (j -= 1) {
|
||||
if (P1 - s.d[@intCast(j + EMX)] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
fl = ((j - self.v) * 2) < K;
|
||||
if (fl) {
|
||||
break;
|
||||
}
|
||||
|
||||
// repeatedly add self to s
|
||||
s = s.add(self);
|
||||
}
|
||||
|
||||
if (fl) {
|
||||
s = s.cmpt();
|
||||
}
|
||||
|
||||
// numerator: weighted digit sum
|
||||
const x = s.dsum();
|
||||
var y = i;
|
||||
|
||||
if (x < 0 or y > DMX) {
|
||||
print("{d} {d}\n", .{x, y});
|
||||
print("crat: fail\n", .{});
|
||||
} else {
|
||||
// negative powers
|
||||
var i_pow = self.v;
|
||||
while (i_pow <= -1) : (i_pow += 1) {
|
||||
y *= P;
|
||||
}
|
||||
|
||||
// negative rational
|
||||
const final_x = if (fl) -x else x;
|
||||
print("{d}", .{final_x});
|
||||
if (y > 1) {
|
||||
print("/{d}", .{y});
|
||||
}
|
||||
print("\n", .{});
|
||||
}
|
||||
}
|
||||
|
||||
// print expansion
|
||||
fn printf(self: *const Padic, sw: i32) void {
|
||||
const t = @min(self.v, 0);
|
||||
|
||||
var i = K - 1 + t;
|
||||
while (i >= t) : (i -= 1) {
|
||||
print("{d}", .{self.d[@intCast(i + EMX)]});
|
||||
if (i == 0 and self.v < 0) {
|
||||
print(".", .{});
|
||||
}
|
||||
print(" ", .{});
|
||||
}
|
||||
print("\n", .{});
|
||||
// rational approximation
|
||||
if (sw != 0) {
|
||||
self.crat();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
const data = [_][6]i32{
|
||||
// rational reconstruction depends on the precision
|
||||
// until the dsum-loop overflows
|
||||
[_]i32{ 2, 1, 2, 4, 1, 1 },
|
||||
[_]i32{ 4, 1, 2, 4, 3, 1 },
|
||||
[_]i32{ 4, 1, 2, 5, 3, 1 },
|
||||
[_]i32{ 4, 9, 5, 4, 8, 9 },
|
||||
[_]i32{ 26, 25, 5, 4, -109, 125 },
|
||||
[_]i32{ 49, 2, 7, 6, -4851, 2 },
|
||||
[_]i32{ -9, 5, 3, 8, 27, 7 },
|
||||
[_]i32{ 5, 19, 2, 12, -101, 384 },
|
||||
// two decadic pairs
|
||||
[_]i32{ 2, 7, 10, 7, -1, 7 },
|
||||
[_]i32{ 34, 21, 10, 9, -39034, 791 },
|
||||
// familiar digits
|
||||
[_]i32{ 11, 4, 2, 43, 679001, 207 },
|
||||
[_]i32{ -8, 9, 23, 9, 302113, 92 },
|
||||
[_]i32{ -22, 7, 3, 23, 46071, 379 },
|
||||
[_]i32{ -22, 7, 32749, 3, 46071, 379 },
|
||||
[_]i32{ 35, 61, 5, 20, 9400, 109 },
|
||||
[_]i32{ -101, 109, 61, 7, 583376, 6649 },
|
||||
[_]i32{ -25, 26, 7, 13, 5571, 137 },
|
||||
[_]i32{ 1, 4, 7, 11, 9263, 2837 },
|
||||
[_]i32{ 122, 407, 7, 11, -517, 1477 },
|
||||
// more subtle
|
||||
[_]i32{ 5, 8, 7, 11, 353, 30809 },
|
||||
};
|
||||
|
||||
var sw: i32 = 0;
|
||||
var a = Padic.new();
|
||||
var b = Padic.new();
|
||||
|
||||
for (data) |d| {
|
||||
const q = Ratio{ .a = d[0], .b = d[1] };
|
||||
|
||||
P = d[2];
|
||||
K = d[3];
|
||||
|
||||
sw = a.r2pa(q, 1);
|
||||
if (sw == 1) {
|
||||
break;
|
||||
}
|
||||
a.printf(0);
|
||||
|
||||
const q_b = Ratio{ .a = d[4], .b = d[5] };
|
||||
sw = sw | b.r2pa(q_b, 1);
|
||||
if (sw == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (sw == 0) {
|
||||
b.printf(0);
|
||||
const c = a.add(&b);
|
||||
print("+ =\n", .{});
|
||||
c.printf(1);
|
||||
}
|
||||
print("\n", .{});
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue