This commit is contained in:
parent
87662b3399
commit
9629f9b2fa
2 changed files with 57 additions and 19 deletions
25
padic.py
25
padic.py
|
@ -6,15 +6,12 @@ class PAdic:
|
||||||
def __init__(self, p):
|
def __init__(self, p):
|
||||||
self.p = p
|
self.p = p
|
||||||
self.val = '' # current known value
|
self.val = '' # current known value
|
||||||
self.prec = 0 # current known precision
|
self.prec = 0 # current known precision, also containing leading zeros
|
||||||
self.order = 0 # order/valuation of number
|
self.order = 0 # order/valuation of number
|
||||||
pass # initialize object as subclass perhaps
|
pass # initialize object as subclass perhaps
|
||||||
|
|
||||||
def get(self, prec):
|
def get(self, prec):
|
||||||
'Return value of number with given precision.'
|
'Return value of number with given precision.'
|
||||||
if self.value == 0:
|
|
||||||
return '0' # * prec
|
|
||||||
|
|
||||||
while self.prec < prec:
|
while self.prec < prec:
|
||||||
# update val based on value
|
# update val based on value
|
||||||
self.val = self._nextdigit() + self.val
|
self.val = self._nextdigit() + self.val
|
||||||
|
@ -71,20 +68,24 @@ class PAdicConst(PAdic):
|
||||||
if value == 0:
|
if value == 0:
|
||||||
self.value = value
|
self.value = value
|
||||||
self.val = '0'
|
self.val = '0'
|
||||||
|
self.order = maxint
|
||||||
return
|
return
|
||||||
|
|
||||||
self.norm = Fraction(1)
|
|
||||||
self.order = 0
|
self.order = 0
|
||||||
while not value.numerator % self.p:
|
while not value.numerator % self.p:
|
||||||
self.norm /= self.p
|
|
||||||
self.order += 1
|
self.order += 1
|
||||||
|
self.prec += 1
|
||||||
value.numerator /= self.p
|
value.numerator /= self.p
|
||||||
while not value.denominator % self.p:
|
while not value.denominator % self.p:
|
||||||
self.norm *= self.p
|
|
||||||
valuation -= 1
|
valuation -= 1
|
||||||
value.denominator /= self.p
|
value.denominator /= self.p
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
|
def get(self, prec):
|
||||||
|
if self.value == 0:
|
||||||
|
return '0' # * prec
|
||||||
|
return PAdic.get(self, prec)
|
||||||
|
|
||||||
def _nextdigit(self):
|
def _nextdigit(self):
|
||||||
'Calculate next digit of p-adic number.'
|
'Calculate next digit of p-adic number.'
|
||||||
rem = ModP(self.p, self.value.numerator) / ModP(self.p, self.value.denominator)
|
rem = ModP(self.p, self.value.numerator) / ModP(self.p, self.value.denominator)
|
||||||
|
@ -99,6 +100,13 @@ class PAdicAdd(PAdic):
|
||||||
self.carry = 0
|
self.carry = 0
|
||||||
self.arg1 = arg1
|
self.arg1 = arg1
|
||||||
self.arg2 = arg2
|
self.arg2 = arg2
|
||||||
|
self.order = min(arg1.order, arg2.order) # might be larger than this
|
||||||
|
# loop until first nonzero digit is found
|
||||||
|
digit = self._nextdigit()
|
||||||
|
while digit == 0:
|
||||||
|
self.order += 1
|
||||||
|
self.prec += 1
|
||||||
|
digit = self._nextdigit()
|
||||||
|
|
||||||
def _nextdigit(self):
|
def _nextdigit(self):
|
||||||
s = self.arg1.getdigit(self.prec) + self.arg2.getdigit(self.prec) + self.carry
|
s = self.arg1.getdigit(self.prec) + self.arg2.getdigit(self.prec) + self.carry
|
||||||
|
@ -110,10 +118,11 @@ class PAdicNeg(PAdic):
|
||||||
def __init__(self, p, arg):
|
def __init__(self, p, arg):
|
||||||
PAdic.__init__(self, p)
|
PAdic.__init__(self, p)
|
||||||
self.arg = arg
|
self.arg = arg
|
||||||
|
self.order = arg.order
|
||||||
|
|
||||||
def _nextdigit(self):
|
def _nextdigit(self):
|
||||||
if self.prec == 0:
|
if self.prec == 0:
|
||||||
return self.p - self.arg.getdigit(0)
|
return self.p - self.arg.getdigit(0) # cannot be p, 0th digit of arg must be nonzero
|
||||||
return self.p - 1 - self.arg.getdigit(0)
|
return self.p - 1 - self.arg.getdigit(0)
|
||||||
|
|
||||||
class PAdicMul(PAdic):
|
class PAdicMul(PAdic):
|
||||||
|
|
51
poly.py
51
poly.py
|
@ -1,18 +1,47 @@
|
||||||
# Finding roots of polynomials in p-adic integers using Hensel's lemma
|
# Polynomial class on Z or Z_p
|
||||||
|
|
||||||
from padic import *
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
class Poly:
|
class Poly:
|
||||||
'Polynomial class.'
|
'Polynomial class.'
|
||||||
def __init__(self, coeffs = None):
|
def __init__(self, coeffs = None):
|
||||||
self.coeffs = defaultdict(int, coeffs or {})
|
self.coeffs = defaultdict(int, not coeffs and {} or isinstance(coeffs, int) and {0:coeffs} or coeffs)
|
||||||
self.deg = 0
|
self.deg = int(self.coeffs and max(self.coeffs.keys()))
|
||||||
# TODO arithmetic
|
|
||||||
|
# arithmetic
|
||||||
|
def __add__(self, other):
|
||||||
|
if not isinstance(other, Poly):
|
||||||
|
other = Poly(other)
|
||||||
|
res = Poly()
|
||||||
|
res.deg = max(self.deg, other.deg)
|
||||||
|
for i in xrange(res.deg+1):
|
||||||
|
res.coeffs[i] = self.coeffs[i] + other.coeffs[i]
|
||||||
|
return res
|
||||||
|
def __radd__(self, other):
|
||||||
|
if not isinstance(other, Poly):
|
||||||
|
other = Poly(other)
|
||||||
|
return other.__add__(self)
|
||||||
|
def __sub__(self, other):
|
||||||
|
if not isinstance(other, Poly):
|
||||||
|
other = Poly(other)
|
||||||
|
return self.__add__(other._neg())
|
||||||
|
def __rsub__(self, other):
|
||||||
|
if not isinstance(other, Poly):
|
||||||
|
other = Poly(other)
|
||||||
|
return other.__add__(self._neg())
|
||||||
|
|
||||||
|
def __mul__(self, other):
|
||||||
|
if not isinstance(other, Poly):
|
||||||
|
other = Poly(other)
|
||||||
|
res = Poly()
|
||||||
|
res.deg = self.deg + other.deg
|
||||||
|
for i in xrange(res.deg+1):
|
||||||
|
for j in xrange(i+1):
|
||||||
|
res.coeffs[i] += self.coeffs[j] * other.coeffs[i - j]
|
||||||
|
return res
|
||||||
|
def __rmul__(self, other):
|
||||||
|
if not isinstance(other, Poly):
|
||||||
|
other = Poly(other)
|
||||||
|
return other.__mul__(self)
|
||||||
|
|
||||||
X = Poly({1:1})
|
X = Poly({1:1})
|
||||||
|
|
||||||
class ConstPoly(Poly):
|
|
||||||
'Constant polynomial.'
|
|
||||||
def __init__(self, coeff):
|
|
||||||
Poly.__init__(self, {0:coeff})
|
|
Loading…
Add table
Reference in a new issue