Transcendental functions for 'long double', from Paolo Bonzini.
[gnulib.git] / lib / frexpl.c
1 /* Emulation for frexpl.
2    Contributed by Paolo Bonzini
3
4    Copyright 2002, 2003 Free Software Foundation, Inc.
5
6    This file is part of gnulib.
7
8    gnulib is free software; you can redistribute it and/or modify it
9    under the terms of the GNU Lesser General Public License as published
10    by the Free Software Foundation; either version 2.1, or (at your option)
11    any later version.
12
13    gnulib is distributed in the hope that it will be useful, but WITHOUT
14    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16    License for more details.
17
18    You should have received a copy of the GNU Lesser General Public License
19    along with gnulib; see the file COPYING.LIB.  If not, write to the Free
20    Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21    USA.
22  */
23
24 #include <float.h>
25 #include <math.h>
26
27 #include "mathl.h"
28
29 /* Binary search.  Quite inefficient but portable. */
30 long double
31 frexpl(long double x, int *exp)
32 {
33   long double exponents[20], *next;
34   int exponent, bit;
35
36   /* Check for zero, nan and infinity. */
37   if (x != x || x + x == x )
38     {
39       *exp = 0;
40       return x;
41     }
42
43   if (x < 0)
44     return -frexpl(-x, exp);
45
46   exponent = 0;
47   if (x > 1.0)
48     {
49       for (next = exponents, exponents[0] = 2.0L, bit = 1;
50            *next <= x + x;
51            bit <<= 1, next[1] = next[0] * next[0], next++);
52
53       for (; next >= exponents; bit >>= 1, next--)
54         if (x + x >= *next)
55           {
56             x /= *next;
57             exponent |= bit;
58           }
59
60     }
61
62   else if (x < 0.5)
63     {
64       for (next = exponents, exponents[0] = 0.5L, bit = 1;
65            *next > x;
66            bit <<= 1, next[1] = next[0] * next[0], next++);
67
68       for (; next >= exponents; bit >>= 1, next--)
69         if (x < *next)
70           {
71             x /= *next;
72             exponent |= bit;
73           }
74
75       exponent = -exponent;
76     }
77
78   *exp = exponent;
79   return x;
80 }
81
82 #if 0
83 int
84 main()
85 {
86   long double x;
87   int y;
88   x = frexpl(0.0L / 0.0L, &y); printf ("%.6Lg %d\n", x, y);
89   x = frexpl(1.0L / 0.0L, &y); printf ("%.6Lg %d\n", x, y);
90   x = frexpl(-1.0L / 0.0L, &y); printf ("%.6Lg %d\n", x, y);
91   x = frexpl(0.5L, &y); printf ("%.6Lg %d\n", x, y);
92   x = frexpl(0.75L, &y); printf ("%.6Lg %d\n", x, y);
93   x = frexpl(3.6L, &y); printf ("%.6Lg %d\n", x, y);
94   x = frexpl(17.8L, &y); printf ("%.6Lg %d\n", x, y);
95   x = frexpl(8.0L, &y); printf ("%.6Lg %d\n", x, y);
96   x = frexpl(0.3L, &y); printf ("%.6Lg %d\n", x, y);
97   x = frexpl(0.49L, &y); printf ("%.6Lg %d\n", x, y);
98   x = frexpl(0.049L, &y); printf ("%.6Lg %d\n", x, y);
99   x = frexpl(0.0245L, &y); printf ("%.6Lg %d\n", x, y);
100   x = frexpl(0.0625L, &y); printf ("%.6Lg %d\n", x, y);
101 }
102 #endif
103