2012-03-13 01:17:53 -04:00
|
|
|
/* origin: FreeBSD /usr/src/lib/msun/src/e_jnf.c */
|
|
|
|
/*
|
|
|
|
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* ====================================================
|
|
|
|
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
|
|
|
*
|
|
|
|
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
|
|
|
* Permission to use, copy, modify, and distribute this
|
|
|
|
* software is freely granted, provided that this notice
|
|
|
|
* is preserved.
|
|
|
|
* ====================================================
|
|
|
|
*/
|
|
|
|
|
2012-03-16 21:16:32 -04:00
|
|
|
#define _GNU_SOURCE
|
2012-03-13 01:17:53 -04:00
|
|
|
#include "libm.h"
|
|
|
|
|
|
|
|
float jnf(int n, float x)
|
|
|
|
{
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
uint32_t ix;
|
|
|
|
int nm1, sign, i;
|
|
|
|
float a, b, temp;
|
|
|
|
|
|
|
|
GET_FLOAT_WORD(ix, x);
|
|
|
|
sign = ix>>31;
|
|
|
|
ix &= 0x7fffffff;
|
|
|
|
if (ix > 0x7f800000) /* nan */
|
|
|
|
return x;
|
2012-03-13 01:17:53 -04:00
|
|
|
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
/* J(-n,x) = J(n,-x), use |n|-1 to avoid overflow in -n */
|
|
|
|
if (n == 0)
|
|
|
|
return j0f(x);
|
2012-03-13 01:17:53 -04:00
|
|
|
if (n < 0) {
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
nm1 = -(n+1);
|
2012-03-13 01:17:53 -04:00
|
|
|
x = -x;
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
sign ^= 1;
|
|
|
|
} else
|
|
|
|
nm1 = n-1;
|
|
|
|
if (nm1 == 0)
|
|
|
|
return j1f(x);
|
2012-03-13 01:17:53 -04:00
|
|
|
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
sign &= n; /* even n: 0, odd n: signbit(x) */
|
2012-03-13 01:17:53 -04:00
|
|
|
x = fabsf(x);
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
if (ix == 0 || ix == 0x7f800000) /* if x is 0 or inf */
|
2012-03-19 23:41:19 +01:00
|
|
|
b = 0.0f;
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
else if (nm1 < x) {
|
2012-03-13 01:17:53 -04:00
|
|
|
/* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
|
|
|
|
a = j0f(x);
|
|
|
|
b = j1f(x);
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
for (i=0; i<nm1; ){
|
|
|
|
i++;
|
2012-03-13 01:17:53 -04:00
|
|
|
temp = b;
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
b = b*(2.0f*i/x) - a;
|
2012-03-13 01:17:53 -04:00
|
|
|
a = temp;
|
|
|
|
}
|
|
|
|
} else {
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
if (ix < 0x35800000) { /* x < 2**-20 */
|
2012-03-13 01:17:53 -04:00
|
|
|
/* x is tiny, return the first Taylor expansion of J(n,x)
|
|
|
|
* J(n,x) = 1/n!*(x/2)^n - ...
|
|
|
|
*/
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
if (nm1 > 8) /* underflow */
|
|
|
|
nm1 = 8;
|
|
|
|
temp = 0.5f * x;
|
|
|
|
b = temp;
|
|
|
|
a = 1.0f;
|
|
|
|
for (i=2; i<=nm1+1; i++) {
|
|
|
|
a *= (float)i; /* a = n! */
|
|
|
|
b *= temp; /* b = (x/2)^n */
|
2012-03-13 01:17:53 -04:00
|
|
|
}
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
b = b/a;
|
2012-03-13 01:17:53 -04:00
|
|
|
} else {
|
|
|
|
/* use backward recurrence */
|
|
|
|
/* x x^2 x^2
|
|
|
|
* J(n,x)/J(n-1,x) = ---- ------ ------ .....
|
|
|
|
* 2n - 2(n+1) - 2(n+2)
|
|
|
|
*
|
|
|
|
* 1 1 1
|
|
|
|
* (for large x) = ---- ------ ------ .....
|
|
|
|
* 2n 2(n+1) 2(n+2)
|
|
|
|
* -- - ------ - ------ -
|
|
|
|
* x x x
|
|
|
|
*
|
|
|
|
* Let w = 2n/x and h=2/x, then the above quotient
|
|
|
|
* is equal to the continued fraction:
|
|
|
|
* 1
|
|
|
|
* = -----------------------
|
|
|
|
* 1
|
|
|
|
* w - -----------------
|
|
|
|
* 1
|
|
|
|
* w+h - ---------
|
|
|
|
* w+2h - ...
|
|
|
|
*
|
|
|
|
* To determine how many terms needed, let
|
|
|
|
* Q(0) = w, Q(1) = w(w+h) - 1,
|
|
|
|
* Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
|
|
|
|
* When Q(k) > 1e4 good for single
|
|
|
|
* When Q(k) > 1e9 good for double
|
|
|
|
* When Q(k) > 1e17 good for quadruple
|
|
|
|
*/
|
|
|
|
/* determine k */
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
float t,q0,q1,w,h,z,tmp,nf;
|
|
|
|
int k;
|
2012-03-13 01:17:53 -04:00
|
|
|
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
nf = nm1+1.0f;
|
|
|
|
w = 2*nf/x;
|
|
|
|
h = 2/x;
|
2012-03-13 01:17:53 -04:00
|
|
|
z = w+h;
|
|
|
|
q0 = w;
|
2012-03-13 20:24:23 +01:00
|
|
|
q1 = w*z - 1.0f;
|
2012-03-13 01:17:53 -04:00
|
|
|
k = 1;
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
while (q1 < 1.0e4f) {
|
2012-03-13 01:17:53 -04:00
|
|
|
k += 1;
|
|
|
|
z += h;
|
|
|
|
tmp = z*q1 - q0;
|
|
|
|
q0 = q1;
|
|
|
|
q1 = tmp;
|
|
|
|
}
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
for (t=0.0f, i=k; i>=0; i--)
|
|
|
|
t = 1.0f/(2*(i+nf)/x-t);
|
2012-03-13 01:17:53 -04:00
|
|
|
a = t;
|
2012-03-19 23:41:19 +01:00
|
|
|
b = 1.0f;
|
2012-03-13 01:17:53 -04:00
|
|
|
/* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
|
|
|
|
* Hence, if n*(log(2n/x)) > ...
|
|
|
|
* single 8.8722839355e+01
|
|
|
|
* double 7.09782712893383973096e+02
|
|
|
|
* long double 1.1356523406294143949491931077970765006170e+04
|
|
|
|
* then recurrent value may overflow and the result is
|
|
|
|
* likely underflow to zero
|
|
|
|
*/
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
tmp = nf*logf(fabsf(w));
|
2012-03-13 20:24:23 +01:00
|
|
|
if (tmp < 88.721679688f) {
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
for (i=nm1; i>0; i--) {
|
2012-03-13 01:17:53 -04:00
|
|
|
temp = b;
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
b = 2.0f*i*b/x - a;
|
2012-03-13 01:17:53 -04:00
|
|
|
a = temp;
|
|
|
|
}
|
|
|
|
} else {
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
for (i=nm1; i>0; i--){
|
2012-03-13 01:17:53 -04:00
|
|
|
temp = b;
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
b = 2.0f*i*b/x - a;
|
2012-03-13 01:17:53 -04:00
|
|
|
a = temp;
|
|
|
|
/* scale b to avoid spurious overflow */
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
if (b > 0x1p60f) {
|
2012-03-13 01:17:53 -04:00
|
|
|
a /= b;
|
|
|
|
t /= b;
|
2012-03-19 23:41:19 +01:00
|
|
|
b = 1.0f;
|
2012-03-13 01:17:53 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
z = j0f(x);
|
|
|
|
w = j1f(x);
|
|
|
|
if (fabsf(z) >= fabsf(w))
|
|
|
|
b = t*z/b;
|
|
|
|
else
|
|
|
|
b = t*w/a;
|
|
|
|
}
|
|
|
|
}
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
return sign ? -b : b;
|
2012-03-13 01:17:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
float ynf(int n, float x)
|
|
|
|
{
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
uint32_t ix, ib;
|
|
|
|
int nm1, sign, i;
|
2012-03-13 01:17:53 -04:00
|
|
|
float a, b, temp;
|
|
|
|
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
GET_FLOAT_WORD(ix, x);
|
|
|
|
sign = ix>>31;
|
|
|
|
ix &= 0x7fffffff;
|
|
|
|
if (ix > 0x7f800000) /* nan */
|
|
|
|
return x;
|
|
|
|
if (sign && ix != 0) /* x < 0 */
|
|
|
|
return 0/0.0f;
|
2012-03-13 01:17:53 -04:00
|
|
|
if (ix == 0x7f800000)
|
2012-03-19 23:41:19 +01:00
|
|
|
return 0.0f;
|
2012-03-13 01:17:53 -04:00
|
|
|
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
if (n == 0)
|
|
|
|
return y0f(x);
|
|
|
|
if (n < 0) {
|
|
|
|
nm1 = -(n+1);
|
|
|
|
sign = n&1;
|
|
|
|
} else {
|
|
|
|
nm1 = n-1;
|
|
|
|
sign = 0;
|
|
|
|
}
|
|
|
|
if (nm1 == 0)
|
|
|
|
return sign ? -y1f(x) : y1f(x);
|
|
|
|
|
2012-03-13 01:17:53 -04:00
|
|
|
a = y0f(x);
|
|
|
|
b = y1f(x);
|
|
|
|
/* quit if b is -inf */
|
|
|
|
GET_FLOAT_WORD(ib,b);
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
for (i = 0; i < nm1 && ib != 0xff800000; ) {
|
|
|
|
i++;
|
2012-03-13 01:17:53 -04:00
|
|
|
temp = b;
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
b = (2.0f*i/x)*b - a;
|
2012-03-13 01:17:53 -04:00
|
|
|
GET_FLOAT_WORD(ib, b);
|
|
|
|
a = temp;
|
|
|
|
}
|
math: bessel cleanup (jn.c and jnf.c)
both jn and yn functions had integer overflow issues for large
and small n
to handle these issues nm1 (== |n|-1) is used instead of n and -n
in the code and some loops are changed to make sure the iteration
counter does not overflow
(another solution could be to use larger integer type or even double
but that has more size and runtime cost, on x87 loading int64_t or
even uint32_t into an fpu register is more than two times slower than
loading int32_t, and using double for n slows down iteration logic)
yn(-1,0) now returns inf
posix2008 specifies that on overflow and at +-0 all y0,y1,yn functions
return -inf, this is not consistent with math when n<0 odd integer in yn
(eg. when x->0, yn(-1,x)->inf, but historically yn(-1,0) seems to be
special cased and returned -inf)
some threshold values in jnf and ynf were fixed that seems to be
incorrectly copy-pasted from the double version
2013-01-01 22:20:45 +01:00
|
|
|
return sign ? -b : b;
|
2012-03-13 01:17:53 -04:00
|
|
|
}
|