using System; using System.Runtime.CompilerServices; namespace RGB.NET.Core { /// /// Offers some extensions and helper-methods for the work with doubles /// public static class DoubleExtensions { #region Constants /// /// Defines the precision RGB.NET processes floating point comparisons in. /// public const double TOLERANCE = 1E-10; #endregion #region Methods /// /// Checks if two values are equal respecting the . /// /// The first value to compare. /// The first value to compare. /// true if the difference is smaller than the ; otherwise, false. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool EqualsInTolerance(this double value1, double value2) => Math.Abs(value1 - value2) < TOLERANCE; /// /// Clamps the provided value to be bigger or equal min and smaller or equal max. /// /// The value to clamp. /// The lower value of the range the value is clamped to. /// The higher value of the range the value is clamped to. /// The clamped value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Clamp(this double value, double min, double max) { // ReSharper disable ConvertIfStatementToReturnStatement - I'm not sure why, but inlining this statement reduces performance by ~10% if (value < min) return min; if (value > max) return max; return value; // ReSharper restore ConvertIfStatementToReturnStatement } /// /// Clamps the provided value to be bigger or equal min and smaller or equal max. /// /// The value to clamp. /// The lower value of the range the value is clamped to. /// The higher value of the range the value is clamped to. /// The clamped value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Clamp(this int value, int min, int max) { // ReSharper disable ConvertIfStatementToReturnStatement - I'm not sure why, but inlining this statement reduces performance by ~10% if (value < min) return min; if (value > max) return max; return value; // ReSharper restore ConvertIfStatementToReturnStatement } /// /// Enforces the provided value to be in the specified range by wrapping it around the edges if it exceeds them. /// /// The value to wrap. /// The lower value of the range the value is wrapped into. /// The higher value of the range the value is wrapped into. /// The wrapped value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Wrap(this double value, double min, double max) { double range = max - min; while (value >= max) value -= range; while (value < min) value += range; return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte GetByteValueFromPercentage(this double percentage) { if (double.IsNaN(percentage)) return 0; percentage = percentage.Clamp(0, 1.0); return (byte)(percentage >= 1.0 ? 255 : percentage * 256.0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double GetPercentageFromByteValue(this byte value) => ((double)value) / byte.MaxValue; #endregion } }