GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libm/src/e_jnf.c Lines: 0 65 0.0 %
Date: 2017-11-07 Branches: 0 52 0.0 %

Line Branch Exec Source
1
/* e_jnf.c -- float version of e_jn.c.
2
 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3
 */
4
5
/*
6
 * ====================================================
7
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8
 *
9
 * Developed at SunPro, a Sun Microsystems, Inc. business.
10
 * Permission to use, copy, modify, and distribute this
11
 * software is freely granted, provided that this notice
12
 * is preserved.
13
 * ====================================================
14
 */
15
16
#include "math.h"
17
#include "math_private.h"
18
19
static const float
20
two   =  2.0000000000e+00, /* 0x40000000 */
21
one   =  1.0000000000e+00; /* 0x3F800000 */
22
23
static const float zero  =  0.0000000000e+00;
24
25
float
26
jnf(int n, float x)
27
{
28
	int32_t i,hx,ix, sgn;
29
	float a, b, temp, di;
30
	float z, w;
31
32
    /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
33
     * Thus, J(-n,x) = J(n,-x)
34
     */
35
	GET_FLOAT_WORD(hx,x);
36
	ix = 0x7fffffff&hx;
37
    /* if J(n,NaN) is NaN */
38
	if(ix>0x7f800000) return x+x;
39
	if(n<0){
40
		n = -n;
41
		x = -x;
42
		hx ^= 0x80000000;
43
	}
44
	if(n==0) return(j0f(x));
45
	if(n==1) return(j1f(x));
46
	sgn = (n&1)&(hx>>31);	/* even n -- 0, odd n -- sign(x) */
47
	x = fabsf(x);
48
	if(ix==0||ix>=0x7f800000) 	/* if x is 0 or inf */
49
	    b = zero;
50
	else if((float)n<=x) {
51
		/* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
52
	    a = j0f(x);
53
	    b = j1f(x);
54
	    for(i=1;i<n;i++){
55
		temp = b;
56
		b = b*((float)(i+i)/x) - a; /* avoid underflow */
57
		a = temp;
58
	    }
59
	} else {
60
	    if(ix<0x30800000) {	/* x < 2**-29 */
61
    /* x is tiny, return the first Taylor expansion of J(n,x)
62
     * J(n,x) = 1/n!*(x/2)^n  - ...
63
     */
64
		if(n>33)	/* underflow */
65
		    b = zero;
66
		else {
67
		    temp = x*(float)0.5; b = temp;
68
		    for (a=one,i=2;i<=n;i++) {
69
			a *= (float)i;		/* a = n! */
70
			b *= temp;		/* b = (x/2)^n */
71
		    }
72
		    b = b/a;
73
		}
74
	    } else {
75
		/* use backward recurrence */
76
		/* 			x      x^2      x^2
77
		 *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
78
		 *			2n  - 2(n+1) - 2(n+2)
79
		 *
80
		 * 			1      1        1
81
		 *  (for large x)   =  ----  ------   ------   .....
82
		 *			2n   2(n+1)   2(n+2)
83
		 *			-- - ------ - ------ -
84
		 *			 x     x         x
85
		 *
86
		 * Let w = 2n/x and h=2/x, then the above quotient
87
		 * is equal to the continued fraction:
88
		 *		    1
89
		 *	= -----------------------
90
		 *		       1
91
		 *	   w - -----------------
92
		 *			  1
93
		 * 	        w+h - ---------
94
		 *		       w+2h - ...
95
		 *
96
		 * To determine how many terms needed, let
97
		 * Q(0) = w, Q(1) = w(w+h) - 1,
98
		 * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
99
		 * When Q(k) > 1e4	good for single
100
		 * When Q(k) > 1e9	good for double
101
		 * When Q(k) > 1e17	good for quadruple
102
		 */
103
	    /* determine k */
104
		float t,v;
105
		float q0,q1,h,tmp; int32_t k,m;
106
		w  = (n+n)/(float)x; h = (float)2.0/(float)x;
107
		q0 = w;  z = w+h; q1 = w*z - (float)1.0; k=1;
108
		while(q1<(float)1.0e9) {
109
			k += 1; z += h;
110
			tmp = z*q1 - q0;
111
			q0 = q1;
112
			q1 = tmp;
113
		}
114
		m = n+n;
115
		for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
116
		a = t;
117
		b = one;
118
		/*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
119
		 *  Hence, if n*(log(2n/x)) > ...
120
		 *  single 8.8722839355e+01
121
		 *  double 7.09782712893383973096e+02
122
		 *  long double 1.1356523406294143949491931077970765006170e+04
123
		 *  then recurrent value may overflow and the result is
124
		 *  likely underflow to zero
125
		 */
126
		tmp = n;
127
		v = two/x;
128
		tmp = tmp*logf(fabsf(v*tmp));
129
		if(tmp<(float)8.8721679688e+01) {
130
	    	    for(i=n-1,di=(float)(i+i);i>0;i--){
131
		        temp = b;
132
			b *= di;
133
			b  = b/x - a;
134
		        a = temp;
135
			di -= two;
136
	     	    }
137
		} else {
138
	    	    for(i=n-1,di=(float)(i+i);i>0;i--){
139
		        temp = b;
140
			b *= di;
141
			b  = b/x - a;
142
		        a = temp;
143
			di -= two;
144
		    /* scale b to avoid spurious overflow */
145
			if(b>(float)1e10) {
146
			    a /= b;
147
			    t /= b;
148
			    b  = one;
149
			}
150
	     	    }
151
		}
152
	    	b = (t*j0f(x)/b);
153
	    }
154
	}
155
	if(sgn==1) return -b; else return b;
156
}
157
158
float
159
ynf(int n, float x)
160
{
161
	int32_t i,hx,ix,ib;
162
	int32_t sign;
163
	float a, b, temp;
164
165
	GET_FLOAT_WORD(hx,x);
166
	ix = 0x7fffffff&hx;
167
    /* if Y(n,NaN) is NaN */
168
	if(ix>0x7f800000) return x+x;
169
	if(ix==0) return -one/zero;
170
	if(hx<0) return zero/zero;
171
	sign = 1;
172
	if(n<0){
173
		n = -n;
174
		sign = 1 - ((n&1)<<1);
175
	}
176
	if(n==0) return(y0f(x));
177
	if(n==1) return(sign*y1f(x));
178
	if(ix==0x7f800000) return zero;
179
180
	a = y0f(x);
181
	b = y1f(x);
182
	/* quit if b is -inf */
183
	GET_FLOAT_WORD(ib,b);
184
	for(i=1;i<n&&ib!=0xff800000;i++){
185
	    temp = b;
186
	    b = ((float)(i+i)/x)*b - a;
187
	    GET_FLOAT_WORD(ib,b);
188
	    a = temp;
189
	}
190
	if(sign>0) return b; else return -b;
191
}