Skip to content

ILinearQuantity, ILogarithmicQuantity and IAffineQuantity interfaces #1461

Open
@lipchev

Description

@lipchev

Following my comments on the subject in #1200 here is the proposed modification to the IQuantity interfaces:

  1. ILinearQuantity - in v6 Wishlist #1200 I used the name IVectorQuantity but after some reflection I decided that the word Linear is a better fit (in fact, if we look at the conversion expressions- they are all of the form ax, without an offset)
/// <summary>
///     Represents a quantity that has both magnitude and direction, supporting various arithmetic operations and
///     comparisons.
/// </summary>
/// <remarks>
///     This interface defines standard linear arithmetic operations such as addition, subtraction, multiplication, and
///     division.
///     These types of quantities naturally support comparison operations with either absolute or relative tolerance, which
///     is useful for determining equality within a certain margin of error.
///     <para>
///         For more information, see the Wikipedia page on
///         <a href="https://en.wikipedia.org/wiki/Dimensional_analysis#Geometry:_position_vs._displacement">
///             Dimensional
///             Analysis
///         </a>
///         .
///     </para>
/// </remarks>
/// <typeparam name="TSelf">The type that implements this interface.</typeparam>
public interface ILinearQuantity<TSelf> : IQuantityInstance<TSelf>
#if NET7_0_OR_GREATER
    , IAdditiveIdentity<TSelf, TSelf>
#endif
    where TSelf : ILinearQuantity<TSelf>
{
#if NET7_0_OR_GREATER
    /// <summary>
    ///     The zero value of this quantity.
    /// </summary>
    static abstract TSelf Zero { get; }

    static TSelf IAdditiveIdentity<TSelf, TSelf>.AdditiveIdentity
    {
        get => TSelf.Zero;
    }

#endif

#if EXTENDED_EQUALS_INTERFACE
        /// <summary>
        ///     <para>
        ///     Compare equality to <paramref name="other"/> given a <paramref name="tolerance"/> for the maximum allowed +/- difference.
        ///     </para>
        ///     <example>
        ///     In this example, the two quantities will be equal if the value of b is within 0.01 of a (0.01m or 1cm).
        ///     <code>
        ///     var a = Length.FromMeters(2.0);
        ///     var b = Length.FromMeters(2.1);
        ///     var tolerance = Length.FromCentimeters(10);
        ///     a.Equals(b, tolerance); // true, 2m equals 2.1m +/- 0.1m
        ///     </code>
        ///     </example>
        ///     <para>
        ///     It is generally advised against specifying "zero" tolerance, due to the nature of floating-point operations.
        ///     </para>
        /// </summary>
        /// <param name="other">The other quantity to compare to.</param>
        /// <param name="tolerance">The absolute tolerance value. Must be greater than or equal to zero.</param>
        /// <returns>True if the absolute difference between the two values is not greater than the specified tolerance.</returns>
        bool Equals(TSelf? other, TSelf tolerance);
#endif
}

/// <summary>
///     An <see cref="IQuantity{TSelf, TUnitType}" /> that (in .NET 7+) implements generic math interfaces for arithmetic
///     operations.
/// </summary>
/// <typeparam name="TSelf">The type itself, for the CRT pattern.</typeparam>
/// <typeparam name="TUnitType">The underlying unit enum type.</typeparam>
public interface IArithmeticQuantity<TSelf, TUnitType> : IQuantity<TSelf, TUnitType>, ILinearQuantity<TSelf>
#if NET7_0_OR_GREATER
    , IAdditionOperators<TSelf, TSelf, TSelf>
    , ISubtractionOperators<TSelf, TSelf, TSelf>
    , IMultiplyOperators<TSelf, QuantityValue, TSelf>
    , IDivisionOperators<TSelf, QuantityValue, TSelf>
    , IUnaryNegationOperators<TSelf, TSelf>
#endif
    where TSelf : IArithmeticQuantity<TSelf, TUnitType>
    where TUnitType : struct, Enum
{
}
  1. ILogarithmicQuantity - in NET7_OR_GREATER I introduce the static LogarithmicScalingFactor, however in netstandard this needs to either be an instance member ( 😞 ) or alternatively I could introduce an extra interface for it's QuantityInfo, overriding the property to something of the sort new ILogarithmicQuantityInfo<TQuantity> QuantityInfo { get; }
/// <summary>
///     Represents a logarithmic quantity that supports arithmetic operations and implements generic math interfaces 
///     (in .NET 7+). This interface is designed for quantities that are logarithmic in nature, such as decibels.
/// </summary>
/// <typeparam name="TSelf">The type itself, for the CRT pattern.</typeparam>
/// <remarks>
///     Logarithmic quantities are different from linear quantities in that they represent values on a logarithmic scale.
///     This interface extends <see cref="IQuantity{TSelf, TUnitType}" /> and provides additional functionality specific 
///     to logarithmic quantities, including arithmetic operations and a logarithmic scaling factor.
///     The logarithmic scale assumed here is base-10.
/// </remarks>
public interface ILogarithmicQuantity<TSelf> : IQuantityInstance<TSelf>
#if NET7_0_OR_GREATER
    , IMultiplicativeIdentity<TSelf, TSelf>
#endif
    where TSelf : ILogarithmicQuantity<TSelf>
{
#if NET7_0_OR_GREATER
    /// <summary>
    ///     Gets the logarithmic scaling factor used to convert between linear and logarithmic units.
    ///     This factor is typically 10, but there are exceptions such as the PowerRatio, which uses 20.
    /// </summary>
    /// <value>
    ///     The logarithmic scaling factor.
    /// </value>
    static abstract QuantityValue LogarithmicScalingFactor { get; }
    
    /// <summary>
    ///     The zero value of this quantity.
    /// </summary>
    static abstract TSelf Zero { get; }
    
    static TSelf IMultiplicativeIdentity<TSelf, TSelf>.MultiplicativeIdentity => TSelf.Zero;
#else
    /// <summary>
    ///     Gets the logarithmic scaling factor used to convert between linear and logarithmic units.
    ///     This factor is typically 10, but there are exceptions such as the PowerRatio, which uses 20.
    /// </summary>
    /// <value>
    ///     The logarithmic scaling factor.
    /// </value>
    QuantityValue LogarithmicScalingFactor { get; }
#endif
}

/// <inheritdoc cref="ILogarithmicQuantity{TSelf}"/>
/// <typeparam name="TSelf">The type itself, for the CRT pattern.</typeparam>
/// <typeparam name="TUnitType">The underlying unit enum type.</typeparam>
public interface ILogarithmicQuantity<TSelf, TUnitType> : IQuantity<TSelf, TUnitType>, ILogarithmicQuantity<TSelf>
#if NET7_0_OR_GREATER
    , IAdditionOperators<TSelf, TSelf, TSelf>
    , ISubtractionOperators<TSelf, TSelf, TSelf>
    , IMultiplyOperators<TSelf, QuantityValue, TSelf>
    , IDivisionOperators<TSelf, QuantityValue, TSelf>
    , IUnaryNegationOperators<TSelf, TSelf>
#endif
    where TSelf : ILogarithmicQuantity<TSelf, TUnitType>
    where TUnitType : struct, Enum
{
}
  1. IAffineQuantity: there is only one of these- the Temperature with it's TOffset being the TemperatureDelta (also note that the conversion functions here are of the form ax + b)
/// <summary>
///     An <see cref="IQuantity{TSelf}"/> that (in .NET 7+) implements generic math interfaces for arithmetic operations.
/// </summary>
/// <typeparam name="TSelf">The type itself, for the CRT pattern.</typeparam>
/// <typeparam name="TOffset"></typeparam>
public interface IAffineQuantity<TSelf, TOffset> : IQuantityInstance<TSelf>
#if NET7_0_OR_GREATER
    , IAdditiveIdentity<TSelf, TOffset>
    where TOffset : IAdditiveIdentity<TOffset, TOffset>
#endif
    where TSelf : IAffineQuantity<TSelf, TOffset>
{
#if NET7_0_OR_GREATER
    /// <summary>
    ///     The zero value of this quantity.
    /// </summary>
    static abstract TSelf Zero { get; }

    static TOffset IAdditiveIdentity<TSelf, TOffset>.AdditiveIdentity => TOffset.AdditiveIdentity;
#endif
        
#if EXTENDED_EQUALS_INTERFACE
    /// <summary>
    ///     <para>
    ///     Compare equality to <paramref name="other"/> given a <paramref name="tolerance"/> for the maximum allowed +/- difference.
    ///     </para>
    ///     <example>
    ///     In this example, the two quantities will be equal if the value of b is within 0.01 of a (0.01m or 1cm).
    ///     <code>
    ///     var a = Length.FromMeters(2.0);
    ///     var b = Length.FromMeters(2.1);
    ///     var tolerance = Length.FromCentimeters(10);
    ///     a.Equals(b, tolerance); // true, 2m equals 2.1m +/- 0.1m
    ///     </code>
    ///     </example>
    ///     <para>
    ///     It is generally advised against specifying "zero" tolerance, due to the nature of floating-point operations.
    ///     </para>
    /// </summary>
    /// <param name="other">The other quantity to compare to.</param>
    /// <param name="tolerance">The absolute tolerance value. Must be greater than or equal to zero.</param>
    /// <returns>True if the absolute difference between the two values is not greater than the specified tolerance.</returns>
    bool Equals(TSelf? other, TOffset tolerance);
#endif
}

/// <summary>
///     An <see cref="IQuantity{TSelf, TUnitType}"/> that (in .NET 7+) implements generic math interfaces for arithmetic operations.
/// </summary>
/// <typeparam name="TSelf">The type itself, for the CRT pattern.</typeparam>
/// <typeparam name="TUnitType">The underlying unit enum type.</typeparam>
/// <typeparam name="TOffset"></typeparam>
public interface IAffineQuantity<TSelf, TUnitType, TOffset> : IQuantity<TSelf, TUnitType>, IAffineQuantity<TSelf, TOffset>
#if NET7_0_OR_GREATER
    , IAdditionOperators<TSelf, TOffset, TSelf>
    , ISubtractionOperators<TSelf, TSelf, TOffset>
    where TOffset : IAdditiveIdentity<TOffset, TOffset>
#endif
    where TSelf : IAffineQuantity<TSelf, TUnitType, TOffset>
    where TUnitType : struct, Enum
{
}

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions