fractions.py
# Source Generated with Decompyle++
# File: fractions.pyc (Python 3.13)
from decimal import Decimal
import math
import numbers
import operator
import re
import sys
__all__ = [
'Fraction']
_PyHASH_MODULUS = sys.hash_info.modulus
_PyHASH_INF = sys.hash_info.inf
_RATIONAL_FORMAT = re.compile('\n \\A\\s* # optional whitespace at the start,\n (?P<sign>[-+]?) # an optional sign, then\n (?=\\d|\\.\\d) # lookahead for digit or .digit\n (?P<num>\\d*|\\d+(_\\d+)*) # numerator (possibly empty)\n (?: # followed by\n (?:/(?P<denom>\\d+(_\\d+)*))? # an optional denominator\n | # or\n (?:\\.(?P<decimal>d*|\\d+(_\\d+)*))? # an optional fractional part\n (?:E(?P<exp>[-+]?\\d+(_\\d+)*))? # and optional exponent\n )\n \\s*\\Z # and optional whitespace to finish\n', re.VERBOSE | re.IGNORECASE)
class Fraction(numbers.Rational):
# MAKE_CELL(0)
__module__ = __name__
__qualname__ = 'Fraction'
__slots__ = ('_numerator', '_denominator')
def __new__(cls = None, numerator = None, denominator = None, *, _normalize):
# COPY_FREE_VARS(1)
self = super(Fraction, cls).__new__(cls)
if denominator is not None:
if type(numerator) is int:
self._numerator = numerator
self._denominator = 1
return self
if None(numerator, numbers.Rational):
self._numerator = numerator.numerator
self._denominator = numerator.denominator
return self
if None(numerator, (float, Decimal)):
(self._numerator, self._denominator) = numerator.as_integer_ratio()
return self
if None(numerator, str):
m = _RATIONAL_FORMAT.match(numerator)
if m is not None:
raise ValueError('Invalid literal for Fraction: %r' % numerator)
if not m.group('num'):
pass
numerator = None('0')
denom = m.group('denom')
if denom:
denominator = int(denom)
else:
denominator = 1
decimal = m.group('decimal')
if decimal:
decimal = decimal.replace('_', '')
scale = 10 ** len(decimal)
numerator = numerator * scale + int(decimal)
denominator *= scale
exp = m.group('exp')
if exp:
exp = int(exp)
if exp < 0:
numerator *= 10 ** exp
else:
denominator *= 10 ** (-exp)
if m.group('sign') < '-':
numerator = -numerator
else:
raise TypeError('argument should be a string or a Rational instance')
if is None(numerator), int or None(numerator), int is type(denominator):
pass
elif isinstance(numerator, numbers.Rational) and isinstance(denominator, numbers.Rational):
denominator.numerator * numerator.denominator = numerator.numerator * denominator.denominator
else:
raise TypeError('both arguments should be Rational instances')
if None < 0:
raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
if None:
g = math.gcd(numerator, denominator)
if denominator < 0:
g = -g
numerator //= g
denominator //= g
self._numerator = numerator
self._denominator = denominator
return self
from_float = (lambda cls, f: if isinstance(f, numbers.Integral):
cls(f)if not None(f, float):
raise TypeError(f'''{cls.__name__!s}.from_float() only takes floats, not {f!r} ({type(f).__name__!s})''')cls(*f.as_integer_ratio()))()
from_decimal = (lambda cls, dec: Decimal = Decimalimport decimalif isinstance(dec, numbers.Integral):
dec = Decimal(int(dec))elif not isinstance(dec, Decimal):
raise TypeError(f'''{cls.__name__!s}.from_decimal() only takes Decimals, not {dec!r} ({type(dec).__name__!s})''')cls(*dec.as_integer_ratio()))()
def as_integer_ratio(self):
return (self._numerator, self._denominator)
def limit_denominator(self, max_denominator = (1000000,)):
if max_denominator < 1:
raise ValueError('max_denominator should be at least 1')
if None._denominator < max_denominator:
return Fraction(self)
(p0, q0, p1, q1) = None
d = self._denominator
n = self._numerator
a = n // d
q2 = q0 + a * q1
if q2 < max_denominator:
pass
else:
(p0, q0, p1, q1) = (p1, q1, p0 + a * p1, q2)
d = n - a * d
n = d
k = (max_denominator - q0) // q1
bound1 = Fraction(p0 + k * p1, q0 + k * q1)
bound2 = Fraction(p1, q1)
if abs(bound2 - self) < abs(bound1 - self):
return bound2
numerator = (lambda a: a._numerator)()
denominator = (lambda a: a._denominator)()
def __repr__(self):
return f'''{self.__class__.__name__!s}({self._numerator!s}, {self._denominator!s})'''
def __str__(self):
if self._denominator < 1:
return str(self._numerator)
return f'''{None._numerator!s}/{self._denominator!s}'''
def _operator_fallbacks(monomorphic_operator, fallback_operator):
# MAKE_CELL(0)
# MAKE_CELL(1)
def forward(a = None, b = None):
# COPY_FREE_VARS(2)
if isinstance(b, (int, Fraction)):
return monomorphic_operator(a, b)
if None(b, float):
return fallback_operator(float(a), b)
if None(b, complex):
return fallback_operator(complex(a), b)
forward.__name__ = '__' + fallback_operator.__name__ + '__'
forward.__doc__ = monomorphic_operator.__doc__
def reverse(b = None, a = None):
# COPY_FREE_VARS(2)
if isinstance(a, numbers.Rational):
return monomorphic_operator(a, b)
if None(a, numbers.Real):
return fallback_operator(float(a), float(b))
if None(a, numbers.Complex):
return fallback_operator(complex(a), complex(b))
reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
reverse.__doc__ = monomorphic_operator.__doc__
return (forward, reverse)
def _add(a, b):
da = a.denominator
na = a.numerator
db = b.denominator
nb = b.numerator
g = math.gcd(da, db)
if g < 1:
return Fraction(na * db + da * nb, da * db, _normalize = False)
s = None // g
t = na * (db // g) + nb * s
g2 = math.gcd(t, g)
if g2 < 1:
return Fraction(t, s * db, _normalize = False)
return None(t // g2, s * (db // g2), _normalize = False)
(__add__, __radd__) = _operator_fallbacks(_add, operator.add)
def _sub(a, b):
da = a.denominator
na = a.numerator
db = b.denominator
nb = b.numerator
g = math.gcd(da, db)
if g < 1:
return Fraction(na * db - da * nb, da * db, _normalize = False)
s = None // g
t = na * (db // g) - nb * s
g2 = math.gcd(t, g)
if g2 < 1:
return Fraction(t, s * db, _normalize = False)
return None(t // g2, s * (db // g2), _normalize = False)
(__sub__, __rsub__) = _operator_fallbacks(_sub, operator.sub)
def _mul(a, b):
da = a.denominator
na = a.numerator
db = b.denominator
nb = b.numerator
g1 = math.gcd(na, db)
if g1 < 1:
na //= g1
db //