1:  using Xint = System.Numerics.BigInteger;
   2:   
   3:   
   4:  namespace Luschny.Math.Factorial
   5:  {
   6:      public class FactorialSwingDouble : IFactorialFunction
   7:      {
   8:          public FactorialSwingDouble() { }
   9:   
  10:          public string Name
  11:          {
  12:              get { return "SwingDouble         "; }
  13:          }
  14:   
  15:          private Xint f;
  16:          private long gN;
  17:   
  18:          public Xint Factorial(int n)
  19:          {
  20:              if (n < 0)
  21:              {
  22:                  throw new System.ArgumentOutOfRangeException("n",
  23:                  Name + ": n >= 0 required, but was " + n);
  24:              }
  25:   
  26:              gN = 1;
  27:              f = Xint.One;
  28:              return RecFactorial(n);
  29:          }
  30:   
  31:          private Xint RecFactorial(int n)
  32:          {
  33:              if (n < 2) return Xint.One;
  34:   
  35:              return Xint.Pow(RecFactorial(n / 2),2) * Swing(n);
  36:          }
  37:   
  38:          private Xint Swing(long n)
  39:          {
  40:              long s = gN - 1 + ((n - gN + 1) % 4);
  41:              bool oddN = (gN & 1) != 1;
  42:   
  43:              for (; gN <= s; gN++)
  44:              {
  45:                  if (oddN = !oddN) f *= gN;
  46:                  else f = (f * 4) / gN;
  47:              }
  48:   
  49:              if (oddN) for (; gN <= n; gN += 4)
  50:              {
  51:                      long m = ((gN + 1) * (gN + 3)) << 1;
  52:                      long d = (gN * (gN + 2)) >> 3;
  53:   
  54:                      f = (f * m) / d;
  55:              }
  56:              else for (; gN <= n; gN += 4)
  57:              {
  58:                      long m = (gN * (gN + 2)) << 1;
  59:                      long d = ((gN + 1) * (gN + 3)) >> 3;
  60:   
  61:                      f = (f * m) / d;
  62:               }
  63:   
  64:              return f;
  65:          }
  66:      }
  67:  } // endOfSwingDouble