after multiple objections of libtom users [1], we decided to change licensing
[libtomfloat.git] / mpf_atan.c
blob870f193ed39471673bc4af81426157e961f5a3bb
1 /* LibTomFloat, multiple-precision floating-point library
3 * LibTomFloat is a library that provides multiple-precision
4 * floating-point artihmetic as well as trigonometric functionality.
6 * This library requires the public domain LibTomMath to be installed.
7 *
8 * This library is free for all purposes without any express
9 * gurantee it works
11 * Tom St Denis, tomstdenis@iahu.ca, http://float.libtomcrypt.org
13 #include <tomfloat.h>
15 /* y = y - (tan(y) - x)/(tan(y+0.1)-tan(x)) */
17 int mpf_atan(mp_float *a, mp_float *b)
19 mp_float oldval, tmp, tmpx, res, sqr;
20 int oddeven, ires, err, itts;
21 long n;
23 /* ensure -1 <= a <= 1 */
24 if ((err = mpf_cmp_d(a, -1, &ires)) != MP_OKAY) {
25 return err;
27 if (ires == MP_LT) {
28 return MP_VAL;
31 if ((err = mpf_cmp_d(a, 1, &ires)) != MP_OKAY) {
32 return err;
34 if (ires == MP_GT) {
35 return MP_VAL;
38 /* easy out if a == 0 */
39 if (mpf_iszero(a) == MP_YES) {
40 return mpf_const_d(b, 1);
43 /* now a != 0 */
45 /* initialize temps */
46 if ((err = mpf_init_multi(b->radix, &oldval, &tmpx, &tmp, &res, &sqr, NULL)) != MP_OKAY) {
47 return err;
50 /* initlialize temps */
51 /* res = 0 */
52 /* tmpx = 1/a */
53 if ((err = mpf_inv(a, &tmpx)) != MP_OKAY) { goto __ERR; }
55 /* sqr = a^2 */
56 if ((err = mpf_sqr(a, &sqr)) != MP_OKAY) { goto __ERR; }
58 /* this is the denom counter. Goes up by two per pass */
59 n = 1;
61 /* we alternate between adding and subtracting */
62 oddeven = 0;
64 /* get number of iterations */
65 itts = mpf_iterations(b);
67 while (itts-- > 0) {
68 if ((err = mpf_copy(&res, &oldval)) != MP_OKAY) { goto __ERR; }
70 /* compute 1/(2n-1) */
71 if ((err = mpf_const_d(&tmp, (2*n++ - 1))) != MP_OKAY) { goto __ERR; }
72 if ((err = mpf_inv(&tmp, &tmp)) != MP_OKAY) { goto __ERR; }
74 /* now multiply a into tmpx twice */
75 if ((err = mpf_mul(&tmpx, &sqr, &tmpx)) != MP_OKAY) { goto __ERR; }
77 /* now multiply the two */
78 if ((err = mpf_mul(&tmpx, &tmp, &tmp)) != MP_OKAY) { goto __ERR; }
80 /* now depending on if this is even or odd we add/sub */
81 oddeven ^= 1;
82 if (oddeven == 1) {
83 if ((err = mpf_add(&res, &tmp, &res)) != MP_OKAY) { goto __ERR; }
84 } else {
85 if ((err = mpf_sub(&res, &tmp, &res)) != MP_OKAY) { goto __ERR; }
88 if (mpf_cmp(&oldval, &res) == MP_EQ) {
89 break;
92 mpf_exch(&res, b);
93 __ERR: mpf_clear_multi(&oldval, &tmpx, &tmp, &res, &sqr, NULL);
94 return err;