< Summary

Line coverage
99%
Covered lines: 133
Uncovered lines: 1
Coverable lines: 134
Total lines: 272
Line coverage: 99.2%
Branch coverage
96%
Covered branches: 48
Total branches: 50
Branch coverage: 96%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/SharpMathLib/SharpMathLib/SharpFractions/Comparison.cs

#LineLine coverage
 1namespace SharpFractions;
 2
 3public readonly partial struct Fraction : IComparable<Fraction>, IEquatable<Fraction>
 4{
 15    public static bool operator ==  (Fraction frac1, Fraction frac2) => Compare(frac1, frac2) == 0;
 16    public static bool operator !=  (Fraction frac1, Fraction frac2) => Compare(frac1, frac2) != 0;
 17    public static bool operator <   (Fraction frac1, Fraction frac2) => Compare(frac1, frac2) == -1;
 18    public static bool operator >   (Fraction frac1, Fraction frac2) => Compare(frac1, frac2) == 1;
 19    public static bool operator <=  (Fraction frac1, Fraction frac2) => Compare(frac1, frac2) != 1;
 110    public static bool operator >=  (Fraction frac1, Fraction frac2) => Compare(frac1, frac2) != -1;
 11
 12    public override bool Equals([NotNullWhen(true)] object? obj)
 213    {
 314        if (obj is null) return false;
 215        if (obj is not Fraction frac) return false;
 016        return Compare(this, frac) == 0;
 217    }
 18
 19    /// <summary>
 20    /// All value comparisons call this method.
 21    /// </summary>
 22    /// <returns>
 23    /// 1 if frac1 > frac2, -1 if frac2 > frac1, 0 if equal
 24    /// </returns>
 25    public static int Compare(Fraction frac1, Fraction frac2)
 3026    {
 3027        (frac1, frac2) = PutOnCommonDenominator(frac1, frac2);
 28
 3629        if (frac1.Numerator > frac2.Numerator) return 1;
 2530        if (frac1.Numerator < frac2.Numerator) return -1;
 2331        return 0;
 3032    }
 33
 134    public int CompareTo(Fraction other) => Compare(this, other);
 2135    public bool Equals(Fraction other) => Compare(this, other) == 0;
 236    public override int GetHashCode() => (Numerator, Denominator).GetHashCode();
 37}

/home/runner/work/SharpMathLib/SharpMathLib/SharpFractions/Fraction.cs

#LineLine coverage
 1namespace SharpFractions;
 2
 3public readonly partial struct Fraction : IComparable<Fraction>, IEquatable<Fraction>
 4{
 5    public readonly BigInteger Numerator;
 6    public readonly BigInteger Denominator;
 7
 8    /// <summary>
 9    /// Creates a fraction with numerator=<c>num</c> and denominator=<c>den</c>
 10    /// </summary>
 11    /// <param name="num"></param>
 12    /// <param name="den"></param>
 13    /// <exception cref="DivideByZeroException"></exception>
 14    public Fraction(BigInteger num, BigInteger den)
 17715    {
 17816        if (den == 0) throw new DivideByZeroException();
 17
 17618        Numerator = num;
 17619        Denominator = den;
 17620    }
 21
 22    /// <summary>
 23    /// Creates a fraction with numerator=<c>integer</c> and denominator=1
 24    /// </summary>
 25    /// <param name="integer"></param>
 7826    public Fraction(BigInteger integer) : this(integer, 1) { }
 27
 28
 629    public bool IsInt   => Numerator % Denominator == 0;
 1330    public bool IsZero  => Numerator == 0;
 231    public bool IsOne   => Numerator == Denominator;
 32
 33    public int Sign
 34    {
 35        get
 636        {
 737            if (Numerator == 0) return 0;
 538            return Numerator.Sign == Denominator.Sign ? 1 : -1;
 639        }
 40    }
 41
 1742    public BigInteger Whole => Numerator / Denominator;
 1343    public BigInteger Part  => Numerator % Denominator;
 44
 45    /// <summary>
 46    /// Returns the fraction in mixed form: 8/3 = 2 and 2/3
 47    /// </summary>
 148    public (BigInteger, Fraction) Mixed => (Whole, new(Part, Denominator));
 49
 150    public static Fraction MinusOne => new(-1);
 251    public static Fraction One      => new(1);
 952    public static Fraction Zero     => new(0);
 53
 54
 55    public Fraction ExpandBy(BigInteger integer)
 2356    {
 2357        return new(Numerator * integer, Denominator * integer);
 2358    }
 59
 60    public Fraction Invert()
 1461    {
 1562        if (Numerator.IsZero) throw new DivideByZeroException();
 1363        return new(Denominator, Numerator);
 1364    }
 65
 66    public Fraction Pow(int power)
 567    {
 668        if (power == 0) return One;
 569        if (power == 1) return this;
 70
 471        if (power < 0) return Invert().Pow(-power);
 72
 273        return new(
 274            BigInteger.Pow(Numerator, power),
 275            BigInteger.Pow(Denominator, power));
 576    }
 77
 178    public Fraction SwapSign() => new(-Numerator, -Denominator);
 79
 80    public Fraction ToSimplest()
 181    {
 182        BigInteger gcdOfNumDen = BigInteger.GreatestCommonDivisor(Numerator, Denominator);
 183        return new(Numerator / gcdOfNumDen, Denominator / gcdOfNumDen);
 184    }
 85
 86
 87    public static Fraction Abs(Fraction fraction)
 388    {
 489        if (fraction.Sign != -1) return fraction;
 90
 91        //Make sure to remove the minus sign:
 392        if (fraction.Numerator < 0) return new(fraction.Numerator * -1, fraction.Denominator);
 93
 194        return new(fraction.Numerator, fraction.Denominator * -1);
 395    }
 96
 97    public static List<BigInteger> ContinuedFraction(Fraction frac)
 498    {
 599        if (frac.IsInt) return new() { frac.Whole };    // Also trivial
 100
 101        //Ensure positive denom:
 102
 4103        if (frac.Denominator < 0) frac = new(-frac.Numerator, -frac.Denominator);
 104
 105        //For the first term we'll have to deal with the possibility of frac being negative:
 106
 107        BigInteger first;
 108
 3109        if (frac.Numerator < 0)
 2110        {
 2111            first = frac.Whole - 1;
 2112        }
 113        else
 1114        {
 1115            first = frac.Whole;
 1116        }
 117
 3118        List<BigInteger> coeffiecients = new() { first };
 119
 3120        frac = (frac - first).Invert();
 121
 122        // Now, redo until completion:
 123
 11124        while (true)
 11125        {
 11126            coeffiecients.Add(frac.Whole);
 127
 11128            frac = new(frac.Part, frac.Denominator);
 129
 14130            if (frac.IsZero) break;
 131
 8132            frac = frac.Invert();
 8133        }
 134
 3135        return coeffiecients;
 4136    }
 137
 138    /// <summary>
 139    /// Puts frac1 and frac2 on their lowest common denominator
 140    /// </summary>
 141    /// <param name="frac1"></param>
 142    /// <param name="frac2"></param>
 143    /// <returns>Two new fractions</returns>
 144    public static (Fraction, Fraction) PutOnCommonDenominator(Fraction frac1, Fraction frac2)
 35145    {
 59146        if (frac1.Denominator == frac2.Denominator) return (frac1, frac2);
 147
 11148        BigInteger newDenom = BigIntExtra.LeastCommonMultiple(frac1.Denominator, frac2.Denominator);
 11149        BigInteger toExpandFrac1By = newDenom / frac1.Denominator;
 11150        BigInteger toExpandFrac2By = newDenom / frac2.Denominator;
 151
 11152        return (frac1.ExpandBy(toExpandFrac1By), frac2.ExpandBy(toExpandFrac2By));
 35153    }
 154}

/home/runner/work/SharpMathLib/SharpMathLib/SharpFractions/Operators.cs

#LineLine coverage
 1namespace SharpFractions;
 2
 3public readonly partial struct Fraction : IComparable<Fraction>, IEquatable<Fraction>
 4{
 5    public static Fraction operator +(Fraction frac)
 16    {
 17        return new(frac.Numerator, frac.Denominator);
 18    }
 9
 10    public static Fraction operator +(Fraction left, Fraction right)
 111    {
 112        (left, right) = PutOnCommonDenominator(left, right);
 13
 114        return new(left.Numerator + right.Numerator, left.Denominator);
 115    }
 16
 17    public static Fraction operator -(Fraction frac)
 118    {
 119        return new(-frac.Numerator, frac.Denominator);
 120    }
 21
 22    public static Fraction operator -(Fraction left, Fraction right)
 323    {
 324        (left, right) = PutOnCommonDenominator(left, right);
 25
 326        return new(left.Numerator - right.Numerator, left.Denominator);
 327    }
 28
 29    public static Fraction operator *(Fraction left, Fraction right)
 130    {
 131        return new(left.Numerator * right.Numerator, left.Denominator * right.Denominator);
 132    }
 33
 34    public static Fraction operator /(Fraction left, Fraction right)
 235    {
 336        if (right.Numerator == 0) throw new DivideByZeroException();
 37
 138        return new(left.Numerator * right.Denominator, left.Denominator * right.Numerator);
 139    }
 40
 41
 42    // For interaction with integer types:
 43
 344    public static implicit operator Fraction(BigInteger bigInteger) => new(bigInteger);
 145    public static implicit operator Fraction(long longInteger)      => new(longInteger);
 146    public static implicit operator Fraction(int integer)           => new(integer);
 147    public static implicit operator Fraction(short shortInteger)    => new(shortInteger);
 48}

/home/runner/work/SharpMathLib/SharpMathLib/SharpFractions/StringRepresentation.cs

#LineLine coverage
 1namespace SharpFractions;
 2
 3public readonly partial struct Fraction : IComparable<Fraction>, IEquatable<Fraction>
 4{
 5    public override string ToString()
 16    {
 17        return $"{Numerator}/{Denominator}";
 18    }
 9
 10    public static bool TryParse(string toParse, out Fraction frac)
 611    {
 712        if (toParse == null) throw new ArgumentNullException(nameof(toParse));
 13
 514        frac = Zero;
 15
 5516        if (toParse.Count(c => c == '/') != 1) return false;
 17
 418        string[] numDen = toParse.Split('/');
 19
 420        string numerator = numDen[0];
 421        string denominator = numDen[1];
 22
 523        if (numerator.Length == 0 || denominator.Length == 0) return false;
 24
 325        bool successNumParse = BigInteger.TryParse(numerator, out BigInteger num);
 326        bool successDenParse = BigInteger.TryParse(denominator, out BigInteger den);
 27
 428        if (!(successNumParse && successDenParse)) return false;
 29
 230        frac = new(num, den);
 231        return true;
 532    }
 33}