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