//
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using IStation.Numerics.LinearAlgebra;
using Complex = System.Numerics.Complex;
namespace IStation.Numerics
{
// TODO PERF: Cache/Precompute 10^x terms
public static partial class Precision
{
///
/// Compares two doubles and determines if they are equal
/// within the specified maximum absolute error.
///
/// The norm of the first value (can be negative).
/// The norm of the second value (can be negative).
/// The norm of the difference of the two values (can be negative).
/// The absolute accuracy required for being almost equal.
/// True if both doubles are almost equal up to the specified maximum absolute error, false otherwise.
public static bool AlmostEqualNorm(this double a, double b, double diff, double maximumAbsoluteError)
{
// If A or B are infinity (positive or negative) then
// only return true if they are exactly equal to each other -
// that is, if they are both infinities of the same sign.
if (double.IsInfinity(a) || double.IsInfinity(b))
{
return a == b;
}
// If A or B are a NAN, return false. NANs are equal to nothing,
// not even themselves.
if (double.IsNaN(a) || double.IsNaN(b))
{
return false;
}
return Math.Abs(diff) < maximumAbsoluteError;
}
///
/// Compares two doubles and determines if they are equal
/// within the specified maximum absolute error.
///
/// The first value.
/// The second value.
/// The absolute accuracy required for being almost equal.
/// True if both doubles are almost equal up to the specified maximum absolute error, false otherwise.
public static bool AlmostEqualNorm(this T a, T b, double maximumAbsoluteError)
where T : IPrecisionSupport
{
return AlmostEqualNorm(a.Norm(), b.Norm(), a.NormOfDifference(b), maximumAbsoluteError);
}
///
/// Compares two doubles and determines if they are equal
/// within the specified maximum error.
///
/// The norm of the first value (can be negative).
/// The norm of the second value (can be negative).
/// The norm of the difference of the two values (can be negative).
/// The accuracy required for being almost equal.
/// True if both doubles are almost equal up to the specified maximum error, false otherwise.
public static bool AlmostEqualNormRelative(this double a, double b, double diff, double maximumError)
{
// If A or B are infinity (positive or negative) then
// only return true if they are exactly equal to each other -
// that is, if they are both infinities of the same sign.
if (double.IsInfinity(a) || double.IsInfinity(b))
{
return a == b;
}
// If A or B are a NAN, return false. NANs are equal to nothing,
// not even themselves.
if (double.IsNaN(a) || double.IsNaN(b))
{
return false;
}
// If one is almost zero, fall back to absolute equality
if (Math.Abs(a) < DoublePrecision || Math.Abs(b) < DoublePrecision)
{
return Math.Abs(diff) < maximumError;
}
if ((a == 0 && Math.Abs(b) < maximumError) || (b == 0 && Math.Abs(a) < maximumError))
{
return true;
}
return Math.Abs(diff) < maximumError * Math.Max(Math.Abs(a), Math.Abs(b));
}
///
/// Compares two doubles and determines if they are equal
/// within the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
/// True if both doubles are almost equal up to the specified maximum error, false otherwise.
public static bool AlmostEqualNormRelative(this T a, T b, double maximumError)
where T : IPrecisionSupport
{
return AlmostEqualNormRelative(a.Norm(), b.Norm(), a.NormOfDifference(b), maximumError);
}
///
/// Compares two doubles and determines if they are equal within
/// the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqual(this double a, double b, double maximumAbsoluteError)
{
return AlmostEqualNorm(a, b, a - b, maximumAbsoluteError);
}
///
/// Compares two complex and determines if they are equal within
/// the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqual(this float a, float b, double maximumAbsoluteError)
{
return AlmostEqualNorm(a, b, a - b, maximumAbsoluteError);
}
///
/// Compares two complex and determines if they are equal within
/// the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqual(this Complex a, Complex b, double maximumAbsoluteError)
{
return AlmostEqualNorm(a.Norm(), b.Norm(), a.NormOfDifference(b), maximumAbsoluteError);
}
///
/// Compares two complex and determines if they are equal within
/// the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqual(this Complex32 a, Complex32 b, double maximumAbsoluteError)
{
return AlmostEqualNorm(a.Norm(), b.Norm(), a.NormOfDifference(b), maximumAbsoluteError);
}
///
/// Compares two doubles and determines if they are equal within
/// the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqualRelative(this double a, double b, double maximumError)
{
return AlmostEqualNormRelative(a, b, a - b, maximumError);
}
///
/// Compares two complex and determines if they are equal within
/// the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqualRelative(this float a, float b, double maximumError)
{
return AlmostEqualNormRelative(a, b, a - b, maximumError);
}
///
/// Compares two complex and determines if they are equal within
/// the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqualRelative(this Complex a, Complex b, double maximumError)
{
return AlmostEqualNormRelative(a.Norm(), b.Norm(), a.NormOfDifference(b), maximumError);
}
///
/// Compares two complex and determines if they are equal within
/// the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqualRelative(this Complex32 a, Complex32 b, double maximumError)
{
return AlmostEqualNormRelative(a.Norm(), b.Norm(), a.NormOfDifference(b), maximumError);
}
///
/// Checks whether two real numbers are almost equal.
///
/// The first number
/// The second number
/// true if the two values differ by no more than 10 * 2^(-52); false otherwise.
public static bool AlmostEqual(this double a, double b)
{
return AlmostEqualNorm(a, b, a - b, DefaultDoubleAccuracy);
}
///
/// Checks whether two real numbers are almost equal.
///
/// The first number
/// The second number
/// true if the two values differ by no more than 10 * 2^(-52); false otherwise.
public static bool AlmostEqual(this float a, float b)
{
return AlmostEqualNorm(a, b, a - b, DefaultSingleAccuracy);
}
///
/// Checks whether two Complex numbers are almost equal.
///
/// The first number
/// The second number
/// true if the two values differ by no more than 10 * 2^(-52); false otherwise.
public static bool AlmostEqual(this Complex a, Complex b)
{
return AlmostEqualNorm(a.Norm(), b.Norm(), a.NormOfDifference(b), DefaultDoubleAccuracy);
}
///
/// Checks whether two Complex numbers are almost equal.
///
/// The first number
/// The second number
/// true if the two values differ by no more than 10 * 2^(-52); false otherwise.
public static bool AlmostEqual(this Complex32 a, Complex32 b)
{
return AlmostEqualNorm(a.Norm(), b.Norm(), a.NormOfDifference(b), DefaultSingleAccuracy);
}
///
/// Checks whether two real numbers are almost equal.
///
/// The first number
/// The second number
/// true if the two values differ by no more than 10 * 2^(-52); false otherwise.
public static bool AlmostEqualRelative(this double a, double b)
{
return AlmostEqualNormRelative(a, b, a - b, DefaultDoubleAccuracy);
}
///
/// Checks whether two real numbers are almost equal.
///
/// The first number
/// The second number
/// true if the two values differ by no more than 10 * 2^(-52); false otherwise.
public static bool AlmostEqualRelative(this float a, float b)
{
return AlmostEqualNormRelative(a, b, a - b, DefaultSingleAccuracy);
}
///
/// Checks whether two Complex numbers are almost equal.
///
/// The first number
/// The second number
/// true if the two values differ by no more than 10 * 2^(-52); false otherwise.
public static bool AlmostEqualRelative(this Complex a, Complex b)
{
return AlmostEqualNormRelative(a.Norm(), b.Norm(), a.NormOfDifference(b), DefaultDoubleAccuracy);
}
///
/// Checks whether two Complex numbers are almost equal.
///
/// The first number
/// The second number
/// true if the two values differ by no more than 10 * 2^(-52); false otherwise.
public static bool AlmostEqualRelative(this Complex32 a, Complex32 b)
{
return AlmostEqualNormRelative(a.Norm(), b.Norm(), a.NormOfDifference(b), DefaultSingleAccuracy);
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not, using the
/// number of decimal places as an absolute measure.
///
///
///
/// The values are equal if the difference between the two numbers is smaller than 0.5e-decimalPlaces. We divide by
/// two so that we have half the range on each side of the numbers, e.g. if == 2, then 0.01 will equal between
/// 0.005 and 0.015, but not 0.02 and not 0.00
///
///
/// The norm of the first value (can be negative).
/// The norm of the second value (can be negative).
/// The norm of the difference of the two values (can be negative).
/// The number of decimal places.
public static bool AlmostEqualNorm(this double a, double b, double diff, int decimalPlaces)
{
// If A or B are a NAN, return false. NANs are equal to nothing,
// not even themselves.
if (double.IsNaN(a) || double.IsNaN(b))
{
return false;
}
// If A or B are infinity (positive or negative) then
// only return true if they are exactly equal to each other -
// that is, if they are both infinities of the same sign.
if (double.IsInfinity(a) || double.IsInfinity(b))
{
return a == b;
}
// The values are equal if the difference between the two numbers is smaller than
// 10^(-numberOfDecimalPlaces). We divide by two so that we have half the range
// on each side of the numbers, e.g. if decimalPlaces == 2,
// then 0.01 will equal between 0.005 and 0.015, but not 0.02 and not 0.00
return Math.Abs(diff) < Math.Pow(10, -decimalPlaces) / 2d;
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not, using the
/// number of decimal places as an absolute measure.
///
///
///
/// The values are equal if the difference between the two numbers is smaller than 0.5e-decimalPlaces. We divide by
/// two so that we have half the range on each side of the numbers, e.g. if == 2, then 0.01 will equal between
/// 0.005 and 0.015, but not 0.02 and not 0.00
///
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqualNorm(this T a, T b, int decimalPlaces)
where T : IPrecisionSupport
{
return AlmostEqualNorm(a.Norm(), b.Norm(), a.NormOfDifference(b), decimalPlaces);
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not. If the numbers
/// are very close to zero an absolute difference is compared, otherwise the relative difference is compared.
///
///
///
/// The values are equal if the difference between the two numbers is smaller than 10^(-numberOfDecimalPlaces). We divide by
/// two so that we have half the range on each side of the numbers, e.g. if == 2, then 0.01 will equal between
/// 0.005 and 0.015, but not 0.02 and not 0.00
///
///
/// The norm of the first value (can be negative).
/// The norm of the second value (can be negative).
/// The norm of the difference of the two values (can be negative).
/// The number of decimal places.
/// Thrown if is smaller than zero.
public static bool AlmostEqualNormRelative(this double a, double b, double diff, int decimalPlaces)
{
if (decimalPlaces < 0)
{
// Can't have a negative number of decimal places
throw new ArgumentOutOfRangeException(nameof(decimalPlaces));
}
// If A or B are a NAN, return false. NANs are equal to nothing,
// not even themselves.
if (double.IsNaN(a) || double.IsNaN(b))
{
return false;
}
// If A or B are infinity (positive or negative) then
// only return true if they are exactly equal to each other -
// that is, if they are both infinities of the same sign.
if (double.IsInfinity(a) || double.IsInfinity(b))
{
return a == b;
}
// If both numbers are equal, get out now. This should remove the possibility of both numbers being zero
// and any problems associated with that.
if (a.Equals(b))
{
return true;
}
// If one is almost zero, fall back to absolute equality
if (Math.Abs(a) < DoublePrecision || Math.Abs(b) < DoublePrecision)
{
// The values are equal if the difference between the two numbers is smaller than
// 10^(-numberOfDecimalPlaces). We divide by two so that we have half the range
// on each side of the numbers, e.g. if decimalPlaces == 2,
// then 0.01 will equal between 0.005 and 0.015, but not 0.02 and not 0.00
return Math.Abs(diff) < Math.Pow(10, -decimalPlaces) / 2d;
}
// If the magnitudes of the two numbers are equal to within one magnitude the numbers could potentially be equal
int magnitudeOfFirst = Magnitude(a);
int magnitudeOfSecond = Magnitude(b);
int magnitudeOfMax = Math.Max(magnitudeOfFirst, magnitudeOfSecond);
if (magnitudeOfMax > (Math.Min(magnitudeOfFirst, magnitudeOfSecond) + 1))
{
return false;
}
// The values are equal if the difference between the two numbers is smaller than
// 10^(-numberOfDecimalPlaces). We divide by two so that we have half the range
// on each side of the numbers, e.g. if decimalPlaces == 2,
// then 0.01 will equal between 0.00995 and 0.01005, but not 0.0015 and not 0.0095
return Math.Abs(diff) < Math.Pow(10, magnitudeOfMax - decimalPlaces) / 2d;
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not. If the numbers
/// are very close to zero an absolute difference is compared, otherwise the relative difference is compared.
///
///
///
/// The values are equal if the difference between the two numbers is smaller than 10^(-numberOfDecimalPlaces). We divide by
/// two so that we have half the range on each side of the numbers, e.g. if == 2, then 0.01 will equal between
/// 0.005 and 0.015, but not 0.02 and not 0.00
///
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqualNormRelative(this T a, T b, int decimalPlaces)
where T : IPrecisionSupport
{
return AlmostEqualNormRelative(a.Norm(), b.Norm(), a.NormOfDifference(b), decimalPlaces);
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not, using the
/// number of decimal places as an absolute measure.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqual(this double a, double b, int decimalPlaces)
{
return AlmostEqualNorm(a, b, a - b, decimalPlaces);
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not, using the
/// number of decimal places as an absolute measure.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqual(this float a, float b, int decimalPlaces)
{
return AlmostEqualNorm(a, b, a - b, decimalPlaces);
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not, using the
/// number of decimal places as an absolute measure.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqual(this Complex a, Complex b, int decimalPlaces)
{
return AlmostEqualNorm(a.Norm(), b.Norm(), a.NormOfDifference(b), decimalPlaces);
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not, using the
/// number of decimal places as an absolute measure.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqual(this Complex32 a, Complex32 b, int decimalPlaces)
{
return AlmostEqualNorm(a.Norm(), b.Norm(), a.NormOfDifference(b), decimalPlaces);
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not. If the numbers
/// are very close to zero an absolute difference is compared, otherwise the relative difference is compared.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqualRelative(this double a, double b, int decimalPlaces)
{
return AlmostEqualNormRelative(a, b, a - b, decimalPlaces);
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not. If the numbers
/// are very close to zero an absolute difference is compared, otherwise the relative difference is compared.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqualRelative(this float a, float b, int decimalPlaces)
{
return AlmostEqualNormRelative(a, b, a - b, decimalPlaces);
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not. If the numbers
/// are very close to zero an absolute difference is compared, otherwise the relative difference is compared.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqualRelative(this Complex a, Complex b, int decimalPlaces)
{
return AlmostEqualNormRelative(a.Norm(), b.Norm(), a.NormOfDifference(b), decimalPlaces);
}
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not. If the numbers
/// are very close to zero an absolute difference is compared, otherwise the relative difference is compared.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqualRelative(this Complex32 a, Complex32 b, int decimalPlaces)
{
return AlmostEqualNormRelative(a.Norm(), b.Norm(), a.NormOfDifference(b), decimalPlaces);
}
///
/// Compares two doubles and determines if they are equal to within the tolerance or not. Equality comparison is based on the binary representation.
///
///
///
/// Determines the 'number' of floating point numbers between two values (i.e. the number of discrete steps
/// between the two numbers) and then checks if that is within the specified tolerance. So if a tolerance
/// of 1 is passed then the result will be true only if the two numbers have the same binary representation
/// OR if they are two adjacent numbers that only differ by one step.
///
///
/// The comparison method used is explained in http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm . The article
/// at http://www.extremeoptimization.com/resources/Articles/FPDotNetConceptsAndFormats.aspx explains how to transform the C code to
/// .NET enabled code without using pointers and unsafe code.
///
///
/// The first value.
/// The second value.
/// The maximum number of floating point values between the two values. Must be 1 or larger.
/// Thrown if is smaller than one.
public static bool AlmostEqualNumbersBetween(this double a, double b, long maxNumbersBetween)
{
// Make sure maxNumbersBetween is non-negative and small enough that the
// default NAN won't compare as equal to anything.
if (maxNumbersBetween < 1)
{
throw new ArgumentOutOfRangeException(nameof(maxNumbersBetween));
}
// If A or B are infinity (positive or negative) then
// only return true if they are exactly equal to each other -
// that is, if they are both infinities of the same sign.
if (double.IsInfinity(a) || double.IsInfinity(b))
{
return a == b;
}
// If A or B are a NAN, return false. NANs are equal to nothing,
// not even themselves.
if (double.IsNaN(a) || double.IsNaN(b))
{
return false;
}
// Get the first double and convert it to an integer value (by using the binary representation)
long firstUlong = AsDirectionalInt64(a);
// Get the second double and convert it to an integer value (by using the binary representation)
long secondUlong = AsDirectionalInt64(b);
// Now compare the values.
// Note that this comparison can overflow so we'll approach this differently
// Do note that we could overflow this way too. We should probably check that we don't.
return (a > b) ? (secondUlong + maxNumbersBetween >= firstUlong) : (firstUlong + maxNumbersBetween >= secondUlong);
}
///
/// Compares two floats and determines if they are equal to within the tolerance or not. Equality comparison is based on the binary representation.
///
/// The first value.
/// The second value.
/// The maximum number of floating point values between the two values. Must be 1 or larger.
/// Thrown if is smaller than one.
public static bool AlmostEqualNumbersBetween(this float a, float b, int maxNumbersBetween)
{
// Make sure maxNumbersBetween is non-negative and small enough that the
// default NAN won't compare as equal to anything.
if (maxNumbersBetween < 1)
{
throw new ArgumentOutOfRangeException(nameof(maxNumbersBetween));
}
// If A or B are infinity (positive or negative) then
// only return true if they are exactly equal to each other -
// that is, if they are both infinities of the same sign.
if (float.IsInfinity(a) || float.IsInfinity(b))
{
return a == b;
}
// If A or B are a NAN, return false. NANs are equal to nothing,
// not even themselves.
if (float.IsNaN(a) || float.IsNaN(b))
{
return false;
}
// Get the first float and convert it to an integer value (by using the binary representation)
int firstUlong = AsDirectionalInt32(a);
// Get the second float and convert it to an integer value (by using the binary representation)
int secondUlong = AsDirectionalInt32(b);
// Now compare the values.
// Note that this comparison can overflow so we'll approach this differently
// Do note that we could overflow this way too. We should probably check that we don't.
return (a > b) ? (secondUlong + maxNumbersBetween >= firstUlong) : (firstUlong + maxNumbersBetween >= secondUlong);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The accuracy required for being almost equal.
public static bool ListAlmostEqual(this IList a, IList b, double maximumAbsoluteError)
{
return ListForAll(a, b, AlmostEqual, maximumAbsoluteError);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The accuracy required for being almost equal.
public static bool ListAlmostEqual(this IList a, IList b, double maximumAbsoluteError)
{
return ListForAll(a, b, AlmostEqual, maximumAbsoluteError);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The accuracy required for being almost equal.
public static bool ListAlmostEqual(this IList a, IList b, double maximumAbsoluteError)
{
return ListForAll(a, b, AlmostEqual, maximumAbsoluteError);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The accuracy required for being almost equal.
public static bool ListAlmostEqual(this IList a, IList b, double maximumAbsoluteError)
{
return ListForAll(a, b, AlmostEqual, maximumAbsoluteError);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The accuracy required for being almost equal.
public static bool ListAlmostEqualRelative(this IList a, IList b, double maximumError)
{
return ListForAll(a, b, AlmostEqualRelative, maximumError);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The accuracy required for being almost equal.
public static bool ListAlmostEqualRelative(this IList a, IList b, double maximumError)
{
return ListForAll(a, b, AlmostEqualRelative, maximumError);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The accuracy required for being almost equal.
public static bool ListAlmostEqualRelative(this IList a, IList b, double maximumError)
{
return ListForAll(a, b, AlmostEqualRelative, maximumError);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The accuracy required for being almost equal.
public static bool ListAlmostEqualRelative(this IList a, IList b, double maximumError)
{
return ListForAll(a, b, AlmostEqualRelative, maximumError);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The number of decimal places.
public static bool ListAlmostEqual(this IList a, IList b, int decimalPlaces)
{
return ListForAll(a, b, AlmostEqual, decimalPlaces);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The number of decimal places.
public static bool ListAlmostEqual(this IList a, IList b, int decimalPlaces)
{
return ListForAll(a, b, AlmostEqual, decimalPlaces);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The number of decimal places.
public static bool ListAlmostEqual(this IList a, IList b, int decimalPlaces)
{
return ListForAll(a, b, AlmostEqual, decimalPlaces);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The number of decimal places.
public static bool ListAlmostEqual(this IList a, IList b, int decimalPlaces)
{
return ListForAll(a, b, AlmostEqual, decimalPlaces);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The number of decimal places.
public static bool ListAlmostEqualRelative(this IList a, IList b, int decimalPlaces)
{
return ListForAll(a, b, AlmostEqualRelative, decimalPlaces);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The number of decimal places.
public static bool ListAlmostEqualRelative(this IList a, IList b, int decimalPlaces)
{
return ListForAll(a, b, AlmostEqualRelative, decimalPlaces);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The number of decimal places.
public static bool ListAlmostEqualRelative(this IList a, IList b, int decimalPlaces)
{
return ListForAll(a, b, AlmostEqualRelative, decimalPlaces);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The number of decimal places.
public static bool ListAlmostEqualRelative(this IList a, IList b, int decimalPlaces)
{
return ListForAll(a, b, AlmostEqualRelative, decimalPlaces);
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The accuracy required for being almost equal.
public static bool ListAlmostEqualNorm(this IList a, IList b, double maximumAbsoluteError)
where T : IPrecisionSupport
{
if (a == null && b == null)
{
return true;
}
if (a == null || b == null || a.Count != b.Count)
{
return false;
}
for (int i = 0; i < a.Count; i++)
{
if (!AlmostEqualNorm(a[i], b[i], maximumAbsoluteError))
{
return false;
}
}
return true;
}
///
/// Compares two lists of doubles and determines if they are equal within the
/// specified maximum error.
///
/// The first value list.
/// The second value list.
/// The accuracy required for being almost equal.
public static bool ListAlmostEqualNormRelative(this IList a, IList b, double maximumError)
where T : IPrecisionSupport
{
if (a == null && b == null)
{
return true;
}
if (a == null || b == null || a.Count != b.Count)
{
return false;
}
for (int i = 0; i < a.Count; i++)
{
if (!AlmostEqualNormRelative(a[i], b[i], maximumError))
{
return false;
}
}
return true;
}
private static bool ListForAll(IList a, IList b, Func predicate, TP parameter)
{
if (a == null && b == null)
{
return true;
}
if (a == null || b == null || a.Count != b.Count)
{
return false;
}
for (int i = 0; i < a.Count; i++)
{
if (!predicate(a[i], b[i], parameter))
{
return false;
}
}
return true;
}
///
/// Compares two vectors and determines if they are equal within the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqual(this Vector a, Vector b, double maximumAbsoluteError)
where T : struct, IEquatable, IFormattable
{
return AlmostEqualNorm(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), maximumAbsoluteError);
}
///
/// Compares two vectors and determines if they are equal within the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqualRelative(this Vector a, Vector b, double maximumError)
where T : struct, IEquatable, IFormattable
{
return AlmostEqualNormRelative(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), maximumError);
}
///
/// Compares two vectors and determines if they are equal to within the specified number
/// of decimal places or not, using the number of decimal places as an absolute measure.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqual(this Vector a, Vector b, int decimalPlaces)
where T : struct, IEquatable, IFormattable
{
return AlmostEqualNorm(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), decimalPlaces);
}
///
/// Compares two vectors and determines if they are equal to within the specified number of decimal places or not.
/// If the numbers are very close to zero an absolute difference is compared, otherwise the relative difference is compared.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqualRelative(this Vector a, Vector b, int decimalPlaces)
where T : struct, IEquatable, IFormattable
{
return AlmostEqualNormRelative(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), decimalPlaces);
}
///
/// Compares two matrices and determines if they are equal within the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqual(this Matrix a, Matrix b, double maximumAbsoluteError)
where T : struct, IEquatable, IFormattable
{
return AlmostEqualNorm(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), maximumAbsoluteError);
}
///
/// Compares two matrices and determines if they are equal within the specified maximum error.
///
/// The first value.
/// The second value.
/// The accuracy required for being almost equal.
public static bool AlmostEqualRelative(this Matrix a, Matrix b, double maximumError)
where T : struct, IEquatable, IFormattable
{
return AlmostEqualNormRelative(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), maximumError);
}
///
/// Compares two matrices and determines if they are equal to within the specified number
/// of decimal places or not, using the number of decimal places as an absolute measure.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqual(this Matrix a, Matrix b, int decimalPlaces)
where T : struct, IEquatable, IFormattable
{
return AlmostEqualNorm(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), decimalPlaces);
}
///
/// Compares two matrices and determines if they are equal to within the specified number of decimal places or not.
/// If the numbers are very close to zero an absolute difference is compared, otherwise the relative difference is compared.
///
/// The first value.
/// The second value.
/// The number of decimal places.
public static bool AlmostEqualRelative(this Matrix a, Matrix b, int decimalPlaces)
where T : struct, IEquatable, IFormattable
{
return AlmostEqualNormRelative(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), decimalPlaces);
}
}
}