1 /*******************************************************************************
2  * chi2.cpp
3  *
4  * This module contains the function for the chi square distribution.
5  *
6  * This software is derived from the Cephes Math Library and is
7  * incorporated herein by permission of the author, Stephen L. Moshier.
8  *
9  *   Cephes Math Library Release 2.0:  April, 1987
10  *   Copyright 1984, 1987 by Stephen L. Moshier
11  *
12  * The author reserves the right to distribute this material elsewhere under
13  * different terms. This file is provided within POV-Ray under the following
14  * terms:
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions are met:
18  *
19  *  1. Redistributions of source code must retain the above copyright notice,
20  *     this list of conditions and the following disclaimer.
21  *  2. Redistributions in binary form must reproduce the above copyright notice,
22  *     this list of conditions and the following disclaimer in the documentation
23  *     and/or other materials provided with the distribution.
24  *  3. Neither the names of the copyright holders nor the names of contributors
25  *     may be used to endorse or promote products derived from this software
26  *     without specific prior written permission.
27  *
28  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
32  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  *  POSSIBILITY OF SUCH DAMAGE.
39  * ---------------------------------------------------------------------------
40  * $File: //depot/public/povray/3.x/source/backend/math/chi2.cpp $
41  * $Revision: #1 $
42  * $Change: 6069 $
43  * $DateTime: 2013/11/06 11:59:40 $
44  * $Author: chrisc $
45  *******************************************************************************/
46 
47 // frame.h must always be the first POV file included (pulls in platform config)
48 #include "backend/frame.h"
49 #include "backend/math/chi2.h"
50 #include "base/pov_err.h"
51 
52 // this must be the last file included
53 #include "base/povdebug.h"
54 
55 namespace pov
56 {
57 
58 /*
59 Cephes Math Library Release 2.0:  April, 1987
60 Copyright 1984, 1987 by Stephen L. Moshier
61 Direct inquiries to 30 Frost Street, Cambridge, MA 02140
62 */
63 
64 /*****************************************************************************
65 * Local preprocessor defines
66 ******************************************************************************/
67 
68 const DBL MAXLGM = 2.556348e305;
69 const DBL BIG    = 1.44115188075855872E+17;
70 const DBL MACHEP = 1.38777878078144567553E-17; /* 2**-56 */
71 const DBL MAXLOG = 8.8029691931113054295988E1; /* log(2**127) */
72 const DBL MAXNUM = 1.701411834604692317316873e38;  /* 2**127 */
73 const DBL LOGPI  = 1.14472988584940017414;
74 
75 /*
76  * A[]: Stirling's formula expansion of log gamma
77  * B[], C[]: log gamma function between 2 and 3
78  */
79 
80 const DBL A[] =
81 {
82 	 8.11614167470508450300E-4,
83 	-5.95061904284301438324E-4,
84 	 7.93650340457716943945E-4,
85 	-2.77777777730099687205E-3,
86 	 8.33333333333331927722E-2
87 };
88 
89 const DBL B[] =
90 {
91 	-1.37825152569120859100E3,
92 	-3.88016315134637840924E4,
93 	-3.31612992738871184744E5,
94 	-1.16237097492762307383E6,
95 	-1.72173700820839662146E6,
96 	-8.53555664245765465627E5
97 };
98 
99 const DBL C[] =
100 {
101 	 1.00000000000000000000E0,
102 	-3.51815701436523470549E2,
103 	-1.70642106651881159223E4,
104 	-2.20528590553854454839E5,
105 	-1.13933444367982507207E6,
106 	-2.53252307177582951285E6,
107 	-2.01889141433532773231E6
108 };
109 
110 /* log(sqrt(2pi)) */
111 
112 const DBL LS2PI = 0.91893853320467274178;
113 
114 /* sqrt(2pi) */
115 
116 const DBL s2pi = 2.50662827463100050242E0;
117 
118 /* approximation for 0 <= |y - 0.5| <= 3/8 */
119 
120 const DBL P0[5] =
121 {
122 	-5.99633501014107895267E1,
123 	 9.80010754185999661536E1,
124 	-5.66762857469070293439E1,
125 	 1.39312609387279679503E1,
126 	-1.23916583867381258016E0,
127 };
128 
129 const DBL Q0[8] =
130 {
131 /*	 1.00000000000000000000E0,*/
132 	 1.95448858338141759834E0,
133 	 4.67627912898881538453E0,
134 	 8.63602421390890590575E1,
135 	-2.25462687854119370527E2,
136 	 2.00260212380060660359E2,
137 	-8.20372256168333339912E1,
138 	 1.59056225126211695515E1,
139 	-1.18331621121330003142E0,
140 };
141 
142 /*
143  * Approximation for interval z = sqrt(-2 log y ) between 2 and 8
144  * i.e., y between exp(-2) = .135 and exp(-32) = 1.27e-14.
145  */
146 
147 const DBL P1[9] =
148 {
149 	 4.05544892305962419923E0,
150 	 3.15251094599893866154E1,
151 	 5.71628192246421288162E1,
152 	 4.40805073893200834700E1,
153 	 1.46849561928858024014E1,
154 	 2.18663306850790267539E0,
155 	-1.40256079171354495875E-1,
156 	-3.50424626827848203418E-2,
157 	-8.57456785154685413611E-4,
158 };
159 
160 const DBL Q1[8] =
161 {
162 /*	 1.00000000000000000000E0,*/
163 	 1.57799883256466749731E1,
164 	 4.53907635128879210584E1,
165 	 4.13172038254672030440E1,
166 	 1.50425385692907503408E1,
167 	 2.50464946208309415979E0,
168 	-1.42182922854787788574E-1,
169 	-3.80806407691578277194E-2,
170 	-9.33259480895457427372E-4,
171 };
172 
173 /*
174  * Approximation for interval z = sqrt(-2 log y ) between 8 and 64
175  * i.e., y between exp(-32) = 1.27e-14 and exp(-2048) = 3.67e-890.
176  */
177 
178 const DBL P2[9] =
179 {
180 	3.23774891776946035970E0,
181 	6.91522889068984211695E0,
182 	3.93881025292474443415E0,
183 	1.33303460815807542389E0,
184 	2.01485389549179081538E-1,
185 	1.23716634817820021358E-2,
186 	3.01581553508235416007E-4,
187 	2.65806974686737550832E-6,
188 	6.23974539184983293730E-9,
189 };
190 
191 const DBL Q2[8] =
192 {
193 /*	1.00000000000000000000E0,*/
194 	6.02427039364742014255E0,
195 	3.67983563856160859403E0,
196 	1.37702099489081330271E0,
197 	2.16236993594496635890E-1,
198 	1.34204006088543189037E-2,
199 	3.28014464682127739104E-4,
200 	2.89247864745380683936E-6,
201 	6.79019408009981274425E-9,
202 };
203 
204 
205 /*****************************************************************************
206 * Static functions
207 ******************************************************************************/
208 
209 static DBL igami (DBL a, DBL y0);
210 static DBL lgam (DBL x, int *sgngam);
211 static DBL polevl (DBL x, const DBL * coef, int N);
212 static DBL p1evl (DBL x, const DBL * coef, int N);
213 static DBL igamc (DBL a, DBL x);
214 static DBL igam (DBL a, DBL x);
215 static DBL ndtri (DBL y0);
216 
217 
218 
219 /*              chdtri()
220  *
221  *  Inverse of complemented Chi-square distribution
222  *
223  *
224  *
225  * SYNOPSIS:
226  *
227  * DBL df, x, y, chdtri();
228  *
229  * x = chdtri( df, y );
230  *
231  *
232  *
233  *
234  * DESCRIPTION:
235  *
236  * Finds the Chi-square argument x such that the integral
237  * from x to infinity of the Chi-square density is equal
238  * to the given cumulative probability y.
239  *
240  * This is accomplished using the inverse gamma integral
241  * function and the relation
242  *
243  *    x/2 = igami( df/2, y );
244  *
245  *
246  *
247  *
248  * ACCURACY:
249  *
250  * See igami.c.
251  *
252  * ERROR MESSAGES:
253  *
254  *   message         condition      value returned
255  * chdtri domain   y < 0 or y > 1        0.0
256  *                     v < 1
257  *
258  */
259 
chdtri(DBL df,DBL y)260 DBL chdtri(DBL df, DBL  y)
261 {
262 	DBL x;
263 
264 	if ((y < 0.0) || (y > 1.0) || (df < 1.0))
265 	{
266 		throw POV_EXCEPTION_STRING("Illegal values in chdtri().");
267 
268 		return (0.0);
269 	}
270 
271 	x = igami(0.5 * df, y);
272 
273 	return (2.0 * x);
274 }
275 
276 
277 
278 /*              lgam()
279  *
280  *  Natural logarithm of gamma function
281  *
282  *
283  *
284  * SYNOPSIS:
285  *
286  * DBL x, y, lgam();
287  *
288  * y = lgam( x );
289  *
290  *
291  *
292  * DESCRIPTION:
293  *
294  * Returns the base e (2.718...) logarithm of the absolute
295  * value of the gamma function of the argument.
296  * The sign (+1 or -1) of the gamma function is returned in a
297  * variable named sgngam.
298  *
299  * For arguments greater than 13, the logarithm of the gamma
300  * function is approximated by the logarithmic version of
301  * Stirling's formula using a polynomial approximation of
302  * degree 4. Arguments between -33 and +33 are reduced by
303  * recurrence to the interval [2,3] of a rational approximation.
304  * The cosecant reflection formula is employed for arguments
305  * less than -33.
306  *
307  * Arguments greater than MAXLGM return MAXNUM and an error
308  * message.  MAXLGM = 2.035093e36 for DEC
309  * arithmetic or 2.556348e305 for IEEE arithmetic.
310  *
311  *
312  *
313  * ACCURACY:
314  *
315  *
316  * arithmetic      domain        # trials     peak         rms
317  *    DEC     0, 3                  7000     5.2e-17     1.3e-17
318  *    DEC     2.718, 2.035e36       5000     3.9e-17     9.9e-18
319  *    IEEE    0, 3                 28000     5.4e-16     1.1e-16
320  *    IEEE    2.718, 2.556e305     40000     3.5e-16     8.3e-17
321  * The error criterion was relative when the function magnitude
322  * was greater than one but absolute when it was less than one.
323  *
324  * The following test used the relative error criterion, though
325  * at certain points the relative error could be much higher than
326  * indicated.
327  *    IEEE    -200, -4             10000     4.8e-16     1.3e-16
328  *
329  */
330 
lgam(DBL x,int * sgngam)331 static DBL lgam(DBL x, int *sgngam)
332 {
333 	DBL p, q, w, z;
334 	int i;
335 
336 	*sgngam = 1;
337 
338 	if (x < -34.0)
339 	{
340 		q = -x;
341 		w = lgam(q, sgngam);  /* note this modifies sgngam! */
342 		p = floor(q);
343 
344 		if (p == q)
345 		{
346 			goto loverf;
347 		}
348 
349 		i = p;
350 
351 		if ((i & 1) == 0)
352 		{
353 			*sgngam = -1;
354 		}
355 		else
356 		{
357 			*sgngam = 1;
358 		}
359 
360 		z = q - p;
361 
362 		if (z > 0.5)
363 		{
364 			p += 1.0;
365 
366 			z = p - q;
367 		}
368 
369 		z = q * sin(M_PI * z);
370 
371 		if (z == 0.0)
372 		{
373 			goto loverf;
374 		}
375 
376 /*		z = log(M_PI) - log( z ) - w;*/
377 
378 		z = LOGPI - log(z) - w;
379 
380 		return (z);
381 	}
382 
383 	if (x < 13.0)
384 	{
385 		z = 1.0;
386 
387 		while (x >= 3.0)
388 		{
389 			x -= 1.0;
390 
391 			z *= x;
392 		}
393 
394 		while (x < 2.0)
395 		{
396 			if (x == 0.0)
397 			{
398 				goto loverf;
399 			}
400 
401 			z /= x;
402 
403 			x += 1.0;
404 		}
405 
406 		if (z < 0.0)
407 		{
408 			*sgngam = -1;
409 
410 			z = -z;
411 		}
412 		else
413 		{
414 			*sgngam = 1;
415 		}
416 
417 		if (x == 2.0)
418 		{
419 			return (log(z));
420 		}
421 
422 		x -= 2.0;
423 
424 		p = x * polevl(x, B, 5) / p1evl(x, C, 6);
425 
426 		return (log(z) + p);
427 	}
428 
429 	if (x > MAXLGM)
430 	{
431 		loverf:
432 /*
433 		mtherr("lgam", OVERFLOW);
434 */
435 		return (*sgngam * MAXNUM);
436 	}
437 
438 	q = (x - 0.5) * log(x) - x + LS2PI;
439 
440 	if (x > 1.0e8)
441 	{
442 		return (q);
443 	}
444 
445 	p = 1.0 / (x * x);
446 
447 	if (x >= 1000.0)
448 	{
449 		q += ((7.9365079365079365079365e-4 * p -
450 		       2.7777777777777777777778e-3) * p +
451 		       0.0833333333333333333333) / x;
452 	}
453 	else
454 	{
455 		q += polevl(p, A, 4) / x;
456 	}
457 
458 	return (q);
459 }
460 
461 
462 
463 /*              igamc()
464  *
465  *  Complemented incomplete gamma integral
466  *
467  *
468  *
469  * SYNOPSIS:
470  *
471  * DBL a, x, y, igamc();
472  *
473  * y = igamc( a, x );
474  *
475  *
476  *
477  * DESCRIPTION:
478  *
479  * The function is defined by
480  *
481  *
482  *  igamc(a,x)   =   1 - igam(a,x)
483  *
484  *                            inf.
485  *                              -
486  *                     1       | |  -t  a-1
487  *               =   -----     |   e   t   dt.
488  *                    -      | |
489  *                   | (a)    -
490  *                             x
491  *
492  *
493  * In this implementation both arguments must be positive.
494  * The integral is evaluated by either a power series or
495  * continued fraction expansion, depending on the relative
496  * values of a and x.
497  *
498  *
499  *
500  * ACCURACY:
501  *
502  *                      Relative error:
503  * arithmetic   domain     # trials      peak         rms
504  *    DEC       0,30         2000       2.7e-15     4.0e-16
505  *    IEEE      0,30        60000       1.4e-12     6.3e-15
506  *
507  */
508 
igamc(DBL a,DBL x)509 static DBL igamc(DBL a, DBL  x)
510 {
511 	DBL ans, c, yc, ax, y, z;
512 	DBL pk, pkm1, pkm2, qk, qkm1, qkm2;
513 	DBL r, t;
514 	int sgngam = 0;
515 
516 	if ((x <= 0) || (a <= 0))
517 	{
518 		return (1.0);
519 	}
520 
521 	if ((x < 1.0) || (x < a))
522 	{
523 		return (1.0 - igam(a, x));
524 	}
525 
526 	ax = a * log(x) - x - lgam(a, &sgngam);
527 
528 	if (ax < -MAXLOG)
529 	{
530 /*
531 		mtherr("igamc", UNDERFLOW);
532 */
533 		return (0.0);
534 	}
535 
536 	ax = exp(ax);
537 
538 /* continued fraction */
539 
540 	y = 1.0 - a;
541 	z = x + y + 1.0;
542 	c = 0.0;
543 
544 	pkm2 = 1.0;
545 	qkm2 = x;
546 	pkm1 = x + 1.0;
547 	qkm1 = z * x;
548 
549 	ans = pkm1 / qkm1;
550 
551 	do
552 	{
553 		c += 1.0;
554 		y += 1.0;
555 		z += 2.0;
556 
557 		yc = y * c;
558 
559 		pk = pkm1 * z - pkm2 * yc;
560 		qk = qkm1 * z - qkm2 * yc;
561 
562 		if (qk != 0)
563 		{
564 			r = pk / qk;
565 			t = fabs((ans - r) / r);
566 			ans = r;
567 		}
568 		else
569 		{
570 			t = 1.0;
571 		}
572 
573 		pkm2 = pkm1;
574 		pkm1 = pk;
575 		qkm2 = qkm1;
576 		qkm1 = qk;
577 
578 		if (fabs(pk) > BIG)
579 		{
580 			pkm2 /= BIG;
581 			pkm1 /= BIG;
582 			qkm2 /= BIG;
583 			qkm1 /= BIG;
584 		}
585 	}
586 	while (t > MACHEP);
587 
588 	return (ans * ax);
589 }
590 
591 
592 
593 /*              igam.c
594  *
595  *  Incomplete gamma integral
596  *
597  *
598  *
599  * SYNOPSIS:
600  *
601  * DBL a, x, y, igam();
602  *
603  * y = igam( a, x );
604  *
605  *
606  *
607  * DESCRIPTION:
608  *
609  * The function is defined by
610  *
611  *                           x
612  *                            -
613  *                   1       | |  -t  a-1
614  *  igam(a,x)  =   -----     |   e   t   dt.
615  *                  -      | |
616  *                 | (a)    -
617  *                           0
618  *
619  *
620  * In this implementation both arguments must be positive.
621  * The integral is evaluated by either a power series or
622  * continued fraction expansion, depending on the relative
623  * values of a and x.
624  *
625  *
626  *
627  * ACCURACY:
628  *
629  *                      Relative error:
630  * arithmetic   domain     # trials      peak         rms
631  *    DEC       0,30         4000       4.4e-15     6.3e-16
632  *    IEEE      0,30        10000       3.6e-14     5.1e-15
633  *
634  */
635 
636 /* left tail of incomplete gamma function:
637  *
638  *          inf.      k
639  *   a  -x   -       x
640  *  x  e     >   ----------
641  *           -     -
642  *          k=0   | (a+k+1)
643  *
644  */
645 
igam(DBL a,DBL x)646 static DBL igam(DBL a, DBL  x)
647 {
648 	DBL ans, ax, c, r;
649 	int sgngam = 0;
650 
651 	if ((x <= 0) || (a <= 0))
652 	{
653 		return (0.0);
654 	}
655 
656 	if ((x > 1.0) && (x > a))
657 	{
658 		return (1.0 - igamc(a, x));
659 	}
660 
661 /* Compute  x**a * exp(-x) / gamma(a)  */
662 	ax = a * log(x) - x - lgam(a, &sgngam);
663 
664 	if (ax < -MAXLOG)
665 	{
666 /*
667 		mtherr("igam", UNDERFLOW);
668 */
669 		return (0.0);
670 	}
671 
672 	ax = exp(ax);
673 
674 /* power series */
675 	r = a;
676 	c = 1.0;
677 	ans = 1.0;
678 
679 	do
680 	{
681 		r += 1.0;
682 		c *= x / r;
683 		ans += c;
684 	}
685 	while (c / ans > MACHEP);
686 
687 	return (ans * ax / a);
688 }
689 
690 
691 
692 /*              igami()
693  *
694  *      Inverse of complemented imcomplete gamma integral
695  *
696  *
697  *
698  * SYNOPSIS:
699  *
700  * DBL a, x, y, igami();
701  *
702  * x = igami( a, y );
703  *
704  *
705  *
706  * DESCRIPTION:
707  *
708  * Given y, the function finds x such that
709  *
710  *  igamc( a, x ) = y.
711  *
712  * Starting with the approximate value
713  *
714  *         3
715  *  x = a t
716  *
717  *  where
718  *
719  *  t = 1 - d - ndtri(y) sqrt(d)
720  *
721  * and
722  *
723  *  d = 1/9a,
724  *
725  * the routine performs up to 10 Newton iterations to find the
726  * root of igamc(a,x) - y = 0.
727  *
728  *
729  * ACCURACY:
730  *
731  * Tested for a ranging from 0.5 to 30 and x from 0 to 0.5.
732  *
733  *                      Relative error:
734  * arithmetic   domain     # trials      peak         rms
735  *    DEC       0,0.5         3400       8.8e-16     1.3e-16
736  *    IEEE      0,0.5        10000       1.1e-14     1.0e-15
737  *
738  */
739 
igami(DBL a,DBL y0)740 static DBL igami(DBL a, DBL  y0)
741 {
742 	DBL d, y, x0, lgm;
743 	int i;
744 	int sgngam = 0;
745 
746 /* approximation to inverse function */
747 	d = 1.0 / (9.0 * a);
748 	y = (1.0 - d - ndtri(y0) * sqrt(d));
749 
750 	x0 = a * y * y * y;
751 
752 	lgm = lgam(a, &sgngam);
753 
754 	for (i = 0; i < 10; i++)
755 	{
756 		if (x0 <= 0.0)
757 		{
758 /*
759 			mtherr("igami", UNDERFLOW);
760 */
761 			return (0.0);
762 		}
763 
764 		y = igamc(a, x0);
765 
766 /* compute the derivative of the function at this point */
767 		d = (a - 1.0) * log(x0) - x0 - lgm;
768 
769 		if (d < -MAXLOG)
770 		{
771 /*
772 			mtherr("igami", UNDERFLOW);
773 */
774 			goto done;
775 		}
776 
777 		d = -exp(d);
778 
779 /* compute the step to the next approximation of x */
780 		if (d == 0.0)
781 		{
782 			goto done;
783 		}
784 
785 		d = (y - y0) / d;
786 
787 		x0 = x0 - d;
788 
789 		if (i < 3)
790 		{
791 			continue;
792 		}
793 
794 		if (fabs(d / x0) < 2.0 * MACHEP)
795 		{
796 			goto done;
797 		}
798 	}
799 
800 done:
801 
802 	return (x0);
803 }
804 
805 
806 
807 /*              ndtri.c
808  *
809  *  Inverse of Normal distribution function
810  *
811  *
812  *
813  * SYNOPSIS:
814  *
815  * DBL x, y, ndtri();
816  *
817  * x = ndtri( y );
818  *
819  *
820  *
821  * DESCRIPTION:
822  *
823  * Returns the argument, x, for which the area under the
824  * Gaussian probability density function (integrated from
825  * minus infinity to x) is equal to y.
826  *
827  *
828  * For small arguments 0 < y < exp(-2), the program computes
829  * z = sqrt( -2.0 * log(y) );  then the approximation is
830  * x = z - log(z)/z  - (1/z) P(1/z) / Q(1/z).
831  * There are two rational functions P/Q, one for 0 < y < exp(-32)
832  * and the other for y up to exp(-2).  For larger arguments,
833  * w = y - 0.5, and  x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)).
834  *
835  *
836  * ACCURACY:
837  *
838  *                      Relative error:
839  * arithmetic   domain        # trials      peak         rms
840  *    DEC      0.125, 1         5500       9.5e-17     2.1e-17
841  *    DEC      6e-39, 0.135     3500       5.7e-17     1.3e-17
842  *    IEEE     0.125, 1        20000       7.2e-16     1.3e-16
843  *    IEEE     3e-308, 0.135   50000       4.6e-16     9.8e-17
844  *
845  *
846  * ERROR MESSAGES:
847  *
848  *   message         condition    value returned
849  * ndtri domain       x <= 0        -MAXNUM
850  * ndtri domain       x >= 1         MAXNUM
851  *
852  */
853 
ndtri(DBL y0)854 static DBL ndtri(DBL y0)
855 {
856 	DBL x, y, z, y2, x0, x1;
857 	int code;
858 
859 	if (y0 <= 0.0)
860 	{
861 /*
862 		mtherr("ndtri", DOMAIN);
863 */
864 		return (-MAXNUM);
865 	}
866 
867 	if (y0 >= 1.0)
868 	{
869 /*
870 		mtherr("ndtri", DOMAIN);
871 */
872 		return (MAXNUM);
873 	}
874 
875 	code = 1;
876 
877 	y = y0;
878 
879 	if (y > (1.0 - 0.13533528323661269189)) /* 0.135... = exp(-2) */
880 	{
881 		y = 1.0 - y;
882 		code = 0;
883 	}
884 
885 	if (y > 0.13533528323661269189)
886 	{
887 		y = y - 0.5;
888 		y2 = y * y;
889 		x = y + y * (y2 * polevl(y2, P0, 4) / p1evl(y2, Q0, 8));
890 		x = x * s2pi;
891 
892 		return (x);
893 	}
894 
895 	x = sqrt(-2.0 * log(y));
896 	x0 = x - log(x) / x;
897 
898 	z = 1.0 / x;
899 
900 	if (x < 8.0)  /* y > exp(-32) = 1.2664165549e-14 */
901 	{
902 		x1 = z * polevl(z, P1, 8) / p1evl(z, Q1, 8);
903 	}
904 	else
905 	{
906 		x1 = z * polevl(z, P2, 8) / p1evl(z, Q2, 8);
907 	}
908 
909 	x = x0 - x1;
910 
911 	if (code != 0)
912 	{
913 		x = -x;
914 	}
915 
916 	return (x);
917 }
918 
919 
920 
921 /*              polevl.c
922  *              p1evl.c
923  *
924  *  Evaluate polynomial
925  *
926  *
927  *
928  * SYNOPSIS:
929  *
930  * int N;
931  * DBL x, y, coef[N+1], polevl[];
932  *
933  * y = polevl( x, coef, N );
934  *
935  *
936  *
937  * DESCRIPTION:
938  *
939  * Evaluates polynomial of degree N:
940  *
941  *                     2          N
942  * y  =  C  + C x + C x  +...+ C x
943  *        0    1     2          N
944  *
945  * Coefficients are stored in reverse order:
946  *
947  * coef[0] = C  , ..., coef[N] = C  .
948  *            N                   0
949  *
950  *  The function p1evl() assumes that coef[N] = 1.0 and is
951  * omitted from the array.  Its calling arguments are
952  * otherwise the same as polevl().
953  *
954  *
955  * SPEED:
956  *
957  * In the interest of speed, there are no checks for out
958  * of bounds arithmetic.  This routine is used by most of
959  * the functions in the library.  Depending on available
960  * equipment features, the user may wish to rewrite the
961  * program in microcode or assembly language.
962  *
963  */
964 
polevl(DBL x,const DBL coef[],int N)965 static DBL polevl(DBL x, const DBL coef[], int N)
966 {
967 	DBL ans;
968 	int i;
969 	DBL const *p;
970 
971 	p = coef;
972 	ans = *p++;
973 	i = N;
974 
975 	do
976 	{
977 		ans = ans * x + *p++;
978 	}
979 	while (--i);
980 
981 	return (ans);
982 }
983 
984 /*              p1evl() */
985 /*                                          N
986  * Evaluate polynomial when coefficient of x  is 1.0.
987  * Otherwise same as polevl.
988  */
989 
p1evl(DBL x,const DBL coef[],int N)990 static DBL p1evl(DBL x, const DBL coef[], int N)
991 {
992 	DBL ans;
993 	DBL const *p;
994 	int i;
995 
996 	p = coef;
997 	ans = x + *p++;
998 	i = N - 1;
999 
1000 	do
1001 	{
1002 		ans = ans * x + *p++;
1003 	}
1004 	while (--i);
1005 
1006 	return (ans);
1007 }
1008 
1009 }
1010