Exemplo n.º 1
0
 /// <summary>
 /// Returns NormalCdfMomentRatio(i,x) for i=n,n+1,n+2,...
 /// </summary>
 /// <param name="n">A starting index &gt;= 0</param>
 /// <param name="x">A real number</param>
 /// <param name="useConFrac">If true, do not use the lookup table</param>
 /// <returns></returns>
 private static IEnumerator <double> NormalCdfMomentRatioSequence(int n, double x, bool useConFrac = false)
 {
     if (n < 0)
     {
         throw new ArgumentException("n < 0");
     }
     if (x > -1)
     {
         // Use the upward recurrence.
         double rPrev = MMath.NormalCdfRatio(x);
         if (n == 0)
         {
             yield return(rPrev);
         }
         double r = x * rPrev + 1;
         if (n <= 1)
         {
             yield return(r);
         }
         for (int i = 1; ; i++)
         {
             double rNew = (x * r + rPrev) / (i + 1);
             rPrev = r;
             r     = rNew;
             if (n <= i + 1)
             {
                 yield return(r);
             }
         }
     }
     else
     {
         // Use the downward recurrence.
         // Each batch of tableSize items is generated in advance.
         // If tableSize is larger than 50, the results will lose accuracy.
         // If tableSize is too small, then the recurrence is used less often, requiring more computation.
         int maxTableSize = 30;
         // rtable[tableStart-i] = R_i
         double[] rtable     = new double[maxTableSize];
         int      tableStart = -1;
         int      tableSize  = 2;
         for (int i = n; ; i++)
         {
             if (i > tableStart)
             {
                 // build the table
                 tableStart = i + tableSize - 1;
                 if (useConFrac)
                 {
                     rtable[0] = MMath.NormalCdfMomentRatioConFrac(tableStart, x);
                     rtable[1] = MMath.NormalCdfMomentRatioConFrac(tableStart - 1, x);
                 }
                 else
                 {
                     rtable[0] = MMath.NormalCdfMomentRatio(tableStart, x);
                     rtable[1] = MMath.NormalCdfMomentRatio(tableStart - 1, x);
                 }
                 for (int j = 2; j < tableSize; j++)
                 {
                     int nj = tableStart - j + 1;
                     if (rtable[j - 2] == 0 && rtable[j - 1] == 0)
                     {
                         rtable[j] = MMath.NormalCdfMomentRatio(nj - 1, x);
                     }
                     else
                     {
                         rtable[j] = (nj + 1) * rtable[j - 2] - x * rtable[j - 1];
                     }
                 }
                 // Increase tableSize up to the maximum.
                 tableSize = Math.Min(maxTableSize, 2 * tableSize);
             }
             yield return(rtable[tableStart - i]);
         }
     }
 }