1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright © 2021 Keith Packard
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * 3. Neither the name of the copyright holder nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include "stdio_private.h"
37 #include <float.h>
38
39 #if __LDBL_MAX_10_EXP__ >= 4096
40 #define NPOW_10 13
41 #elif __LDBL_MAX_10_EXP__ >= 2048
42 #define NPOW_10 12
43 #elif __LDBL_MAX_10_EXP__ >= 1024
44 #define NPOW_10 11
45 #elif __LDBL_MAX_10_EXP__ >= 512
46 #define NPOW_10 10
47 #elif __LDBL_MAX_10_EXP__ >= 256
48 #define NPOW_10 9
49 #elif __LDBL_MAX_10_EXP__ >= 128
50 #define NPOW_10 8
51 #elif __LDBL_MAX_10_EXP__ >= 64
52 #define NPOW_10 7
53 #elif __LDBL_MAX_10_EXP__ >= 32
54 #define NPOW_10 6
55 #else
56 #error __LDBL_MAX_10_EXP__ too small
57 #endif
58
59 static const long double pwr_p10 [NPOW_10] = {
60 1e+1L, 1e+2L, 1e+4L, 1e+8L, 1e+16L, 1e+32L,
61 #if NPOW_10 >= 7
62 1e+64L,
63 #endif
64 #if NPOW_10 >= 8
65 1e+128L,
66 #endif
67 #if NPOW_10 >= 9
68 1e+256L,
69 #endif
70 #if NPOW_10 >= 10
71 1e+512L,
72 #endif
73 #if NPOW_10 >= 11
74 1e+1024L,
75 #endif
76 #if NPOW_10 >= 12
77 1e+2048L,
78 #endif
79 #if NPOW_10 >= 13
80 1e+4096L
81 #endif
82 };
83
84 static const long double pwr_m10 [NPOW_10] = {
85 1e-1L, 1e-2L, 1e-4L, 1e-8L, 1e-16L, 1e-32L,
86 #if NPOW_10 >= 7
87 1e-64L,
88 #endif
89 #if NPOW_10 >= 8
90 1e-128L,
91 #endif
92 #if NPOW_10 >= 9
93 1e-256L,
94 #endif
95 #if NPOW_10 >= 10
96 1e-512L,
97 #endif
98 #if NPOW_10 >= 11
99 1e-1024L,
100 #endif
101 #if NPOW_10 >= 12
102 1e-2048L,
103 #endif
104 #if NPOW_10 >= 13
105 1e-4096L
106 #endif
107 };
108
109 long double
__atold_engine(_u128 m10,int e10)110 __atold_engine(_u128 m10, int e10)
111 {
112 long double flt = _u128_to_ld(m10);
113 int pwr;
114 const long double *pptr;
115
116 if (e10 < 0) {
117 pptr = (pwr_m10 + NPOW_10 - 1);
118 e10 = -e10;
119 } else {
120 pptr = (pwr_p10 + NPOW_10 - 1);
121 }
122 for (pwr = 1 << (NPOW_10 - 1); pwr; pwr >>= 1) {
123 for (; e10 >= pwr; e10 -= pwr) {
124 flt *= *pptr;
125 }
126 pptr--;
127 }
128 return flt;
129 }
130