Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 21 additions & 20 deletions av/rational.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
_INT32_MAX: cython.longlong = 2147483647


@cython.final
@cython.cclass
class AVRational:
"""
An exact rational number stored as two int32s, mirroring FFmpeg's
``AVRational``.
``AVRational``. It is a final class and cannot be subclassed.

Values are always reduced to lowest terms with a positive denominator.
Arithmetic between two :class:`AVRational` uses FFmpeg's ``av_mul_q``
Expand Down Expand Up @@ -82,71 +83,71 @@ def __reduce__(self):
return (AVRational, (self.num, self.den))

def __eq__(self, other):
if isinstance(other, AVRational):
if type(other) is AVRational:
o: AVRational = other
return self.num == o.num and self.den == o.den
if self.den == 0:
return False
return Fraction(self.num, self.den) == other
return Fraction(self.num, self.den).__eq__(other)

def __lt__(self, other):
return Fraction(self.num, self.den) < other
return Fraction(self.num, self.den).__lt__(other)

def __le__(self, other):
return Fraction(self.num, self.den) <= other
return Fraction(self.num, self.den).__le__(other)

def __gt__(self, other):
return Fraction(self.num, self.den) > other
return Fraction(self.num, self.den).__gt__(other)

def __ge__(self, other):
return Fraction(self.num, self.den) >= other
return Fraction(self.num, self.den).__ge__(other)

def __neg__(self):
return AVRational(-self.num, self.den)

def __mul__(self, other):
if isinstance(other, AVRational):
if type(other) is AVRational:
o: AVRational = other
return from_avrational(lib.av_mul_q(self._q(), o._q()))
return Fraction(self.num, self.den) * other
return Fraction(self.num, self.den).__mul__(other)

def __rmul__(self, other):
return other * Fraction(self.num, self.den)
return Fraction(self.num, self.den).__rmul__(other)

def __truediv__(self, other):
if isinstance(other, AVRational):
if type(other) is AVRational:
o: AVRational = other
if o.num == 0:
raise ZeroDivisionError(f"{self} / {other}")
return from_avrational(lib.av_div_q(self._q(), o._q()))
return Fraction(self.num, self.den) / other
return Fraction(self.num, self.den).__truediv__(other)

def __rtruediv__(self, other):
return other / Fraction(self.num, self.den)
return Fraction(self.num, self.den).__rtruediv__(other)

def __add__(self, other):
if isinstance(other, AVRational):
if type(other) is AVRational:
o: AVRational = other
return from_avrational(lib.av_add_q(self._q(), o._q()))
return Fraction(self.num, self.den) + other
return Fraction(self.num, self.den).__add__(other)

def __radd__(self, other):
return other + Fraction(self.num, self.den)
return Fraction(self.num, self.den).__radd__(other)

def __sub__(self, other):
if isinstance(other, AVRational):
if type(other) is AVRational:
o: AVRational = other
return from_avrational(lib.av_sub_q(self._q(), o._q()))
return Fraction(self.num, self.den) - other
return Fraction(self.num, self.den).__sub__(other)

def __rsub__(self, other):
return other - Fraction(self.num, self.den)
return Fraction(self.num, self.den).__rsub__(other)


@cython.cfunc
def from_avrational(q: lib.AVRational) -> AVRational:
obj: AVRational = AVRational.__new__(AVRational)
# FFmpeg does not guarantee reduced form; our invariant requires it.
# FFmpeg does not guarantee reduced form
lib.av_reduce(
cython.address(obj.num), cython.address(obj.den), q.num, q.den, _INT32_MAX
)
Expand Down
Loading