Subversion Repositories Kolibri OS

Rev

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

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