def asin(x, err=defaultError): """ asin(x [,err]) returns arc sine of x. """ if x > 1 or x < -1: raise ValueError("%s is not in the range [-1, 1]." % str(x)) if x < 0: return -asin(-x) if err <= defaultError: u = sqrt(rational.Rational(1, 2)) if x > u: return pi(err) / 2 - asin(sqrt(1 - x**2)) if x == 0: return rational.Integer(0) y = rational.Rational(x) y2 = y**2 i = 2 retval = y term = rational.Rational(y) oldvalue = 0 while not err.nearlyEqual(retval, oldvalue): oldvalue = +retval term *= y2 * (i - 1)**2 / (i * (i + 1)) i += 2 retval += term else: retval = rational.Rational(math.asin(x)) return retval
def exp(x, err=defaultError): """ Return exponential of x. """ if err <= defaultError: reduced = rational.Rational(x) if reduced < 0: reverse = -1 reduced = -reduced else: reverse = 1 i = 0 while reduced >= 2: reduced /= 2 i += 1 if reduced == 0: retval = rational.Integer(1) else: series = ExponentialPowerSeries( itertools.cycle((rational.Integer(1), ))) retval = series(reduced, err) if i > 0: retval **= 2**i if reverse < 0: retval = 1 / retval else: retval = rational.Rational(math.exp(x)) return retval
def atan(x, err=defaultError): """ atan(x [,err]) returns arc tangent of x. """ if not isinstance(err, defaultError.__class__) or err <= defaultError: # atan(x) = -atan(-x) if x < 0: return -atan(-x, err) # atan(x) = pi/2 - atan(1/x) elif x > 1: return pi(err) / 2 - atan(1 / x, err) elif x == 1: return pi(err) / 4 elif x == 0: return rational.Integer(0) y = rational.Rational(x) y2 = y**2 retval = y oldvalue = 0 term = rational.Rational(x) i = 1 while not err.nearlyEqual(retval, oldvalue): oldvalue = +retval i += 2 term *= -y2 * (i - 2) / i retval += term else: retval = rational.Rational(math.atan(x)) return retval
def frexp(x): """ Return a tuple (m, e) where x = m * 2 ** e, 1/2 <= abs(m) < 1 and e is an integer. This function is provided as the counter-part of math.frexp, but it might not be useful. """ if x == 0: return (rational.Rational(0), 0) m = rational.Rational(x) e = 0 if x > 0: while m >= 1: m /= 2 e += 1 while m < rational.Rational(1, 2): m *= 2 e -= 1 else: while m <= -1: m /= 2 e += 1 while m > rational.Rational(-1, 2): m *= 2 e -= 1 return (m, e)
def testSqrt(self): # sqrt(2) = [1; 2, 2, ...] sqrt2 = cf.RegularContinuedFraction( itertools.chain([1], itertools.cycle([2]))) self.assertEqual(rational.Rational(17, 12), sqrt2.convergent(3)) self.assertEqual(rational.Rational(41, 29), sqrt2.convergent(4)) # convergent(smaller than previous call) == convergent(previous call) self.assertEqual(rational.Rational(41, 29), sqrt2.convergent(3))
def testWithFloat(self): a = imaginary.Complex(8, 1) b = rational.Rational(1, 8) a_add_b = imaginary.Complex(8 + rational.Rational(1, 8), 1) a_mul_b = imaginary.Complex(1, rational.Rational(1, 8)) assert a_add_b == a + b assert a_add_b == b + a assert a_mul_b == a * b assert a_mul_b == b * a
def tranc(x): """ tranc(x) returns the integer; if x is an integer then x itself, otherwise the nearest integer to x. If x has the fraction part 1/2, then bigger one will be chosen. """ rx = rational.Rational(x) if rx.denominator == 1: return rational.Integer(rx.numerator) return floor(x + rational.Rational(1, 2))
def testInit(self): self.assertEqual(16, self.a.c4) self.assertEqual(-152, self.a.c6) self.assertEqual(-11, self.a.disc) self.assertEqual(rational.Rational(self.a.c4**3, self.a.disc), self.a.j) self.assertEqual(-48, self.b.c4) self.assertEqual(0, self.b.c6) self.assertEqual(-64, self.b.disc) self.assertEqual(rational.Rational(self.b.c4**3, self.b.disc), self.b.j)
def terms(self, x): """ Generator of terms of series with assigned x value. """ if x == 0: yield rational.Rational(next(self.iterator)) else: i = 0 r = rational.Rational(1, 1) for an in self.iterator: yield an * r i += 1 r *= rational.Rational(x, i)
def __call__(self, x, maxerror): if self.dirtyflag: raise Exception( 'ExponentialPowerSeries cannot be called more than once') self.dirtyflag = True value, oldvalue = rational.Rational(0), rational.Rational(0) maxDenom = minNumer = 0 if isinstance(maxerror, RelativeError): for t in self.terms(x): if not t: continue if not maxDenom: value += t maxDenom = (maxerror.relativeerrorrange.denominator * value.denominator)**2 elif value.denominator < maxDenom: value += t if maxerror.nearlyEqual(value, oldvalue): break else: if not minNumer: minNumer = maxerror.relativeerrorrange.numerator * abs( value.numerator ) // maxerror.relativeerrorrange.denominator approx = t.numerator * value.denominator // t.denominator value.numerator += approx if abs(approx) < minNumer: break oldvalue = +value else: for t in self.terms(x): if not t: continue if not maxDenom: value += t maxDenom = (maxerror.absoluteerrorrange.denominator * value.denominator)**2 elif value.denominator < maxDenom: value += t else: if not minNumer: minNumer = maxerror.absoluteerrorrange.numerator * value.numerator // maxerror.absoluteerrorrange.denominator approx = t.numerator * value.denominator // t.denominator value.numerator += approx if abs(approx) < minNumer: break oldvalue = +value return value
def cosh(x, err=defaultError): """ cosh(x [,err]) returns the hyperbolic cosine of x. """ if err <= defaultError: series = ExponentialPowerSeries( itertools.cycle(( rational.Integer(1), 0, ))) rx = rational.Rational(x) if rx == 0: return rational.Integer(1) return series(rx, err) else: return rational.Rational(math.cosh(x))
def pow(x, y, err=defaultError): """ x ** y """ if isinstance(y, int): return rational.Rational(x)**y return exp(y * log(x, err=err), err)
def exp(x, err=defaultError): """ exp(x [,err]) is the exponential function. """ try: rx = rational.Rational(x) if isinstance(err, RelativeError): _err = real.RelativeError(0, err.relativeerrorrange) elif isinstance(err, AbsoluteError): _err = real.AbsoluteError(0, err.absoluteerrorrange) return real.exp(rx, _err) except TypeError: pass if (defaultError >= err) or isinstance(err, AbsoluteError): # divide real part and imaginary part if isinstance(err, RelativeError): _err = real.RelativeError(0, err.relativeerrorrange, 2) elif isinstance(err, AbsoluteError): _err = real.AbsoluteError(0, err.absoluteerrorrange, 2) radius = real.exp(x.real, _err) if isinstance(err, RelativeError): _err = RelativeError(err.relativeerrorrange / 2) elif isinstance(err, AbsoluteError): _err = AbsoluteError(err.absoluteerrorrange / 2) arg = expi(x.imag, _err) return radius * arg else: return Complex(cmath.exp(complex(x.real,x.imag)))
def testReduce(self): F = (multiutil.polynomial( { (2, 0): rational.Integer(1), (1, 2): rational.Integer(2) }, rational.theRationalField, 2), multiutil.polynomial( { (1, 1): rational.Integer(1), (0, 3): rational.Integer(2), (0, 0): rational.Integer(-1) }, rational.theRationalField, 2)) rgb_expected = [ multiutil.polynomial({(1, 0): rational.Integer(1)}, rational.theRationalField, 2), multiutil.polynomial( { (0, 3): rational.Integer(1), (0, 0): rational.Rational(-1, 2) }, rational.theRationalField, 2) ] G_from_F = groebner.normal_strategy(F, self.lex) rgb = groebner.reduce_groebner(G_from_F, self.lex) self.assertEqual(2, len(rgb)) self.assertEqual(rgb_expected, rgb)
def _algnumber_to_vector(omega, field): """ omega -> vector (w.r.t. theta) """ n = field.degree vect = [rational.Rational(omega.coeff[j], omega.denom) for j in range(n)] return vector.Vector(vect)
def sinh(x, err=defaultError): """ sinh(x [,err]) returns the hyperbolic sine of x. """ if not isinstance(err, defaultError.__class__) or err <= defaultError: series = ExponentialPowerSeries( itertools.cycle(( 0, rational.Integer(1), ))) rx = rational.Rational(x) if rx == 0: return rational.Rational(0) return series(rx, err) else: return rational.Rational(math.sinh(x))
def qpoly(coeffs): """ Return a rational coefficient polynomial constructed from given coeffs. The coeffs is a list of coefficients in ascending order. """ terms = [(i, rational.Rational(c)) for (i, c) in enumerate(coeffs)] return uniutil.polynomial(terms, rational.theRationalField)
def acos(x, err=defaultError): """ acos(x [,err]) returns arc cosine of x. """ if x > 1 or x < -1: raise ValueError("%s is not in the range [-1, 1]." % str(x)) if x == 0: return pi(err) / 2 if err <= defaultError: rx = rational.Rational(x) y = sqrt(1 - rx**2) if rx > 0: return asin(y, err) else: return pi(err) + asin(-y, err) else: return rational.Rational(math.acos(x))
def _cosTaylor(x, err=defaultError): """ _cosTaylor(x [,err]) returns the cosine of x by Taylor series. It is recomended to use only for 0 <= x <= pi / 4. """ cosSeries = ExponentialPowerSeries( itertools.cycle((rational.Integer(1), 0, rational.Integer(-1), 0))) rx = rational.Rational(x) return cosSeries(rx, err)
def _sinTaylor(x, err=defaultError): """ _sinTaylor(x [,err]) returns the sine of x by Taylor expansion. It is recommended to use only for 0 <= x <= pi / 4. """ rx = rational.Rational(x) sinSeries = ExponentialPowerSeries( itertools.cycle((0, rational.Integer(1), 0, rational.Integer(-1)))) return sinSeries(rx, err)
def floor(x): """ floor(x) returns the integer; if x is an integer then x itself, otherwise the biggest integer less than x. """ rx = rational.Rational(x) if rx.denominator == 1: return rational.Integer(rx.numerator) return rx.numerator // rx.denominator
def ceil(x): """ ceil(x) returns the integer; if x is an integer then x itself, otherwise the smallest integer greater than x. """ rx = rational.Rational(x) if rx.denominator == 1: return rational.Integer(rx.numerator) return rx.numerator // rx.denominator + 1
def get_rationals(self): """ Return a list of rational list, which is basis divided by denominator. """ if self.rational_basis is None: self.rational_basis = [] for base in self.basis: self.rational_basis.append([rational.Rational(c, self.denominator) for c in base]) return self.rational_basis
def _convertToRational(x): """ Convert to rational from: * int, * long, or * float. A complex object cannot be converted and raise TypeError. """ if isinstance(x, float): retval = +rational.Rational(long(math.frexp(x)[0] * 2**53), 2 **(53 - math.frexp(x)[1])) elif isinstance(x, (int, long)): retval = rational.Integer(x) elif isinstance(x, complex): raise TypeError, "The real module cannot handle %s. Please use imaginary module." % x else: # fall back retval = rational.Rational(x) return retval
def sqrt(x, err=defaultError): """ sqrt(x [,err]) returns the positive square root of real number x. """ rx = rational.Rational(x) if rx.numerator < 0: raise ValueError("negative number is passed to sqrt") if rx.numerator == 0: return rational.Integer(0) if err <= defaultError: n = rx.denominator * rx.numerator rt = rational.Rational(arith1.floorsqrt(n), rx.denominator) newrt = (rt + rx / rt) / 2 while not err.nearlyEqual(rt, newrt): rt = newrt newrt = (rt + rx / rt) / 2 else: newrt = rational.Rational(math.sqrt(x.toFloat())) return newrt
def piGaussLegendre(err=defaultError): """ piGaussLegendre computes pi by Gauss-Legendre algorithm. """ if isinstance(err, RelativeError): _err = err.absoluteerror(3.1415926535897932) else: _err = err werr = AbsoluteError(0, _err.absoluteerrorrange**2) maxdenom = int(1 / werr.absoluteerrorrange) * 2 a = rational.Integer(1) b = (1 / sqrt(rational.Rational(2), werr)).trim(maxdenom) t = rational.Rational(1, 4) x = 1 while not _err.nearlyEqual(a, b): a, b, c = (a + b) / 2, sqrt(a * b, werr).trim(maxdenom), (b - a)**2 / 4 t -= x * c x *= 2 return (a + b)**2 / (t * 4)
def sin(x, err=defaultError): """ sin(x [,err]) returns the sine of x. """ if not isinstance(err, defaultError.__class__) or err <= defaultError: rx = rational.Rational(x) sign = rational.Rational(1) # sin(-x) = -sin(x) if rx < 0: sign = -sign rx = -rx # sin(x + 2 * pi) = sin(x) if rx >= 2 * pi: rx -= floor(rx / (pi * 2)) * (pi * 2) # sin(x + pi) = -sin(x) if rx >= pi: rx -= pi sign = -sign # sin(x) = sin(pi - x) if rx > pi / 2: rx = pi - rx # sin(0) = 0 is a special case which must not be computed with series. if rx == 0: return rational.Rational(0) # sin(x) = cos(pi/2 - x) (pi/2 >= x > 4/pi) if rx > pi / 4: if rx == pi / 3: retval = sqrt(3) / 2 else: retval = _cosTaylor(pi / 2 - rx, err) elif rx == pi / 4: retval = 1 / sqrt(2) elif rx == pi / 6: retval = rational.Rational(1, 2) else: retval = _sinTaylor(rx, err) if retval > 1: retval = rational.Integer(1) retval *= sign else: retval = rational.Rational(math.sin(x)) return retval
def valuation(self): """ Return the canonical p-adic valuation. If n = ak*p**k + ..., the value is p**(-k). If n is zero, the value is also zero. """ if not self: return 0 for i, e in enumerate(self.expansion): if e: return rational.Rational(1, p**i)
def fmod(x, y): """ returns x - n * y, where n is the quotient of x / y, rounded towards zero to an integer. """ fquot = rational.Rational(x) / y if fquot < 0: n = -floor(-fquot) else: n = floor(fquot) return x - n * y
def get_polynomials(self): """ Return a list of rational polynomials, which is made from basis divided by denominator. """ if self.poly_basis is None: self.poly_basis = [] for base in self.basis: self.poly_basis.append(_rational_polynomial([rational.Rational(c, self.denominator) for c in base])) return self.poly_basis