This commit is contained in:
@@ -1,17 +1,9 @@
|
||||
namespace Just.PreciseMath;
|
||||
|
||||
public readonly partial struct DoubleDouble :
|
||||
IAdditiveIdentity<DoubleDouble, DoubleDouble>,
|
||||
IMultiplicativeIdentity<DoubleDouble, DoubleDouble>,
|
||||
IUnaryPlusOperators<DoubleDouble, DoubleDouble>,
|
||||
IUnaryNegationOperators<DoubleDouble, DoubleDouble>,
|
||||
IAdditionOperators<DoubleDouble, DoubleDouble, DoubleDouble>,
|
||||
IAdditionOperators<DoubleDouble, double, DoubleDouble>,
|
||||
ISubtractionOperators<DoubleDouble, DoubleDouble, DoubleDouble>,
|
||||
ISubtractionOperators<DoubleDouble, double, DoubleDouble>,
|
||||
IMultiplyOperators<DoubleDouble, DoubleDouble, DoubleDouble>,
|
||||
IMultiplyOperators<DoubleDouble, double, DoubleDouble>,
|
||||
IDivisionOperators<DoubleDouble, DoubleDouble, DoubleDouble>,
|
||||
IDivisionOperators<DoubleDouble, double, DoubleDouble>
|
||||
{
|
||||
/// <summary>Returns the operand unchanged.</summary>
|
||||
|
||||
@@ -1,13 +1,25 @@
|
||||
namespace Just.PreciseMath;
|
||||
|
||||
public readonly partial struct DoubleDouble : IComparable<DoubleDouble>, IComparable,
|
||||
IEquatable<DoubleDouble>,
|
||||
IEqualityOperators<DoubleDouble, DoubleDouble, bool>,
|
||||
IComparisonOperators<DoubleDouble, DoubleDouble, bool>
|
||||
{
|
||||
/// <summary>Returns the normalized components.</summary>
|
||||
public void Decompose(out double high, out double low)
|
||||
/// <summary>
|
||||
/// Tests numerical equality; NaN operands are never equal.
|
||||
/// </summary>
|
||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(DoubleDouble left, DoubleDouble right)
|
||||
{
|
||||
high = _high;
|
||||
low = _low;
|
||||
return left._high == right._high && left._low == right._low;
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests numerical inequality; NaN operands are always unequal.
|
||||
/// </summary>
|
||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(DoubleDouble left, DoubleDouble right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
/// <summary>Orders NaN before other values, and compares finite values using both components.</summary>
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
namespace Just.PreciseMath;
|
||||
|
||||
public readonly partial struct DoubleDouble :
|
||||
IFloatingPointConstants<DoubleDouble>
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an additive identity value.
|
||||
/// </summary>
|
||||
public static DoubleDouble AdditiveIdentity => Zero;
|
||||
/// <summary>
|
||||
/// Represents a multiplicative identity value.
|
||||
/// </summary>
|
||||
public static DoubleDouble MultiplicativeIdentity => One;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a value that is not a number (NaN).
|
||||
/// </summary>
|
||||
public static DoubleDouble NaN => new(double.NaN);
|
||||
|
||||
/// <summary>Gets positive infinity with a positive-zero low component.</summary>
|
||||
public static DoubleDouble PositiveInfinity => new(double.PositiveInfinity);
|
||||
|
||||
/// <summary>Gets negative infinity with a positive-zero low component.</summary>
|
||||
public static DoubleDouble NegativeInfinity => new(double.NegativeInfinity);
|
||||
|
||||
/// <summary>
|
||||
/// Represents a unit value.
|
||||
/// </summary>
|
||||
public static DoubleDouble One => new(1.0, 0);
|
||||
/// <summary>
|
||||
/// Represents a negative unit value.
|
||||
/// </summary>
|
||||
public static DoubleDouble NegativeOne => new(-1.0, 0);
|
||||
/// <summary>
|
||||
/// Represents a zero value.
|
||||
/// </summary>
|
||||
public static DoubleDouble Zero => new();
|
||||
|
||||
/// <summary>Gets negative zero with a positive-zero low component.</summary>
|
||||
/// <remarks>Compares equal to <see cref="Zero"/> while preserving the high component's sign bit.</remarks>
|
||||
public static DoubleDouble NegativeZero => new(-0.0);
|
||||
|
||||
/// <summary>Gets the smallest positive representable value, 2^-1074.</summary>
|
||||
/// <remarks>
|
||||
/// The high component is the minimum positive binary64 subnormal and the low
|
||||
/// component is positive zero. This is not machine epsilon or a relative-error tolerance.
|
||||
/// </remarks>
|
||||
public static DoubleDouble Epsilon => new(double.Epsilon);
|
||||
|
||||
// Mathematical constants store normalized, precomputed binary64 pairs: the
|
||||
// nearest high and then the nearest residual of the high-precision value.
|
||||
// No DD arithmetic, parsing, normalization or heap allocation occurs on access.
|
||||
// Reproduce with the tests' ReferenceData/generate_constants.py.
|
||||
/// <summary>
|
||||
/// Represents the ratio of the circumference of a circle to its diameter, specified by the constant, π.
|
||||
/// </summary>
|
||||
public static DoubleDouble Pi => new(3.141592653589793, 1.2246467991473532e-16);
|
||||
/// <summary>
|
||||
/// Represents the natural logarithmic base, specified by the constant, e.
|
||||
/// </summary>
|
||||
public static DoubleDouble E => new(2.718281828459045, 1.4456468917292502e-16);
|
||||
/// <summary>
|
||||
/// Represents the natural logarithm of value 2.
|
||||
/// </summary>
|
||||
public static DoubleDouble Ln2 => new(0.6931471805599453, 2.3190468138462996e-17);
|
||||
|
||||
/// <summary>Gets τ = 2π, the angle of one full turn in radians.</summary>
|
||||
public static DoubleDouble Tau => new(6.283185307179586, 2.4492935982947064e-16);
|
||||
|
||||
/// <summary>Gets π/2, the angle of 90 degrees in radians.</summary>
|
||||
public static DoubleDouble PiOver2 => new(1.5707963267948966, 6.123233995736766e-17);
|
||||
|
||||
/// <summary>Gets π/3, the angle of 60 degrees in radians.</summary>
|
||||
public static DoubleDouble PiOver3 => new(1.0471975511965979, -1.072081766451091e-16);
|
||||
|
||||
/// <summary>Gets π/4, the angle of 45 degrees in radians.</summary>
|
||||
public static DoubleDouble PiOver4 => new(0.7853981633974483, 3.061616997868383e-17);
|
||||
|
||||
/// <summary>Gets π/6, the angle of 30 degrees in radians.</summary>
|
||||
public static DoubleDouble PiOver6 => new(0.5235987755982989, -5.360408832255455e-17);
|
||||
|
||||
/// <summary>Gets 1/π.</summary>
|
||||
public static DoubleDouble InvPi => new(0.3183098861837907, -1.9678676675182486e-17);
|
||||
|
||||
/// <summary>Gets 1/(2π), the factor for converting radians to turns.</summary>
|
||||
public static DoubleDouble InvTau => new(0.15915494309189535, -9.839338337591243e-18);
|
||||
|
||||
/// <summary>Gets π/180. Multiply an angle in degrees by this value to obtain radians.</summary>
|
||||
public static DoubleDouble DegToRad => new(0.017453292519943295, 2.9486522708701687e-19);
|
||||
|
||||
/// <summary>Gets 180/π. Multiply an angle in radians by this value to obtain degrees.</summary>
|
||||
public static DoubleDouble RadToDeg => new(57.29577951308232, -1.9878495670576283e-15);
|
||||
|
||||
/// <summary>Gets 1/e = exp(-1).</summary>
|
||||
public static DoubleDouble InvE => new(0.36787944117144233, -1.2428753672788363e-17);
|
||||
|
||||
/// <summary>Gets ln(10), the factor for converting base-10 logarithms to natural logarithms.</summary>
|
||||
public static DoubleDouble Ln10 => new(2.302585092994046, -2.1707562233822494e-16);
|
||||
|
||||
/// <summary>Gets log₂(e) = 1/ln(2), the factor for converting natural logarithms to base 2.</summary>
|
||||
public static DoubleDouble Log2E => new(1.4426950408889634, 2.0355273740931033e-17);
|
||||
|
||||
/// <summary>Gets log₁₀(e) = 1/ln(10), the factor for converting natural logarithms to base 10.</summary>
|
||||
public static DoubleDouble Log10E => new(0.4342944819032518, 1.098319650216765e-17);
|
||||
|
||||
/// <summary>Gets log₂(10), the factor for converting base-10 logarithms to base 2.</summary>
|
||||
public static DoubleDouble Log2Of10 => new(3.321928094887362, 1.661617516973592e-16);
|
||||
|
||||
/// <summary>Gets log₁₀(2), the factor for converting base-2 logarithms to base 10.</summary>
|
||||
public static DoubleDouble Log10Of2 => new(0.3010299956639812, -2.8037281277851704e-18);
|
||||
|
||||
/// <summary>Gets √2.</summary>
|
||||
public static DoubleDouble Sqrt2 => new(1.4142135623730951, -9.667293313452913e-17);
|
||||
|
||||
/// <summary>Gets √3.</summary>
|
||||
public static DoubleDouble Sqrt3 => new(1.7320508075688772, 1.0035084221806903e-16);
|
||||
|
||||
/// <summary>Gets √5.</summary>
|
||||
public static DoubleDouble Sqrt5 => new(2.23606797749979, -1.0864230407365012e-16);
|
||||
|
||||
/// <summary>Gets 1/√2, also the sine and cosine of π/4.</summary>
|
||||
public static DoubleDouble InvSqrt2 => new(0.7071067811865476, -4.833646656726457e-17);
|
||||
|
||||
/// <summary>Gets 1/√3, also the tangent of π/6.</summary>
|
||||
public static DoubleDouble InvSqrt3 => new(0.5773502691896257, 3.3450280739356345e-17);
|
||||
|
||||
/// <summary>Gets √π, the Gaussian integral over the real line for exp(-x²).</summary>
|
||||
public static DoubleDouble SqrtPi => new(1.772453850905516, -7.666586499825799e-17);
|
||||
|
||||
/// <summary>Gets 1/√π, a Gaussian normalization factor.</summary>
|
||||
public static DoubleDouble InvSqrtPi => new(0.5641895835477563, 7.66772980658294e-18);
|
||||
|
||||
/// <summary>Gets 2/√π, the normalization factor in the error-function integral.</summary>
|
||||
public static DoubleDouble TwoInvSqrtPi => new(1.1283791670955126, 1.533545961316588e-17);
|
||||
|
||||
/// <summary>Gets √(2π), used in Gaussian integrals and Stirling's approximation.</summary>
|
||||
public static DoubleDouble SqrtTau => new(2.5066282746310007, -1.8328579980459167e-16);
|
||||
|
||||
/// <summary>Gets 1/√(2π), the standard normal probability density's normalization factor.</summary>
|
||||
public static DoubleDouble InvSqrtTau => new(0.3989422804014327, -2.49232720227773e-17);
|
||||
|
||||
/// <summary>Gets the golden ratio φ = (1 + √5)/2.</summary>
|
||||
public static DoubleDouble GoldenRatio => new(1.618033988749895, -5.432115203682506e-17);
|
||||
}
|
||||
@@ -12,13 +12,12 @@ namespace Just.PreciseMath;
|
||||
/// rounded. Equals treats NaNs as equal for collections, while operators do not.
|
||||
/// </remarks>
|
||||
public readonly partial struct DoubleDouble :
|
||||
IEquatable<DoubleDouble>,
|
||||
IEqualityOperators<DoubleDouble, DoubleDouble, bool>,
|
||||
ISignedNumber<DoubleDouble>
|
||||
{
|
||||
internal readonly double _high;
|
||||
internal readonly double _low;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Stores trusted components without normalization or validation.
|
||||
/// </summary>
|
||||
@@ -72,129 +71,6 @@ public readonly partial struct DoubleDouble :
|
||||
{
|
||||
}
|
||||
|
||||
#region Static constants
|
||||
/// <summary>
|
||||
/// Represents an additive identity value.
|
||||
/// </summary>
|
||||
public static DoubleDouble AdditiveIdentity => Zero;
|
||||
/// <summary>
|
||||
/// Represents a multiplicative identity value.
|
||||
/// </summary>
|
||||
public static DoubleDouble MultiplicativeIdentity => One;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a value that is not a number (NaN).
|
||||
/// </summary>
|
||||
public static DoubleDouble NaN => new(double.NaN);
|
||||
/// <summary>
|
||||
/// Represents a unit value.
|
||||
/// </summary>
|
||||
public static DoubleDouble One => new(1.0, 0);
|
||||
/// <summary>
|
||||
/// Represents a negative unit value.
|
||||
/// </summary>
|
||||
public static DoubleDouble NegativeOne => new(-1.0, 0);
|
||||
/// <summary>
|
||||
/// Represents a zero value.
|
||||
/// </summary>
|
||||
public static DoubleDouble Zero => new();
|
||||
|
||||
// Mathematical constants store normalized, precomputed binary64 pairs: the
|
||||
// nearest high and then the nearest residual of the high-precision value.
|
||||
// No DD arithmetic, parsing, normalization or heap allocation occurs on access.
|
||||
// Reproduce with the tests' ReferenceData/generate_constants.py.
|
||||
/// <summary>
|
||||
/// Represents the ratio of the circumference of a circle to its diameter, specified by the constant, π.
|
||||
/// </summary>
|
||||
public static DoubleDouble Pi => new(3.141592653589793, 1.2246467991473532e-16);
|
||||
/// <summary>
|
||||
/// Represents the natural logarithmic base, specified by the constant, e.
|
||||
/// </summary>
|
||||
public static DoubleDouble E => new(2.718281828459045, 1.4456468917292502e-16);
|
||||
/// <summary>
|
||||
/// Represents the natural logarithm of value 2.
|
||||
/// </summary>
|
||||
public static DoubleDouble Ln2 => new(0.6931471805599453, 2.3190468138462996e-17);
|
||||
|
||||
/// <summary>Gets τ = 2π, the angle of one full turn in radians.</summary>
|
||||
public static DoubleDouble Tau => new(6.283185307179586, 2.4492935982947064e-16);
|
||||
|
||||
/// <summary>Gets π/2, the angle of 90 degrees in radians.</summary>
|
||||
public static DoubleDouble PiOver2 => new(1.5707963267948966, 6.123233995736766e-17);
|
||||
|
||||
/// <summary>Gets π/3, the angle of 60 degrees in radians.</summary>
|
||||
public static DoubleDouble PiOver3 => new(1.0471975511965979, -1.072081766451091e-16);
|
||||
|
||||
/// <summary>Gets π/4, the angle of 45 degrees in radians.</summary>
|
||||
public static DoubleDouble PiOver4 => new(0.7853981633974483, 3.061616997868383e-17);
|
||||
|
||||
/// <summary>Gets π/6, the angle of 30 degrees in radians.</summary>
|
||||
public static DoubleDouble PiOver6 => new(0.5235987755982989, -5.360408832255455e-17);
|
||||
|
||||
/// <summary>Gets 1/π.</summary>
|
||||
public static DoubleDouble InvPi => new(0.3183098861837907, -1.9678676675182486e-17);
|
||||
|
||||
/// <summary>Gets 1/(2π), the factor for converting radians to turns.</summary>
|
||||
public static DoubleDouble InvTau => new(0.15915494309189535, -9.839338337591243e-18);
|
||||
|
||||
/// <summary>Gets π/180. Multiply an angle in degrees by this value to obtain radians.</summary>
|
||||
public static DoubleDouble DegToRad => new(0.017453292519943295, 2.9486522708701687e-19);
|
||||
|
||||
/// <summary>Gets 180/π. Multiply an angle in radians by this value to obtain degrees.</summary>
|
||||
public static DoubleDouble RadToDeg => new(57.29577951308232, -1.9878495670576283e-15);
|
||||
|
||||
/// <summary>Gets 1/e = exp(-1).</summary>
|
||||
public static DoubleDouble InvE => new(0.36787944117144233, -1.2428753672788363e-17);
|
||||
|
||||
/// <summary>Gets ln(10), the factor for converting base-10 logarithms to natural logarithms.</summary>
|
||||
public static DoubleDouble Ln10 => new(2.302585092994046, -2.1707562233822494e-16);
|
||||
|
||||
/// <summary>Gets log₂(e) = 1/ln(2), the factor for converting natural logarithms to base 2.</summary>
|
||||
public static DoubleDouble Log2E => new(1.4426950408889634, 2.0355273740931033e-17);
|
||||
|
||||
/// <summary>Gets log₁₀(e) = 1/ln(10), the factor for converting natural logarithms to base 10.</summary>
|
||||
public static DoubleDouble Log10E => new(0.4342944819032518, 1.098319650216765e-17);
|
||||
|
||||
/// <summary>Gets log₂(10), the factor for converting base-10 logarithms to base 2.</summary>
|
||||
public static DoubleDouble Log2Of10 => new(3.321928094887362, 1.661617516973592e-16);
|
||||
|
||||
/// <summary>Gets log₁₀(2), the factor for converting base-2 logarithms to base 10.</summary>
|
||||
public static DoubleDouble Log10Of2 => new(0.3010299956639812, -2.8037281277851704e-18);
|
||||
|
||||
/// <summary>Gets √2.</summary>
|
||||
public static DoubleDouble Sqrt2 => new(1.4142135623730951, -9.667293313452913e-17);
|
||||
|
||||
/// <summary>Gets √3.</summary>
|
||||
public static DoubleDouble Sqrt3 => new(1.7320508075688772, 1.0035084221806903e-16);
|
||||
|
||||
/// <summary>Gets √5.</summary>
|
||||
public static DoubleDouble Sqrt5 => new(2.23606797749979, -1.0864230407365012e-16);
|
||||
|
||||
/// <summary>Gets 1/√2, also the sine and cosine of π/4.</summary>
|
||||
public static DoubleDouble InvSqrt2 => new(0.7071067811865476, -4.833646656726457e-17);
|
||||
|
||||
/// <summary>Gets 1/√3, also the tangent of π/6.</summary>
|
||||
public static DoubleDouble InvSqrt3 => new(0.5773502691896257, 3.3450280739356345e-17);
|
||||
|
||||
/// <summary>Gets √π, the Gaussian integral over the real line for exp(-x²).</summary>
|
||||
public static DoubleDouble SqrtPi => new(1.772453850905516, -7.666586499825799e-17);
|
||||
|
||||
/// <summary>Gets 1/√π, a Gaussian normalization factor.</summary>
|
||||
public static DoubleDouble InvSqrtPi => new(0.5641895835477563, 7.66772980658294e-18);
|
||||
|
||||
/// <summary>Gets 2/√π, the normalization factor in the error-function integral.</summary>
|
||||
public static DoubleDouble TwoInvSqrtPi => new(1.1283791670955126, 1.533545961316588e-17);
|
||||
|
||||
/// <summary>Gets √(2π), used in Gaussian integrals and Stirling's approximation.</summary>
|
||||
public static DoubleDouble SqrtTau => new(2.5066282746310007, -1.8328579980459167e-16);
|
||||
|
||||
/// <summary>Gets 1/√(2π), the standard normal probability density's normalization factor.</summary>
|
||||
public static DoubleDouble InvSqrtTau => new(0.3989422804014327, -2.49232720227773e-17);
|
||||
|
||||
/// <summary>Gets the golden ratio φ = (1 + √5)/2.</summary>
|
||||
public static DoubleDouble GoldenRatio => new(1.618033988749895, -5.432115203682506e-17);
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// High part of DoubleDouble
|
||||
/// </summary>
|
||||
@@ -224,20 +100,10 @@ public readonly partial struct DoubleDouble :
|
||||
return HashCode.Combine(_high, _low);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests numerical equality; NaN operands are never equal.
|
||||
/// </summary>
|
||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(DoubleDouble left, DoubleDouble right)
|
||||
/// <summary>Returns the normalized components.</summary>
|
||||
public void Decompose(out double high, out double low)
|
||||
{
|
||||
return left._high == right._high && left._low == right._low;
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests numerical inequality; NaN operands are always unequal.
|
||||
/// </summary>
|
||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(DoubleDouble left, DoubleDouble right)
|
||||
{
|
||||
return !(left == right);
|
||||
high = _high;
|
||||
low = _low;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user