struct Fraction { int n; int d; } library FRMath { static function add(Fraction x, Fraction y) : Fraction { return {x.n * y.d + y.n * x.d, x.d * y.d}; } static function sAdd(Fraction x, Fraction y) : Fraction { require(x.d > 0 && y.d > 0); return {x.n * y.d + y.n * x.d, x.d * y.d}; } static function sub(Fraction x, Fraction y) : Fraction { return {x.n * y.d - y.n * x.d, x.d * y.d}; } static function sSub(Fraction x, Fraction y) : Fraction { require(x.d > 0 && y.d > 0); return {x.n * y.d - y.n * x.d, x.d * y.d}; } static function mul(Fraction x, Fraction y) : Fraction { return {x.n * y.n, x.d * y.d}; } static function sMul(Fraction x, Fraction y) : Fraction { require(x.d > 0 && y.d > 0); return {x.n * y.n, x.d * y.d}; } static function div(Fraction x, Fraction y) : Fraction { return {x.n * y.d, x.d * y.n}; } static function sDiv(Fraction x, Fraction y) : Fraction { require(x.d > 0 && y.d > 0 && y.n != 0); return {x.n * y.d, x.d * y.n}; } static function abs(Fraction x) : Fraction { return {abs(x.n), abs(x.d)}; } static function sAbs(Fraction x) : Fraction { require(x.d > 0); return {abs(x.n), x.d}; } static function equal(Fraction x, Fraction y) : bool { return FRMath.sub(x, y).n == 0; } static function sEqual(Fraction x, Fraction y) : bool { return FRMath.sSub(x, y).n == 0; } static function toInt(Fraction x) : int { return x.n / x.d; } static function fromInt(int numerator, int denominator) : Fraction { return {numerator, denominator}; } static function scaleUp(Fraction x, int s) : int { return (x.n * s) / x.d; } }