Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/* ef_jn.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 "fdlibm.h"
17
 
18
#ifdef __STDC__
19
static const float
20
#else
21
static float
22
#endif
23
invsqrtpi=  5.6418961287e-01, /* 0x3f106ebb */
24
two   =  2.0000000000e+00, /* 0x40000000 */
25
one   =  1.0000000000e+00; /* 0x3F800000 */
26
 
27
#ifdef __STDC__
28
static const float zero  =  0.0000000000e+00;
29
#else
30
static float zero  =  0.0000000000e+00;
31
#endif
32
 
33
#ifdef __STDC__
34
	float __ieee754_jnf(int n, float x)
35
#else
36
	float __ieee754_jnf(n,x)
37
	int n; float x;
38
#endif
39
{
40
	__int32_t i,hx,ix, sgn;
41
	float a, b, temp, di;
42
	float z, w;
43
 
44
    /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
45
     * Thus, J(-n,x) = J(n,-x)
46
     */
47
	GET_FLOAT_WORD(hx,x);
48
	ix = 0x7fffffff&hx;
49
    /* if J(n,NaN) is NaN */
50
	if(FLT_UWORD_IS_NAN(ix)) return x+x;
51
	if(n<0){
52
		n = -n;
53
		x = -x;
54
		hx ^= 0x80000000;
55
	}
56
	if(n==0) return(__ieee754_j0f(x));
57
	if(n==1) return(__ieee754_j1f(x));
58
	sgn = (n&1)&(hx>>31);	/* even n -- 0, odd n -- sign(x) */
59
	x = fabsf(x);
60
	if(FLT_UWORD_IS_ZERO(ix)||FLT_UWORD_IS_INFINITE(ix))
61
	    b = zero;
62
	else if((float)n<=x) {
63
		/* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
64
	    a = __ieee754_j0f(x);
65
	    b = __ieee754_j1f(x);
66
	    for(i=1;i
67
		temp = b;
68
		b = b*((float)(i+i)/x) - a; /* avoid underflow */
69
		a = temp;
70
	    }
71
	} else {
72
	    if(ix<0x30800000) {	/* x < 2**-29 */
73
    /* x is tiny, return the first Taylor expansion of J(n,x)
74
     * J(n,x) = 1/n!*(x/2)^n  - ...
75
     */
76
		if(n>33)	/* underflow */
77
		    b = zero;
78
		else {
79
		    temp = x*(float)0.5; b = temp;
80
		    for (a=one,i=2;i<=n;i++) {
81
			a *= (float)i;		/* a = n! */
82
			b *= temp;		/* b = (x/2)^n */
83
		    }
84
		    b = b/a;
85
		}
86
	    } else {
87
		/* use backward recurrence */
88
		/* 			x      x^2      x^2
89
		 *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
90
		 *			2n  - 2(n+1) - 2(n+2)
91
		 *
92
		 * 			1      1        1
93
		 *  (for large x)   =  ----  ------   ------   .....
94
		 *			2n   2(n+1)   2(n+2)
95
		 *			-- - ------ - ------ -
96
		 *			 x     x         x
97
		 *
98
		 * Let w = 2n/x and h=2/x, then the above quotient
99
		 * is equal to the continued fraction:
100
		 *		    1
101
		 *	= -----------------------
102
		 *		       1
103
		 *	   w - -----------------
104
		 *			  1
105
		 * 	        w+h - ---------
106
		 *		       w+2h - ...
107
		 *
108
		 * To determine how many terms needed, let
109
		 * Q(0) = w, Q(1) = w(w+h) - 1,
110
		 * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
111
		 * When Q(k) > 1e4	good for single
112
		 * When Q(k) > 1e9	good for double
113
		 * When Q(k) > 1e17	good for quadruple
114
		 */
115
	    /* determine k */
116
		float t,v;
117
		float q0,q1,h,tmp; __int32_t k,m;
118
		w  = (n+n)/(float)x; h = (float)2.0/(float)x;
119
		q0 = w;  z = w+h; q1 = w*z - (float)1.0; k=1;
120
		while(q1<(float)1.0e9) {
121
			k += 1; z += h;
122
			tmp = z*q1 - q0;
123
			q0 = q1;
124
			q1 = tmp;
125
		}
126
		m = n+n;
127
		for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
128
		a = t;
129
		b = one;
130
		/*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
131
		 *  Hence, if n*(log(2n/x)) > ...
132
		 *  single 8.8722839355e+01
133
		 *  double 7.09782712893383973096e+02
134
		 *  long double 1.1356523406294143949491931077970765006170e+04
135
		 *  then recurrent value may overflow and the result is
136
		 *  likely underflow to zero
137
		 */
138
		tmp = n;
139
		v = two/x;
140
		tmp = tmp*__ieee754_logf(fabsf(v*tmp));
141
		if(tmp<(float)8.8721679688e+01) {
142
	    	    for(i=n-1,di=(float)(i+i);i>0;i--){
143
		        temp = b;
144
			b *= di;
145
			b  = b/x - a;
146
		        a = temp;
147
			di -= two;
148
	     	    }
149
		} else {
150
	    	    for(i=n-1,di=(float)(i+i);i>0;i--){
151
		        temp = b;
152
			b *= di;
153
			b  = b/x - a;
154
		        a = temp;
155
			di -= two;
156
		    /* scale b to avoid spurious overflow */
157
			if(b>(float)1e10) {
158
			    a /= b;
159
			    t /= b;
160
			    b  = one;
161
			}
162
	     	    }
163
		}
164
	    	b = (t*__ieee754_j0f(x)/b);
165
	    }
166
	}
167
	if(sgn==1) return -b; else return b;
168
}
169
 
170
#ifdef __STDC__
171
	float __ieee754_ynf(int n, float x)
172
#else
173
	float __ieee754_ynf(n,x)
174
	int n; float x;
175
#endif
176
{
177
	__int32_t i,hx,ix,ib;
178
	__int32_t sign;
179
	float a, b, temp;
180
 
181
	GET_FLOAT_WORD(hx,x);
182
	ix = 0x7fffffff&hx;
183
    /* if Y(n,NaN) is NaN */
184
	if(FLT_UWORD_IS_NAN(ix)) return x+x;
185
	if(FLT_UWORD_IS_ZERO(ix)) return -one/zero;
186
	if(hx<0) return zero/zero;
187
	sign = 1;
188
	if(n<0){
189
		n = -n;
190
		sign = 1 - ((n&1)<<1);
191
	}
192
	if(n==0) return(__ieee754_y0f(x));
193
	if(n==1) return(sign*__ieee754_y1f(x));
194
	if(FLT_UWORD_IS_INFINITE(ix)) return zero;
195
 
196
	a = __ieee754_y0f(x);
197
	b = __ieee754_y1f(x);
198
	/* quit if b is -inf */
199
	GET_FLOAT_WORD(ib,b);
200
	for(i=1;i
201
	    temp = b;
202
	    b = ((float)(i+i)/x)*b - a;
203
	    GET_FLOAT_WORD(ib,b);
204
	    a = temp;
205
	}
206
	if(sign>0) return b; else return -b;
207
}