def __mul__(self, other): """Multiplication""" if type(other) in [int, str, float, Rational]: other = QPoly([cast_to_rational(other)]) L = poly_mult(self.coef, other.coef) return QPoly(L)
def __rsub__(self, other): """Subtraction is NOT commutative""" if type(other) in [int, str, float, Rational]: other = QPoly([cast_to_rational(other)]) L = poly_add(self.coef, [-c for c in other.coef]) return QPoly(L)
def bisection_method(poly, lo, hi, den_lim=1000, iter_lim=1000): """Approximate a root by the bisection method limited by denominator and number of iterations""" assert type(poly) == QPoly lo = cast_to_rational(lo) hi = cast_to_rational(hi) oldmid = hi for i in range(iter_lim): mid = rational_round((hi + lo) / 2, den_lim) if sign(poly(lo)) != sign(poly(mid)): lo, hi = lo, mid elif sign(poly(mid)) != sign(poly(hi)): lo, hi = mid, hi if mid == oldmid: return mid oldmid = mid return mid
def evaluate(self, x, N): """Truncates the power series and evaluates it""" x = cast_to_rational(x) out = 0 for pos, val in enumerate(self.a): if pos > N: break out += val * (x - self.c)**pos return out
def __add__(self, other): if type(other) == RFunc: return RFunc(self.N * other.D + other.N * self.D, self.D * other.D) elif type(other) == QPoly: return self + RFunc(other) elif type(other) in [int, str, float, Rational]: other = RFunc([cast_to_rational(other)]) return self + other else: return NotImplemented
def __truediv__(self, other): if type(other) == RFunc: return self * other.inv() elif type(other) == QPoly: return self / RFunc(other) elif type(other) in [int, str, float, Rational]: other = RFunc([cast_to_rational(other)]) return self / other else: return NotImplemented
def __add__(self, other): """Addition""" # If we can turn the other into a rational do that if type(other) in [int, str, float, Rational]: other = QPoly([cast_to_rational(other)]) L = poly_add(self.coef, other.coef) return QPoly(L) elif type(other) == QPoly: L = poly_add(self.coef, other.coef) return QPoly(L) else: return NotImplemented
def newtons_method(poly, start, den_lim=1000, iter_lim=1000): """Approximate a root by Newton's method limited by denominator and number of iterations""" assert type(poly) == QPoly p = poly dp = poly.derivative() r = cast_to_rational(start) for i in range(iter_lim): rnew = rational_round(r - p(r) / dp(r), den_lim) if rnew == r: return r r = rnew return r
def __init__(self, coef): if type(coef) not in [list, tuple]: raise TypeError(f"coef must be list or tuple not {type(coef)}") self.coef = [cast_to_rational(c) for c in coef] self.normalize()
def __setitem__(self, n, val): """Allow valid coefficients to be set""" self.coef[n] = cast_to_rational(val)
def __init__(self, a, c=0): if not isinstance(a, types.GeneratorType): raise Exception(f"{a} is not a generator") self.a = a self.c = cast_to_rational(c)
def __init__(self, re, im): self.re = cast_to_rational(re) self.im = cast_to_rational(im)