summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2007-03-22 17:12:00 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2007-03-22 17:12:00 +0000
commit79c1064cdd08d5b305845b9eb41d790b50d4d468 (patch)
treed3a3fc05a58905a2091e9b14ff9f79ee8464a00b
parent508d281088b07df8116e0340ee01ba8ab7186774 (diff)
downloadmpfr-79c1064cdd08d5b305845b9eb41d790b50d4d468.tar.gz
added Bessel functions of first kind: j0, j1, jn
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@4385 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--Makefile.am2
-rw-r--r--algorithms.tex46
-rw-r--r--jn.c140
-rw-r--r--mpfr.h4
-rw-r--r--mpfr.texi11
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/reuse.c4
-rw-r--r--tests/tj0.c96
-rw-r--r--tests/tj1.c84
-rw-r--r--tests/tjn.c136
10 files changed, 521 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am
index 0ed9f3991..e58367370 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,7 +7,7 @@ include_HEADERS = mpfr.h mpf2mpfr.h
lib_LTLIBRARIES = libmpfr.la
-libmpfr_la_SOURCES = mpfr.h mpf2mpfr.h mpfr-gmp.h mpfr-impl.h mpfr-longlong.h mpfr-test.h exceptions.c extract.c uceil_exp2.c uceil_log2.c ufloor_log2.c add.c add1.c add_ui.c agm.c clear.c cmp.c cmp_abs.c cmp_si.c cmp_ui.c comparisons.c div_2exp.c div_2si.c div_2ui.c div.c div_ui.c dump.c eq.c exp10.c exp2.c exp3.c exp.c frac.c get_d.c get_exp.c get_str.c init.c inp_str.c isinteger.c isinf.c isnan.c isnum.c const_log2.c log.c mul_2exp.c mul_2si.c mul_2ui.c mul.c mul_ui.c neg.c next.c out_str.c const_pi.c pow.c pow_si.c pow_ui.c print_raw.c print_rnd_mode.c random2.c random.c reldiff.c round_prec.c set.c setmax.c setmin.c set_d.c set_dfl_prec.c set_exp.c set_rnd.c set_f.c set_prc_raw.c set_prec.c set_q.c set_si.c set_str.c set_str_raw.c set_ui.c set_z.c sqrt.c sqrt_ui.c sub.c sub1.c sub_ui.c rint.c ui_div.c ui_sub.c urandomb.c get_z_exp.c swap.c factorial.c cosh.c sinh.c tanh.c acosh.c asinh.c atanh.c atan.c cmp2.c exp_2.c asin.c const_euler.c cos.c sin.c tan.c fma.c hypot.c log1p.c expm1.c log2.c log10.c ui_pow.c ui_pow_ui.c minmax.c dim.c copysign.c gmp_op.c init2.c acos.c sin_cos.c set_nan.c set_inf.c powerof2.c gamma.c set_ld.c get_ld.c cbrt.c volatile.c fits_s.h fits_sshort.c fits_sint.c fits_slong.c fits_u.h fits_ushort.c fits_uint.c fits_ulong.c fits_uintmax.c fits_intmax.c get_si.c get_ui.c zeta.c cmp_d.c erf.c inits.c inits2.c clears.c sgn.c check.c sub1sp.c version.c mpn_exp.c mpfr-gmp.c mp_clz_tab.c sum.c add1sp.c free_cache.c si_op.c cmp_ld.c set_ui_2exp.c set_si_2exp.c set_uj.c set_sj.c get_sj.c get_uj.c get_z.c iszero.c cache.c sqr.c int_ceil_log2.c isqrt.c strtofr.c pow_z.c logging.c mulders.c get_f.c round_p.c erfc.c atan2.c subnormal.c const_catalan.c root.c gen_inverse.h sec.c csc.c cot.c eint.c sech.c csch.c coth.c round_near_x.c constant.c abort_prec_max.c stack_interface.c lngamma.c zeta_ui.c set_d64.c get_d64.c
+libmpfr_la_SOURCES = mpfr.h mpf2mpfr.h mpfr-gmp.h mpfr-impl.h mpfr-longlong.h mpfr-test.h exceptions.c extract.c uceil_exp2.c uceil_log2.c ufloor_log2.c add.c add1.c add_ui.c agm.c clear.c cmp.c cmp_abs.c cmp_si.c cmp_ui.c comparisons.c div_2exp.c div_2si.c div_2ui.c div.c div_ui.c dump.c eq.c exp10.c exp2.c exp3.c exp.c frac.c get_d.c get_exp.c get_str.c init.c inp_str.c isinteger.c isinf.c isnan.c isnum.c const_log2.c log.c mul_2exp.c mul_2si.c mul_2ui.c mul.c mul_ui.c neg.c next.c out_str.c const_pi.c pow.c pow_si.c pow_ui.c print_raw.c print_rnd_mode.c random2.c random.c reldiff.c round_prec.c set.c setmax.c setmin.c set_d.c set_dfl_prec.c set_exp.c set_rnd.c set_f.c set_prc_raw.c set_prec.c set_q.c set_si.c set_str.c set_str_raw.c set_ui.c set_z.c sqrt.c sqrt_ui.c sub.c sub1.c sub_ui.c rint.c ui_div.c ui_sub.c urandomb.c get_z_exp.c swap.c factorial.c cosh.c sinh.c tanh.c acosh.c asinh.c atanh.c atan.c cmp2.c exp_2.c asin.c const_euler.c cos.c sin.c tan.c fma.c hypot.c log1p.c expm1.c log2.c log10.c ui_pow.c ui_pow_ui.c minmax.c dim.c copysign.c gmp_op.c init2.c acos.c sin_cos.c set_nan.c set_inf.c powerof2.c gamma.c set_ld.c get_ld.c cbrt.c volatile.c fits_s.h fits_sshort.c fits_sint.c fits_slong.c fits_u.h fits_ushort.c fits_uint.c fits_ulong.c fits_uintmax.c fits_intmax.c get_si.c get_ui.c zeta.c cmp_d.c erf.c inits.c inits2.c clears.c sgn.c check.c sub1sp.c version.c mpn_exp.c mpfr-gmp.c mp_clz_tab.c sum.c add1sp.c free_cache.c si_op.c cmp_ld.c set_ui_2exp.c set_si_2exp.c set_uj.c set_sj.c get_sj.c get_uj.c get_z.c iszero.c cache.c sqr.c int_ceil_log2.c isqrt.c strtofr.c pow_z.c logging.c mulders.c get_f.c round_p.c erfc.c atan2.c subnormal.c const_catalan.c root.c gen_inverse.h sec.c csc.c cot.c eint.c sech.c csch.c coth.c round_near_x.c constant.c abort_prec_max.c stack_interface.c lngamma.c zeta_ui.c set_d64.c get_d64.c jn.c
libmpfr_la_LIBADD = @LIBOBJS@
diff --git a/algorithms.tex b/algorithms.tex
index f2bf6f90c..e54c0f56c 100644
--- a/algorithms.tex
+++ b/algorithms.tex
@@ -456,7 +456,7 @@ error is bounded by $2k$ ulps.
If the rounding are not away from zero, the following lemma is still useful
\cite{Graillat05}:
-\begin{lemma}
+\begin{lemma} \label{lemma_graillat}
Let $\delta_1, \ldots, \delta_n$ be $n$ real values such that
$|\delta_i| \leq \epsilon$, for $n \epsilon < 1$.
Then we can write $\prod_{i=1}^n (1+\delta_i)
@@ -2995,6 +2995,50 @@ this gives a total bound of $(18n+51) 2^{-p} v_{n+1}$, which is less
than $(18n+51) \ulp(r)$, or twice this in the improbable case where there
is an exponent loss in the final subtraction $r = \circ(v_{n+1}-w)$.
+\subsection{The Bessel function}
+
+The Bessel function $J_n(z)$ of first kind and integer order $n$
+is defined as follows \cite[Eq.~(9.1.10)]{AbSt73}:
+\[ J_n(z) = (z/2)^n \sum_{k=0}^{\infty} \frac{(-z^2/4)^k}{k! (k+n)!}. \]
+We use the following algorithm, with working precision $w$, and rounding
+to nearest:
+\begin{quote}
+$x \leftarrow \circ(z^n)$ \\
+$y \leftarrow \circ(z^2)/4$ [division by $4$ is exact] \\
+$u \leftarrow \circ(n!)$ \\
+$t \leftarrow \circ(x/u)/2^n$ [division by $2^n$ is exact] \\
+$s \leftarrow t$ \\
+for $k$ from $1$ do \\
+\q $t \leftarrow -\circ(ty)$ \\
+\q $t \leftarrow \circ(t/k)$ \\
+\q $t \leftarrow \circ(t/(k+n))$ \\
+\q $s \leftarrow \circ(s+t)$ \\
+\q if $|t| < \ulp(s)$ and $z^2 \leq 2k(k+n)$ then return $s$. \\
+\end{quote}
+The condition $z^2 \leq 2k(k+n)$ ensures that the next term of the
+expansion is smaller than $|t|/2$, thus the sum of the remaining terms
+is smaller than $|t| < \ulp(s)$.
+Using Higham's method, with $\theta$ denoting a random variable of value
+$|\theta| \leq 2^{-w}$ --- different instances of $\theta$ denoting
+different values --- we can write $x = z^n (1+\theta)$,
+$y = z^2/4 (1+\theta)$,
+and before the for-loop $s = t = (z/2)^n/n! (1+\theta)^3$.
+Now write $t = (z/2)^n (-z^2/4)^k / (k! (k+n)!) (1+\theta)^{e_k}$ at the end of
+the for-loop with index $k$; each loop involves a factor $(1+\theta)^4$,
+thus we have $e_k = 4k+3$.
+Now let $T$ be an upper bound on the values of $|t|$ and $|s|$ during the
+for-loop, and assume we exit at $k=K$.
+The roundoff error in the additions
+$\circ(s+t)$, including the error in the series
+truncation, is bounded by $(K/2+1) \ulp(T)$.
+The error in the value of $t$ at step $k$ is bounded by $\epsilon_k :=
+T |(1+\theta)^{4k+3}
+-1|$; if we assume $(4k+3) 2^{-w} \leq 1/2$, Lemma~\ref{lemma_graillat}
+yields $\epsilon_k \leq 2 T (4k+3) 2^{-w}$. Summing from $k=0$ to $K$,
+this gives an absolute error bound on $s$ at the end of the for-loop of:
+\[ (K/2+1) \ulp(T) + 2 (2K^2+5K+3) 2^{-w} T \leq (4K^2+21/2K+7) \ulp(T), \]
+where we used $2^{-w} T \leq \ulp(T)$.
+
\subsection{Summary}
\begin{table}
diff --git a/jn.c b/jn.c
new file mode 100644
index 000000000..7dab618f4
--- /dev/null
+++ b/jn.c
@@ -0,0 +1,140 @@
+/* mpfr_j0, mpfr_j1, mpfr_jn -- Bessel functions of 1st kind and integer order.
+ http://www.opengroup.org/onlinepubs/009695399/functions/j0.html
+
+Copyright 2007 Free Software Foundation, Inc.
+Contributed by the Arenaire and Cacao projects, INRIA.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+MA 02110-1301, USA. */
+
+#define MPFR_NEED_LONGLONG_H
+#include "mpfr-impl.h"
+
+/* Relations: j(-n,z) = (-1)^n j(n,z) */
+
+int
+mpfr_j0 (mpfr_ptr res, mpfr_srcptr z, mp_rnd_t r)
+{
+ return mpfr_jn (res, z, 0, r);
+}
+
+int
+mpfr_j1 (mpfr_ptr res, mpfr_srcptr z, mp_rnd_t r)
+{
+ return mpfr_jn (res, z, 1, r);
+}
+
+int
+mpfr_jn (mpfr_ptr res, mpfr_srcptr z, int n, mp_rnd_t r)
+{
+ int inex, absn;
+ mp_prec_t prec, err;
+ mp_exp_t exps, expT;
+ mpfr_t y, s, t;
+ unsigned long k, zz;
+ MPFR_ZIV_DECL (loop);
+
+ MPFR_LOG_FUNC (("x[%#R]=%R n=%d rnd=%d", z, z, n, r),
+ ("y[%#R]=%R inexact=%d", res, res, inex));
+
+ absn = (n >= 0) ? n : -n;
+
+ if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (z)))
+ {
+ if (MPFR_IS_NAN (z))
+ {
+ MPFR_SET_NAN (res);
+ MPFR_RET_NAN;
+ }
+ /* j(n,z) tends to zero when z goes to +Inf or -Inf, oscillating around
+ 0. We choose to return +0 in that case. */
+ else if (MPFR_IS_INF (z)) /* FIXME: according to j(-n,z) = (-1)^n j(n,z)
+ we might want to give a sign depending on
+ z and n */
+ return mpfr_set_ui (res, 0, r);
+ else /* z=0: j(0,0)=1, j(n odd,+/-0) = +/-0 if n > 0, -/+0 if n < 0,
+ j(n even,+/-0) = +0 */
+ {
+ if (n == 0)
+ return mpfr_set_ui (res, 1, r);
+ else if (absn & 1) /* n odd */
+ return (n > 0) ? mpfr_set (res, z, r) : mpfr_neg (res, z, r);
+ else /* n even */
+ return mpfr_set_ui (res, 0, r);
+ }
+ }
+
+ prec = MPFR_PREC (res) + MPFR_INT_CEIL_LOG2 (MPFR_PREC (res)) + 3;
+
+ mpfr_init2 (y, prec);
+ mpfr_init2 (s, prec);
+ mpfr_init2 (t, prec);
+
+ MPFR_ZIV_INIT (loop, prec);
+ for (;;)
+ {
+ mpfr_pow_ui (t, z, absn, GMP_RNDN);
+ mpfr_mul (y, z, z, GMP_RNDN);
+ zz = mpfr_get_ui (y, GMP_RNDU);
+ MPFR_ASSERTN (zz < ULONG_MAX);
+ mpfr_div_2ui (y, y, 2, GMP_RNDN);
+ mpfr_fac_ui (s, absn, GMP_RNDN);
+ mpfr_div (t, t, s, GMP_RNDN);
+ if (absn > 0)
+ mpfr_div_2ui (t, t, absn, GMP_RNDN);
+ mpfr_set (s, t, GMP_RNDN);
+ exps = MPFR_EXP (s);
+ expT = exps;
+ for (k = 1; ; k++)
+ {
+ mpfr_mul (t, t, y, GMP_RNDN);
+ mpfr_neg (t, t, GMP_RNDN);
+ if (k + absn <= ULONG_MAX / k)
+ mpfr_div_ui (t, t, k * (k + absn), GMP_RNDN);
+ else
+ {
+ mpfr_div_ui (t, t, k, GMP_RNDN);
+ mpfr_div_ui (t, t, absn, GMP_RNDN);
+ }
+ exps = MPFR_EXP (t);
+ if (exps > expT)
+ expT = exps;
+ mpfr_add (s, s, t, GMP_RNDN);
+ exps = MPFR_EXP (s);
+ if (exps > expT)
+ expT = exps;
+ if (MPFR_EXP (t) + (mp_exp_t) prec <= MPFR_EXP (s) &&
+ zz / (2 * k) < k + n)
+ break;
+ }
+ /* the error is bounded by (4k^2+21/2k+7) ulp(s)*2^(expT-exps)
+ <= (k+2)^2 ulp(s)*2^(2+expT-exps) */
+ err = 2 * MPFR_INT_CEIL_LOG2(k + 2) + 2 + expT - MPFR_EXP (s);
+ if (MPFR_LIKELY (MPFR_CAN_ROUND (s, prec - err, MPFR_PREC(res), r)))
+ break;
+ MPFR_ZIV_NEXT (loop, prec);
+ }
+ MPFR_ZIV_FREE (loop);
+
+ inex = (n >= 0) ? mpfr_set (res, s, r) : mpfr_neg (res, s, r);
+
+ mpfr_clear (y);
+ mpfr_clear (s);
+ mpfr_clear (t);
+
+ return inex;
+}
diff --git a/mpfr.h b/mpfr.h
index 8d512e03b..7c4c73322 100644
--- a/mpfr.h
+++ b/mpfr.h
@@ -513,6 +513,10 @@ __MPFR_DECLSPEC int mpfr_zeta _MPFR_PROTO ((mpfr_ptr,mpfr_srcptr,mpfr_rnd_t));
__MPFR_DECLSPEC int mpfr_zeta_ui _MPFR_PROTO ((mpfr_ptr,unsigned long,mpfr_rnd_t));
__MPFR_DECLSPEC int mpfr_fac_ui _MPFR_PROTO ((mpfr_ptr, unsigned long int,
mpfr_rnd_t));
+__MPFR_DECLSPEC int mpfr_j0 _MPFR_PROTO ((mpfr_ptr,mpfr_srcptr,mpfr_rnd_t));
+__MPFR_DECLSPEC int mpfr_j1 _MPFR_PROTO ((mpfr_ptr,mpfr_srcptr,mpfr_rnd_t));
+__MPFR_DECLSPEC int mpfr_jn _MPFR_PROTO ((mpfr_ptr, mpfr_srcptr, int,
+ mpfr_rnd_t));
__MPFR_DECLSPEC int mpfr_min _MPFR_PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr,
mpfr_rnd_t));
diff --git a/mpfr.texi b/mpfr.texi
index e3157044f..e26020044 100644
--- a/mpfr.texi
+++ b/mpfr.texi
@@ -1482,6 +1482,17 @@ Set @var{rop} to the value of the complementary error function on @var{op},
rounded in the direction @var{rnd}.
@end deftypefun
+@deftypefun int mpfr_j0 (mpfr_t @var{rop}, mpfr_t @var{op}, mp_rnd_t @var{rnd})
+@deftypefunx int mpfr_j1 (mpfr_t @var{rop}, mpfr_t @var{op}, mp_rnd_t @var{rnd})
+@deftypefunx int mpfr_jn (mpfr_t @var{rop}, mpfr_t @var{op}, int @var{n}, mp_rnd_t @var{rnd})
+Set @var{rop} to the value of the first order Bessel function of order 0, 1
+and @var{n} on @var{op}, rounded in the direction @var{rnd}. When @var{op} is
+NaN, @var{rop} is always set to NaN. When @var{op} is plus or minus Infinity,
+@var{rop} is set to +0. When @var{op} is zero, and @var{n} is not zero,
+@var{rop} is +0 or -0 depending on the parity and sign of @var{n}, and the
+sign of @var{op}.
+@end deftypefun
+
@deftypefun int mpfr_fma (mpfr_t @var{rop}, mpfr_t @var{op1}, mpfr_t @var{op2}, mpfr_t @var{op3}, mp_rnd_t @var{rnd})
Set @var{rop} to @math{@var{op1} @GMPtimes{} @var{op2} + @var{op3}},
rounded in the direction @var{rnd}.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f75349f0b..179e11e82 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS = 1.6 gnu $(top_builddir)/ansi2knr
-check_PROGRAMS = tversion tinternals tinits tsgn tcheck tisnan texceptions tset_exp tset tabs tset_d tset_f tset_q tset_si tset_str tset_z tset_ld tset_sj tswap tcopysign tcmp tcmp2 tcmpabs tcmp_d tcmp_ld tcomparisons teq tadd tsub tmul tdiv tsub1sp tadd1sp tadd_ui tsub_ui tcmp_ui tdiv_ui tmul_ui tsqrt_ui tui_div tui_sub tgmpop tsi_op tmul_2exp tfma tsum tdim tminmax tnext tfits tget_d tget_d_2exp tget_z tget_str tget_sj tout_str tinp_str toutimpl tcan_round tround_prec tsqrt tconst_log2 tconst_pi tconst_euler trandom ttrunc trint tfrac texp texp2 texpm1 tlog tlog2 tlog10 tlog1p tpow tui_pow tpow3 tcosh tsinh ttanh tacosh tasinh tatanh thyperbolic tasin tacos tcos tatan tsin ttan tsin_cos tagm thypot tfactorial tgamma terf tcbrt tzeta mpf_compat mpfr_compat reuse tsqr tstrtofr tpow_z tget_f tconst_catalan troot tsec tcsc tcot teint tcoth tcsch tsech tstckintc tsubnormal tlngamma tzeta_ui tget_ld_2exp tget_set_d64
+check_PROGRAMS = tversion tinternals tinits tsgn tcheck tisnan texceptions tset_exp tset tabs tset_d tset_f tset_q tset_si tset_str tset_z tset_ld tset_sj tswap tcopysign tcmp tcmp2 tcmpabs tcmp_d tcmp_ld tcomparisons teq tadd tsub tmul tdiv tsub1sp tadd1sp tadd_ui tsub_ui tcmp_ui tdiv_ui tmul_ui tsqrt_ui tui_div tui_sub tgmpop tsi_op tmul_2exp tfma tsum tdim tminmax tnext tfits tget_d tget_d_2exp tget_z tget_str tget_sj tout_str tinp_str toutimpl tcan_round tround_prec tsqrt tconst_log2 tconst_pi tconst_euler trandom ttrunc trint tfrac texp texp2 texpm1 tlog tlog2 tlog10 tlog1p tpow tui_pow tpow3 tcosh tsinh ttanh tacosh tasinh tatanh thyperbolic tasin tacos tcos tatan tsin ttan tsin_cos tagm thypot tfactorial tgamma terf tcbrt tzeta mpf_compat mpfr_compat reuse tsqr tstrtofr tpow_z tget_f tconst_catalan troot tsec tcsc tcot teint tcoth tcsch tsech tstckintc tsubnormal tlngamma tzeta_ui tget_ld_2exp tget_set_d64 tj0 tj1 tjn
EXTRA_DIST = tgeneric.c tgeneric_ui.c mpf_compat.h inp_str.data
diff --git a/tests/reuse.c b/tests/reuse.c
index cdd0092fb..1c1fb80dd 100644
--- a/tests/reuse.c
+++ b/tests/reuse.c
@@ -590,8 +590,10 @@ main (void)
test2 (mpfr_csc, "mpfr_csc", p, rnd);
test2 (mpfr_cot, "mpfr_cot", p, rnd);
- test2 (mpfr_erf, "mpfr_erf", p, rnd);
+ test2 (mpfr_erf, "mpfr_erf", p, rnd);
test2 (mpfr_erfc, "mpfr_erfc", p, rnd);
+ test2 (mpfr_j0, "mpfr_j0", p, rnd);
+ test2 (mpfr_j1, "mpfr_j1", p, rnd);
test2 (mpfr_zeta, "mpfr_zeta", p, rnd);
test2 (mpfr_gamma, "mpfr_gamma", p, rnd);
diff --git a/tests/tj0.c b/tests/tj0.c
new file mode 100644
index 000000000..2f80eb8fb
--- /dev/null
+++ b/tests/tj0.c
@@ -0,0 +1,96 @@
+/* tj0 -- test file for the Bessel function of first kind (order 0)
+
+Copyright 2007 Free Software Foundation, Inc.
+Contributed by the Arenaire and Cacao projects, INRIA.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+MA 02110-1301, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mpfr-test.h"
+
+#define TEST_FUNCTION mpfr_zeta
+#include "tgeneric.c"
+
+int
+main (int argc, char *argv[])
+{
+ mpfr_t x, y;
+
+ tests_start_mpfr ();
+
+ mpfr_init (x);
+ mpfr_init (y);
+
+ /* special values */
+ mpfr_set_nan (x);
+ mpfr_j0 (y, x, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_nan_p (y));
+
+ mpfr_set_inf (x, 1); /* +Inf */
+ mpfr_j0 (y, x, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y));
+
+ mpfr_set_inf (x, -1); /* -Inf */
+ mpfr_j0 (y, x, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y));
+
+ mpfr_set_ui (x, 0, GMP_RNDN); /* +0 */
+ mpfr_j0 (y, x, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0); /* j0(+0)=1 */
+
+ mpfr_set_ui (x, 0, GMP_RNDN);
+ mpfr_neg (x, x, GMP_RNDN); /* -0 */
+ mpfr_j0 (y, x, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0); /* j0(-0)=1 */
+
+ mpfr_set_prec (x, 53);
+ mpfr_set_prec (y, 53);
+
+ mpfr_set_ui (x, 1, GMP_RNDN);
+ mpfr_j0 (y, x, GMP_RNDN);
+ mpfr_set_str_binary (x, "0.1100001111100011111111101101111010111101110001111");
+ if (mpfr_cmp (x, y))
+ {
+ printf ("Error in mpfr_j0 for x=1, rnd=GMP_RNDN\n");
+ printf ("Expected "); mpfr_dump (x);
+ printf ("Got "); mpfr_dump (y);
+ exit (1);
+ }
+
+ mpfr_set_si (x, -1, GMP_RNDN);
+ mpfr_j0 (y, x, GMP_RNDN);
+ mpfr_set_str_binary (x, "0.1100001111100011111111101101111010111101110001111");
+ if (mpfr_cmp (x, y))
+ {
+ printf ("Error in mpfr_j0 for x=-1, rnd=GMP_RNDN\n");
+ printf ("Expected "); mpfr_dump (x);
+ printf ("Got "); mpfr_dump (y);
+ exit (1);
+ }
+
+ mpfr_clear (x);
+ mpfr_clear (y);
+
+ test_generic (2, 100, 1);
+
+ tests_end_mpfr ();
+
+ return 0;
+}
diff --git a/tests/tj1.c b/tests/tj1.c
new file mode 100644
index 000000000..5151aa5af
--- /dev/null
+++ b/tests/tj1.c
@@ -0,0 +1,84 @@
+/* tj1 -- test file for the Bessel function of first kind (order 1)
+
+Copyright 2007 Free Software Foundation, Inc.
+Contributed by the Arenaire and Cacao projects, INRIA.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+MA 02110-1301, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mpfr-test.h"
+
+#define TEST_FUNCTION mpfr_zeta
+#include "tgeneric.c"
+
+int
+main (int argc, char *argv[])
+{
+ mpfr_t x, y;
+
+ tests_start_mpfr ();
+
+ mpfr_init (x);
+ mpfr_init (y);
+
+ /* special values */
+ mpfr_set_nan (x);
+ mpfr_j1 (y, x, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_nan_p (y));
+
+ mpfr_set_inf (x, 1); /* +Inf */
+ mpfr_j1 (y, x, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y));
+
+ mpfr_set_inf (x, -1); /* -Inf */
+ mpfr_j1 (y, x, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y));
+
+ mpfr_set_ui (x, 0, GMP_RNDN); /* +0 */
+ mpfr_j1 (y, x, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); /* j1(+0)=+0 */
+
+ mpfr_set_ui (x, 0, GMP_RNDN);
+ mpfr_neg (x, x, GMP_RNDN); /* -0 */
+ mpfr_j1 (y, x, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_NEG (y)); /* j1(-0)=-0 */
+
+ mpfr_set_prec (x, 53);
+ mpfr_set_prec (y, 53);
+
+ mpfr_set_ui (x, 1, GMP_RNDN);
+ mpfr_j1 (y, x, GMP_RNDN);
+ mpfr_set_str_binary (x, "0.0111000010100111001001111011101001011100001100011011");
+ if (mpfr_cmp (x, y))
+ {
+ printf ("Error in mpfr_j1 for x=1, rnd=GMP_RNDN\n");
+ printf ("Expected "); mpfr_dump (x);
+ printf ("Got "); mpfr_dump (y);
+ exit (1);
+ }
+ mpfr_clear (x);
+ mpfr_clear (y);
+
+ test_generic (2, 100, 1);
+
+ tests_end_mpfr ();
+
+ return 0;
+}
diff --git a/tests/tjn.c b/tests/tjn.c
new file mode 100644
index 000000000..5d4eb6186
--- /dev/null
+++ b/tests/tjn.c
@@ -0,0 +1,136 @@
+/* tjn -- test file for the Bessel function of first kind
+
+Copyright 2007 Free Software Foundation, Inc.
+Contributed by the Arenaire and Cacao projects, INRIA.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+MA 02110-1301, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mpfr-test.h"
+
+int
+main (int argc, char *argv[])
+{
+ mpfr_t x, y;
+
+ tests_start_mpfr ();
+
+ mpfr_init (x);
+ mpfr_init (y);
+
+ /* special values */
+ mpfr_set_nan (x);
+ mpfr_jn (y, x, 17, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_nan_p (y));
+
+ mpfr_set_inf (x, 1); /* +Inf */
+ mpfr_jn (y, x, 17, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y));
+
+ mpfr_set_inf (x, -1); /* -Inf */
+ mpfr_jn (y, x, 17, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y));
+
+ mpfr_set_ui (x, 0, GMP_RNDN); /* +0 */
+ mpfr_jn (y, x, 0, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0); /* j0(+0)=1 */
+ mpfr_jn (y, x, 17, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); /* j17(+0)=+0 */
+ mpfr_jn (y, x, -17, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_NEG (y)); /* j-17(+0)=-0 */
+ mpfr_jn (y, x, 42, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); /* j42(+0)=+0 */
+
+ mpfr_set_ui (x, 0, GMP_RNDN);
+ mpfr_neg (x, x, GMP_RNDN); /* -0 */
+ mpfr_jn (y, x, 0, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0); /* j0(-0)=1 */
+ mpfr_jn (y, x, 17, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_NEG (y)); /* j17(-0)=-0 */
+ mpfr_jn (y, x, -17, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); /* j-17(-0)=+0 */
+ mpfr_jn (y, x, 42, GMP_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); /* j42(-0)=+0 */
+
+ mpfr_set_prec (x, 53);
+ mpfr_set_prec (y, 53);
+
+ mpfr_set_ui (x, 1, GMP_RNDN);
+ mpfr_jn (y, x, 0, GMP_RNDN);
+ mpfr_set_str_binary (x, "0.1100001111100011111111101101111010111101110001111");
+ if (mpfr_cmp (x, y))
+ {
+ printf ("Error in mpfr_jn for n=0, x=1, rnd=GMP_RNDN\n");
+ printf ("Expected "); mpfr_dump (x);
+ printf ("Got "); mpfr_dump (y);
+ exit (1);
+ }
+
+ mpfr_set_si (x, -1, GMP_RNDN);
+ mpfr_jn (y, x, 0, GMP_RNDN);
+ mpfr_set_str_binary (x, "0.1100001111100011111111101101111010111101110001111");
+ if (mpfr_cmp (x, y))
+ {
+ printf ("Error in mpfr_jn for n=0, x=-1, rnd=GMP_RNDN\n");
+ printf ("Expected "); mpfr_dump (x);
+ printf ("Got "); mpfr_dump (y);
+ exit (1);
+ }
+
+ mpfr_set_ui (x, 1, GMP_RNDN);
+ mpfr_jn (y, x, 1, GMP_RNDN);
+ mpfr_set_str_binary (x, "0.0111000010100111001001111011101001011100001100011011");
+ if (mpfr_cmp (x, y))
+ {
+ printf ("Error in mpfr_jn for n=1, x=1, rnd=GMP_RNDN\n");
+ printf ("Expected "); mpfr_dump (x);
+ printf ("Got "); mpfr_dump (y);
+ exit (1);
+ }
+
+ mpfr_set_ui (x, 1, GMP_RNDN);
+ mpfr_jn (y, x, 17, GMP_RNDN);
+ mpfr_set_str_binary (x, "0.1100011111001010101001001001000110110000010001011E-65");
+ if (mpfr_cmp (x, y))
+ {
+ printf ("Error in mpfr_jn for n=17, x=1, rnd=GMP_RNDN\n");
+ printf ("Expected "); mpfr_dump (x);
+ printf ("Got "); mpfr_dump (y);
+ exit (1);
+ }
+
+ mpfr_set_ui (x, 1, GMP_RNDN);
+ mpfr_jn (y, x, 42, GMP_RNDN);
+ mpfr_set_str_binary (x, "0.10000111100011010100111011100111101101000100000001001E-211");
+ if (mpfr_cmp (x, y))
+ {
+ printf ("Error in mpfr_jn for n=42, x=1, rnd=GMP_RNDN\n");
+ printf ("Expected "); mpfr_dump (x);
+ printf ("Got "); mpfr_dump (y);
+ exit (1);
+ }
+
+ mpfr_clear (x);
+ mpfr_clear (y);
+
+ tests_end_mpfr ();
+
+ return 0;
+}