1:  using Xint = System.Numerics.BigInteger;
   2:  using Xmath = Luschny.Math.MathUtils.Xmath;
   3:   
   4:  namespace Luschny.Math.Factorial
   5:  {
   6:      public class FactorialBoitenSplit : IFactorialFunction
   7:      {
   8:          public FactorialBoitenSplit() { }
   9:   
  10:          public string Name
  11:          {
  12:              get { return "BoitenSplit         "; }
  13:          }
  14:   
  15:          public Xint Factorial(int n)
  16:          {
  17:              if (n < 0)
  18:              {
  19:                  throw new System.ArgumentOutOfRangeException("n",
  20:                  Name + ": n >= 0 required, but was " + n);
  21:              }
  22:   
  23:              if (n < 2) return Xint.One;
  24:   
  25:              Xint p = Xint.One;
  26:              Xint r = Xint.One;
  27:   
  28:              int h = 0, shift = 0, k = 1;
  29:              int log2n = Xmath.FloorLog2(n);
  30:   
  31:              while (h != n)
  32:              {
  33:                  shift += h;
  34:                  h = n >> log2n--;
  35:                  int high = (h & 1) == 1 ? h : h - 1;
  36:   
  37:                  while (k != high)
  38:                  {
  39:                      k += 2;
  40:                      p *= k;
  41:                  }
  42:                  r *= p;
  43:              }
  44:   
  45:              return r << shift;
  46:          }
  47:      }
  48:  } // endOfFactorialBoitenSplit