1:  using Luschny.Math.Arithmetic;
   2:   
   3:  namespace Luschny.Math.Factorial
   4:  {
   5:      public class FactorialDifference : IFactorialFunction
   6:      {
   7:          public FactorialDifference() { }
   8:   
   9:          public string Name
  10:          {
  11:              get { return "Difference"; }
  12:          }
  13:   
  14:          public Xint Factorial(int n)
  15:          {
  16:              if (n < 0)
  17:              {
  18:                  throw new System.ArgumentOutOfRangeException("n",
  19:                        Name + ": n >= 0 required, but was " + n);
  20:              }
  21:   
  22:              if (n < 2) return Xint.One;
  23:   
  24:              Xint f;
  25:   
  26:              switch (n % 4)
  27:              {
  28:                  case 1: f = (Xint) n; break;
  29:                  case 2: f = (Xint)((long)n * (n - 1)); break;
  30:                  case 3: f = (Xint)((long)n * (n - 1) * (n - 2)); break;
  31:                  default: f = Xint.One; break;
  32:              }
  33:   
  34:              long prod = 24;
  35:              long diff1 = 1656;
  36:              long diff2 = 8544;
  37:              long diff3 = 13056;
  38:   
  39:              int i = n / 4;
  40:              while (i-- > 0)
  41:              {
  42:                  f = f * prod; 
  43:                  prod += diff1;
  44:                  diff1 += diff2;
  45:                  diff2 += diff3;
  46:                  diff3 += 6144;
  47:              }
  48:              return f;
  49:          }
  50:      }
  51:  }  // endOfFactorialDifference