Skip to content

Commit

Permalink
Refactor IAngle and IAngleUnits
Browse files Browse the repository at this point in the history
  • Loading branch information
aalmada committed Oct 29, 2023
1 parent e3db11d commit f04f507
Show file tree
Hide file tree
Showing 10 changed files with 424 additions and 244 deletions.
42 changes: 21 additions & 21 deletions src/NetFabric.Numerics.Angle/Angle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static partial class Angle
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Angle<TAngleUnits, T> Clamp<TAngleUnits, T>(Angle<TAngleUnits, T> vector, Angle<TAngleUnits, T> min, Angle<TAngleUnits, T> max)
where TAngleUnits : struct, IAngleUnits<TAngleUnits>
where TAngleUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> new(T.Clamp(vector.Value, min.Value, max.Value));

Expand All @@ -61,7 +61,7 @@ public static Angle<TAngleUnits, T> Clamp<TAngleUnits, T>(Angle<TAngleUnits, T>
/// <returns>The reduced angle of <paramref name="angle"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AngleReduced<TUnits, T> Reduce<TUnits, T>(Angle<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
{
var reduced = angle.Value % Angle<TUnits, T>.Full.Value;
Expand All @@ -87,7 +87,7 @@ public static AngleReduced<TUnits, T> Reduce<TUnits, T>(Angle<TUnits, T> angle)
/// <returns>The reference angle of <paramref name="angle"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AngleReduced<TUnits, T> GetReference<TUnits, T>(AngleReduced<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
{
var quadrant = GetQuadrant(angle);
Expand Down Expand Up @@ -133,7 +133,7 @@ public static AngleReduced<TUnits, T> GetReference<TUnits, T>(AngleReduced<TUnit
/// <returns>The quadrant of <paramref name="angle"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Quadrant GetQuadrant<TUnits, T>(AngleReduced<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
{
var value = angle.Value;
Expand Down Expand Up @@ -172,7 +172,7 @@ public static Quadrant GetQuadrant<TUnits, T>(AngleReduced<TUnits, T> angle)
/// </para>
/// </remarks>
public static Angle<TUnits, T> Abs<TUnits, T>(Angle<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> T.Sign(angle.Value) >= 0
? angle
Expand All @@ -187,7 +187,7 @@ public static Angle<TUnits, T> Abs<TUnits, T>(Angle<TUnits, T> angle)
/// <returns>A number that indicates the sign of value, -1 if value is less than zero, 0 if value equal to zero, 1 if value is grater than zero.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Sign<TUnits, T>(Angle<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> T.Sign(angle.Value);

Expand Down Expand Up @@ -219,7 +219,7 @@ public static int Sign<TUnits, T>(Angle<TUnits, T> angle)
/// <returns>The result of the linear interpolation.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Angle<TUnits, T> Lerp<TUnits, T>(Angle<TUnits, T> a1, Angle<TUnits, T> a2, T t)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPointIeee754<T>, IMinMaxValue<T>
#if NET8_0_OR_GREATER
=> new(T.Lerp(a1.Value, a2.Value, t));
Expand All @@ -237,7 +237,7 @@ public static Angle<TUnits, T> Lerp<TUnits, T>(Angle<TUnits, T> a1, Angle<TUnits
/// <returns>The smallest of the two angles.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Angle<TUnits, T> Min<TUnits, T>(Angle<TUnits, T> left, Angle<TUnits, T> right)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> new(T.Min(left.Value, right.Value));

Expand All @@ -251,7 +251,7 @@ public static Angle<TUnits, T> Min<TUnits, T>(Angle<TUnits, T> left, Angle<TUnit
/// <returns>The largest of the two angles.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Angle<TUnits, T> Max<TUnits, T>(Angle<TUnits, T> left, Angle<TUnits, T> right)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> new(T.Max(left.Value, right.Value));

Expand All @@ -266,7 +266,7 @@ public static Angle<TUnits, T> Max<TUnits, T>(Angle<TUnits, T> left, Angle<TUnit
/// <returns>true if the reduction of the absolute angle is zero; otherwise false.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsZero<TUnits, T>(Angle<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> angle == Angle<TUnits, T>.Zero;

Expand All @@ -281,7 +281,7 @@ public static bool IsZero<TUnits, T>(Angle<TUnits, T> angle)
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsNaN<TUnits, T>(Angle<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> T.IsNaN(angle.Value);

Expand All @@ -296,7 +296,7 @@ public static bool IsNaN<TUnits, T>(Angle<TUnits, T> angle)
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInfinity<TUnits, T>(Angle<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> T.IsInfinity(angle.Value);

Expand All @@ -311,7 +311,7 @@ public static bool IsInfinity<TUnits, T>(Angle<TUnits, T> angle)
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsFinite<TUnits, T>(Angle<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> T.IsFinite(angle.Value);

Expand All @@ -330,7 +330,7 @@ public static bool IsFinite<TUnits, T>(Angle<TUnits, T> angle)
/// otherwise false.
/// </returns>
public static bool IsAcute<TUnits, T>(AngleReduced<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> angle.Value > Angle<TUnits, T>.Zero.Value && angle.Value < Angle<TUnits, T>.Right.Value;

Expand All @@ -347,7 +347,7 @@ public static bool IsAcute<TUnits, T>(AngleReduced<TUnits, T> angle)
/// </remarks>
/// <returns>true if the reduction of the absolute angle is 90 degrees; otherwise false.</returns>
public static bool IsRight<TUnits, T>(AngleReduced<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> angle.Value == Angle<TUnits, T>.Right.Value;

Expand All @@ -367,7 +367,7 @@ public static bool IsRight<TUnits, T>(AngleReduced<TUnits, T> angle)
/// 180 degrees; otherwise false.
/// </returns>
public static bool IsObtuse<TUnits, T>(AngleReduced<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> angle.Value > Angle<TUnits, T>.Right.Value && angle.Value < Angle<TUnits, T>.Straight.Value;

Expand All @@ -384,7 +384,7 @@ public static bool IsObtuse<TUnits, T>(AngleReduced<TUnits, T> angle)
/// </remarks>
/// <returns>true if the reduction of the absolute angle is 180 degrees; otherwise false.</returns>
public static bool IsStraight<TUnits, T>(AngleReduced<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> angle.Value == Angle<TUnits, T>.Straight.Value;

Expand All @@ -404,7 +404,7 @@ public static bool IsStraight<TUnits, T>(AngleReduced<TUnits, T> angle)
/// 360 degrees; otherwise false.
/// </returns>
public static bool IsReflex<TUnits, T>(AngleReduced<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> angle.Value > Angle<TUnits, T>.Straight.Value;

Expand All @@ -421,7 +421,7 @@ public static bool IsReflex<TUnits, T>(AngleReduced<TUnits, T> angle)
/// </remarks>
/// <returns>true if the angle is not right or a multiple of a right angle; otherwise false.</returns>
public static bool IsOblique<TUnits, T>(AngleReduced<TUnits, T> angle)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> angle.Value % Angle<TUnits, T>.Right.Value != T.Zero;

Expand All @@ -437,7 +437,7 @@ public static bool IsOblique<TUnits, T>(AngleReduced<TUnits, T> angle)
/// a right angle value to determine if they are complementary.
/// </remarks>
public static bool AreComplementary<TUnits, T>(AngleReduced<TUnits, T> first, AngleReduced<TUnits, T> second)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> first.Value + second.Value == Angle<TUnits, T>.Right.Value;

Expand All @@ -453,7 +453,7 @@ public static bool AreComplementary<TUnits, T>(AngleReduced<TUnits, T> first, An
/// a straight angle value to determine if they are supplementary.
/// </remarks>
public static bool AreSupplementary<TUnits, T>(AngleReduced<TUnits, T> first, AngleReduced<TUnits, T> second)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> first.Value + second.Value == Angle<TUnits, T>.Straight.Value;

Expand Down
8 changes: 4 additions & 4 deletions src/NetFabric.Numerics.Angle/AngleAverage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static partial class Angle
/// The resulting angle represents the average value of all the angles.
/// </remarks>
public static Angle<TUnits, T>? Average<TUnits, T>(this IEnumerable<Angle<TUnits, T>> source)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
{
var sum = T.Zero;
Expand Down Expand Up @@ -42,7 +42,7 @@ public static partial class Angle
/// The resulting angle represents the average value of all the angles.
/// </remarks>
public static Angle<TUnits, T>? Average<TUnits, T>(this Angle<TUnits, T>[] source)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> source.AsSpan().Average();

Expand All @@ -57,7 +57,7 @@ public static partial class Angle
/// The resulting angle represents the average value of all the angles.
/// </remarks>
public static Angle<TUnits, T>? Average<TUnits, T>(this Span<Angle<TUnits, T>> source)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> ((ReadOnlySpan<Angle<TUnits, T>>)source).Average();

Expand All @@ -72,7 +72,7 @@ public static partial class Angle
/// The resulting angle represents the average value of all the angles.
/// </remarks>
public static Angle<TUnits, T>? Average<TUnits, T>(this ReadOnlySpan<Angle<TUnits, T>> source)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> source.Length == 0
? null
Expand Down
76 changes: 65 additions & 11 deletions src/NetFabric.Numerics.Angle/AngleReduced`2.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Windows.Markup;

namespace NetFabric.Numerics;

Expand Down Expand Up @@ -37,16 +35,14 @@ namespace NetFabric.Numerics;
[DebuggerTypeProxy(typeof(AngleReducedDebugView<,>))]
[SkipLocalsInit]
public readonly record struct AngleReduced<TUnits, T>(T Value)
: IAngle<AngleReduced<TUnits, T>, T>,
IUnaryPlusOperators<AngleReduced<TUnits, T>, AngleReduced<TUnits, T>>,
IUnaryNegationOperators<AngleReduced<TUnits, T>, Angle<TUnits, T>>,
IAdditionOperators<AngleReduced<TUnits, T>, Angle<TUnits, T>, Angle<TUnits, T>>,
ISubtractionOperators<AngleReduced<TUnits, T>, Angle<TUnits, T>, Angle<TUnits, T>>,
IDivisionOperators<AngleReduced<TUnits, T>, T, Angle<TUnits, T>>,
IModulusOperators<AngleReduced<TUnits, T>, T, Angle<TUnits, T>>
where TUnits : IAngleUnits<TUnits>
: IAngle<AngleReduced<TUnits, T>, TUnits, T, Angle<TUnits, T>>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
{

object IAngle.Value
=> Value;

/// <summary>
/// Creates an instance of the current type from a value,
/// throwing an overflow exception for any values that fall outside the representable range of the current type.
Expand Down Expand Up @@ -346,7 +342,7 @@ readonly int IComparable.CompareTo(object? obj)
/// </summary>
/// <returns>A string that represents the current angle.</returns>
/// <remarks>
/// The string representation of the angle includes the numerical value followed by the unit of measurement (e.g., º, rad, grad, or rev).
/// The string representation of the angle includes the numerical value followed by the unit of measurement (e.g., , rad, grad, or rev).
/// </remarks>
public override readonly string? ToString()
=> Value.ToString();
Expand All @@ -373,4 +369,62 @@ public readonly bool TryFormat(Span<char> destination, out int charsWritten, Rea
/// <returns></returns>
public readonly string ToString(string? format, IFormatProvider? formatProvider)
=> Value.ToString(format, formatProvider);

/// <summary>
/// Parses a string into an angle.
/// </summary>
/// <param name="s">The string to parse.</param>
/// <param name="provider">An object that provides culture-specific formatting information about s.</param>
/// <returns>The result of parsing <paramref name="s"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="s"/> is <see langword="null"/>.</exception>
/// <exception cref="FormatException"><paramref name="s"/> is not in the correct format.</exception>
/// <exception cref="OverflowException"><paramref name="s"/> represents a number less than <see cref="Angle{TUnits,T}.MinValue"/> or greater than <see cref="Angle{TUnits,T}.MaxValue"/>.</exception>
public static AngleReduced<TUnits, T> Parse(string s, IFormatProvider? provider)
=> new(T.Parse(s, provider));

/// <summary>
/// Tries to parse a string into an angle.
/// </summary>
/// <param name="s">The string to parse.</param>
/// <param name="provider">An object that provides culture-specific formatting information about <paramref name="s"/>.</param>
/// <param name="result">When this method returns, contains the result of successfully parsing <paramref name="s"/> or an undefined value on failure.</param>
/// <returns>true if <paramref name="s"/> was successfully parsed; otherwise, false.</returns>
public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out AngleReduced<TUnits, T> result)
{
if (T.TryParse(s, provider, out var value))
{
result = new(value);
return true;
}

result = default;
return false;
}

/// <summary>
/// Parses a span of characters into an angle.
/// </summary>
/// <param name="s">The span of characters to parse.</param>
/// <param name="provider">An object that provides culture-specific formatting information about <paramref name="s"/>.</param>
/// <returns>The result of parsing <paramref name="s"/>.</returns>
public static AngleReduced<TUnits, T> Parse(ReadOnlySpan<char> s, IFormatProvider? provider)
=> new(T.Parse(s, provider));

/// <summary>
/// Tries to parse a span of characters into an angle.
/// </summary>
/// <param name="s">The span of characters to parse.</param>
/// <param name="provider">An object that provides culture-specific formatting information about <paramref name="s"/>.</param>
/// <param name="result">When this method returns, contains the result of successfully parsing <paramref name="s"/>, or an undefined value on failure.</param>
/// <returns> true if <paramref name="s"/> was successfully parsed; otherwise, false.</returns>
public static bool TryParse(ReadOnlySpan<char> s, IFormatProvider? provider, [MaybeNullWhen(false)] out AngleReduced<TUnits, T> result)
{
if(T.TryParse(s, provider, out var value)) {
result = new(value);
return true;
}

result = default;
return false;
}
}
8 changes: 4 additions & 4 deletions src/NetFabric.Numerics.Angle/AngleSum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static partial class Angle
/// The sum of angles is computed by adding all the angles in the given <paramref name="source"/> collection.
/// </remarks>
public static Angle<TUnits, T> Sum<TUnits, T>(this IEnumerable<Angle<TUnits, T>> source)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
{
if(source.TryGetSpan(out var span))
Expand All @@ -36,7 +36,7 @@ public static Angle<TUnits, T> Sum<TUnits, T>(this IEnumerable<Angle<TUnits, T>>
/// The sum of angles is computed by adding all the angles in the given <paramref name="source"/> collection.
/// </remarks>
public static Angle<TUnits, T> Sum<TUnits, T>(this Angle<TUnits, T>[] source)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> source.AsSpan().Sum();

Expand All @@ -49,7 +49,7 @@ public static Angle<TUnits, T> Sum<TUnits, T>(this Angle<TUnits, T>[] source)
/// The sum of angles is computed by adding all the angles in the given <paramref name="source"/> collection.
/// </remarks>
public static Angle<TUnits, T> Sum<TUnits, T>(this Span<Angle<TUnits, T>> source)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> ((ReadOnlySpan<Angle<TUnits, T>>)source).Sum();

Expand All @@ -62,7 +62,7 @@ public static Angle<TUnits, T> Sum<TUnits, T>(this Span<Angle<TUnits, T>> source
/// The sum of angles is computed by adding all the angles in the given <paramref name="source"/> collection.
/// </remarks>
public static Angle<TUnits, T> Sum<TUnits, T>(this ReadOnlySpan<Angle<TUnits, T>> source)
where TUnits : IAngleUnits<TUnits>
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
{
var sum = T.Zero;
Expand Down
Loading

0 comments on commit f04f507

Please sign in to comment.