made the rational struct immutable
ill add a mutable equivalent in 2.4.1
This commit is contained in:
parent
80b78c4bdb
commit
516e70709d
@ -28,7 +28,7 @@ internal static class RationalHelper
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
result = new(min.Numerator + max.Numerator, min.Denominator + max.Denominator, false);
|
result = new(min.numerator + max.numerator, min.denominator + max.denominator, false);
|
||||||
resultValue = result.GetValue();
|
resultValue = result.GetValue();
|
||||||
|
|
||||||
if (remainder == resultValue) break;
|
if (remainder == resultValue) break;
|
||||||
@ -40,7 +40,9 @@ internal static class RationalHelper
|
|||||||
}
|
}
|
||||||
while (Mathf.Absolute(resultValue - value) > tolerance);
|
while (Mathf.Absolute(resultValue - value) > tolerance);
|
||||||
|
|
||||||
result.Numerator += additional * result.Denominator;
|
if (additional != 0)
|
||||||
|
result = new(result.numerator + additional * result.denominator, result.denominator);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
namespace Nerd_STF.Mathematics;
|
namespace Nerd_STF.Mathematics;
|
||||||
|
|
||||||
public record struct Rational : IAbsolute<Rational>, IAverage<Rational>, ICeiling<Rational, int>, IClamp<Rational>,
|
public readonly record struct Rational : IAbsolute<Rational>, IAverage<Rational>, ICeiling<Rational, int>, IClamp<Rational>,
|
||||||
IComparable<Rational>, IComparable<float>, IDivide<Rational>, IEquatable<Rational>, IEquatable<float>,
|
IComparable<Rational>, IComparable<float>, IDivide<Rational>, IEquatable<Rational>, IEquatable<float>,
|
||||||
IFloor<Rational, int>, IIndexAll<int>, IIndexRangeAll<int>, ILerp<Rational, float>, IMathOperators<Rational>,
|
IFloor<Rational, int>, IIndexGet<int>, IIndexRangeGet<int>, ILerp<Rational, float>, IMathOperators<Rational>,
|
||||||
IMax<Rational>, IMedian<Rational>, IMin<Rational>, IPresets1d<Rational>, IProduct<Rational>,
|
IMax<Rational>, IMedian<Rational>, IMin<Rational>, IPresets1d<Rational>, IProduct<Rational>,
|
||||||
IRound<Rational, int>, ISplittable<Rational, (int[] nums, int[] dens)>, ISubtract<Rational>,
|
IRound<Rational, int>, ISplittable<Rational, (int[] nums, int[] dens)>, ISubtract<Rational>,
|
||||||
ISum<Rational>
|
ISum<Rational>
|
||||||
@ -10,37 +10,18 @@ public record struct Rational : IAbsolute<Rational>, IAverage<Rational>, ICeilin
|
|||||||
public static Rational One => new(1, 1);
|
public static Rational One => new(1, 1);
|
||||||
public static Rational Zero => new(0, 1);
|
public static Rational Zero => new(0, 1);
|
||||||
|
|
||||||
public int Numerator
|
public readonly int numerator;
|
||||||
{
|
public readonly int denominator;
|
||||||
get => p_num;
|
|
||||||
set => p_num = value;
|
|
||||||
}
|
|
||||||
public int Denominator
|
|
||||||
{
|
|
||||||
get => p_den;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (Math.Sign(value) == -1)
|
|
||||||
{
|
|
||||||
p_num *= -1;
|
|
||||||
p_den = -value;
|
|
||||||
}
|
|
||||||
else p_den = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int p_num;
|
public Rational Reciprocal => new(denominator, numerator);
|
||||||
private int p_den;
|
|
||||||
|
|
||||||
public Rational Reciprocal => new(p_den, p_num);
|
|
||||||
public Rational Simplified
|
public Rational Simplified
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
int[] denFactors = Mathf.PrimeFactors(p_den);
|
int[] denFactors = Mathf.PrimeFactors(denominator);
|
||||||
|
|
||||||
int newNum = p_num,
|
int newNum = numerator,
|
||||||
newDen = p_den;
|
newDen = denominator;
|
||||||
|
|
||||||
foreach (int factor in denFactors)
|
foreach (int factor in denFactors)
|
||||||
{
|
{
|
||||||
@ -57,8 +38,8 @@ public record struct Rational : IAbsolute<Rational>, IAverage<Rational>, ICeilin
|
|||||||
public Rational() : this(0, 1) { }
|
public Rational() : this(0, 1) { }
|
||||||
public Rational(int numerator, int denominator, bool simplified = true)
|
public Rational(int numerator, int denominator, bool simplified = true)
|
||||||
{
|
{
|
||||||
Numerator = numerator;
|
this.numerator = numerator * Math.Sign(denominator);
|
||||||
Denominator = denominator;
|
this.denominator = Mathf.Absolute(denominator);
|
||||||
if (simplified) this = Simplified;
|
if (simplified) this = Simplified;
|
||||||
}
|
}
|
||||||
public Rational(Fill<int> fill, bool simplified = true) : this(fill(0), fill(1), simplified) { }
|
public Rational(Fill<int> fill, bool simplified = true) : this(fill(0), fill(1), simplified) { }
|
||||||
@ -67,30 +48,14 @@ public record struct Rational : IAbsolute<Rational>, IAverage<Rational>, ICeilin
|
|||||||
{
|
{
|
||||||
get => index switch
|
get => index switch
|
||||||
{
|
{
|
||||||
0 => p_num,
|
0 => numerator,
|
||||||
1 => p_den,
|
1 => denominator,
|
||||||
_ => throw new IndexOutOfRangeException(nameof(index))
|
_ => throw new IndexOutOfRangeException(nameof(index))
|
||||||
};
|
};
|
||||||
set
|
|
||||||
{
|
|
||||||
switch (index)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
p_num = value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
p_den = value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: throw new IndexOutOfRangeException(nameof(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public int this[Index index]
|
public int this[Index index]
|
||||||
{
|
{
|
||||||
get => this[index.IsFromEnd ? 2 - index.Value : index.Value];
|
get => this[index.IsFromEnd ? 2 - index.Value : index.Value];
|
||||||
set => this[index.IsFromEnd ? 2 - index.Value : index.Value] = value;
|
|
||||||
}
|
}
|
||||||
public int[] this[Range range]
|
public int[] this[Range range]
|
||||||
{
|
{
|
||||||
@ -102,12 +67,6 @@ public record struct Rational : IAbsolute<Rational>, IAverage<Rational>, ICeilin
|
|||||||
for (int i = start; i < end; i++) res.Add(this[i]);
|
for (int i = start; i < end; i++) res.Add(this[i]);
|
||||||
return res.ToArray();
|
return res.ToArray();
|
||||||
}
|
}
|
||||||
set
|
|
||||||
{
|
|
||||||
int start = range.Start.IsFromEnd ? 2 - range.Start.Value : range.Start.Value;
|
|
||||||
int end = range.End.IsFromEnd ? 2 - range.End.Value : range.End.Value;
|
|
||||||
for (int i = start; i < end; i++) this[i] = value[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Rational FromFloat(float value, float tolerance = 1e-5f,
|
public static Rational FromFloat(float value, float tolerance = 1e-5f,
|
||||||
@ -120,20 +79,20 @@ public record struct Rational : IAbsolute<Rational>, IAverage<Rational>, ICeilin
|
|||||||
};
|
};
|
||||||
|
|
||||||
public static Rational Absolute(Rational value) =>
|
public static Rational Absolute(Rational value) =>
|
||||||
new(Mathf.Absolute(value.p_num), value.p_den);
|
new(Mathf.Absolute(value.numerator), value.denominator);
|
||||||
public static Rational Average(params Rational[] vals) => Sum(vals) / (float)vals.Length;
|
public static Rational Average(params Rational[] vals) => Sum(vals) / (float)vals.Length;
|
||||||
public static int Ceiling(Rational r)
|
public static int Ceiling(Rational r)
|
||||||
{
|
{
|
||||||
int mod = r.p_num % r.p_den;
|
int mod = r.numerator % r.denominator;
|
||||||
|
|
||||||
if (mod == 0) return r.p_num / r.p_den;
|
if (mod == 0) return r.numerator / r.denominator;
|
||||||
return r.p_num + (r.p_den - mod);
|
return r.numerator + (r.denominator - mod);
|
||||||
}
|
}
|
||||||
public static Rational Clamp(Rational val, Rational min, Rational max)
|
public static Rational Clamp(Rational val, Rational min, Rational max)
|
||||||
=> FromFloat(Mathf.Clamp(val.GetValue(), min.GetValue(), max.GetValue()));
|
=> FromFloat(Mathf.Clamp(val.GetValue(), min.GetValue(), max.GetValue()));
|
||||||
public static Rational Divide(Rational val, params Rational[] vals) =>
|
public static Rational Divide(Rational val, params Rational[] vals) =>
|
||||||
val / Product(vals);
|
val / Product(vals);
|
||||||
public static int Floor(Rational val) => val.p_num / val.p_den;
|
public static int Floor(Rational val) => val.numerator / val.denominator;
|
||||||
public static Rational Lerp(Rational a, Rational b, float t, bool clamp = true) =>
|
public static Rational Lerp(Rational a, Rational b, float t, bool clamp = true) =>
|
||||||
FromFloat(Mathf.Lerp(a.GetValue(), b.GetValue(), t, clamp));
|
FromFloat(Mathf.Lerp(a.GetValue(), b.GetValue(), t, clamp));
|
||||||
public static Rational Product(params Rational[] vals)
|
public static Rational Product(params Rational[] vals)
|
||||||
@ -142,7 +101,7 @@ public record struct Rational : IAbsolute<Rational>, IAverage<Rational>, ICeilin
|
|||||||
foreach (Rational r in vals) res *= r;
|
foreach (Rational r in vals) res *= r;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
public static int Round(Rational r) => (int)Mathf.Round(r.p_num, r.p_den) / r.p_den;
|
public static int Round(Rational r) => (int)Mathf.Round(r.numerator, r.denominator) / r.denominator;
|
||||||
public static Rational Subtract(Rational val, params Rational[] vals) =>
|
public static Rational Subtract(Rational val, params Rational[] vals) =>
|
||||||
val - Sum(vals);
|
val - Sum(vals);
|
||||||
public static Rational Sum(params Rational[] vals)
|
public static Rational Sum(params Rational[] vals)
|
||||||
@ -157,13 +116,13 @@ public record struct Rational : IAbsolute<Rational>, IAverage<Rational>, ICeilin
|
|||||||
int[] nums = new int[vals.Length], dens = new int[vals.Length];
|
int[] nums = new int[vals.Length], dens = new int[vals.Length];
|
||||||
for (int i = 0; i < vals.Length; i++)
|
for (int i = 0; i < vals.Length; i++)
|
||||||
{
|
{
|
||||||
nums[i] = vals[i].p_num;
|
nums[i] = vals[i].numerator;
|
||||||
dens[i] = vals[i].p_den;
|
dens[i] = vals[i].denominator;
|
||||||
}
|
}
|
||||||
return (nums, dens);
|
return (nums, dens);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetValue() => p_num / (float)p_den;
|
public float GetValue() => numerator / (float)denominator;
|
||||||
|
|
||||||
public int CompareTo(Rational other) => GetValue().CompareTo(other.GetValue());
|
public int CompareTo(Rational other) => GetValue().CompareTo(other.GetValue());
|
||||||
public int CompareTo(float other) => GetValue().CompareTo(other);
|
public int CompareTo(float other) => GetValue().CompareTo(other);
|
||||||
@ -171,42 +130,42 @@ public record struct Rational : IAbsolute<Rational>, IAverage<Rational>, ICeilin
|
|||||||
{
|
{
|
||||||
Rational thisSim = Simplified,
|
Rational thisSim = Simplified,
|
||||||
otherSim = other.Simplified;
|
otherSim = other.Simplified;
|
||||||
return thisSim.p_num == otherSim.p_num &&
|
return thisSim.numerator == otherSim.numerator &&
|
||||||
thisSim.p_den == otherSim.p_den;
|
thisSim.denominator == otherSim.denominator;
|
||||||
}
|
}
|
||||||
public bool Equals(float other) => GetValue() == other;
|
public bool Equals(float other) => GetValue() == other;
|
||||||
public override int GetHashCode() => base.GetHashCode();
|
public override int GetHashCode() => base.GetHashCode();
|
||||||
|
|
||||||
private bool PrintMembers(StringBuilder builder)
|
private bool PrintMembers(StringBuilder builder)
|
||||||
{
|
{
|
||||||
builder.Append(p_num);
|
builder.Append(numerator);
|
||||||
builder.Append(" / ");
|
builder.Append(" / ");
|
||||||
builder.Append(p_den);
|
builder.Append(denominator);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Rational operator +(Rational a, Rational b)
|
public static Rational operator +(Rational a, Rational b)
|
||||||
{
|
{
|
||||||
int sharedDen = a.p_den * b.p_den,
|
int sharedDen = a.denominator * b.denominator,
|
||||||
newNumA = a.p_num * b.p_den,
|
newNumA = a.numerator * b.denominator,
|
||||||
newNumB = b.p_num * a.p_den;
|
newNumB = b.numerator * a.denominator;
|
||||||
return new Rational(newNumA + newNumB, sharedDen).Simplified;
|
return new Rational(newNumA + newNumB, sharedDen).Simplified;
|
||||||
}
|
}
|
||||||
public static Rational operator +(Rational a, float b) => a + FromFloat(b);
|
public static Rational operator +(Rational a, float b) => a + FromFloat(b);
|
||||||
public static Rational operator +(float a, Rational b) => FromFloat(a) + b;
|
public static Rational operator +(float a, Rational b) => FromFloat(a) + b;
|
||||||
public static Rational operator -(Rational r) => new(-r.p_num, r.p_den);
|
public static Rational operator -(Rational r) => new(-r.numerator, r.denominator);
|
||||||
public static Rational operator -(Rational a, Rational b)
|
public static Rational operator -(Rational a, Rational b)
|
||||||
{
|
{
|
||||||
int sharedDen = a.p_den * b.p_den,
|
int sharedDen = a.denominator * b.denominator,
|
||||||
newNumA = a.p_num * b.p_den,
|
newNumA = a.numerator * b.denominator,
|
||||||
newNumB = b.p_num * a.p_den;
|
newNumB = b.numerator * a.denominator;
|
||||||
return new Rational(newNumA - newNumB, sharedDen).Simplified;
|
return new Rational(newNumA - newNumB, sharedDen).Simplified;
|
||||||
}
|
}
|
||||||
public static Rational operator -(Rational a, float b) => a - FromFloat(b);
|
public static Rational operator -(Rational a, float b) => a - FromFloat(b);
|
||||||
public static Rational operator -(float a, Rational b) => FromFloat(a) - b;
|
public static Rational operator -(float a, Rational b) => FromFloat(a) - b;
|
||||||
public static Rational operator *(Rational a, Rational b) =>
|
public static Rational operator *(Rational a, Rational b) =>
|
||||||
new Rational(a.p_num * b.p_num, a.p_den * b.p_den);
|
new Rational(a.numerator * b.numerator, a.denominator * b.denominator).Simplified;
|
||||||
public static Rational operator *(Rational a, float b) => a * FromFloat(b);
|
public static Rational operator *(Rational a, float b) => a * FromFloat(b);
|
||||||
public static Rational operator *(float a, Rational b) => FromFloat(a) * b;
|
public static Rational operator *(float a, Rational b) => FromFloat(a) * b;
|
||||||
public static Rational operator /(Rational a, Rational b) => a * b.Reciprocal;
|
public static Rational operator /(Rational a, Rational b) => a * b.Reciprocal;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user