New module 'math'. <math.h> replaces mathl.h.
[gnulib.git] / lib / frexpl.c
1 /* Emulation for frexpl.
2    Contributed by Paolo Bonzini
3
4    Copyright 2002, 2003, 2007 Free Software Foundation, Inc.
5
6    This file is part of gnulib.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2, or (at your option)
11    any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License along
19    with this program; if not, write to the Free Software Foundation,
20    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
21
22 #include <config.h>
23
24 /* Specification.  */
25 #include <math.h>
26
27 #include <float.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 (void)
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