Skip to content

Commit

Permalink
Allowing instantiation of PAdic from floats, if the corresponding rat…
Browse files Browse the repository at this point in the history
…ional can be identified with confidence. Fixed issue where multivariate newton used the same sequence of pseudo random numbers for all variables, causing issues if something special (e.g. a pole) appears when they are all equal.
  • Loading branch information
GDeLaurentis committed Oct 18, 2024
1 parent be854b3 commit 2163465
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 5 deletions.
2 changes: 1 addition & 1 deletion pyadic/interpolation.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def multivariate_Newton_polynomial_interpolation(f, prime, seed=0, depth=0, verb
tpoly = tpoly.subs({'t': 't1', })
return tpoly

t_sequence_generator = FFSequenceGenerator(prime, seed)
t_sequence_generator = FFSequenceGenerator(prime, seed=seed + depth) # do not use same sequence for all variables!!!
avals, tvals, subtracted = [], [], [f]

dynamic_fsubtracted_string = f"""def fsubtracted(i, {''.join([f't{i}, ' for i in range(1, num_args + 1)])}):
Expand Down
17 changes: 13 additions & 4 deletions pyadic/padic.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import fractions
import functools
import math
import numbers
import numpy
import random
import re

from fractions import Fraction as Q

from .finite_field import ModP, finite_field_sqrt, isinteger
from .field_extension import FieldExtension

Expand Down Expand Up @@ -55,7 +56,7 @@ def wrapper_padicfy(self, other):
if self.p != other.p:
raise ValueError(f"Can't cast a {other.p}-adic to a {self.p}-adic.")
return func(self, other)
elif isinteger(other) or isinstance(other, ModP) or isinstance(other, fractions.Fraction) or (hasattr(other, "imag") and not isinstance(other, numpy.ndarray)):
elif isinteger(other) or isinstance(other, ModP) or isinstance(other, Q) or (hasattr(other, "imag") and not isinstance(other, numpy.ndarray)):
return func(self, PAdic(other, self.p, max((self.n + self.k, self.k))))
else:
return NotImplemented
Expand Down Expand Up @@ -116,11 +117,19 @@ def __init__(self, num, p=None, k=None, n=0, from_addition=False):
self.k = self.k + factors_of_p
if all_precision_loss_warning and self.k == 0:
print("Lost all precision @", self)
elif isinstance(num, fractions.Fraction):
elif isinstance(num, Q):
res = PAdic(num.numerator, p, k, n, from_addition) / PAdic(num.denominator, p, k, n, from_addition)
self.num, self.p, self.k, self.n = res.num, res.p, res.k, res.n
elif isinstance(num, PAdic):
self.num, self.p, self.k, self.n = num.num, num.p, num.k, num.n
elif isinstance(num, float):
if not (Q(num).limit_denominator(10 ** 3) == Q(num).limit_denominator(10 ** 5) == Q(num).limit_denominator(10 ** 8)):
raise ValueError(f"PAdic instantiation from float failed. It's unclear to which rational {num} corresponds to.")
res = PAdic(Q(num).limit_denominator(10 ** 3), p, k, n, from_addition)
self.p = res.p
self.k = res.k
self.n = res.n
self.num = res.num
elif hasattr(num, "imag"):
res = PAdic(num.real, p, k, n, from_addition)
if num.imag != 0:
Expand All @@ -136,7 +145,7 @@ def __init__(self, num, p=None, k=None, n=0, from_addition=False):
elif p is None and k is None and isinstance(num, str):
self.num, self.p, self.k, self.n = self.__rstr__(num)
elif isinstance(num, str):
num = fractions.Fraction(num)
num = Q(num)
res = PAdic(num.numerator, p, k, n, from_addition) / PAdic(num.denominator, p, k, n, from_addition)
self.num, self.p, self.k, self.n = res.num, res.p, res.k, res.n
else:
Expand Down

0 comments on commit 2163465

Please sign in to comment.