namespace VisualMath.Accord.Math { using System; using System.Collections.Generic; using AForge; /// /// Set of mathematical tools. /// public static class Tools { #region Framework-wide random number generator private static Random random = new Random(); /// /// Gets a reference to the random number generator used /// internally by the Accord.NET classes and methods. /// public static Random Random { get { return random; } } /// /// Sets a random seed for the internal number generator. /// /// /// This method is only available in the debug version /// of the framework. /// [System.Diagnostics.Conditional("DEBUG")] public static void SetRandomSeed(int seed) { #if DEBUG random = new Random(seed); #endif } #endregion /// /// Returns the next power of 2 after the input value x. /// /// Input value x. /// Returns the next power of 2 after the input value x. public static int NextPowerOf2(int x) { --x; x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; return ++x; } /// /// Returns the previous power of 2 after the input value x. /// /// Input value x. /// Returns the previous power of 2 after the input value x. public static int PreviousPowerOf2(int x) { return NextPowerOf2(x + 1) / 2; } /// /// Hypotenuse calculus without overflow/underflow /// /// first value /// second value /// The hypotenuse Sqrt(a^2 + b^2) public static double Hypotenuse(double a, double b) { double r = 0.0; double absA = System.Math.Abs(a); double absB = System.Math.Abs(b); if (absA > absB) { r = b / a; r = absA * System.Math.Sqrt(1 + r * r); } else if (b != 0) { r = a / b; r = absB * System.Math.Sqrt(1 + r * r); } return r; } /// /// Gets the proper modulus operation for /// a integer x and modulo m. /// public static int Mod(int x, int m) { if (m < 0) m = -m; int r = x % m; return r < 0 ? r + m : r; } /// /// Converts the value x (which is measured in the scale /// 'from') to another value measured in the scale 'to'. /// public static int Scale(this IntRange from, IntRange to, int x) { if (from.Length == 0) return 0; return (to.Length) * (x - from.Min) / from.Length + to.Min; } /// /// Converts the value x (which is measured in the scale /// 'from') to another value measured in the scale 'to'. /// public static double Scale(this DoubleRange from, DoubleRange to, double x) { if (from.Length == 0) return 0; return (to.Length) * (x - from.Min) / from.Length + to.Min; } /// /// Converts the value x (which is measured in the scale /// 'from') to another value measured in the scale 'to'. /// public static double Scale(double fromMin, double fromMax, double toMin, double toMax, double x) { if (fromMax - fromMin == 0) return 0; return (toMax - toMin) * (x - fromMin) / (fromMax - fromMin) + toMin; } /// /// Returns the hyperbolic arc cosine of the specified value. /// public static double Acosh(double x) { if (x < 1.0) throw new ArgumentOutOfRangeException("x"); return System.Math.Log(x + System.Math.Sqrt(x * x - 1)); } /// /// Returns the hyperbolic arc sine of the specified value. /// public static double Asinh(double d) { double x; int sign; if (d == 0.0) return d; if (d < 0.0) { sign = -1; x = -d; } else { sign = 1; x = d; } return sign * System.Math.Log(x + System.Math.Sqrt(x * x + 1)); } /// /// Returns the hyperbolic arc tangent of the specified value. /// public static double Atanh(double d) { if (d > 1.0 || d < -1.0) throw new ArgumentOutOfRangeException("d"); return 0.5 * System.Math.Log((1.0 + d) / (1.0 - d)); } /// /// Returns the factorial falling power of the specified value. /// public static int FactorialPower(int value, int degree) { int t = value; for (int i = 0; i < degree; i++) t *= degree--; return t; } /// /// Truncated power function. /// public static double TruncatedPower(double value, double degree) { double x = System.Math.Pow(value, degree); return (x > 0) ? x : 0.0; } } /// /// Directions for the General Comparer. /// public enum ComparerDirection { /// /// Sorting will be performed in ascending order. /// Ascending, /// /// Sorting will be performed in descending order. /// Descending }; /// /// General comparer which supports multiple directions /// and comparison of absolute values. /// public class GeneralComparer : IComparer { private bool absolute; private int direction = 1; /// /// Constructs a new General Comparer. /// /// The direction to compare. public GeneralComparer(ComparerDirection direction) : this(direction, false) { } /// /// Constructs a new General Comparer. /// /// The direction to compare. /// True to compare absolute values, false otherwise. Default is false. public GeneralComparer(ComparerDirection direction, bool useAbsoluteValues) { this.direction = (direction == ComparerDirection.Ascending) ? 1 : -1; this.absolute = useAbsoluteValues; } /// /// Compares two objects and returns a value indicating whether one is less than, /// equal to, or greater than the other. /// /// The first object to compare. /// The second object to compare. public int Compare(double x, double y) { if (absolute) return direction * (System.Math.Abs(x).CompareTo(System.Math.Abs(y))); else return direction * (x.CompareTo(y)); } } }