< Summary

Information
Class: MyNet.Primitives.MathExtensions
Assembly: MyNet.Primitives
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Primitives/Extensions/MathExtensions.cs
Tag: 323_28699572109
Line coverage
95%
Covered lines: 58
Uncovered lines: 3
Coverable lines: 61
Total lines: 292
Line coverage: 95%
Branch coverage
78%
Covered branches: 55
Total branches: 70
Branch coverage: 78.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
IsEven(...)100%11100%
IsOdd(...)100%11100%
Repeat(...)100%22100%
Range()100%66100%
ExtractDouble(...)91.66%121287.5%
AnyNan(...)100%11100%
AnyInfinity(...)100%11100%
IsCloseTo(...)100%1010100%
IsGreaterThan(...)100%11100%
IsLessThan(...)100%11100%
IsLessThanOrClose(...)50%22100%
IsGreaterThanOrClose(...)50%22100%
IsOne(...)100%11100%
IsZero(...)100%11100%
Range()66.66%7671.42%
IsCloseTo(...)87.5%88100%
IsGreaterThan(...)100%11100%
IsLessThan(...)100%11100%
IsLessThanOrClose(...)50%22100%
IsGreaterThanOrClose(...)50%22100%
IsOne(...)100%11100%
IsZero(...)100%11100%
IsCloseTo(...)90%1010100%
IsCloseTo(...)25%88100%

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Primitives/Extensions/MathExtensions.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="MathExtensions.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System;
 8using System.Collections.Generic;
 9using System.Diagnostics.CodeAnalysis;
 10using System.Globalization;
 11using System.Linq;
 12
 13#pragma warning disable IDE0130 // Namespace does not match folder structure
 14namespace MyNet.Primitives;
 15#pragma warning restore IDE0130 // Namespace does not match folder structure
 16
 17public static class MathExtensions
 18{
 19    /// <summary>
 20    /// The smallest positive double such that 1.0 + DblEpsilon != 1.0.
 21    /// </summary>
 22    public const double DblEpsilon = 2.2204460492503131e-016;
 23
 24    /// <summary>
 25    /// The smallest positive float such that 1.0f + FloatEpsilon != 1.0f.
 26    /// </summary>
 27    public const float FloatEpsilon = 1.1920929E-07f;
 28
 29    extension(int value)
 30    {
 31        /// <summary>
 32        /// Returns whether the integer is even.
 33        /// </summary>
 34        /// <returns>True if the integer is even, otherwise false.</returns>
 1535        public bool IsEven() => value % 2 == 0;
 36
 37        /// <summary>
 38        /// Returns whether the integer is odd.
 39        /// </summary>
 40        /// <returns>True if the integer is odd, otherwise false.</returns>
 1241        public bool IsOdd() => value % 2 != 0;
 42
 43        /// <summary>
 44        /// Iterates a specified action a given number of times, passing the current iteration index to the action.
 45        /// </summary>
 46        /// <param name="action">The action to perform.</param>
 47        public void Repeat(Action<int> action)
 48        {
 1549            ArgumentOutOfRangeException.ThrowIfNegative(value);
 1250            ArgumentNullException.ThrowIfNull(action);
 51
 6652            for (var i = 0; i < value; i++)
 2453                action(i);
 954        }
 55
 56        /// <summary>
 57        /// Generates a sequence of integers starting from a specified minimum value, incrementing by a specified step, 
 58        /// </summary>
 59        /// <param name="min">The starting value of the sequence.</param>
 60        /// <param name="step">The increment value for each step in the sequence.</param>
 61        /// <returns>An enumerable sequence of integers.</returns>
 62        /// <exception cref="ArgumentOutOfRangeException">Thrown if the step is zero.</exception>
 63        public IEnumerable<int> Range(int min = 0, int step = 1)
 64        {
 1265            ArgumentOutOfRangeException.ThrowIfZero(step);
 66
 967            if (step > 0)
 68            {
 6069                for (var i = min; i <= value; i += step)
 2470                    yield return i;
 71            }
 72            else
 73            {
 3074                for (var i = min; i >= value; i += step)
 1275                    yield return i;
 76            }
 977        }
 78    }
 79
 80    extension(object? value)
 81    {
 82        /// <summary>
 83        /// Extracts a double value from an object, returning NaN if the object is not a double or if the value is infin
 84        /// </summary>
 85        /// <returns>The extracted double value, or NaN if the extraction fails.</returns>
 86        public double ExtractDouble()
 1887            => value switch
 1888            {
 389                null => double.NaN,
 990                double d when !double.IsInfinity(d) => d,
 691                float f when !float.IsInfinity(f) => f,
 992                IConvertible c => Convert.ToDouble(c, CultureInfo.InvariantCulture),
 093                _ => double.NaN
 1894            };
 95    }
 96
 97    extension(IEnumerable<double> vals)
 98    {
 99        /// <summary>
 100        /// Returns whether any of the double values in the enumerable are NaN.
 101        /// </summary>
 102        /// <returns>True if any of the values are NaN, otherwise false.</returns>
 6103        public bool AnyNan() => vals.Any(double.IsNaN);
 104
 105        /// <summary>
 106        /// Returns whether any of the double values in the enumerable are infinity (either positive or negative).
 107        /// </summary>
 108        /// <returns>True if any of the values are infinity, otherwise false.</returns>
 6109        public bool AnyInfinity() => vals.Any(double.IsInfinity);
 110    }
 111
 112    extension(double value)
 113    {
 114        /// <summary>
 115        /// Returns whether two doubles are "close".
 116        /// </summary>
 117        /// <param name="value2"> The second double to compare. </param>
 118        /// <returns>
 119        /// bool - the result of the AreClose comparision.
 120        /// </returns>
 121        [SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator", Justification = "NaN and infinity are handled
 122        public bool IsCloseTo(double value2)
 123        {
 138124            if (double.IsNaN(value) || double.IsNaN(value2))
 6125                return false;
 126
 132127            if (value == value2)
 15128                return true;
 129
 117130            if (double.IsInfinity(value) || double.IsInfinity(value2))
 3131                return value == value2;
 132
 114133            var eps = DblEpsilon * Math.Max(1.0, Math.Max(Math.Abs(value), Math.Abs(value2)));
 114134            var delta = value - value2;
 135
 114136            return Math.Abs(delta) <= eps;
 137        }
 138
 139        /// <summary>
 140        /// IsGreaterThan - Returns whether the first double is strictly greater than the second double.
 141        /// </summary>
 142        /// <param name="value2"> The second double to compare. </param>
 143        /// <returns> True if the first double is strictly greater than the second double, otherwise false. </returns>
 6144        public bool IsGreaterThan(double value2) => value > value2 + DblEpsilon;
 145
 146        /// <summary>
 147        /// IsLessThan - Returns whether the first double is strictly less than the second double.
 148        /// </summary>
 149        /// <param name="value2"> The second double to compare. </param>
 150        /// <returns> True if the first double is strictly less than the second double, otherwise false. </returns>
 6151        public bool IsLessThan(double value2) => value < value2 - DblEpsilon;
 152
 153        /// <summary>
 154        /// IsLessThanOrClose - Returns whether the first double is less than or close to
 155        /// the second double.  That is, whether the first is strictly less than or within
 156        /// epsilon of the other number.
 157        /// </summary>
 158        /// <param name="value2"> The second double to compare. </param>
 3159        public bool IsLessThanOrClose(double value2) => value <= value2 || value.IsCloseTo(value2);
 160
 161        /// <summary>
 162        /// IsGreaterThanOrClose - Returns whether the first double is greater than or close to
 163        /// the second double.  That is, whether the first is strictly greater than or within
 164        /// epsilon of the other number.
 165        /// </summary>
 166        /// <param name="value2"> The second double to compare. </param>
 3167        public bool IsGreaterThanOrClose(double value2) => value >= value2 || value.IsCloseTo(value2);
 168
 169        /// <summary>
 170        /// IsOne - Returns whether the double is "close" to 1.  Same as AreClose(double, 1),
 171        /// but this is faster.
 172        /// </summary>
 6173        public bool IsOne() => Math.Abs(value - 1.0) < 10.0 * DblEpsilon;
 174
 175        /// <summary>
 176        /// IsZero - Returns whether the double is "close" to 0.  Same as AreClose(double, 0),
 177        /// but this is faster.
 178        /// </summary>
 6179        public bool IsZero() => Math.Abs(value) < 10.0 * DblEpsilon;
 180
 181        /// <summary>
 182        /// Generates a sequence of doubles starting from the value of the double on which the method is called, increme
 183        /// </summary>
 184        /// <param name="max">The maximum value of the sequence.</param>
 185        /// <param name="step">The increment between each value in the sequence.</param>
 186        /// <returns>An enumerable sequence of doubles.</returns>
 187        /// <exception cref="ArgumentOutOfRangeException">Thrown when the step is zero.</exception>
 188        public IEnumerable<double> Range(double max, double step = 1)
 189        {
 6190            ArgumentOutOfRangeException.ThrowIfZero(step);
 191
 3192            if (step > 0)
 193            {
 24194                for (var i = value; i <= max + DblEpsilon; i += step)
 9195                    yield return i;
 196            }
 197            else
 198            {
 0199                for (var i = value; i >= max - DblEpsilon; i += step)
 0200                    yield return i;
 201            }
 3202        }
 203    }
 204
 205    extension(double? value)
 206    {
 207        /// <summary>
 208        /// Returns whether two nullable doubles are "close".  If both values are null, they are considered close.
 209        /// </summary>
 210        /// <param name="value2">The second double to compare.</param>
 211        /// <returns>True if the values are considered close, otherwise false.</returns>
 9212        public bool IsCloseTo(double? value2) => (!value.HasValue && !value2.HasValue) || (value.HasValue && value2.HasV
 213    }
 214
 215    extension(float value)
 216    {
 217        /// <summary>
 218        /// IsGreaterThan - Returns whether the first float is strictly greater than the second float.
 219        /// </summary>
 220        /// <param name="value2"> The second float to compare. </param>
 221        /// <returns> True if the first float is strictly greater than the second float, otherwise false. </returns>
 3222        public bool IsGreaterThan(float value2) => value > value2 + FloatEpsilon;
 223
 224        /// <summary>
 225        /// IsLessThan - Returns whether the first float is strictly less than the second float.
 226        /// </summary>
 227        /// <param name="value2"> The second float to compare. </param>
 228        /// <returns> True if the first float is strictly less than the second float, otherwise false. </returns>
 3229        public bool IsLessThan(float value2) => value < value2 - FloatEpsilon;
 230
 231        /// <summary>
 232        /// IsLessThanOrClose - Returns whether the first float is less than or close to
 233        /// the second float.  That is, whether the first is strictly less than or within
 234        /// epsilon of the other number.
 235        /// </summary>
 236        /// <param name="value2"> The second float to compare. </param>
 3237        public bool IsLessThanOrClose(float value2) => value <= value2 || value.IsCloseTo(value2);
 238
 239        /// <summary>
 240        /// IsGreaterThanOrClose - Returns whether the first float is greater than or close to
 241        /// the second float.  That is, whether the first is strictly greater than or within
 242        /// epsilon of the other number.
 243        /// </summary>
 244        /// <param name="value2"> The second float to compare. </param>
 3245        public bool IsGreaterThanOrClose(float value2) => value >= value2 || value.IsCloseTo(value2);
 246
 247        /// <summary>
 248        /// IsOne - Returns whether the float is "close" to 1.  Same as AreClose(float, 1),
 249        /// but this is faster.
 250        /// </summary>
 3251        public bool IsOne() => Math.Abs(value - 1.0f) < 10.0f * FloatEpsilon;
 252
 253        /// <summary>
 254        /// IsZero - Returns whether the float is "close" to 0.  Same as AreClose(float, 0),
 255        /// but this is faster.
 256        /// </summary>
 3257        public bool IsZero() => Math.Abs(value) < 10.0f * FloatEpsilon;
 258
 259        /// <summary>
 260        /// Returns whether two float are "close".
 261        /// </summary>
 262        /// <param name="value2"> The second float to compare. </param>
 263        /// <returns>
 264        /// bool - the result of the AreClose comparision.
 265        /// </returns>
 266        [SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator", Justification = "NaN and infinity are handled
 267        public bool IsCloseTo(float value2)
 268        {
 12269            if (float.IsNaN(value) || float.IsNaN(value2))
 6270                return false;
 271
 6272            if (float.IsInfinity(value) || float.IsInfinity(value2))
 3273                return value == value2;
 274
 3275            var eps = (Math.Abs(value) + Math.Abs(value2) + 10.0) * DblEpsilon;
 3276            var delta = value - value2;
 277
 3278            return -eps < delta && delta < eps;
 279        }
 280    }
 281
 282    extension(float? value)
 283    {
 284        /// <summary>
 285        /// Returns whether two nullable floats are "close".  If both values are null, they are considered close.
 286        /// </summary>
 287        /// <param name="value2">The second float to compare.</param>
 288        /// <returns>True if the values are considered close, otherwise false.</returns>
 3289        public bool IsCloseTo(float? value2) => (!value.HasValue && !value2.HasValue) || (value.HasValue && value2.HasVa
 290    }
 291}
 292