Lots of nice changes. Made angle, more interfaces, working on fraction.
This commit is contained in:
parent
467b5903cc
commit
0704b8eec7
@ -1,6 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Nerd_STF.Mathematics.Abstract
|
namespace Nerd_STF.Abstract
|
||||||
{
|
{
|
||||||
public interface ICombinationIndexer<TItem>
|
public interface ICombinationIndexer<TItem>
|
||||||
{
|
{
|
||||||
@ -1,14 +1,14 @@
|
|||||||
#if CS11_OR_GREATER
|
#if CS11_OR_GREATER
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Nerd_STF.Mathematics.Abstract
|
namespace Nerd_STF.Abstract
|
||||||
{
|
{
|
||||||
public interface IFromTuple<TSelf, TTuple>
|
public interface IFromTuple<TSelf, TTuple>
|
||||||
where TSelf : IFromTuple<TSelf, TTuple>
|
where TSelf : IFromTuple<TSelf, TTuple>
|
||||||
where TTuple : struct, ITuple
|
where TTuple : struct, ITuple
|
||||||
{
|
{
|
||||||
public static abstract implicit operator TSelf(TTuple tuple);
|
static abstract implicit operator TSelf(TTuple tuple);
|
||||||
public static abstract implicit operator TTuple(TSelf tuple);
|
static abstract implicit operator TTuple(TSelf tuple);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
10
Nerd_STF/Abstract/IInterpolable.cs
Normal file
10
Nerd_STF/Abstract/IInterpolable.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#if CS11_OR_GREATER
|
||||||
|
namespace Nerd_STF.Abstract
|
||||||
|
{
|
||||||
|
public interface IInterpolable<TSelf>
|
||||||
|
where TSelf : IInterpolable<TSelf>
|
||||||
|
{
|
||||||
|
static abstract TSelf Lerp(TSelf a, TSelf b, double t, bool clamp = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
10
Nerd_STF/Abstract/IModifiable.cs
Normal file
10
Nerd_STF/Abstract/IModifiable.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Nerd_STF.Abstract
|
||||||
|
{
|
||||||
|
public interface IModifiable<TSelf>
|
||||||
|
where TSelf : IModifiable<TSelf>
|
||||||
|
{
|
||||||
|
void Modify(Action<TSelf> action);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
Nerd_STF/Abstract/INumberGroup.cs
Normal file
26
Nerd_STF/Abstract/INumberGroup.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Nerd_STF.Abstract
|
||||||
|
{
|
||||||
|
public interface INumberGroup<TSelf, TItem> : ICombinationIndexer<TItem>,
|
||||||
|
IEnumerable<TItem>,
|
||||||
|
IEquatable<TSelf>,
|
||||||
|
IModifiable<TSelf>
|
||||||
|
#if CS11_OR_GREATER
|
||||||
|
,IInterpolable<TSelf>,
|
||||||
|
ISimpleMathOperations<TSelf>,
|
||||||
|
IVectorOperations<TSelf>
|
||||||
|
#endif
|
||||||
|
where TSelf : INumberGroup<TSelf, TItem>
|
||||||
|
#if CS11_OR_GREATER
|
||||||
|
where TItem : INumber<TItem>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
TItem this[int index] { get; set; }
|
||||||
|
|
||||||
|
TItem[] ToArray();
|
||||||
|
List<TItem> ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
10
Nerd_STF/Abstract/IPresets1d.cs
Normal file
10
Nerd_STF/Abstract/IPresets1d.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#if CS11_OR_GREATER
|
||||||
|
namespace Nerd_STF.Abstract
|
||||||
|
{
|
||||||
|
public interface IPresets1d<TSelf> where TSelf : IPresets1d<TSelf>
|
||||||
|
{
|
||||||
|
static abstract TSelf One { get; }
|
||||||
|
static abstract TSelf Zero { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
13
Nerd_STF/Abstract/IPresets2d.cs
Normal file
13
Nerd_STF/Abstract/IPresets2d.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#if CS11_OR_GREATER
|
||||||
|
namespace Nerd_STF.Abstract
|
||||||
|
{
|
||||||
|
public interface IPresets2d<TSelf> : IPresets1d<TSelf>
|
||||||
|
where TSelf : IPresets2d<TSelf>
|
||||||
|
{
|
||||||
|
static abstract TSelf Down { get; }
|
||||||
|
static abstract TSelf Left { get; }
|
||||||
|
static abstract TSelf Right { get; }
|
||||||
|
static abstract TSelf Up { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
Nerd_STF/Abstract/IPresets3d.cs
Normal file
11
Nerd_STF/Abstract/IPresets3d.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#if CS11_OR_GREATER
|
||||||
|
namespace Nerd_STF.Abstract
|
||||||
|
{
|
||||||
|
public interface IPresets3d<TSelf> : IPresets2d<TSelf>
|
||||||
|
where TSelf : IPresets3d<TSelf>
|
||||||
|
{
|
||||||
|
static abstract TSelf Backward { get; }
|
||||||
|
static abstract TSelf Forward { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -1,11 +1,11 @@
|
|||||||
#if CS11_OR_GREATER
|
#if CS11_OR_GREATER
|
||||||
namespace Nerd_STF.Mathematics.Abstract
|
namespace Nerd_STF.Abstract
|
||||||
{
|
{
|
||||||
public interface IPresets4d<TSelf> : IPresets3d<TSelf>
|
public interface IPresets4d<TSelf> : IPresets3d<TSelf>
|
||||||
where TSelf : IPresets4d<TSelf>
|
where TSelf : IPresets4d<TSelf>
|
||||||
{
|
{
|
||||||
public static abstract TSelf LowW { get; }
|
static abstract TSelf LowW { get; }
|
||||||
public static abstract TSelf HighW { get; }
|
static abstract TSelf HighW { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
19
Nerd_STF/Abstract/IRoundable.cs
Normal file
19
Nerd_STF/Abstract/IRoundable.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#if CS11_OR_GREATER
|
||||||
|
namespace Nerd_STF.Abstract
|
||||||
|
{
|
||||||
|
public interface IRoundable<TSelf> : IRoundable<TSelf, TSelf>
|
||||||
|
where TSelf : IRoundable<TSelf> { }
|
||||||
|
|
||||||
|
public interface IRoundable<TSelf, TOut>
|
||||||
|
where TSelf : IRoundable<TSelf, TOut>
|
||||||
|
{
|
||||||
|
static abstract TOut Ceiling(TSelf val);
|
||||||
|
static abstract TOut Floor(TSelf val);
|
||||||
|
static abstract TOut Round(TSelf val);
|
||||||
|
|
||||||
|
static abstract void Ceiling(ref TSelf val);
|
||||||
|
static abstract void Floor(ref TSelf val);
|
||||||
|
static abstract void Round(ref TSelf val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
17
Nerd_STF/Abstract/ISimpleMathOperations.cs
Normal file
17
Nerd_STF/Abstract/ISimpleMathOperations.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#if CS11_OR_GREATER
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Nerd_STF.Abstract
|
||||||
|
{
|
||||||
|
public interface ISimpleMathOperations<TSelf> : IAdditionOperators<TSelf, TSelf, TSelf>,
|
||||||
|
ISubtractionOperators<TSelf, TSelf, TSelf>,
|
||||||
|
IMultiplyOperators<TSelf, TSelf, TSelf>,
|
||||||
|
IDivisionOperators<TSelf, TSelf, TSelf>
|
||||||
|
where TSelf : ISimpleMathOperations<TSelf>
|
||||||
|
{
|
||||||
|
static abstract TSelf Product(IEnumerable<TSelf> vals);
|
||||||
|
static abstract TSelf Sum(IEnumerable<TSelf> vals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -2,13 +2,13 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Nerd_STF.Mathematics.Abstract
|
namespace Nerd_STF.Abstract
|
||||||
{
|
{
|
||||||
public interface ISplittable<TSelf, TTuple>
|
public interface ISplittable<TSelf, TTuple>
|
||||||
where TSelf : ISplittable<TSelf, TTuple>
|
where TSelf : ISplittable<TSelf, TTuple>
|
||||||
where TTuple : struct, ITuple
|
where TTuple : struct, ITuple
|
||||||
{
|
{
|
||||||
public static abstract TTuple SplitArray(IEnumerable<TSelf> values);
|
static abstract TTuple SplitArray(IEnumerable<TSelf> values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
17
Nerd_STF/Abstract/IVectorOperations.cs
Normal file
17
Nerd_STF/Abstract/IVectorOperations.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#if CS11_OR_GREATER
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Nerd_STF.Abstract
|
||||||
|
{
|
||||||
|
public interface IVectorOperations<TSelf> : ISimpleMathOperations<TSelf>
|
||||||
|
where TSelf : IVectorOperations<TSelf>
|
||||||
|
{
|
||||||
|
double Magnitude { get; }
|
||||||
|
|
||||||
|
static abstract TSelf ClampMagnitude(TSelf val, double minMag, double maxMag);
|
||||||
|
static abstract void ClampMagnitude(ref TSelf val, double minMag, double maxMag);
|
||||||
|
static abstract double Dot(TSelf a, TSelf b);
|
||||||
|
static abstract double Dot(IEnumerable<TSelf> vals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -1,16 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Nerd_STF.Mathematics.Abstract
|
|
||||||
{
|
|
||||||
public interface INumberGroup<TSelf, TItem> : ICombinationIndexer<TItem>,
|
|
||||||
IEnumerable<TItem>,
|
|
||||||
IEquatable<TSelf>
|
|
||||||
where TSelf : INumberGroup<TSelf, TItem>
|
|
||||||
{
|
|
||||||
TItem this[int index] { get; set; }
|
|
||||||
|
|
||||||
TItem[] ToArray();
|
|
||||||
List<TItem> ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
#if CS11_OR_GREATER
|
|
||||||
namespace Nerd_STF.Mathematics.Abstract
|
|
||||||
{
|
|
||||||
public interface IPresets1d<TSelf> where TSelf : IPresets1d<TSelf>
|
|
||||||
{
|
|
||||||
public static abstract TSelf One { get; }
|
|
||||||
public static abstract TSelf Zero { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
#if CS11_OR_GREATER
|
|
||||||
namespace Nerd_STF.Mathematics.Abstract
|
|
||||||
{
|
|
||||||
public interface IPresets2d<TSelf> : IPresets1d<TSelf>
|
|
||||||
where TSelf : IPresets2d<TSelf>
|
|
||||||
{
|
|
||||||
public static abstract TSelf Down { get; }
|
|
||||||
public static abstract TSelf Left { get; }
|
|
||||||
public static abstract TSelf Right { get; }
|
|
||||||
public static abstract TSelf Up { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
#if CS11_OR_GREATER
|
|
||||||
namespace Nerd_STF.Mathematics.Abstract
|
|
||||||
{
|
|
||||||
public interface IPresets3d<TSelf> : IPresets2d<TSelf>
|
|
||||||
where TSelf : IPresets3d<TSelf>
|
|
||||||
{
|
|
||||||
public static abstract TSelf Backward { get; }
|
|
||||||
public static abstract TSelf Forward { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
253
Nerd_STF/Mathematics/Angle.cs
Normal file
253
Nerd_STF/Mathematics/Angle.cs
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
using Nerd_STF.Abstract;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Nerd_STF.Mathematics
|
||||||
|
{
|
||||||
|
public struct Angle : IComparable<Angle>,
|
||||||
|
IEquatable<Angle>,
|
||||||
|
IModifiable<Angle>
|
||||||
|
#if CS11_OR_GREATER
|
||||||
|
,IPresets2d<Angle>,
|
||||||
|
IFromTuple<Angle, (double, Angle.Unit)>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
public static Angle Down => new Angle(0.75);
|
||||||
|
public static Angle Left => new Angle(0.5);
|
||||||
|
public static Angle Right => new Angle(0);
|
||||||
|
public static Angle Up => new Angle(0.25);
|
||||||
|
|
||||||
|
public static Angle Full => new Angle(1);
|
||||||
|
public static Angle Half => new Angle(0.5);
|
||||||
|
public static Angle Quarter => new Angle(0.25);
|
||||||
|
public static Angle Zero => new Angle(0);
|
||||||
|
|
||||||
|
#if CS11_OR_GREATER
|
||||||
|
static Angle IPresets1d<Angle>.One => new Angle(1, Unit.Degrees);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public double Degrees
|
||||||
|
{
|
||||||
|
get => revTheta * 360;
|
||||||
|
set => revTheta = value / 360;
|
||||||
|
}
|
||||||
|
public double Gradians
|
||||||
|
{
|
||||||
|
get => revTheta * 400;
|
||||||
|
set => revTheta = value / 400;
|
||||||
|
}
|
||||||
|
public double Radians
|
||||||
|
{
|
||||||
|
get => revTheta * Constants.Tau;
|
||||||
|
set => revTheta = value / Constants.Tau;
|
||||||
|
}
|
||||||
|
public double Revolutions
|
||||||
|
{
|
||||||
|
get => revTheta;
|
||||||
|
set => revTheta = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Angle Complimentary => new Angle(0.25 - MathE.AbsoluteMod(revTheta, 1));
|
||||||
|
public Angle Supplimentary => new Angle(0.5 - MathE.AbsoluteMod(revTheta, 1));
|
||||||
|
public Angle Normalized => new Angle(MathE.AbsoluteMod(revTheta, 1));
|
||||||
|
public Angle Reflected => new Angle(MathE.AbsoluteMod(-revTheta, 1));
|
||||||
|
|
||||||
|
private double revTheta;
|
||||||
|
|
||||||
|
public Angle(double theta, Unit unit)
|
||||||
|
{
|
||||||
|
switch (unit)
|
||||||
|
{
|
||||||
|
case Unit.Revolutions: revTheta = theta; break;
|
||||||
|
case Unit.Degrees: revTheta = theta / 360; break;
|
||||||
|
case Unit.Radians: revTheta = theta / Constants.Tau; break;
|
||||||
|
case Unit.Gradians: revTheta = theta / 400; break;
|
||||||
|
default: throw new ArgumentException($"Unknown angle unit \"{unit}.\"", nameof(unit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Angle(double revTheta)
|
||||||
|
{
|
||||||
|
this.revTheta = revTheta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double this[Unit unit]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (unit)
|
||||||
|
{
|
||||||
|
case Unit.Revolutions: return revTheta;
|
||||||
|
case Unit.Degrees: return revTheta * 360;
|
||||||
|
case Unit.Radians: return revTheta * Constants.Tau;
|
||||||
|
case Unit.Gradians: return revTheta * 400;
|
||||||
|
default: throw new ArgumentException($"Unknown angle unit \"{unit}.\"", nameof(unit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (unit)
|
||||||
|
{
|
||||||
|
case Unit.Revolutions: revTheta = value; break;
|
||||||
|
case Unit.Degrees: revTheta = value / 360; break;
|
||||||
|
case Unit.Radians: revTheta = value / Constants.Tau; break;
|
||||||
|
case Unit.Gradians: revTheta = value / 400; break;
|
||||||
|
default: throw new ArgumentException($"Unknown angle unit \"{unit}.\"", nameof(unit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Angle Average(IEnumerable<Angle> angles)
|
||||||
|
{
|
||||||
|
Angle sum = Zero;
|
||||||
|
int count = 0;
|
||||||
|
foreach (Angle ang in angles)
|
||||||
|
{
|
||||||
|
sum += ang;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
public static Angle Clamp(Angle value, Angle min, Angle max) =>
|
||||||
|
new Angle(MathE.Clamp(value.revTheta, min.revTheta, max.revTheta));
|
||||||
|
public static void Clamp(ref Angle value, Angle min, Angle max) =>
|
||||||
|
MathE.Clamp(ref value.revTheta, min.revTheta, max.revTheta);
|
||||||
|
public static Angle Max(IEnumerable<Angle> values) => Max(false, values);
|
||||||
|
public static Angle Max(bool normalize, IEnumerable<Angle> values)
|
||||||
|
{
|
||||||
|
bool any = false;
|
||||||
|
Angle best = Zero;
|
||||||
|
double bestNormalized = 0;
|
||||||
|
foreach (Angle ang in values)
|
||||||
|
{
|
||||||
|
if (!any)
|
||||||
|
{
|
||||||
|
best = ang;
|
||||||
|
if (normalize) bestNormalized = MathE.AbsoluteMod(ang.revTheta, 1);
|
||||||
|
any = true;
|
||||||
|
}
|
||||||
|
else if (normalize)
|
||||||
|
{
|
||||||
|
double angNormalized = MathE.AbsoluteMod(ang.revTheta, 1);
|
||||||
|
if (angNormalized > bestNormalized)
|
||||||
|
{
|
||||||
|
best = ang;
|
||||||
|
bestNormalized = angNormalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ang.revTheta > best.revTheta) best = ang;
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
public static Angle Min(IEnumerable<Angle> values) => Min(false, values);
|
||||||
|
public static Angle Min(bool normalize, IEnumerable<Angle> values)
|
||||||
|
{
|
||||||
|
bool any = false;
|
||||||
|
Angle best = Zero;
|
||||||
|
double bestNormalized = 0;
|
||||||
|
foreach (Angle ang in values)
|
||||||
|
{
|
||||||
|
if (!any)
|
||||||
|
{
|
||||||
|
best = ang;
|
||||||
|
if (normalize) bestNormalized = MathE.AbsoluteMod(ang.revTheta, 1);
|
||||||
|
any = true;
|
||||||
|
}
|
||||||
|
else if (normalize)
|
||||||
|
{
|
||||||
|
double angNormalized = MathE.AbsoluteMod(ang.revTheta, 1);
|
||||||
|
if (angNormalized < bestNormalized)
|
||||||
|
{
|
||||||
|
best = ang;
|
||||||
|
bestNormalized = angNormalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ang.revTheta < best.revTheta) best = ang;
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
public static Angle Sum(IEnumerable<Angle> angles)
|
||||||
|
{
|
||||||
|
Angle sum = Zero;
|
||||||
|
foreach (Angle ang in angles) sum += ang;
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double[] SplitArray(Unit unit, IEnumerable<Angle> values)
|
||||||
|
{
|
||||||
|
int count = values.Count();
|
||||||
|
double[] angles = new double[count];
|
||||||
|
int index = 0;
|
||||||
|
foreach (Angle val in values)
|
||||||
|
{
|
||||||
|
angles[index] = val[unit];
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return angles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Modify(Action<Angle> action) => action(this);
|
||||||
|
|
||||||
|
public int CompareTo(Angle other) => revTheta.CompareTo(other.revTheta);
|
||||||
|
public bool Equals(Angle other) => revTheta == other.revTheta;
|
||||||
|
#if CS8_OR_GREATER
|
||||||
|
public override bool Equals(object? other)
|
||||||
|
#else
|
||||||
|
public override bool Equals(object other)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (other is null) return false;
|
||||||
|
else if (other is Angle otherAng) return Equals(otherAng);
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
public override int GetHashCode() => revTheta.GetHashCode();
|
||||||
|
public override string ToString() => ToString(Unit.Degrees, null);
|
||||||
|
public string ToString(Unit unit) => ToString(unit, null);
|
||||||
|
#if CS8_OR_GREATER
|
||||||
|
public string ToString(string? format) =>
|
||||||
|
#else
|
||||||
|
public string ToString(string format) =>
|
||||||
|
#endif
|
||||||
|
ToString(Unit.Degrees, format);
|
||||||
|
#if CS8_OR_GREATER
|
||||||
|
public string ToString(Unit unit, string? format)
|
||||||
|
#else
|
||||||
|
public string ToString(Unit unit, string format)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
switch (unit)
|
||||||
|
{
|
||||||
|
case Unit.Revolutions: return $"{revTheta.ToString(format)} rev";
|
||||||
|
case Unit.Degrees: return $"{(revTheta * 360).ToString(format)} deg";
|
||||||
|
case Unit.Radians: return $"{(revTheta * Constants.Tau).ToString(format)} rad";
|
||||||
|
case Unit.Gradians: return $"{(revTheta * 400).ToString(format)} grad";
|
||||||
|
default: throw new ArgumentException($"Unknown angle unit \"{unit}.\"", nameof(unit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Angle operator +(Angle a, Angle b) => new Angle(a.revTheta + b.revTheta);
|
||||||
|
public static Angle operator -(Angle a) => new Angle(-a.revTheta);
|
||||||
|
public static Angle operator -(Angle a, Angle b) => new Angle(a.revTheta - b.revTheta);
|
||||||
|
public static Angle operator *(Angle a, double b) => new Angle(a.revTheta * b);
|
||||||
|
public static Angle operator /(Angle a, double b) => new Angle(a.revTheta / b);
|
||||||
|
public static bool operator ==(Angle a, Angle b) => a.Equals(b);
|
||||||
|
public static bool operator !=(Angle a, Angle b) => !a.Equals(b);
|
||||||
|
public static bool operator >(Angle a, Angle b) => a.CompareTo(b) > 0;
|
||||||
|
public static bool operator <(Angle a, Angle b) => a.CompareTo(b) < 0;
|
||||||
|
public static bool operator >=(Angle a, Angle b) => a.CompareTo(b) >= 0;
|
||||||
|
public static bool operator <=(Angle a, Angle b) => a.CompareTo(b) <= 0;
|
||||||
|
|
||||||
|
public static implicit operator Angle((double, Unit) tuple) => new Angle(tuple.Item1, tuple.Item2);
|
||||||
|
#if CS11_OR_GREATER
|
||||||
|
static implicit IFromTuple<Angle, (double, Unit)>.operator ValueTuple<double, Unit>(Angle angle) => (angle.revTheta, Unit.Revolutions);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public enum Unit
|
||||||
|
{
|
||||||
|
Revolutions,
|
||||||
|
Degrees,
|
||||||
|
Radians,
|
||||||
|
Gradians
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,5 +23,17 @@ namespace Nerd_STF.Mathematics.Equations
|
|||||||
double Integrate(double lower, double upper);
|
double Integrate(double lower, double upper);
|
||||||
|
|
||||||
// TODO: Solve
|
// TODO: Solve
|
||||||
|
|
||||||
|
#if CS8_OR_GREATER
|
||||||
|
static IEquation operator +(IEquation a, IEquation b) => a.Add(b);
|
||||||
|
static IEquation operator +(IEquation a, double b) => a.Add(b);
|
||||||
|
static IEquation operator -(IEquation a) => a.Negate();
|
||||||
|
static IEquation operator -(IEquation a, IEquation b) => a.Subtract(b);
|
||||||
|
static IEquation operator -(IEquation a, double b) => a.Subtract(b);
|
||||||
|
static IEquation operator *(IEquation a, IEquation b) => a.Multiply(b);
|
||||||
|
static IEquation operator *(IEquation a, double b) => a.Multiply(b);
|
||||||
|
static IEquation operator /(IEquation a, IEquation b) => a.Divide(b);
|
||||||
|
static IEquation operator /(IEquation a, double b) => a.Divide(b);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,6 +79,8 @@ namespace Nerd_STF.Mathematics.Equations
|
|||||||
public IEquation Add(IEquation other)
|
public IEquation Add(IEquation other)
|
||||||
{
|
{
|
||||||
if (other is Polynomial otherPoly) return Add(otherPoly);
|
if (other is Polynomial otherPoly) return Add(otherPoly);
|
||||||
|
else if (other is Quadratic otherQuad) return Add((Polynomial)otherQuad);
|
||||||
|
else if (other is Linear otherLinear) return Add((Polynomial)otherLinear);
|
||||||
else return new Equation((double x) => Get(x) + other.Get(x));
|
else return new Equation((double x) => Get(x) + other.Get(x));
|
||||||
}
|
}
|
||||||
public Polynomial Add(double constant)
|
public Polynomial Add(double constant)
|
||||||
|
|||||||
@ -183,6 +183,7 @@ namespace Nerd_STF.Mathematics.Equations
|
|||||||
public static Polynomial operator *(Quadratic a, double b) => a.Multiply(b);
|
public static Polynomial operator *(Quadratic a, double b) => a.Multiply(b);
|
||||||
public static IEquation operator /(Quadratic a, IEquation b) => a.Divide(b);
|
public static IEquation operator /(Quadratic a, IEquation b) => a.Divide(b);
|
||||||
public static Quadratic operator /(Quadratic a, double b) => a.Divide(b);
|
public static Quadratic operator /(Quadratic a, double b) => a.Divide(b);
|
||||||
|
|
||||||
public static bool operator ==(Quadratic a, Quadratic b) => a.Equals(b);
|
public static bool operator ==(Quadratic a, Quadratic b) => a.Equals(b);
|
||||||
public static bool operator ==(Quadratic a, Polynomial b) => a.Equals(b);
|
public static bool operator ==(Quadratic a, Polynomial b) => a.Equals(b);
|
||||||
public static bool operator !=(Quadratic a, Quadratic b) => !a.Equals(b);
|
public static bool operator !=(Quadratic a, Quadratic b) => !a.Equals(b);
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
using Nerd_STF.Exceptions;
|
using Nerd_STF.Abstract;
|
||||||
using Nerd_STF.Mathematics.Abstract;
|
using Nerd_STF.Exceptions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@ -13,6 +12,7 @@ namespace Nerd_STF.Mathematics
|
|||||||
#if CS11_OR_GREATER
|
#if CS11_OR_GREATER
|
||||||
,IFromTuple<Float2, (double, double)>,
|
,IFromTuple<Float2, (double, double)>,
|
||||||
IPresets2d<Float2>,
|
IPresets2d<Float2>,
|
||||||
|
IRoundable<Float2, Int2>,
|
||||||
ISplittable<Float2, (double[] Xs, double[] Ys)>
|
ISplittable<Float2, (double[] Xs, double[] Ys)>
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -236,6 +236,8 @@ namespace Nerd_STF.Mathematics
|
|||||||
y = this.y;
|
y = this.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Modify(Action<Float2> action) => action(this);
|
||||||
|
|
||||||
public bool Equals(Float2 other) => x == other.x && y == other.y;
|
public bool Equals(Float2 other) => x == other.x && y == other.y;
|
||||||
#if CS8_OR_GREATER
|
#if CS8_OR_GREATER
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Nerd_STF.Exceptions;
|
using Nerd_STF.Abstract;
|
||||||
using Nerd_STF.Mathematics.Abstract;
|
using Nerd_STF.Exceptions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -11,6 +11,7 @@ namespace Nerd_STF.Mathematics
|
|||||||
#if CS11_OR_GREATER
|
#if CS11_OR_GREATER
|
||||||
,IFromTuple<Float3, (double, double, double)>,
|
,IFromTuple<Float3, (double, double, double)>,
|
||||||
IPresets2d<Float3>,
|
IPresets2d<Float3>,
|
||||||
|
IRoundable<Float3, Int3>,
|
||||||
ISplittable<Float3, (double[] Xs, double[] Ys, double[] Zs)>
|
ISplittable<Float3, (double[] Xs, double[] Ys, double[] Zs)>
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -261,6 +262,8 @@ namespace Nerd_STF.Mathematics
|
|||||||
z = this.z;
|
z = this.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Modify(Action<Float3> action) => action(this);
|
||||||
|
|
||||||
public bool Equals(Float3 other) => x == other.x && y == other.y && z == other.z;
|
public bool Equals(Float3 other) => x == other.x && y == other.y && z == other.z;
|
||||||
#if CS8_OR_GREATER
|
#if CS8_OR_GREATER
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
|
|||||||
@ -2,8 +2,8 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Nerd_STF.Abstract;
|
||||||
using Nerd_STF.Exceptions;
|
using Nerd_STF.Exceptions;
|
||||||
using Nerd_STF.Mathematics.Abstract;
|
|
||||||
|
|
||||||
namespace Nerd_STF.Mathematics
|
namespace Nerd_STF.Mathematics
|
||||||
{
|
{
|
||||||
@ -11,6 +11,7 @@ namespace Nerd_STF.Mathematics
|
|||||||
#if CS11_OR_GREATER
|
#if CS11_OR_GREATER
|
||||||
,IFromTuple<Float4, (double, double, double, double)>,
|
,IFromTuple<Float4, (double, double, double, double)>,
|
||||||
IPresets4d<Float4>,
|
IPresets4d<Float4>,
|
||||||
|
IRoundable<Float4, Int4>,
|
||||||
ISplittable<Float4, (double[] Ws, double[] Xs, double[] Ys, double[] Zs)>
|
ISplittable<Float4, (double[] Ws, double[] Xs, double[] Ys, double[] Zs)>
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -281,6 +282,8 @@ namespace Nerd_STF.Mathematics
|
|||||||
z = this.z;
|
z = this.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Modify(Action<Float4> action) => action(this);
|
||||||
|
|
||||||
public bool Equals(Float4 other) => w == other.w && x == other.x && y == other.y && z == other.z;
|
public bool Equals(Float4 other) => w == other.w && x == other.x && y == other.y && z == other.z;
|
||||||
#if CS8_OR_GREATER
|
#if CS8_OR_GREATER
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Nerd_STF.Exceptions;
|
using Nerd_STF.Abstract;
|
||||||
using Nerd_STF.Mathematics.Abstract;
|
using Nerd_STF.Exceptions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -120,27 +120,27 @@ namespace Nerd_STF.Mathematics
|
|||||||
MathE.Clamp(ref value.x, min.x, max.x);
|
MathE.Clamp(ref value.x, min.x, max.x);
|
||||||
MathE.Clamp(ref value.y, min.y, max.y);
|
MathE.Clamp(ref value.y, min.y, max.y);
|
||||||
}
|
}
|
||||||
public static Int2 ClampMagnitude(Int2 value, int minMag, int maxMag)
|
public static Int2 ClampMagnitude(Int2 value, double minMag, double maxMag)
|
||||||
{
|
{
|
||||||
Int2 copy = value;
|
Int2 copy = value;
|
||||||
ClampMagnitude(ref copy, minMag, maxMag);
|
ClampMagnitude(ref copy, minMag, maxMag);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
public static void ClampMagnitude(ref Int2 value, int minMag, int maxMag)
|
public static void ClampMagnitude(ref Int2 value, double minMag, double maxMag)
|
||||||
{
|
{
|
||||||
if (minMag > maxMag) throw new ClampOrderMismatchException(nameof(minMag), nameof(maxMag));
|
if (minMag > maxMag) throw new ClampOrderMismatchException(nameof(minMag), nameof(maxMag));
|
||||||
double mag = value.Magnitude;
|
double mag = value.Magnitude;
|
||||||
if (mag < minMag)
|
if (mag < minMag)
|
||||||
{
|
{
|
||||||
double factor = minMag / mag;
|
double factor = minMag / mag;
|
||||||
value.x = (int)(value.x * factor);
|
value.x = MathE.Ceiling(value.x * factor);
|
||||||
value.y = (int)(value.y * factor);
|
value.y = MathE.Ceiling(value.y * factor);
|
||||||
}
|
}
|
||||||
else if (mag > maxMag)
|
else if (mag > maxMag)
|
||||||
{
|
{
|
||||||
double factor = maxMag / mag;
|
double factor = maxMag / mag;
|
||||||
value.x = (int)(value.x * factor);
|
value.x = MathE.Floor(value.x * factor);
|
||||||
value.y = (int)(value.y * factor);
|
value.y = MathE.Floor(value.y * factor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static Int3 Cross(Int2 a, Int2 b) => Int3.Cross(a, b);
|
public static Int3 Cross(Int2 a, Int2 b) => Int3.Cross(a, b);
|
||||||
@ -155,6 +155,10 @@ namespace Nerd_STF.Mathematics
|
|||||||
}
|
}
|
||||||
return x + y;
|
return x + y;
|
||||||
}
|
}
|
||||||
|
#if CS11_OR_GREATER
|
||||||
|
static double IVectorOperations<Int2>.Dot(Int2 a, Int2 b) => Dot(a, b);
|
||||||
|
static double IVectorOperations<Int2>.Dot(IEnumerable<Int2> vals) => Dot(vals);
|
||||||
|
#endif
|
||||||
public static Int2 Lerp(Int2 a, Int2 b, double t, bool clamp = true) =>
|
public static Int2 Lerp(Int2 a, Int2 b, double t, bool clamp = true) =>
|
||||||
new Int2(MathE.Lerp(a.x, b.x, t, clamp),
|
new Int2(MathE.Lerp(a.x, b.x, t, clamp),
|
||||||
MathE.Lerp(a.y, b.y, t, clamp));
|
MathE.Lerp(a.y, b.y, t, clamp));
|
||||||
@ -203,6 +207,8 @@ namespace Nerd_STF.Mathematics
|
|||||||
y = this.y;
|
y = this.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Modify(Action<Int2> action) => action(this);
|
||||||
|
|
||||||
public bool Equals(Int2 other) => x == other.x && y == other.y;
|
public bool Equals(Int2 other) => x == other.x && y == other.y;
|
||||||
#if CS8_OR_GREATER
|
#if CS8_OR_GREATER
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Nerd_STF.Exceptions;
|
using Nerd_STF.Abstract;
|
||||||
using Nerd_STF.Mathematics.Abstract;
|
using Nerd_STF.Exceptions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -129,13 +129,13 @@ namespace Nerd_STF.Mathematics
|
|||||||
MathE.Clamp(ref value.y, min.y, max.y);
|
MathE.Clamp(ref value.y, min.y, max.y);
|
||||||
MathE.Clamp(ref value.z, min.z, max.z);
|
MathE.Clamp(ref value.z, min.z, max.z);
|
||||||
}
|
}
|
||||||
public static Int3 ClampMagnitude(Int3 value, int minMag, int maxMag)
|
public static Int3 ClampMagnitude(Int3 value, double minMag, double maxMag)
|
||||||
{
|
{
|
||||||
Int3 copy = value;
|
Int3 copy = value;
|
||||||
ClampMagnitude(ref copy, minMag, maxMag);
|
ClampMagnitude(ref copy, minMag, maxMag);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
public static void ClampMagnitude(ref Int3 value, int minMag, int maxMag)
|
public static void ClampMagnitude(ref Int3 value, double minMag, double maxMag)
|
||||||
{
|
{
|
||||||
if (minMag > maxMag) throw new ClampOrderMismatchException(nameof(minMag), nameof(maxMag));
|
if (minMag > maxMag) throw new ClampOrderMismatchException(nameof(minMag), nameof(maxMag));
|
||||||
double mag = value.Magnitude;
|
double mag = value.Magnitude;
|
||||||
@ -143,16 +143,16 @@ namespace Nerd_STF.Mathematics
|
|||||||
if (mag < minMag)
|
if (mag < minMag)
|
||||||
{
|
{
|
||||||
double factor = minMag / mag;
|
double factor = minMag / mag;
|
||||||
value.x = (int)(value.x * factor);
|
value.x = MathE.Ceiling(value.x * factor);
|
||||||
value.y = (int)(value.y * factor);
|
value.y = MathE.Ceiling(value.y * factor);
|
||||||
value.z = (int)(value.z * factor);
|
value.z = MathE.Ceiling(value.z * factor);
|
||||||
}
|
}
|
||||||
else if (mag > maxMag)
|
else if (mag > maxMag)
|
||||||
{
|
{
|
||||||
double factor = maxMag / mag;
|
double factor = maxMag / mag;
|
||||||
value.x = (int)(value.x * factor);
|
value.x = MathE.Floor(value.x * factor);
|
||||||
value.y = (int)(value.y * factor);
|
value.y = MathE.Floor(value.y * factor);
|
||||||
value.z = (int)(value.z * factor);
|
value.z = MathE.Floor(value.z * factor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static Int3 Cross(Int3 a, Int3 b) =>
|
public static Int3 Cross(Int3 a, Int3 b) =>
|
||||||
@ -171,6 +171,10 @@ namespace Nerd_STF.Mathematics
|
|||||||
}
|
}
|
||||||
return x + y + z;
|
return x + y + z;
|
||||||
}
|
}
|
||||||
|
#if CS11_OR_GREATER
|
||||||
|
static double IVectorOperations<Int3>.Dot(Int3 a, Int3 b) => Dot(a, b);
|
||||||
|
static double IVectorOperations<Int3>.Dot(IEnumerable<Int3> vals) => Dot(vals);
|
||||||
|
#endif
|
||||||
public static Int3 Lerp(Int3 a, Int3 b, double t, bool clamp = true) =>
|
public static Int3 Lerp(Int3 a, Int3 b, double t, bool clamp = true) =>
|
||||||
new Int3(MathE.Lerp(a.x, b.x, t, clamp),
|
new Int3(MathE.Lerp(a.x, b.x, t, clamp),
|
||||||
MathE.Lerp(a.y, b.y, t, clamp),
|
MathE.Lerp(a.y, b.y, t, clamp),
|
||||||
@ -223,6 +227,8 @@ namespace Nerd_STF.Mathematics
|
|||||||
z = this.z;
|
z = this.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Modify(Action<Int3> action) => action(this);
|
||||||
|
|
||||||
public bool Equals(Int3 other) => x == other.x && y == other.y && z == other.z;
|
public bool Equals(Int3 other) => x == other.x && y == other.y && z == other.z;
|
||||||
#if CS8_OR_GREATER
|
#if CS8_OR_GREATER
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
using System;
|
using Nerd_STF.Abstract;
|
||||||
|
using Nerd_STF.Exceptions;
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Nerd_STF.Exceptions;
|
|
||||||
using Nerd_STF.Mathematics.Abstract;
|
|
||||||
|
|
||||||
namespace Nerd_STF.Mathematics
|
namespace Nerd_STF.Mathematics
|
||||||
{
|
{
|
||||||
@ -152,18 +152,18 @@ namespace Nerd_STF.Mathematics
|
|||||||
if (mag < minMag)
|
if (mag < minMag)
|
||||||
{
|
{
|
||||||
double factor = minMag / mag;
|
double factor = minMag / mag;
|
||||||
value.w = (int)(value.w * factor);
|
value.w = MathE.Ceiling(value.w * factor);
|
||||||
value.x = (int)(value.x * factor);
|
value.x = MathE.Ceiling(value.x * factor);
|
||||||
value.y = (int)(value.y * factor);
|
value.y = MathE.Ceiling(value.y * factor);
|
||||||
value.z = (int)(value.z * factor);
|
value.z = MathE.Ceiling(value.z * factor);
|
||||||
}
|
}
|
||||||
else if (mag > maxMag)
|
else if (mag > maxMag)
|
||||||
{
|
{
|
||||||
double factor = maxMag / mag;
|
double factor = maxMag / mag;
|
||||||
value.w = (int)(value.w * factor);
|
value.w = MathE.Floor(value.w * factor);
|
||||||
value.x = (int)(value.x * factor);
|
value.x = MathE.Floor(value.x * factor);
|
||||||
value.y = (int)(value.y * factor);
|
value.y = MathE.Floor(value.y * factor);
|
||||||
value.z = (int)(value.z * factor);
|
value.z = MathE.Floor(value.z * factor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static int Dot(Int4 a, Int4 b) => a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z;
|
public static int Dot(Int4 a, Int4 b) => a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z;
|
||||||
@ -179,6 +179,10 @@ namespace Nerd_STF.Mathematics
|
|||||||
}
|
}
|
||||||
return w + x + y + z;
|
return w + x + y + z;
|
||||||
}
|
}
|
||||||
|
#if CS11_OR_GREATER
|
||||||
|
static double IVectorOperations<Int4>.Dot(Int4 a, Int4 b) => Dot(a, b);
|
||||||
|
static double IVectorOperations<Int4>.Dot(IEnumerable<Int4> vals) => Dot(vals);
|
||||||
|
#endif
|
||||||
public static Int4 Lerp(Int4 a, Int4 b, double t, bool clamp = true) =>
|
public static Int4 Lerp(Int4 a, Int4 b, double t, bool clamp = true) =>
|
||||||
new Int4(MathE.Lerp(a.w, b.w, t, clamp),
|
new Int4(MathE.Lerp(a.w, b.w, t, clamp),
|
||||||
MathE.Lerp(a.x, b.x, t, clamp),
|
MathE.Lerp(a.x, b.x, t, clamp),
|
||||||
@ -235,6 +239,8 @@ namespace Nerd_STF.Mathematics
|
|||||||
z = this.z;
|
z = this.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Modify(Action<Int4> action) => action(this);
|
||||||
|
|
||||||
public bool Equals(Int4 other) => w == other.w && x == other.x && y == other.y && z == other.z;
|
public bool Equals(Int4 other) => w == other.w && x == other.x && y == other.y && z == other.z;
|
||||||
#if CS8_OR_GREATER
|
#if CS8_OR_GREATER
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
|
|||||||
@ -435,7 +435,7 @@ namespace Nerd_STF.Mathematics
|
|||||||
}
|
}
|
||||||
else if (val > best) best = val;
|
else if (val > best) best = val;
|
||||||
}
|
}
|
||||||
return any ? best : 0;
|
return best;
|
||||||
}
|
}
|
||||||
public static double Max(IEnumerable<double> values)
|
public static double Max(IEnumerable<double> values)
|
||||||
{
|
{
|
||||||
@ -488,7 +488,7 @@ namespace Nerd_STF.Mathematics
|
|||||||
}
|
}
|
||||||
else if (val < best) best = val;
|
else if (val < best) best = val;
|
||||||
}
|
}
|
||||||
return any ? best : 0;
|
return best;
|
||||||
}
|
}
|
||||||
public static double Min(IEnumerable<double> values)
|
public static double Min(IEnumerable<double> values)
|
||||||
{
|
{
|
||||||
|
|||||||
70
Nerd_STF/Mathematics/Numbers/Fraction.cs
Normal file
70
Nerd_STF/Mathematics/Numbers/Fraction.cs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Nerd_STF.Mathematics.Numbers
|
||||||
|
{
|
||||||
|
public struct Fraction
|
||||||
|
{
|
||||||
|
public static Fraction One => new Fraction(1, 1);
|
||||||
|
public static Fraction Zero => new Fraction(0, 1);
|
||||||
|
|
||||||
|
public int numerator;
|
||||||
|
public int denominator;
|
||||||
|
|
||||||
|
public Fraction(int numerator, int denominator)
|
||||||
|
{
|
||||||
|
this.numerator = numerator;
|
||||||
|
this.denominator = denominator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Fraction Approximate(double number, int iterations = 32)
|
||||||
|
{
|
||||||
|
// Forget what this algorithm is called. When I remember, I'll put its
|
||||||
|
// Wikipedia page here.
|
||||||
|
|
||||||
|
if (number == 0) return Zero;
|
||||||
|
else if (number == 1) return One;
|
||||||
|
else if (number < 0)
|
||||||
|
{
|
||||||
|
Fraction result = Approximate(-number, iterations);
|
||||||
|
result.numerator = -result.numerator;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (number > 1)
|
||||||
|
{
|
||||||
|
int whole = (int)number;
|
||||||
|
Fraction result = Approximate(number % 1, iterations);
|
||||||
|
result.numerator += whole * result.denominator;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int minNum = 0, maxNum = 1, newNum = minNum + maxNum,
|
||||||
|
minDen = 1, maxDen = 1, newDen = minDen + maxDen;
|
||||||
|
double newVal = (double)newNum / newDen;
|
||||||
|
for (int i = 0; i < iterations; i++)
|
||||||
|
{
|
||||||
|
if (number == newVal) break;
|
||||||
|
else if (number > newVal)
|
||||||
|
{
|
||||||
|
minNum = newNum;
|
||||||
|
minDen = newDen;
|
||||||
|
}
|
||||||
|
else // if (number < newVal)
|
||||||
|
{
|
||||||
|
maxNum = newNum;
|
||||||
|
maxDen = newDen;
|
||||||
|
}
|
||||||
|
newNum = minNum + maxNum;
|
||||||
|
newDen = minDen + maxDen;
|
||||||
|
newVal = (double)newNum / newDen;
|
||||||
|
}
|
||||||
|
return new Fraction(newNum, newDen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double GetValue() => (double)numerator / denominator;
|
||||||
|
|
||||||
|
public override string ToString() => $"{numerator} / {denominator}";
|
||||||
|
|
||||||
|
public static implicit operator double(Fraction frac) => frac.GetValue();
|
||||||
|
public static explicit operator Fraction(double num) => Approximate(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,7 +7,7 @@
|
|||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
<Title>Nerd_STF</Title>
|
<Title>Nerd_STF</Title>
|
||||||
<Version>3.0.0-beta1</Version>
|
<Version>3.0.0-beta2</Version>
|
||||||
<Authors>That_One_Nerd</Authors>
|
<Authors>That_One_Nerd</Authors>
|
||||||
<Description>A general-purpose mathematics library for C#.</Description>
|
<Description>A general-purpose mathematics library for C#.</Description>
|
||||||
<PackageProjectUrl>https://github.com/That-One-Nerd/Nerd_STF</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/That-One-Nerd/Nerd_STF</PackageProjectUrl>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user