< Summary

Class:Towel.Constant<T>
Assembly:Towel
File(s):File 1: /home/runner/work/Towel/Towel/Sources/Towel/Constant.cs
Covered lines:211
Uncovered lines:56
Coverable lines:267
Total lines:503
Line coverage:79% (211 of 267)
Covered branches:36
Total branches:46
Branch coverage:78.2% (36 of 46)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: get_Zero()100%2100%
File 1: set_Zero(...)100%1100%
File 1: get_One()100%2100%
File 1: set_One(...)100%1100%
File 1: get_Two()100%2100%
File 1: set_Two(...)100%1100%
File 1: get_Three()100%2100%
File 1: set_Three(...)100%1100%
File 1: get_Four()100%2100%
File 1: set_Four(...)100%1100%
File 1: get_Ten()100%2100%
File 1: set_Ten(...)100%1100%
File 1: get_NegativeOne()100%2100%
File 1: set_NegativeOne(...)100%1100%
File 1: get_Pi()100%2100%
File 1: set_Pi(...)100%1100%
File 1: get_π()0%20%
File 1: set_π(...)100%10%
File 1: get_Pi2()100%2100%
File 1: set_Pi2(...)100%1100%
File 1: get_π2()0%20%
File 1: set_π2(...)100%10%
File 1: get_PiOver2()100%2100%
File 1: set_PiOver2(...)100%1100%
File 1: get_πOver2()0%20%
File 1: set_πOver2(...)100%10%
File 1: get_Pi3Over2()100%2100%
File 1: set_Pi3Over2(...)100%1100%
File 1: get_π3Over2()0%20%
File 1: set_π3Over2(...)100%10%
File 1: get_FourOverPiSquared()100%2100%
File 1: set_FourOverPiSquared(...)100%1100%
File 1: get_FourOverπSquared()50%250%
File 1: set_FourOverπSquared(...)100%1100%
File 1: get_Negative4OverPiSquared()100%2100%
File 1: set_Negative4OverPiSquared(...)100%1100%
File 1: get_Negative4OverπSquared()50%250%
File 1: set_Negative4OverπSquared(...)100%1100%
File 1: ComputePi(...)100%8100%
File 1: .cctor()100%1100%

File(s)

/home/runner/work/Towel/Towel/Sources/Towel/Constant.cs

#LineLine coverage
 1using System.Linq.Expressions;
 2
 3#pragma warning disable IDE1006 // Naming Styles
 4
 5namespace Towel;
 6
 7/// <summary>Contains generic static numerical constant values.</summary>
 8/// <typeparam name="T">The generic numeric type of the constants.</typeparam>
 9public static class Constant<T>
 10{
 11  internal static bool _zero_assigned;
 12  internal static bool _one_assigned;
 13  internal static bool _two_assigned;
 14  internal static bool _three_assigned;
 15  internal static bool _four_assigned;
 16  internal static bool _ten_assigned;
 17  internal static bool _negativeOne_assigned;
 18  internal static bool _pi_assigned;
 19  internal static bool _pi2_assigned;
 20  internal static bool _piOver2_assigned;
 21  internal static bool _pi3Over2_assigned;
 22  internal static bool _fourOverPiSquared_assigned;
 23  internal static bool _fourOverπSquared_assigned;
 24  internal static bool _negative4OverPiSquared_assigned;
 25  internal static bool _negative4OverπSquared_assigned;
 26
 27#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider de
 28
 29  internal static T _zero;
 30  internal static T _one;
 31  internal static T _two;
 32  internal static T _three;
 33  internal static T _four;
 34  internal static T _ten;
 35  internal static T _negativeOne;
 36  internal static T _pi;
 37  internal static T _pi2;
 38  internal static T _piOver2;
 39  internal static T _pi3Over2;
 40  internal static T _fourOverPiSquared;
 41  internal static T _fourOverπSquared;
 42  internal static T _negative4OverPiSquared;
 43  internal static T _negative4OverπSquared;
 44
 45#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider de
 46
 47  /// <summary>Zero [0]</summary>
 48  public static T Zero
 49  {
 50    get
 135765651    {
 135765652      if (!_zero_assigned)
 453      {
 454        _zero = Convert<int, T>(0);
 455        _zero_assigned = true;
 456      }
 135765657      return _zero;
 135765658    }
 59    set
 460    {
 461      _zero = value;
 462      _zero_assigned = true;
 463    }
 64  }
 65
 66  /// <summary>One [1]</summary>
 67  public static T One
 68  {
 69    get
 232570    {
 232571      if (!_one_assigned)
 472      {
 473        _one = Convert<int, T>(1);
 474        _one_assigned = true;
 475      }
 232576      return _one;
 232577    }
 78    set
 479    {
 480      _one = value;
 481      _one_assigned = true;
 482    }
 83  }
 84
 85  /// <summary>Two [2]</summary>
 86  public static T Two
 87  {
 88    get
 172965589    {
 172965590      if (!_two_assigned)
 491      {
 492        _two = Convert<int, T>(2);
 493        _two_assigned = true;
 494      }
 172965595      return _two;
 172965596    }
 97    set
 498    {
 499      _two = value;
 4100      _two_assigned = true;
 4101    }
 102  }
 103
 104  /// <summary>Three [3]</summary>
 105  public static T Three
 106  {
 107    get
 123282108    {
 123282109      if (!_three_assigned)
 4110      {
 4111        _three = Convert<int, T>(3);
 4112        _three_assigned = true;
 4113      }
 123282114      return _three;
 123282115    }
 116    set
 4117    {
 4118      _three = value;
 4119      _three_assigned = true;
 4120    }
 121  }
 122
 123  /// <summary>Four [4]</summary>
 124  public static T Four
 125  {
 126    get
 4127    {
 4128      if (!_four_assigned)
 4129      {
 4130        _four = Convert<int, T>(4);
 4131        _four_assigned = true;
 4132      }
 4133      return _four;
 4134    }
 135    set
 4136    {
 4137      _four = value;
 4138      _four_assigned = true;
 4139    }
 140  }
 141
 142  /// <summary>Ten [10]</summary>
 143  public static T Ten
 144  {
 145    get
 4146    {
 4147      if (!_ten_assigned)
 4148      {
 4149        _ten = Convert<int, T>(10);
 4150        _ten_assigned = true;
 4151      }
 4152      return _ten;
 4153    }
 154    set
 4155    {
 4156      _ten = value;
 4157      _ten_assigned = true;
 4158    }
 159  }
 160
 161  /// <summary>Negative One [-1]</summary>
 162  public static T NegativeOne
 163  {
 164    get
 170165    {
 170166      if (!_negativeOne_assigned)
 4167      {
 4168        _negativeOne = Convert<int, T>(-1);
 4169        _negativeOne_assigned = true;
 4170      }
 170171      return _negativeOne;
 170172    }
 173    set
 4174    {
 4175      _negativeOne = value;
 4176      _negativeOne_assigned = true;
 4177    }
 178  }
 179
 180  /// <summary>π [3.14...]</summary>
 181  public static T Pi
 182  {
 183    get
 66184    {
 66185      if (!_pi_assigned)
 4186      {
 4187        _pi = ComputePi();
 4188        _pi_assigned = true;
 4189      }
 66190      return _pi;
 66191    }
 192    set
 4193    {
 4194      _pi = value;
 4195      _pi_assigned = true;
 4196    }
 197  }
 198
 199  /// <summary>π [3.14...]</summary>
 200  public static T π
 201  {
 202    get
 0203    {
 0204      if (!_pi_assigned)
 0205      {
 0206        _pi = ComputePi();
 0207        _pi_assigned = true;
 0208      }
 0209      return _pi;
 0210    }
 211    set
 0212    {
 0213      _pi = value;
 0214      _pi_assigned = true;
 0215    }
 216  }
 217
 218  /// <summary>2π [6.28...]</summary>
 219  public static T Pi2
 220  {
 221    get
 6222    {
 6223      if (!_pi2_assigned)
 4224      {
 4225        _pi2 = Multiplication(Two, Pi);
 4226        _pi2_assigned = true;
 4227      }
 6228      return _pi2;
 6229    }
 230    set
 4231    {
 4232      _pi2 = value;
 4233      _pi2_assigned = true;
 4234    }
 235  }
 236
 237  /// <summary>2π [6.28...]</summary>
 238  public static T π2
 239  {
 240    get
 0241    {
 0242      if (!_pi2_assigned)
 0243      {
 0244        _pi2 = Multiplication(Two, Pi);
 0245        _pi2_assigned = true;
 0246      }
 0247      return _pi2;
 0248    }
 249    set
 0250    {
 0251      _pi2 = value;
 0252      _pi2_assigned = true;
 0253    }
 254  }
 255
 256  /// <summary>π / 2</summary>
 257  public static T PiOver2
 258  {
 259    get
 4260    {
 4261      if (!_piOver2_assigned)
 4262      {
 4263        _piOver2 = Division(Pi, Two);
 4264        _piOver2_assigned = true;
 4265      }
 4266      return _piOver2;
 4267    }
 268    set
 4269    {
 4270      _piOver2 = value;
 4271      _piOver2_assigned = true;
 4272    }
 273  }
 274
 275  /// <summary>π / 2</summary>
 276  public static T πOver2
 277  {
 278    get
 0279    {
 0280      if (!_piOver2_assigned)
 0281      {
 0282        _piOver2 = Division(Pi, Two);
 0283        _piOver2_assigned = true;
 0284      }
 0285      return _piOver2;
 0286    }
 287    set
 0288    {
 0289      _piOver2 = value;
 0290      _piOver2_assigned = true;
 0291    }
 292  }
 293
 294  /// <summary>3π/2</summary>
 295  public static T Pi3Over2
 296  {
 297    get
 4298    {
 4299      if (!_pi3Over2_assigned)
 4300      {
 4301        _pi3Over2 = Division(Multiplication(Three, Pi), Two);
 4302        _pi3Over2_assigned = true;
 4303      }
 4304      return _pi3Over2;
 4305    }
 306    set
 4307    {
 4308      _pi3Over2 = value;
 4309      _pi3Over2_assigned = true;
 4310    }
 311  }
 312
 313  /// <summary>3π/2</summary>
 314  public static T π3Over2
 315  {
 316    get
 0317    {
 0318      if (!_pi3Over2_assigned)
 0319      {
 0320        _pi3Over2 = Division(Multiplication(Three, Pi), Two);
 0321        _pi3Over2_assigned = true;
 0322      }
 0323      return _pi3Over2;
 0324    }
 325    set
 0326    {
 0327      _pi3Over2 = value;
 0328      _pi3Over2_assigned = true;
 0329    }
 330  }
 331
 332  /// <summary>4/(π^2)</summary>
 333  public static T FourOverPiSquared
 334  {
 335    get
 8336    {
 8337      if (!_fourOverPiSquared_assigned)
 4338      {
 4339        _fourOverPiSquared = Division(Multiplication(Three, Pi), Two);
 4340        _fourOverPiSquared_assigned = true;
 4341      }
 8342      return _fourOverPiSquared;
 8343    }
 344    set
 4345    {
 4346      _fourOverPiSquared = value;
 4347      _fourOverPiSquared_assigned = true;
 4348    }
 349  }
 350
 351  /// <summary>4/(π^2)</summary>
 352  public static T FourOverπSquared
 353  {
 354    get
 4355    {
 4356      if (!_fourOverPiSquared_assigned)
 0357      {
 0358        _fourOverPiSquared = Division(Multiplication(Three, Pi), Two);
 0359        _fourOverPiSquared_assigned = true;
 0360      }
 4361      return _fourOverPiSquared;
 4362    }
 363    set
 4364    {
 4365      _fourOverPiSquared = value;
 4366      _fourOverPiSquared_assigned = true;
 4367    }
 368  }
 369
 370  /// <summary>-4/(π^2)</summary>
 371  public static T Negative4OverPiSquared
 372  {
 373    get
 4374    {
 4375      if (!_negative4OverPiSquared_assigned)
 4376      {
 4377        _negative4OverPiSquared = Negation(FourOverPiSquared);
 4378        _negative4OverPiSquared_assigned = true;
 4379      }
 4380      return _negative4OverPiSquared;
 4381    }
 382    set
 4383    {
 4384      _negative4OverPiSquared = value;
 4385      _negative4OverPiSquared_assigned = true;
 4386    }
 387  }
 388
 389  /// <summary>-4/(π^2)</summary>
 390  public static T Negative4OverπSquared
 391  {
 392    get
 4393    {
 4394      if (!_negative4OverPiSquared_assigned)
 0395      {
 0396        _negative4OverPiSquared = Negation(FourOverPiSquared);
 0397        _negative4OverPiSquared_assigned = true;
 0398      }
 4399      return _negative4OverPiSquared;
 4400    }
 401    set
 4402    {
 4403      _negative4OverPiSquared = value;
 4404      _negative4OverPiSquared_assigned = true;
 4405    }
 406  }
 407
 408  #region Pi
 409
 410  /// <summary>Computes the value of pi for the provided generic type.</summary>
 411  /// <param name="predicate">The cancellation token for cutting off computation.</param>
 412  /// <returns>The computed value of pi.</returns>
 413  public static T ComputePi(Predicate<T>? predicate = null)
 4414  {
 415    // Series: PI = 2 * (1 + 1/3 * (1 + 2/5 * (1 + 3/7 * (...))))
 416    // more terms in computation inproves accuracy
 417
 4418    if (predicate is null)
 4419    {
 4420      int iterations = 0;
 169421      predicate = PI => ++iterations < 100;
 4422    }
 423
 4424    T pi = Constant<T>.One;
 4425    T previous = Constant<T>.Zero;
 338426    for (int i = 1; Inequate(previous, pi) && predicate(pi); i++)
 165427    {
 165428      previous = pi;
 165429      pi = Constant<T>.One;
 11822430      for (int j = i; j >= 1; j--)
 5746431      {
 432        #region Without Custom Runtime Compilation
 433
 434        // T J = FromInt32<T>(j);
 435        // T a = Add(Multiply(Constant<T>.Two, J), Constant<T>.One);
 436        // T b = Divide(J, a);
 437        // T c = Multiply(b, pi);
 438        // T d = Add(Constant<T>.One, c);
 439        // pi = d;
 440
 441        #endregion
 442
 5746443        pi = AddMultiplyDivideAddImplementation.Function(Convert<int, T>(j), pi);
 5746444      }
 165445      pi = Multiplication(Constant<T>.Two, pi);
 165446    }
 4447    pi = MaximumValue(pi, Constant<T>.Three);
 4448    return pi;
 4449  }
 450
 451  internal static class AddMultiplyDivideAddImplementation
 452  {
 4453    internal static Func<T, T, T> Function = (j, pi) =>
 4454    {
 4455      ParameterExpression J = Expression.Parameter(typeof(T));
 4456      ParameterExpression PI = Expression.Parameter(typeof(T));
 4457      Expression BODY = Expression.Add(
 4458        Expression.Constant(One),
 4459        Expression.Multiply(
 4460          PI,
 4461          Expression.Divide(
 4462            J,
 4463            Expression.Add(
 4464              Expression.Multiply(
 4465                Expression.Constant(Two),
 4466                J),
 4467              Expression.Constant(One)))));
 4468      Function = Expression.Lambda<Func<T, T, T>>(BODY, J, PI).Compile();
 4469      return Function(j, pi);
 8470    };
 471  }
 472
 473  #endregion
 474
 475  #region Golden Ratio
 476#if false
 477
 478    /// <summary>GoldenRatio [(1 + SquareRoot(5)) / 2]</summary>
 479    //public static readonly T GoldenRatio = Symbolics.ParseAndSimplifyToConstant<T>("(1 + SquareRoot(5)) / 2");
 480
 481    /// <summary>Epsilon (1.192092896...e-012f)</summary>
 482    //public static readonly T Epsilon = Compute.ComputeEpsilon<T>();
 483
 484#endif
 485  #endregion
 486
 487  #region Epsilon
 488#if false
 489    // Note sure if this method will be necessary.
 490
 491    //internal static T ComputeEpsilon<T>()
 492    //{
 493    //    if (typeof(T) == typeof(float))
 494    //    {
 495    //        return (T)(object)float.Epsilon;
 496    //    }
 497    //
 498    //}
 499#endif
 500  #endregion
 501}
 502
 503#pragma warning restore IDE1006 // Naming Styles