This commit is contained in:
+2
-2
@@ -117,8 +117,8 @@ csharp_style_expression_bodied_constructors = false:silent
|
|||||||
csharp_style_expression_bodied_indexers = true:silent
|
csharp_style_expression_bodied_indexers = true:silent
|
||||||
csharp_style_expression_bodied_lambdas = true:suggestion
|
csharp_style_expression_bodied_lambdas = true:suggestion
|
||||||
csharp_style_expression_bodied_local_functions = false:silent
|
csharp_style_expression_bodied_local_functions = false:silent
|
||||||
csharp_style_expression_bodied_methods = false:silent
|
csharp_style_expression_bodied_methods = when_on_single_line:silent
|
||||||
csharp_style_expression_bodied_operators = false:silent
|
csharp_style_expression_bodied_operators = when_on_single_line:silent
|
||||||
csharp_style_expression_bodied_properties = true:silent
|
csharp_style_expression_bodied_properties = true:silent
|
||||||
|
|
||||||
# Pattern matching preferences
|
# Pattern matching preferences
|
||||||
|
|||||||
@@ -44,18 +44,13 @@ public readonly partial struct DoubleDouble :
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Returns the operand unchanged.</summary>
|
/// <summary>Returns the operand unchanged.</summary>
|
||||||
public static DoubleDouble Plus(DoubleDouble value)
|
public static DoubleDouble Plus(DoubleDouble value) => value;
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Negates the value, including the high zero's sign, retaining canonical NaN and zero residuals.</summary>
|
/// <summary>Negates the value, including the high zero's sign, retaining canonical NaN and zero residuals.</summary>
|
||||||
public static DoubleDouble Negate(DoubleDouble value)
|
public static DoubleDouble Negate(DoubleDouble value) =>
|
||||||
{
|
|
||||||
// Negation preserves normalization; only NaN and zero residuals need canonicalization.
|
// Negation preserves normalization; only NaN and zero residuals need canonicalization.
|
||||||
return new DoubleDouble(double.IsNaN(value._high) ? double.NaN : -value._high,
|
new DoubleDouble(double.IsNaN(value._high) ? double.NaN : -value._high,
|
||||||
value._low == 0.0 ? 0.0 : -value._low);
|
value._low == 0.0 ? 0.0 : -value._low);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Adds normalized expansions, retaining low-sum residuals under cancellation.</summary>
|
/// <summary>Adds normalized expansions, retaining low-sum residuals under cancellation.</summary>
|
||||||
public static DoubleDouble Add(DoubleDouble left, DoubleDouble right)
|
public static DoubleDouble Add(DoubleDouble left, DoubleDouble right)
|
||||||
@@ -159,32 +154,21 @@ public readonly partial struct DoubleDouble :
|
|||||||
|
|
||||||
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
||||||
/// <remarks>Preserves the component bits of addition with the equivalent zero-low scalar expansion.</remarks>
|
/// <remarks>Preserves the component bits of addition with the equivalent zero-low scalar expansion.</remarks>
|
||||||
public static DoubleDouble Add(DoubleDouble left, double right)
|
public static DoubleDouble Add(DoubleDouble left, double right) => PreciseMathHelper.AddScalar(left._high, left._low, right);
|
||||||
{
|
|
||||||
return PreciseMathHelper.AddScalar(left._high, left._low, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
||||||
/// <remarks>Preserves the component bits of addition with the equivalent zero-low scalar expansion.</remarks>
|
/// <remarks>Preserves the component bits of addition with the equivalent zero-low scalar expansion.</remarks>
|
||||||
public static DoubleDouble Add(double left, DoubleDouble right)
|
public static DoubleDouble Add(double left, DoubleDouble right) => Add(right, left);
|
||||||
{
|
|
||||||
return Add(right, left);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
||||||
/// <remarks>Preserves the component bits of subtraction with the equivalent zero-low scalar expansion.</remarks>
|
/// <remarks>Preserves the component bits of subtraction with the equivalent zero-low scalar expansion.</remarks>
|
||||||
public static DoubleDouble Subtract(DoubleDouble left, double right)
|
public static DoubleDouble Subtract(DoubleDouble left, double right) => PreciseMathHelper.AddScalar(left._high, left._low, -right);
|
||||||
{
|
|
||||||
return PreciseMathHelper.AddScalar(left._high, left._low, -right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
||||||
/// <remarks>Preserves the component bits of subtraction with the equivalent zero-low scalar expansion.</remarks>
|
/// <remarks>Preserves the component bits of subtraction with the equivalent zero-low scalar expansion.</remarks>
|
||||||
public static DoubleDouble Subtract(double left, DoubleDouble right)
|
public static DoubleDouble Subtract(double left, DoubleDouble right) =>
|
||||||
{
|
|
||||||
// Negate the components, not the result: exact cancellation must yield +0.
|
// Negate the components, not the result: exact cancellation must yield +0.
|
||||||
return PreciseMathHelper.AddScalar(-right._high, -right._low, left);
|
PreciseMathHelper.AddScalar(-right._high, -right._low, left);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
||||||
public static DoubleDouble Multiply(DoubleDouble left, double right)
|
public static DoubleDouble Multiply(DoubleDouble left, double right)
|
||||||
@@ -207,10 +191,7 @@ public readonly partial struct DoubleDouble :
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
/// <summary>Applies the expansion operation without discarding the low component.</summary>
|
||||||
public static DoubleDouble Multiply(double left, DoubleDouble right)
|
public static DoubleDouble Multiply(double left, DoubleDouble right) => Multiply(right, left);
|
||||||
{
|
|
||||||
return Multiply(right, left);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Divides by a scalar using a quotient estimate and two residual corrections.</summary>
|
/// <summary>Divides by a scalar using a quotient estimate and two residual corrections.</summary>
|
||||||
/// <remarks>Preserves the component bits of division by the equivalent zero-low expansion.</remarks>
|
/// <remarks>Preserves the component bits of division by the equivalent zero-low expansion.</remarks>
|
||||||
|
|||||||
@@ -8,27 +8,18 @@ public readonly partial struct DoubleDouble :
|
|||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public bool Equals(DoubleDouble other)
|
public bool Equals(DoubleDouble other) => _high.Equals(other._high) && _low.Equals(other._low);
|
||||||
{
|
|
||||||
return _high.Equals(other._high) && _low.Equals(other._low);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tests numerical equality; NaN operands are never equal.
|
/// Tests numerical equality; NaN operands are never equal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool operator ==(DoubleDouble left, DoubleDouble right)
|
public static bool operator ==(DoubleDouble left, DoubleDouble right) => left._high == right._high && left._low == right._low;
|
||||||
{
|
|
||||||
return left._high == right._high && left._low == right._low;
|
|
||||||
}
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tests numerical inequality; NaN operands are always unequal.
|
/// Tests numerical inequality; NaN operands are always unequal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool operator !=(DoubleDouble left, DoubleDouble right)
|
public static bool operator !=(DoubleDouble left, DoubleDouble right) => !(left == right);
|
||||||
{
|
|
||||||
return !(left == right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Orders NaN before other values, and compares finite values using both components.</summary>
|
/// <summary>Orders NaN before other values, and compares finite values using both components.</summary>
|
||||||
public int CompareTo(DoubleDouble other)
|
public int CompareTo(DoubleDouble other)
|
||||||
@@ -51,63 +42,33 @@ public readonly partial struct DoubleDouble :
|
|||||||
throw new ArgumentException($"Object must be of type {nameof(DoubleDouble)}.", nameof(obj));
|
throw new ArgumentException($"Object must be of type {nameof(DoubleDouble)}.", nameof(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Compares both components; NaN operands are unordered.</summary>
|
||||||
|
public static bool operator <(DoubleDouble left, DoubleDouble right) => left._high < right._high || (left._high == right._high && left._low < right._low);
|
||||||
|
|
||||||
|
/// <summary>Compares both components; NaN operands are unordered.</summary>
|
||||||
|
public static bool operator >(DoubleDouble left, DoubleDouble right) => left._high > right._high || (left._high == right._high && left._low > right._low);
|
||||||
|
|
||||||
|
/// <summary>Compares both components; NaN operands are unordered.</summary>
|
||||||
|
public static bool operator <=(DoubleDouble left, DoubleDouble right) => left._high < right._high || (left._high == right._high && left._low <= right._low);
|
||||||
|
|
||||||
|
/// <summary>Compares both components; NaN operands are unordered.</summary>
|
||||||
|
public static bool operator >=(DoubleDouble left, DoubleDouble right) => left._high > right._high || (left._high == right._high && left._low >= right._low);
|
||||||
|
|
||||||
/// <summary>Applies binary64 IsNaN classification to the canonical high component.</summary>
|
/// <summary>Applies binary64 IsNaN classification to the canonical high component.</summary>
|
||||||
public static bool IsNaN(DoubleDouble value)
|
public static bool IsNaN(DoubleDouble value) => double.IsNaN(value._high);
|
||||||
{
|
|
||||||
return double.IsNaN(value._high);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Applies binary64 IsFinite classification to the canonical high component.</summary>
|
/// <summary>Applies binary64 IsFinite classification to the canonical high component.</summary>
|
||||||
public static bool IsFinite(DoubleDouble value)
|
public static bool IsFinite(DoubleDouble value) => double.IsFinite(value._high);
|
||||||
{
|
|
||||||
return double.IsFinite(value._high);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Applies binary64 IsInfinity classification to the canonical high component.</summary>
|
/// <summary>Applies binary64 IsInfinity classification to the canonical high component.</summary>
|
||||||
public static bool IsInfinity(DoubleDouble value)
|
public static bool IsInfinity(DoubleDouble value) => double.IsInfinity(value._high);
|
||||||
{
|
|
||||||
return double.IsInfinity(value._high);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Applies binary64 IsPositiveInfinity classification to the canonical high component.</summary>
|
/// <summary>Applies binary64 IsPositiveInfinity classification to the canonical high component.</summary>
|
||||||
public static bool IsPositiveInfinity(DoubleDouble value)
|
public static bool IsPositiveInfinity(DoubleDouble value) => double.IsPositiveInfinity(value._high);
|
||||||
{
|
|
||||||
return double.IsPositiveInfinity(value._high);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Applies binary64 IsNegativeInfinity classification to the canonical high component.</summary>
|
/// <summary>Applies binary64 IsNegativeInfinity classification to the canonical high component.</summary>
|
||||||
public static bool IsNegativeInfinity(DoubleDouble value)
|
public static bool IsNegativeInfinity(DoubleDouble value) => double.IsNegativeInfinity(value._high);
|
||||||
{
|
|
||||||
return double.IsNegativeInfinity(value._high);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Applies binary64 IsNegative classification to the canonical high component.</summary>
|
/// <summary>Applies binary64 IsNegative classification to the canonical high component.</summary>
|
||||||
public static bool IsNegative(DoubleDouble value)
|
public static bool IsNegative(DoubleDouble value) => double.IsNegative(value._high);
|
||||||
{
|
|
||||||
return double.IsNegative(value._high);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Compares both components; NaN operands are unordered.</summary>
|
|
||||||
public static bool operator <(DoubleDouble left, DoubleDouble right)
|
|
||||||
{
|
|
||||||
return left._high < right._high || (left._high == right._high && left._low < right._low);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Compares both components; NaN operands are unordered.</summary>
|
|
||||||
public static bool operator >(DoubleDouble left, DoubleDouble right)
|
|
||||||
{
|
|
||||||
return left._high > right._high || (left._high == right._high && left._low > right._low);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Compares both components; NaN operands are unordered.</summary>
|
|
||||||
public static bool operator <=(DoubleDouble left, DoubleDouble right)
|
|
||||||
{
|
|
||||||
return left._high < right._high || (left._high == right._high && left._low <= right._low);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Compares both components; NaN operands are unordered.</summary>
|
|
||||||
public static bool operator >=(DoubleDouble left, DoubleDouble right)
|
|
||||||
{
|
|
||||||
return left._high > right._high || (left._high == right._high && left._low >= right._low);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,80 +9,35 @@ namespace Just.PreciseMath;
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
public readonly partial struct DoubleDouble : IConvertible
|
public readonly partial struct DoubleDouble : IConvertible
|
||||||
{
|
{
|
||||||
TypeCode IConvertible.GetTypeCode()
|
TypeCode IConvertible.GetTypeCode() => TypeCode.Object;
|
||||||
{
|
|
||||||
return TypeCode.Object;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IConvertible.ToBoolean(IFormatProvider? provider)
|
bool IConvertible.ToBoolean(IFormatProvider? provider) => _high != 0.0;
|
||||||
{
|
|
||||||
return _high != 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char IConvertible.ToChar(IFormatProvider? provider)
|
char IConvertible.ToChar(IFormatProvider? provider) => throw new InvalidCastException("DoubleDouble cannot be converted to Char.");
|
||||||
{
|
|
||||||
throw new InvalidCastException("DoubleDouble cannot be converted to Char.");
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime IConvertible.ToDateTime(IFormatProvider? provider)
|
DateTime IConvertible.ToDateTime(IFormatProvider? provider) => throw new InvalidCastException("DoubleDouble cannot be converted to DateTime.");
|
||||||
{
|
|
||||||
throw new InvalidCastException("DoubleDouble cannot be converted to DateTime.");
|
|
||||||
}
|
|
||||||
|
|
||||||
byte IConvertible.ToByte(IFormatProvider? provider)
|
byte IConvertible.ToByte(IFormatProvider? provider) => (byte)ConversionRoundedInteger();
|
||||||
{
|
|
||||||
return (byte)ConversionRoundedInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
sbyte IConvertible.ToSByte(IFormatProvider? provider)
|
sbyte IConvertible.ToSByte(IFormatProvider? provider) => (sbyte)ConversionRoundedInteger();
|
||||||
{
|
|
||||||
return (sbyte)ConversionRoundedInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
short IConvertible.ToInt16(IFormatProvider? provider)
|
short IConvertible.ToInt16(IFormatProvider? provider) => (short)ConversionRoundedInteger();
|
||||||
{
|
|
||||||
return (short)ConversionRoundedInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
ushort IConvertible.ToUInt16(IFormatProvider? provider)
|
ushort IConvertible.ToUInt16(IFormatProvider? provider) => (ushort)ConversionRoundedInteger();
|
||||||
{
|
|
||||||
return (ushort)ConversionRoundedInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
int IConvertible.ToInt32(IFormatProvider? provider)
|
int IConvertible.ToInt32(IFormatProvider? provider) => (int)ConversionRoundedInteger();
|
||||||
{
|
|
||||||
return (int)ConversionRoundedInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint IConvertible.ToUInt32(IFormatProvider? provider)
|
uint IConvertible.ToUInt32(IFormatProvider? provider) => (uint)ConversionRoundedInteger();
|
||||||
{
|
|
||||||
return (uint)ConversionRoundedInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
long IConvertible.ToInt64(IFormatProvider? provider)
|
long IConvertible.ToInt64(IFormatProvider? provider) => (long)ConversionRoundedInteger();
|
||||||
{
|
|
||||||
return (long)ConversionRoundedInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong IConvertible.ToUInt64(IFormatProvider? provider)
|
ulong IConvertible.ToUInt64(IFormatProvider? provider) => (ulong)ConversionRoundedInteger();
|
||||||
{
|
|
||||||
return (ulong)ConversionRoundedInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
decimal IConvertible.ToDecimal(IFormatProvider? provider)
|
decimal IConvertible.ToDecimal(IFormatProvider? provider) => (decimal)this;
|
||||||
{
|
|
||||||
return (decimal)this;
|
|
||||||
}
|
|
||||||
|
|
||||||
double IConvertible.ToDouble(IFormatProvider? provider)
|
double IConvertible.ToDouble(IFormatProvider? provider) => (double)this;
|
||||||
{
|
|
||||||
return (double)this;
|
|
||||||
}
|
|
||||||
|
|
||||||
float IConvertible.ToSingle(IFormatProvider? provider)
|
float IConvertible.ToSingle(IFormatProvider? provider) => (float)this;
|
||||||
{
|
|
||||||
return (float)this;
|
|
||||||
}
|
|
||||||
|
|
||||||
object IConvertible.ToType(Type conversionType, IFormatProvider? provider)
|
object IConvertible.ToType(Type conversionType, IFormatProvider? provider)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,22 +5,13 @@ namespace Just.PreciseMath;
|
|||||||
public readonly partial struct DoubleDouble : IFormattable
|
public readonly partial struct DoubleDouble : IFormattable
|
||||||
{
|
{
|
||||||
/// <summary>Formats with G32 and the current culture.</summary>
|
/// <summary>Formats with G32 and the current culture.</summary>
|
||||||
public override string ToString()
|
public override string ToString() => ToString(null, null);
|
||||||
{
|
|
||||||
return ToString(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Formats with the specified G, E, or F format and the current culture.</summary>
|
/// <summary>Formats with the specified G, E, or F format and the current culture.</summary>
|
||||||
public string ToString(string? format)
|
public string ToString(string? format) => ToString(format, null);
|
||||||
{
|
|
||||||
return ToString(format, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Formats with G32 and the supplied culture (or current culture when null).</summary>
|
/// <summary>Formats with G32 and the supplied culture (or current culture when null).</summary>
|
||||||
public string ToString(IFormatProvider? provider)
|
public string ToString(IFormatProvider? provider) => ToString(null, provider);
|
||||||
{
|
|
||||||
return ToString(null, provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Returns the exact decimal expansion of the stored value using invariant culture.</summary>
|
/// <summary>Returns the exact decimal expansion of the stored value using invariant culture.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
|
|||||||
@@ -45,35 +45,17 @@ public readonly partial struct DoubleDouble
|
|||||||
throw new NotSupportedException($"Conversion from {typeof(TOther)} to DoubleDouble is not supported.");
|
throw new NotSupportedException($"Conversion from {typeof(TOther)} to DoubleDouble is not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool INumberBase<DoubleDouble>.TryConvertFromChecked<TOther>(TOther value, out DoubleDouble result)
|
static bool INumberBase<DoubleDouble>.TryConvertFromChecked<TOther>(TOther value, out DoubleDouble result) => GenericTryConvertFrom(value, out result);
|
||||||
{
|
|
||||||
return GenericTryConvertFrom(value, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool INumberBase<DoubleDouble>.TryConvertFromSaturating<TOther>(TOther value, out DoubleDouble result)
|
static bool INumberBase<DoubleDouble>.TryConvertFromSaturating<TOther>(TOther value, out DoubleDouble result) => GenericTryConvertFrom(value, out result);
|
||||||
{
|
|
||||||
return GenericTryConvertFrom(value, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool INumberBase<DoubleDouble>.TryConvertFromTruncating<TOther>(TOther value, out DoubleDouble result)
|
static bool INumberBase<DoubleDouble>.TryConvertFromTruncating<TOther>(TOther value, out DoubleDouble result) => GenericTryConvertFrom(value, out result);
|
||||||
{
|
|
||||||
return GenericTryConvertFrom(value, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool INumberBase<DoubleDouble>.TryConvertToChecked<TOther>(DoubleDouble value, out TOther result)
|
static bool INumberBase<DoubleDouble>.TryConvertToChecked<TOther>(DoubleDouble value, out TOther result) => GenericTryConvertTo(value, GenericConversionMode.Checked, out result);
|
||||||
{
|
|
||||||
return GenericTryConvertTo(value, GenericConversionMode.Checked, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool INumberBase<DoubleDouble>.TryConvertToSaturating<TOther>(DoubleDouble value, out TOther result)
|
static bool INumberBase<DoubleDouble>.TryConvertToSaturating<TOther>(DoubleDouble value, out TOther result) => GenericTryConvertTo(value, GenericConversionMode.Saturating, out result);
|
||||||
{
|
|
||||||
return GenericTryConvertTo(value, GenericConversionMode.Saturating, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool INumberBase<DoubleDouble>.TryConvertToTruncating<TOther>(DoubleDouble value, out TOther result)
|
static bool INumberBase<DoubleDouble>.TryConvertToTruncating<TOther>(DoubleDouble value, out TOther result) => GenericTryConvertTo(value, GenericConversionMode.Truncating, out result);
|
||||||
{
|
|
||||||
return GenericTryConvertTo(value, GenericConversionMode.Truncating, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum GenericConversionMode
|
private enum GenericConversionMode
|
||||||
{
|
{
|
||||||
@@ -82,16 +64,13 @@ public readonly partial struct DoubleDouble
|
|||||||
Truncating,
|
Truncating,
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool GenericIsInteger<TOther>()
|
private static bool GenericIsInteger<TOther>() => typeof(TOther) == typeof(byte) || typeof(TOther) == typeof(sbyte)
|
||||||
{
|
|
||||||
return typeof(TOther) == typeof(byte) || typeof(TOther) == typeof(sbyte)
|
|
||||||
|| typeof(TOther) == typeof(short) || typeof(TOther) == typeof(ushort)
|
|| typeof(TOther) == typeof(short) || typeof(TOther) == typeof(ushort)
|
||||||
|| typeof(TOther) == typeof(int) || typeof(TOther) == typeof(uint)
|
|| typeof(TOther) == typeof(int) || typeof(TOther) == typeof(uint)
|
||||||
|| typeof(TOther) == typeof(long) || typeof(TOther) == typeof(ulong)
|
|| typeof(TOther) == typeof(long) || typeof(TOther) == typeof(ulong)
|
||||||
|| typeof(TOther) == typeof(nint) || typeof(TOther) == typeof(nuint)
|
|| typeof(TOther) == typeof(nint) || typeof(TOther) == typeof(nuint)
|
||||||
|| typeof(TOther) == typeof(Int128) || typeof(TOther) == typeof(UInt128)
|
|| typeof(TOther) == typeof(Int128) || typeof(TOther) == typeof(UInt128)
|
||||||
|| typeof(TOther) == typeof(char) || typeof(TOther) == typeof(BigInteger);
|
|| typeof(TOther) == typeof(char) || typeof(TOther) == typeof(BigInteger);
|
||||||
}
|
|
||||||
|
|
||||||
private static bool GenericTryConvertFrom<TOther>(TOther value, out DoubleDouble result) where TOther : INumberBase<TOther>
|
private static bool GenericTryConvertFrom<TOther>(TOther value, out DoubleDouble result) where TOther : INumberBase<TOther>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -95,64 +95,35 @@ public readonly partial struct DoubleDouble
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Returns false: this type has no complex values.</summary>
|
/// <summary>Returns false: this type has no complex values.</summary>
|
||||||
public static bool IsComplexNumber(DoubleDouble value)
|
public static bool IsComplexNumber(DoubleDouble value) => false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Returns false: this type has no imaginary values.</summary>
|
/// <summary>Returns false: this type has no imaginary values.</summary>
|
||||||
public static bool IsImaginaryNumber(DoubleDouble value)
|
public static bool IsImaginaryNumber(DoubleDouble value) => false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Tests whether the value is real, including infinities but excluding NaN.</summary>
|
/// <summary>Tests whether the value is real, including infinities but excluding NaN.</summary>
|
||||||
public static bool IsRealNumber(DoubleDouble value)
|
public static bool IsRealNumber(DoubleDouble value) => !IsNaN(value);
|
||||||
{
|
|
||||||
return !IsNaN(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Tests the high component's sign bit, including positive zero.</summary>
|
/// <summary>Tests the high component's sign bit, including positive zero.</summary>
|
||||||
public static bool IsPositive(DoubleDouble value)
|
public static bool IsPositive(DoubleDouble value) => double.IsPositive(value._high);
|
||||||
{
|
|
||||||
return double.IsPositive(value._high);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Tests whether the normalized high component is a normal binary64 value.</summary>
|
/// <summary>Tests whether the normalized high component is a normal binary64 value.</summary>
|
||||||
public static bool IsNormal(DoubleDouble value)
|
public static bool IsNormal(DoubleDouble value) => double.IsNormal(value._high);
|
||||||
{
|
|
||||||
return double.IsNormal(value._high);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Tests whether the normalized high component is subnormal.</summary>
|
/// <summary>Tests whether the normalized high component is subnormal.</summary>
|
||||||
public static bool IsSubnormal(DoubleDouble value)
|
public static bool IsSubnormal(DoubleDouble value) => double.IsSubnormal(value._high);
|
||||||
{
|
|
||||||
return double.IsSubnormal(value._high);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Tests for either sign of zero.</summary>
|
/// <summary>Tests for either sign of zero.</summary>
|
||||||
public static bool IsZero(DoubleDouble value)
|
public static bool IsZero(DoubleDouble value) => value._high == 0.0 && value._low == 0.0;
|
||||||
{
|
|
||||||
return value._high == 0.0 && value._low == 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Tests whether the exact sum of the normalized components is an integer.</summary>
|
/// <summary>Tests whether the exact sum of the normalized components is an integer.</summary>
|
||||||
public static bool IsInteger(DoubleDouble value)
|
public static bool IsInteger(DoubleDouble value) =>
|
||||||
{
|
|
||||||
// In a normalized pair, a fractional high cannot be made integral by
|
// In a normalized pair, a fractional high cannot be made integral by
|
||||||
// its nonoverlapping residual. An integral high requires an integral low.
|
// its nonoverlapping residual. An integral high requires an integral low.
|
||||||
return double.IsInteger(value._high) && double.IsInteger(value._low);
|
double.IsInteger(value._high) && double.IsInteger(value._low);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Tests integer parity without discarding the residual above 2^53.</summary>
|
/// <summary>Tests integer parity without discarding the residual above 2^53.</summary>
|
||||||
public static bool IsEvenInteger(DoubleDouble value)
|
public static bool IsEvenInteger(DoubleDouble value) => IsInteger(value) && double.IsOddInteger(value._high) == double.IsOddInteger(value._low);
|
||||||
{
|
|
||||||
return IsInteger(value) && double.IsOddInteger(value._high) == double.IsOddInteger(value._low);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Tests integer parity without discarding the residual above 2^53.</summary>
|
/// <summary>Tests integer parity without discarding the residual above 2^53.</summary>
|
||||||
public static bool IsOddInteger(DoubleDouble value)
|
public static bool IsOddInteger(DoubleDouble value) => IsInteger(value) && double.IsOddInteger(value._high) != double.IsOddInteger(value._low);
|
||||||
{
|
|
||||||
return IsInteger(value) && double.IsOddInteger(value._high) != double.IsOddInteger(value._low);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,10 +33,7 @@ public readonly partial struct DoubleDouble
|
|||||||
|
|
||||||
/// <summary>Parses decimal text; returns false and Zero for null, invalid, or oversized input.</summary>
|
/// <summary>Parses decimal text; returns false and Zero for null, invalid, or oversized input.</summary>
|
||||||
/// <exception cref="ArgumentException">The style contains hexadecimal, binary, or undefined flags.</exception>
|
/// <exception cref="ArgumentException">The style contains hexadecimal, binary, or undefined flags.</exception>
|
||||||
public static bool TryParse(string? s, NumberStyles style, IFormatProvider? provider, out DoubleDouble result)
|
public static bool TryParse(string? s, NumberStyles style, IFormatProvider? provider, out DoubleDouble result) => TryParse(s.AsSpan(), style, provider, out result);
|
||||||
{
|
|
||||||
return TryParse(s.AsSpan(), style, provider, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Parses decimal text; returns false and Zero for invalid or oversized input.</summary>
|
/// <summary>Parses decimal text; returns false and Zero for invalid or oversized input.</summary>
|
||||||
/// <remarks>Group sizes are not validated. Currency styles recognize currency separators, and number
|
/// <remarks>Group sizes are not validated. Currency styles recognize currency separators, and number
|
||||||
|
|||||||
@@ -3,98 +3,50 @@ namespace Just.PreciseMath;
|
|||||||
public readonly partial struct DoubleDouble
|
public readonly partial struct DoubleDouble
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="Plus"/>
|
/// <inheritdoc cref="Plus"/>
|
||||||
public static DoubleDouble operator +(DoubleDouble value)
|
public static DoubleDouble operator +(DoubleDouble value) => Plus(value);
|
||||||
{
|
|
||||||
return Plus(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Negate"/>
|
/// <inheritdoc cref="Negate"/>
|
||||||
public static DoubleDouble operator -(DoubleDouble value)
|
public static DoubleDouble operator -(DoubleDouble value) => Negate(value);
|
||||||
{
|
|
||||||
return Negate(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Add(DoubleDouble, DoubleDouble)"/>
|
/// <inheritdoc cref="Add(DoubleDouble, DoubleDouble)"/>
|
||||||
public static DoubleDouble operator +(DoubleDouble left, DoubleDouble right)
|
public static DoubleDouble operator +(DoubleDouble left, DoubleDouble right) => Add(left, right);
|
||||||
{
|
|
||||||
return Add(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Subtract(DoubleDouble, DoubleDouble)"/>
|
/// <inheritdoc cref="Subtract(DoubleDouble, DoubleDouble)"/>
|
||||||
public static DoubleDouble operator -(DoubleDouble left, DoubleDouble right)
|
public static DoubleDouble operator -(DoubleDouble left, DoubleDouble right) => Subtract(left, right);
|
||||||
{
|
|
||||||
return Subtract(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Multiply(DoubleDouble, DoubleDouble)"/>
|
/// <inheritdoc cref="Multiply(DoubleDouble, DoubleDouble)"/>
|
||||||
public static DoubleDouble operator *(DoubleDouble left, DoubleDouble right)
|
public static DoubleDouble operator *(DoubleDouble left, DoubleDouble right) => Multiply(left, right);
|
||||||
{
|
|
||||||
return Multiply(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Divide(DoubleDouble, DoubleDouble)"/>
|
/// <inheritdoc cref="Divide(DoubleDouble, DoubleDouble)"/>
|
||||||
public static DoubleDouble operator /(DoubleDouble left, DoubleDouble right)
|
public static DoubleDouble operator /(DoubleDouble left, DoubleDouble right) => Divide(left, right);
|
||||||
{
|
|
||||||
return Divide(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Add(DoubleDouble, double)"/>
|
/// <inheritdoc cref="Add(DoubleDouble, double)"/>
|
||||||
public static DoubleDouble operator +(DoubleDouble left, double right)
|
public static DoubleDouble operator +(DoubleDouble left, double right) => Add(left, right);
|
||||||
{
|
|
||||||
return Add(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Add(double, DoubleDouble)"/>
|
/// <inheritdoc cref="Add(double, DoubleDouble)"/>
|
||||||
public static DoubleDouble operator +(double left, DoubleDouble right)
|
public static DoubleDouble operator +(double left, DoubleDouble right) => Add(left, right);
|
||||||
{
|
|
||||||
return Add(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Subtract(DoubleDouble, double)"/>
|
/// <inheritdoc cref="Subtract(DoubleDouble, double)"/>
|
||||||
public static DoubleDouble operator -(DoubleDouble left, double right)
|
public static DoubleDouble operator -(DoubleDouble left, double right) => Subtract(left, right);
|
||||||
{
|
|
||||||
return Subtract(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Subtract(double, DoubleDouble)"/>
|
/// <inheritdoc cref="Subtract(double, DoubleDouble)"/>
|
||||||
public static DoubleDouble operator -(double left, DoubleDouble right)
|
public static DoubleDouble operator -(double left, DoubleDouble right) => Subtract(left, right);
|
||||||
{
|
|
||||||
return Subtract(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Multiply(DoubleDouble, double)"/>
|
/// <inheritdoc cref="Multiply(DoubleDouble, double)"/>
|
||||||
public static DoubleDouble operator *(DoubleDouble left, double right)
|
public static DoubleDouble operator *(DoubleDouble left, double right) => Multiply(left, right);
|
||||||
{
|
|
||||||
return Multiply(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Multiply(double, DoubleDouble)"/>
|
/// <inheritdoc cref="Multiply(double, DoubleDouble)"/>
|
||||||
public static DoubleDouble operator *(double left, DoubleDouble right)
|
public static DoubleDouble operator *(double left, DoubleDouble right) => Multiply(left, right);
|
||||||
{
|
|
||||||
return Multiply(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Divide(DoubleDouble, double)"/>
|
/// <inheritdoc cref="Divide(DoubleDouble, double)"/>
|
||||||
public static DoubleDouble operator /(DoubleDouble left, double right)
|
public static DoubleDouble operator /(DoubleDouble left, double right) => Divide(left, right);
|
||||||
{
|
|
||||||
return Divide(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Divide(double, DoubleDouble)"/>
|
/// <inheritdoc cref="Divide(double, DoubleDouble)"/>
|
||||||
public static DoubleDouble operator /(double left, DoubleDouble right)
|
public static DoubleDouble operator /(double left, DoubleDouble right) => Divide(left, right);
|
||||||
{
|
|
||||||
return Divide(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Adds one using double-double arithmetic, including its overflow and nonfinite behavior.</summary>
|
/// <summary>Adds one using double-double arithmetic, including its overflow and nonfinite behavior.</summary>
|
||||||
public static DoubleDouble operator ++(DoubleDouble value)
|
public static DoubleDouble operator ++(DoubleDouble value) => Add(value, 1.0);
|
||||||
{
|
|
||||||
return Add(value, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Subtracts one using double-double arithmetic, including its overflow and nonfinite behavior.</summary>
|
/// <summary>Subtracts one using double-double arithmetic, including its overflow and nonfinite behavior.</summary>
|
||||||
public static DoubleDouble operator --(DoubleDouble value)
|
public static DoubleDouble operator --(DoubleDouble value) => Subtract(value, 1.0);
|
||||||
{
|
|
||||||
return Subtract(value, 1.0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,22 +41,13 @@ public readonly partial struct DoubleDouble : ISpanParsable<DoubleDouble>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Parses using the current culture. Returns false and Zero for null, invalid, or oversized input.</summary>
|
/// <summary>Parses using the current culture. Returns false and Zero for null, invalid, or oversized input.</summary>
|
||||||
public static bool TryParse(string? s, out DoubleDouble result)
|
public static bool TryParse(string? s, out DoubleDouble result) => TryParse(s, null, out result);
|
||||||
{
|
|
||||||
return TryParse(s, null, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Parses using the supplied culture (current when null). Returns false and Zero for null, invalid, or oversized input.</summary>
|
/// <summary>Parses using the supplied culture (current when null). Returns false and Zero for null, invalid, or oversized input.</summary>
|
||||||
public static bool TryParse(string? s, IFormatProvider? provider, out DoubleDouble result)
|
public static bool TryParse(string? s, IFormatProvider? provider, out DoubleDouble result) => TryParse(s.AsSpan(), provider, out result);
|
||||||
{
|
|
||||||
return TryParse(s.AsSpan(), provider, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Parses using the current culture. Returns false and Zero for invalid or oversized input.</summary>
|
/// <summary>Parses using the current culture. Returns false and Zero for invalid or oversized input.</summary>
|
||||||
public static bool TryParse(ReadOnlySpan<char> s, out DoubleDouble result)
|
public static bool TryParse(ReadOnlySpan<char> s, out DoubleDouble result) => TryParse(s, null, out result);
|
||||||
{
|
|
||||||
return TryParse(s, null, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Parses using the supplied culture (current when null). Returns false and Zero for invalid or oversized input.</summary>
|
/// <summary>Parses using the supplied culture (current when null). Returns false and Zero for invalid or oversized input.</summary>
|
||||||
public static bool TryParse(ReadOnlySpan<char> s, IFormatProvider? provider, out DoubleDouble result)
|
public static bool TryParse(ReadOnlySpan<char> s, IFormatProvider? provider, out DoubleDouble result)
|
||||||
|
|||||||
@@ -80,10 +80,7 @@ public readonly partial struct DoubleDouble
|
|||||||
/// The base retains both components.
|
/// The base retains both components.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Pow(DoubleDouble value, double exponent)
|
public static DoubleDouble Pow(DoubleDouble value, double exponent) => Pow(value, new DoubleDouble(exponent));
|
||||||
{
|
|
||||||
return Pow(value, new DoubleDouble(exponent));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Raises a double-double value to a double-double power.</summary>
|
/// <summary>Raises a double-double value to a double-double power.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
|
|||||||
@@ -83,16 +83,10 @@ public readonly partial struct DoubleDouble :
|
|||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj) => obj is DoubleDouble other && Equals(other);
|
||||||
{
|
|
||||||
return obj is DoubleDouble other && Equals(other);
|
|
||||||
}
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public override int GetHashCode()
|
public override int GetHashCode() => HashCode.Combine(_high, _low);
|
||||||
{
|
|
||||||
return HashCode.Combine(_high, _low);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Returns the normalized components.</summary>
|
/// <summary>Returns the normalized components.</summary>
|
||||||
public void Decompose(out double high, out double low)
|
public void Decompose(out double high, out double low)
|
||||||
|
|||||||
@@ -9,120 +9,69 @@ public static class DoubleDoubleExtensions
|
|||||||
{
|
{
|
||||||
/// <inheritdoc cref="DoubleDouble.Abs(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Abs(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Abs(this DoubleDouble value)
|
public static DoubleDouble Abs(this DoubleDouble value) => DoubleDouble.Abs(value);
|
||||||
{
|
|
||||||
return DoubleDouble.Abs(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Square(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Square(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Square(this DoubleDouble value)
|
public static DoubleDouble Square(this DoubleDouble value) => DoubleDouble.Square(value);
|
||||||
{
|
|
||||||
return DoubleDouble.Square(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Reciprocal(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Reciprocal(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Reciprocal(this DoubleDouble value)
|
public static DoubleDouble Reciprocal(this DoubleDouble value) => DoubleDouble.Reciprocal(value);
|
||||||
{
|
|
||||||
return DoubleDouble.Reciprocal(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Sqrt(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Sqrt(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Sqrt(this DoubleDouble value)
|
public static DoubleDouble Sqrt(this DoubleDouble value) => DoubleDouble.Sqrt(value);
|
||||||
{
|
|
||||||
return DoubleDouble.Sqrt(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.InvSqrt(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.InvSqrt(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble InvSqrt(this DoubleDouble value)
|
public static DoubleDouble InvSqrt(this DoubleDouble value) => DoubleDouble.InvSqrt(value);
|
||||||
{
|
|
||||||
return DoubleDouble.InvSqrt(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Cbrt(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Cbrt(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Cbrt(this DoubleDouble value)
|
public static DoubleDouble Cbrt(this DoubleDouble value) => DoubleDouble.Cbrt(value);
|
||||||
{
|
|
||||||
return DoubleDouble.Cbrt(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Exp(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Exp(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Exp(this DoubleDouble value)
|
public static DoubleDouble Exp(this DoubleDouble value) => DoubleDouble.Exp(value);
|
||||||
{
|
|
||||||
return DoubleDouble.Exp(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Exp2(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Exp2(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Exp2(this DoubleDouble value)
|
public static DoubleDouble Exp2(this DoubleDouble value) => DoubleDouble.Exp2(value);
|
||||||
{
|
|
||||||
return DoubleDouble.Exp2(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Exp10(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Exp10(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Exp10(this DoubleDouble value)
|
public static DoubleDouble Exp10(this DoubleDouble value) => DoubleDouble.Exp10(value);
|
||||||
{
|
|
||||||
return DoubleDouble.Exp10(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.ExpM1(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.ExpM1(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble ExpM1(this DoubleDouble value)
|
public static DoubleDouble ExpM1(this DoubleDouble value) => DoubleDouble.ExpM1(value);
|
||||||
{
|
|
||||||
return DoubleDouble.ExpM1(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Exp2M1(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Exp2M1(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Exp2M1(this DoubleDouble value)
|
public static DoubleDouble Exp2M1(this DoubleDouble value) => DoubleDouble.Exp2M1(value);
|
||||||
{
|
|
||||||
return DoubleDouble.Exp2M1(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Exp10M1(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Exp10M1(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Exp10M1(this DoubleDouble value)
|
public static DoubleDouble Exp10M1(this DoubleDouble value) => DoubleDouble.Exp10M1(value);
|
||||||
{
|
|
||||||
return DoubleDouble.Exp10M1(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Log(DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Log(DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Log(this DoubleDouble value)
|
public static DoubleDouble Log(this DoubleDouble value) => DoubleDouble.Log(value);
|
||||||
{
|
|
||||||
return DoubleDouble.Log(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.RootN(DoubleDouble, int)"/>
|
/// <inheritdoc cref="DoubleDouble.RootN(DoubleDouble, int)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble RootN(this DoubleDouble value, int n)
|
public static DoubleDouble RootN(this DoubleDouble value, int n) => DoubleDouble.RootN(value, n);
|
||||||
{
|
|
||||||
return DoubleDouble.RootN(value, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Pow(DoubleDouble, int)"/>
|
/// <inheritdoc cref="DoubleDouble.Pow(DoubleDouble, int)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Pow(this DoubleDouble value, int exponent)
|
public static DoubleDouble Pow(this DoubleDouble value, int exponent) => DoubleDouble.Pow(value, exponent);
|
||||||
{
|
|
||||||
return DoubleDouble.Pow(value, exponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Pow(DoubleDouble, double)"/>
|
/// <inheritdoc cref="DoubleDouble.Pow(DoubleDouble, double)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Pow(this DoubleDouble value, double exponent)
|
public static DoubleDouble Pow(this DoubleDouble value, double exponent) => DoubleDouble.Pow(value, exponent);
|
||||||
{
|
|
||||||
return DoubleDouble.Pow(value, exponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DoubleDouble.Pow(DoubleDouble, DoubleDouble)"/>
|
/// <inheritdoc cref="DoubleDouble.Pow(DoubleDouble, DoubleDouble)"/>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static DoubleDouble Pow(this DoubleDouble value, DoubleDouble exponent)
|
public static DoubleDouble Pow(this DoubleDouble value, DoubleDouble exponent) => DoubleDouble.Pow(value, exponent);
|
||||||
{
|
|
||||||
return DoubleDouble.Pow(value, exponent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,40 +211,22 @@ internal static class PreciseMathHelper
|
|||||||
// All inputs must be finite and normalized; division denominators must be nonzero.
|
// All inputs must be finite and normalized; division denominators must be nonzero.
|
||||||
// Callers retain the special-value, signed-zero, and exponent-range dispatch.
|
// Callers retain the special-value, signed-zero, and exponent-range dispatch.
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static DoubleDouble AddBoundary(DoubleDouble left, DoubleDouble right)
|
internal static DoubleDouble AddBoundary(DoubleDouble left, DoubleDouble right) => ArithmeticFromRatio(ArithmeticUnits(left) + ArithmeticUnits(right), BigInteger.One << 1074);
|
||||||
{
|
|
||||||
return ArithmeticFromRatio(ArithmeticUnits(left) + ArithmeticUnits(right), BigInteger.One << 1074);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static DoubleDouble MultiplyBoundary(DoubleDouble left, DoubleDouble right)
|
internal static DoubleDouble MultiplyBoundary(DoubleDouble left, DoubleDouble right) => ArithmeticFromRatio(ArithmeticUnits(left) * ArithmeticUnits(right), BigInteger.One << 2148);
|
||||||
{
|
|
||||||
return ArithmeticFromRatio(ArithmeticUnits(left) * ArithmeticUnits(right), BigInteger.One << 2148);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static DoubleDouble MultiplyBoundary(DoubleDouble left, double right)
|
internal static DoubleDouble MultiplyBoundary(DoubleDouble left, double right) => ArithmeticFromRatio(ArithmeticUnits(left) * ArithmeticUnits(right), BigInteger.One << 2148);
|
||||||
{
|
|
||||||
return ArithmeticFromRatio(ArithmeticUnits(left) * ArithmeticUnits(right), BigInteger.One << 2148);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static DoubleDouble DivideBoundary(DoubleDouble left, DoubleDouble right)
|
internal static DoubleDouble DivideBoundary(DoubleDouble left, DoubleDouble right) => ArithmeticFromRatio(ArithmeticUnits(left), ArithmeticUnits(right));
|
||||||
{
|
|
||||||
return ArithmeticFromRatio(ArithmeticUnits(left), ArithmeticUnits(right));
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static DoubleDouble DivideBoundary(DoubleDouble left, double right)
|
internal static DoubleDouble DivideBoundary(DoubleDouble left, double right) => ArithmeticFromRatio(ArithmeticUnits(left), ArithmeticUnits(right));
|
||||||
{
|
|
||||||
return ArithmeticFromRatio(ArithmeticUnits(left), ArithmeticUnits(right));
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static DoubleDouble DivideBoundary(double left, DoubleDouble right)
|
internal static DoubleDouble DivideBoundary(double left, DoubleDouble right) => ArithmeticFromRatio(ArithmeticUnits(left), ArithmeticUnits(right));
|
||||||
{
|
|
||||||
return ArithmeticFromRatio(ArithmeticUnits(left), ArithmeticUnits(right));
|
|
||||||
}
|
|
||||||
|
|
||||||
// For finite, nonzero normalized significands and exponents bounded by the
|
// For finite, nonzero normalized significands and exponents bounded by the
|
||||||
// integer-power domain (|exponent| < 2^42). Keep the exponent separate until
|
// integer-power domain (|exponent| < 2^42). Keep the exponent separate until
|
||||||
@@ -297,10 +279,7 @@ internal static class PreciseMathHelper
|
|||||||
// The boundary path uses bounded binary integers (at most about 4200 bits), not
|
// The boundary path uses bounded binary integers (at most about 4200 bits), not
|
||||||
// arbitrary-precision storage. It avoids overflow and double rounding in EFTs
|
// arbitrary-precision storage. It avoids overflow and double rounding in EFTs
|
||||||
// at the binary64 exponent limits. The common path remains allocation-free.
|
// at the binary64 exponent limits. The common path remains allocation-free.
|
||||||
internal static BigInteger ArithmeticUnits(DoubleDouble value)
|
internal static BigInteger ArithmeticUnits(DoubleDouble value) => ArithmeticUnits(value._high) + ArithmeticUnits(value._low);
|
||||||
{
|
|
||||||
return ArithmeticUnits(value._high) + ArithmeticUnits(value._low);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static BigInteger ArithmeticUnits(double value)
|
internal static BigInteger ArithmeticUnits(double value)
|
||||||
{
|
{
|
||||||
@@ -342,11 +321,9 @@ internal static class PreciseMathHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
private static DoubleDouble AddScalarBoundary(double high, double low, double value)
|
private static DoubleDouble AddScalarBoundary(double high, double low, double value) =>
|
||||||
{
|
|
||||||
// As in AddScalar, high/low are normalized but a negated zero low is allowed.
|
// As in AddScalar, high/low are normalized but a negated zero low is allowed.
|
||||||
return ArithmeticFromRatio(ArithmeticUnits(high) + ArithmeticUnits(low) + ArithmeticUnits(value), BigInteger.One << 1074);
|
ArithmeticFromRatio(ArithmeticUnits(high) + ArithmeticUnits(low) + ArithmeticUnits(value), BigInteger.One << 1074);
|
||||||
}
|
|
||||||
|
|
||||||
// Round an exact rational to binary64, ties-to-even, including subnormal and
|
// Round an exact rational to binary64, ties-to-even, including subnormal and
|
||||||
// overflow boundaries. Denominator is positive; sign is retained on underflow.
|
// overflow boundaries. Denominator is positive; sign is retained on underflow.
|
||||||
|
|||||||
@@ -43,8 +43,10 @@ Do not claim API completeness or accuracy beyond tested contracts.
|
|||||||
|
|
||||||
Follow `.editorconfig`, not incidental style in unfinished code.
|
Follow `.editorconfig`, not incidental style in unfinished code.
|
||||||
|
|
||||||
- Use file-scoped namespaces, explicit types rather than `var`, and block-bodied
|
- Use file-scoped namespaces and explicit types rather than `var`. Prefer
|
||||||
methods. Preserve the configured expression-bodied property/accessor preferences.
|
expression-bodied methods and operators when the expression fits on one line;
|
||||||
|
otherwise use block bodies. Preserve the configured expression-bodied preferences
|
||||||
|
for other member kinds.
|
||||||
- Use `_camelCase` for non-public instance fields, including internal fields;
|
- Use `_camelCase` for non-public instance fields, including internal fields;
|
||||||
`s_camelCase` for non-public mutable static fields; PascalCase for member constants
|
`s_camelCase` for non-public mutable static fields; PascalCase for member constants
|
||||||
and static readonly fields. Method-local constants follow local-variable camelCase.
|
and static readonly fields. Method-local constants follow local-variable camelCase.
|
||||||
|
|||||||
Reference in New Issue
Block a user