// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. module fractions import math import math.bits // Fraction Struct struct Fraction { n i64 d i64 } // A factory function for creating a Fraction, adds a boundary condition pub fn fraction(n i64, d i64) Fraction{ if d != 0 { return Fraction{n, d} } else { panic('Denominator cannot be zero') } } // To String method pub fn (f Fraction) str() string { return '$f.n/$f.d' } // Fraction add using operator overloading pub fn (f1 Fraction) + (f2 Fraction) Fraction { if f1.d == f2.d { return Fraction{f1.n + f2.n, f1.d} } else { return Fraction{(f1.n * f2.d) + (f2.n * f1.d), f1.d * f2.d} } } // Fraction subtract using operator overloading pub fn (f1 Fraction) - (f2 Fraction) Fraction { if f1.d == f2.d { return Fraction{f1.n - f2.n, f1.d} } else { return Fraction{(f1.n * f2.d) - (f2.n * f1.d), f1.d * f2.d} } } // Fraction multiply using operator overloading // pub fn (f1 Fraction) * (f2 Fraction) Fraction { // return Fraction{f1.n * f2.n,f1.d * f2.d} // } // Fraction divide using operator overloading // pub fn (f1 Fraction) / (f2 Fraction) Fraction { // return Fraction{f1.n * f2.d,f1.d * f2.n} // } // Fraction add method pub fn (f1 Fraction) add(f2 Fraction) Fraction { return f1 + f2 } // Fraction subtract method pub fn (f1 Fraction) subtract(f2 Fraction) Fraction { return f1 - f2 } // Fraction multiply method pub fn (f1 Fraction) multiply(f2 Fraction) Fraction { return Fraction{f1.n * f2.n, f1.d * f2.d} } // Fraction divide method pub fn (f1 Fraction) divide(f2 Fraction) Fraction { return Fraction{f1.n * f2.d, f1.d * f2.n} } // Fraction reciprocal method pub fn (f1 Fraction) reciprocal() Fraction { if f1.n == 0 { panic('Denominator cannot be zero') } return Fraction{f1.d, f1.n} } // Fraction method which gives greatest common divisor of numerator and denominator pub fn (f1 Fraction) gcd() i64 { return math.gcd(f1.n, f1.d) } // Fraction method which reduces the fraction pub fn (f1 Fraction) reduce() Fraction { cf := f1.gcd() return Fraction{f1.n / cf, f1.d / cf} } // Converts Fraction to decimal pub fn (f1 Fraction) f64() f64 { return f64(f1.n) / f64(f1.d) } // Returns the absolute value of an i64 fn abs(num i64) i64 { if num < 0 { return -num } else { return num } } // Two integers are safe to multiply when their bit lengths // sum up to less than 64 (conservative estimate). fn safe_to_multiply(a, b i64) bool { return (bits.len_64(abs(a)) + bits.len_64(abs(b))) < 64 } // Compares two Fractions pub fn (f1 Fraction) equals(f2 Fraction) bool { if safe_to_multiply(f1.n, f2.d) && safe_to_multiply(f2.n, f1.d) { return (f1.n * f2.d) == (f2.n * f1.d) } r1 := f1.reduce() r2 := f2.reduce() return (r1.n == r2.n) && (r1.d == r2.d) }