def _divider(p1, p2, op="truediv"): p1 = Polynomial.polify(p1).simplify() p2 = Polynomial.polify(p2).simplify() if p1.isZero(): return 0 if p1.degree < p2.degree: if op == "truediv": return Fraction(p1, p2) if op == "floordiv": return 0 if op == "modulo": return p1 divisorTerms = [] p1Term1 = p1.terms[0] p1Term1_coeff = p1Term1 if utils.isnumeric(p1Term1) else p1Term1.c p2Term2 = p2.terms[0] p2Term1_coeff = p2Term2 if utils.isnumeric(p2Term2) else p2Term2.c divisorVal = PowerTerm(p1Term1_coeff / p2Term1_coeff, x, p1.degree - p2.degree) divisorTerms.append(divisorVal) newP1 = Polynomial.polify(p1 - (p2 * divisorVal)).simplify() divisorTerms.append(newP1._divider(p2, op)) if op == "modulo": return divisorTerms.pop() return sum(divisorTerms)
def _divider(p1, p2, op = "truediv"): p1 = Polynomial.polify(p1).simplify() p2 = Polynomial.polify(p2).simplify() if p1.isZero(): return 0 if p1.degree < p2.degree: if op == "truediv": return Fraction(p1 , p2) if op == "floordiv": return 0 if op == "modulo": return p1 divisorTerms = [] p1Term1 = p1.terms[0] p1Term1_coeff = p1Term1 if utils.isnumeric(p1Term1) else p1Term1.c p2Term2 = p2.terms[0] p2Term1_coeff = p2Term2 if utils.isnumeric(p2Term2) else p2Term2.c divisorVal = PowerTerm(p1Term1_coeff / p2Term1_coeff, x, p1.degree - p2.degree) divisorTerms.append(divisorVal) newP1 = Polynomial.polify(p1 - (p2 * divisorVal)).simplify() divisorTerms.append(newP1._divider(p2, op)) if op == "modulo": return divisorTerms.pop() return sum(divisorTerms)
def __mul__(e1, e2): assert map(Expression.isExpression, (e1, e2)), "Arguements must be of Class Term" multiplied = 0 for term1 in [e1] if utils.isnumeric(e1) else e1.terms: for term2 in [e2] if utils.isnumeric(e2) else e2.terms: multiplied += (term1 * term2) return multiplied
def __mul__(e1, e2): assert map(Expression.isExpression, (e1, e2) ), "Arguements must be of Class Term" multiplied = 0 for term1 in [e1] if utils.isnumeric(e1) else e1.terms: for term2 in [e2] if utils.isnumeric(e2) else e2.terms: multiplied += (term1 * term2) return multiplied
def __init__(self, terms): assert isinstance(terms, list), "Terms must be a list " for term in terms: assert PowerTerm.isPwrTerm(term) or utils.isnumeric(term), "Every Term must be a PowerTerm" + " " + str(term) assert utils.isnumeric(term) or utils.isnumeric(term.exp), "Every Term must be a PowerTerm" super(Polynomial, self).__init__(terms) self.set_terms(terms) self.maxDegree = None
def __init__(self, terms): assert isinstance(terms, list), "Terms must be a list " for term in terms: assert PowerTerm.isPwrTerm(term) or utils.isnumeric( term), "Every Term must be a PowerTerm" + " " + str(term) assert utils.isnumeric(term) or utils.isnumeric( term.exp), "Every Term must be a PowerTerm" super(Polynomial, self).__init__(terms) self.set_terms(terms) self.maxDegree = None
def __add__(x1, x2): assert map(Expression.isExpression, (x1, x2)), "Arguements must be an Expression" if x1.__class__ == x2.__class__: return PowerTerm(2, x1, 1) if utils.isnumeric(x2): return Expression(x1.terms + [x2]) return Expression(x1.terms + x2.terms)
def __init__(self, coefficient=1, main=X(), exp=1): super(PowerTerm, self).__init__() assert utils.isnumeric(coefficient), "Coefficient must be a number" assert Expression.isExpression(main) assert Expression.isExpression(exp) self.c = coefficient self.main = main self.exp = exp
def __init__(self, coefficient=1, main = X(), exp=1): super(PowerTerm, self).__init__() assert utils.isnumeric(coefficient), "Coefficient must be a number" assert Expression.isExpression(main) assert Expression.isExpression(exp) self.c = coefficient self.main = main self.exp = exp
def __add__(x1, x2): assert map(Expression.isExpression, (x1, x2) ), "Arguements must be an Expression" if x1.__class__ == x2.__class__: return PowerTerm(2, x1, 1) if utils.isnumeric(x2): return Expression(x1.terms + [x2]) return Expression(x1.terms + x2.terms)
def simplify(self): for term in self.terms: lst = [] if utils.isnumeric(term): lst.append(term) else: lst.append(term.simplify()) self.set_terms(list(filter(lambda x: x, self.terms))) ## NEED TO FIX return self
def evaluate(self, *args): evaluated = [] for term in self.termsList: if utils.isnumeric(term): evaluated.append(term) else: evaluated.append(term(*args)) return sum(evaluated)
def simplify(self): newTerms = [] for term in self.terms: if utils.isnumeric(term): if term != 0: newTerms.append(term) elif term.c != 0: newTerms.append(term) self.set_terms(newTerms) return self._combine_terms()._sort()
def __mul__(x1, x2): assert map(Expression.isExpression, (x1, x2) ), "Arguements must be an Expression" if x2.__class__ == Expression: return x2.__mul__(x1) if x1.__class__ == x2.__class__: return PowerTerm(1, x1, 2) if x1.var == x2.var else MultTerm((x1, x2)) if utils.isnumeric(x2): return PowerTerm(x2, x1, 1) return x2.__mul__(x1)
def __mul__(x1, x2): assert map(Expression.isExpression, (x1, x2)), "Arguements must be an Expression" if x2.__class__ == Expression: return x2.__mul__(x1) if x1.__class__ == x2.__class__: return PowerTerm(1, x1, 2) if x1.var == x2.var else MultTerm( (x1, x2)) if utils.isnumeric(x2): return PowerTerm(x2, x1, 1) return x2.__mul__(x1)
def reduceCoefficients(self): allTerms = self.num.terms + self.den.terms coefficients = list( term if utils.isnumeric(term) else term.coefficient for term in allTerms) def gcd_help(x, y): x, y = map(abs, (x, y)) if y > x: return gcd_help(y, x) if y == 0: return x return gcd_help(y, x % y) gcd = reduce(gcd_help, coefficients) for term in allTerms: if utils.isnumeric(term): term /= gcd else: term.set_coefficient(term.coefficient / gcd) return self
def __add__(p1, p2): assert map(Expression.isExpression, (p1, p2) ), "Arguements must be of type ExponentialTerm" if p2 == 0: return p1 if p1.exp == 0 and utils.isnumeric(p2): return p2 + p1.c if PowerTerm.isPwrTerm(p2) and p1.exp == p2.exp and p1.main == p2.main: # ERROR HERE WITH VAR return PowerTerm(p1.c + p2.c, p1.main, p1.exp) else: return Expression([p1, p2])
def reduceCoefficients(self): allTerms = self.num.terms + self.den.terms coefficients = list(term if utils.isnumeric(term) else term.coefficient for term in allTerms) def gcd_help(x, y): x, y = map(abs, (x, y)) if y > x: return gcd_help(y, x) if y == 0: return x return gcd_help(y, x % y) gcd = reduce(gcd_help, coefficients) for term in allTerms: if utils.isnumeric(term): term /= gcd else: term.set_coefficient(term.coefficient / gcd) return self
def __add__(p1, p2): assert map(Expression.isExpression, (p1, p2)), "Arguements must be of type ExponentialTerm" if p2 == 0: return p1 if p1.exp == 0 and utils.isnumeric(p2): return p2 + p1.c if PowerTerm.isPwrTerm( p2 ) and p1.exp == p2.exp and p1.main == p2.main: # ERROR HERE WITH VAR return PowerTerm(p1.c + p2.c, p1.main, p1.exp) else: return Expression([p1, p2])
def __mul__(p1, p2): assert map(Expression.isExpression, (p1, p2)), "Arguements must be of type ExponentialTerm" if p2.__class__ == Expression: return p2.__mul__(p1) if p1.__class__ == p2.__class__ and p1.main == p2.main: return PowerTerm(p1.c * p2.c, p1.main, p1.exp + p2.exp) if p2 == p1.main: copy = p1.copy() return copy.set_exp(copy.exp + 1) if utils.isnumeric(p2): return PowerTerm(p1.c * p2, p1.main, p1.exp) if p2.__class__ == Fraction: return p2.__mul__(p1) return MultTerm([p1, p2])
def __mul__(p1, p2): assert map(Expression.isExpression, (p1, p2) ), "Arguements must be of type ExponentialTerm" if p2.__class__ == Expression: return p2.__mul__(p1) if p1.__class__ == p2.__class__ and p1.main == p2.main: return PowerTerm(p1.c * p2.c, p1.main, p1.exp + p2.exp) if p2 == p1.main: copy = p1.copy() return copy.set_exp(copy.exp + 1) if utils.isnumeric(p2): return PowerTerm(p1.c * p2, p1.main, p1.exp) if p2.__class__ == Fraction: return p2.__mul__(p1) return MultTerm([p1, p2])
def __init__(self, terms): super(MultTerm, self).__init__() self.termsMultiplied = list(terms) self.c = 1 for term in self.termsMultiplied: if MultTerm.isMultTerm(term): self.termsMultiplied.extend(term.termsMultiplied) self.c *= term.c self.termsMultiplied.remove(term) for term in self.termsMultiplied: if utils.isnumeric(term): self.c *= term self.termsMultiplied.remove(term) else: self.c *= term.c term.set_coefficient(1)
def __str__(self): output = "" for term in self.terms: c = exp = 0 if utils.isnumeric(term): c = term else: c, exp = term.c, term.exp if c == 0: continue elif exp == 0: output += str(c) + " + " elif c == 1: output += "x^" + str(exp) + " + " else: output += str(c) + "x^" + str(exp) + " + " output = output[:len(output) - 3] if output == "": return "0" return output
def __str__(self): output = "" for term in self.terms: c = exp = 0 if utils.isnumeric(term): c = term else: c, exp = term.c, term.exp if c == 0: continue elif exp == 0: output += str(c) + " + " elif c == 1: output += "x^" + str(exp) + " + " else: output += str(c) + "x^" + str(exp) + " + " output = output[: len(output) - 3] if output == "": return "0" return output
def polify(p): if Polynomial.isPolynomial(p): return p return Polynomial([p]) if utils.isnumeric(p) else Polynomial(p.terms)
def degree(self): degree_fn = lambda x: 0 if utils.isnumeric(x) else x.exp return max(list(map(degree_fn, self.terms)))
def evaluate(self, *args): i, b = self.insideTerm, self.base insideVal = i if utils.isnumeric(i) else i(*args) baseVal = b if utils.isnumeric(b) else b(*args) return self.c * math.log(insideVal, baseVal)
def __call__(self, *args): assert all(map(lambda x: utils.isnumeric(x[1]), args)) return self.evaluate(*args)
def _combine_terms(self): degree_fn = lambda x: 0 if utils.isnumeric(x) else x.exp sep_degrees = utils.list_to_listOfTypes(self.terms, degree_fn) self.set_terms(list(map(sum, sep_degrees))) return self
def _sort(self): degree_fn = lambda x: 0 if utils.isnumeric(x) else x.exp self.set_terms(sorted(self.terms, key = degree_fn, reverse = True)) return self
def evaluate(self, *args): m, e = self.main, self.exp mainVal = m if utils.isnumeric(m) else m(*args) expVal = e if utils.isnumeric(e) else e(*args) return self.c * pow(mainVal, expVal)
def evaluate(self, *args): expVal = self.exp if utils.isnumeric(self.exp) else self.exp(*args) return self.c * math.exp(expVal)
def _sort(self): degree_fn = lambda x: 0 if utils.isnumeric(x) else x.exp self.set_terms(sorted(self.terms, key=degree_fn, reverse=True)) return self
def __div__(e1, e2): """ p1 divided by p2 -> p1/p2 """ # Error Handling done in Mul if utils.isnumeric(e2): return e1 * (1.0/e2) return e1 * e2.reciprocal()
def isExpression(e): return isinstance(e, Expression) or utils.isnumeric(e)
def __div__(e1, e2): """ p1 divided by p2 -> p1/p2 """ # Error Handling done in Mul if utils.isnumeric(e2): return e1 * (1.0 / e2) return e1 * e2.reciprocal()
def encode_single(typ, arg): base, sub, _ = typ # Unsigned integers: uint<sz> if base == 'uint': sub = int(sub) i = decint(arg, False) if not 0 <= i < 2 ** sub: raise ValueOutOfBounds(repr(arg)) return zpad(encode_int(i), 32) # bool: int<sz> elif base == 'bool': assert isinstance(arg, bool) return zpad(encode_int(int(arg)), 32) # Signed integers: int<sz> elif base == 'int': sub = int(sub) i = decint(arg, True) if not -2 ** (sub - 1) <= i < 2 ** (sub - 1): raise ValueOutOfBounds(repr(arg)) return zpad(encode_int(i % 2 ** sub), 32) # Unsigned reals: ureal<high>x<low> elif base == 'ureal': high, low = [int(x) for x in sub.split('x')] if not 0 <= arg < 2 ** high: raise ValueOutOfBounds(repr(arg)) return zpad(encode_int(int(arg * 2 ** low)), 32) # Signed reals: real<high>x<low> elif base == 'real': high, low = [int(x) for x in sub.split('x')] if not -2 ** (high - 1) <= arg < 2 ** (high - 1): raise ValueOutOfBounds(repr(arg)) i = int(arg * 2 ** low) return zpad(encode_int(i % 2 ** (high + low)), 32) # Strings elif base == 'string' or base == 'bytes': if not is_string(arg): raise EncodingError("Expecting string: %r" % arg) # Fixed length: string<sz> if len(sub): assert int(sub) <= 32 assert len(arg) <= int(sub) return arg + b'\x00' * (32 - len(arg)) # Variable length: string else: return zpad(encode_int(len(arg)), 32) + \ arg + \ b'\x00' * (utils.ceil32(len(arg)) - len(arg)) # Hashes: hash<sz> elif base == 'hash': if not (int(sub) and int(sub) <= 32): raise EncodingError("too long: %r" % arg) if isnumeric(arg): return zpad(encode_int(arg), 32) elif len(arg) == int(sub): return zpad(arg, 32) elif len(arg) == int(sub) * 2: return zpad(decode_hex(arg), 32) else: raise EncodingError("Could not parse hash: %r" % arg) # Addresses: address (== hash160) elif base == 'address': assert sub == '' if isnumeric(arg): return zpad(encode_int(arg), 32) elif len(arg) == 20: return zpad(arg, 32) elif len(arg) == 40: return zpad(decode_hex(arg), 32) elif len(arg) == 42 and arg[:2] in {'0x', b'0x'}: return zpad(decode_hex(arg[2:]), 32) else: raise EncodingError("Could not parse address: %r" % arg) raise EncodingError("Unhandled type: %r %r" % (base, sub))
def encode_single(typ, arg): base, sub, _ = typ # Unsigned integers: uint<sz> if base == 'uint': sub = int(sub) i = decint(arg, False) if not 0 <= i < 2**sub: raise ValueOutOfBounds(repr(arg)) return zpad(encode_int(i), 32) # bool: int<sz> elif base == 'bool': assert isinstance(arg, bool) return zpad(encode_int(int(arg)), 32) # Signed integers: int<sz> elif base == 'int': sub = int(sub) i = decint(arg, True) if not -2**(sub - 1) <= i < 2**(sub - 1): raise ValueOutOfBounds(repr(arg)) return zpad(encode_int(i % 2**sub), 32) # Unsigned reals: ureal<high>x<low> elif base == 'ureal': high, low = [int(x) for x in sub.split('x')] if not 0 <= arg < 2**high: raise ValueOutOfBounds(repr(arg)) return zpad(encode_int(int(arg * 2**low)), 32) # Signed reals: real<high>x<low> elif base == 'real': high, low = [int(x) for x in sub.split('x')] if not -2**(high - 1) <= arg < 2**(high - 1): raise ValueOutOfBounds(repr(arg)) i = int(arg * 2**low) return zpad(encode_int(i % 2**(high + low)), 32) # Strings elif base == 'string' or base == 'bytes': if not is_string(arg): raise EncodingError("Expecting string: %r" % arg) # Fixed length: string<sz> if len(sub): assert int(sub) <= 32 assert len(arg) <= int(sub) return arg + b'\x00' * (32 - len(arg)) # Variable length: string else: return zpad(encode_int(len(arg)), 32) + \ arg + \ b'\x00' * (utils.ceil32(len(arg)) - len(arg)) # Hashes: hash<sz> elif base == 'hash': if not (int(sub) and int(sub) <= 32): raise EncodingError("too long: %r" % arg) if isnumeric(arg): return zpad(encode_int(arg), 32) elif len(arg) == int(sub): return zpad(arg, 32) elif len(arg) == int(sub) * 2: return zpad(decode_hex(arg), 32) else: raise EncodingError("Could not parse hash: %r" % arg) # Addresses: address (== hash160) elif base == 'address': assert sub == '' if isnumeric(arg): return zpad(encode_int(arg), 32) elif len(arg) == 20: return zpad(arg, 32) elif len(arg) == 40: return zpad(decode_hex(arg), 32) elif len(arg) == 42 and arg[:2] == '0x': return zpad(decode_hex(arg[2:]), 32) else: raise EncodingError("Could not parse address: %r" % arg) raise EncodingError("Unhandled type: %r %r" % (base, sub))