1 /*
2 * PROJECT C Library, X68000 PROGRAMMING INTERFACE DEFINITION
3 * --------------------------------------------------------------------
4 * This file is written by the Project C Library Group, and completely
5 * in public domain. You can freely use, copy, modify, and redistribute
6 * the whole contents, without this notice.
7 * --------------------------------------------------------------------
8 * $Id: _dtos18.c,v 1.1.1.2 1999/01/20 04:59:39 matz Exp $
9 */
10
11 /* System headers */
12 #include <stdlib.h>
13 #include <sys/xstdlib.h>
14
15 /*
16 ** 本関数は浮動小数点を倍精度整数に変換してから文字列にするため、精度的には
17 ** 倍精度整数に格納できる桁数までしか扱うことができない。したがって最高精度
18 ** は18桁である。
19 */
20
21 /* File scope variables */
22 static double _pos1[32] = {
23 1.0e+17, /* + 0 */
24 1.0e+18, /* + 1 */
25 1.0e+19, /* + 2 */
26 1.0e+20, /* + 3 */
27 1.0e+21, /* + 4 */
28 1.0e+22, /* + 5 */
29 1.0e+23, /* + 6 */
30 1.0e+24, /* + 7 */
31 1.0e+25, /* + 8 */
32 1.0e+26, /* + 9 */
33 1.0e+27, /* +10 */
34 1.0e+28, /* +11 */
35 1.0e+29, /* +12 */
36 1.0e+30, /* +13 */
37 1.0e+31, /* +14 */
38 1.0e+32, /* +15 */
39 1.0e+33, /* +16 */
40 1.0e+34, /* +17 */
41 1.0e+35, /* +18 */
42 1.0e+36, /* +19 */
43 1.0e+37, /* +20 */
44 1.0e+38, /* +21 */
45 1.0e+39, /* +22 */
46 1.0e+40, /* +23 */
47 1.0e+41, /* +24 */
48 1.0e+42, /* +25 */
49 1.0e+43, /* +26 */
50 1.0e+44, /* +27 */
51 1.0e+45, /* +28 */
52 1.0e+46, /* +29 */
53 1.0e+47, /* +30 */
54 1.0e+48, /* +31 */
55 };
56
57 /* File scope variables */
58 static double _neg1[32] = {
59 1.0e+17, /* - 0 */
60 1.0e+16, /* - 1 */
61 1.0e+15, /* - 2 */
62 1.0e+14, /* - 3 */
63 1.0e+13, /* - 4 */
64 1.0e+12, /* - 5 */
65 1.0e+11, /* - 6 */
66 1.0e+10, /* - 7 */
67 1.0e+9, /* - 8 */
68 1.0e+8, /* - 9 */
69 1.0e+7, /* -10 */
70 1.0e+6, /* -11 */
71 1.0e+5, /* -12 */
72 1.0e+4, /* -13 */
73 1.0e+3, /* -14 */
74 1.0e+2, /* -15 */
75 1.0e+1, /* -16 */
76 1.0e+0, /* -17 */
77 1.0e-1, /* -18 */
78 1.0e-2, /* -19 */
79 1.0e-3, /* -20 */
80 1.0e-4, /* -21 */
81 1.0e-5, /* -22 */
82 1.0e-6, /* -23 */
83 1.0e-7, /* -24 */
84 1.0e-8, /* -25 */
85 1.0e-9, /* -26 */
86 1.0e-10, /* -27 */
87 1.0e-11, /* -28 */
88 1.0e-12, /* -29 */
89 1.0e-13, /* -30 */
90 1.0e-14, /* -31 */
91 };
92
93 /* File scope variables */
94 static double _pos2[10] = {
95 1.0e+0, /* 000 */
96 1.0e+32, /* 001 */
97 1.0e+64, /* 010 */
98 1.0e+96, /* 011 */
99 1.0e+128, /* 100 */
100 1.0e+160, /* 101 */
101 1.0e+192, /* 110 */
102 1.0e+224, /* 111 */
103 1.0e+256, /* 1000 */
104 1.0e+288, /* 1001 */
105 };
106
107 /* File scope variables */
108 static double _neg2[10] = {
109 1.0e-0, /* 000 */
110 1.0e-32, /* 001 */
111 1.0e-64, /* 010 */
112 1.0e-96, /* 011 */
113 1.0e-128, /* 100 */
114 1.0e-160, /* 101 */
115 1.0e-192, /* 110 */
116 1.0e-224, /* 111 */
117 1.0e-256, /* 1000 */
118 1.0e-288, /* 1001 */
119 };
120
121 /* File scope functions */
122 static int _cmpd (double x, double y)
123 {
124 unsigned long vx, vy, rc;
125 unsigned long *x_ptr = (unsigned long *) &x;
126 unsigned long *y_ptr = (unsigned long *) &y;
127
128 /* xの指数ビットを取り出す */
129 vx = x_ptr[0] & 0x7FF00000;
130
131 /* yの指数ビットを取り出す */
132 vy = y_ptr[0] & 0x7FF00000;
133
134 /* 指数ビットだけで判断する */
135 if ((rc = vy - vx) != 0)
136 return rc;
137
138 /* xの有効数字の上位ビットを取り出す */
139 vx = x_ptr[0] & 0x000FFFFF;
140
141 /* yの有効数字の上位ビットを取り出す */
142 vy = y_ptr[0] & 0x000FFFFF;
143
144 /* 上位ビットだけで判断する */
145 if ((rc = vy - vx) != 0)
146 return rc;
147
148 /* xの有効数字の下位ビットを取り出す */
149 vx = x_ptr[1];
150
151 /* yの有効数字の下位ビットを取り出す */
152 vy = y_ptr[1];
153
154 /* 最終判断 */
155 return vy - vx;
156 }
157
158 /* Functions */
159 void _dtos18 (double x, int *decpt, int *sign, char *buffer)
160 {
161 short e2;
162 int e, n;
163
164 /* 基数2の指数を求める(バイアスなしの状態) */
165 e2 = (((unsigned short *) &x)[0] & 0x7FF0U) >> 4;
166
167 /* 指数が0の場合は±0.0チェック */
168 if (e2 == 0) {
169
170 unsigned long hi = ((unsigned long *) &x)[0] & 0xFFFFF;
171 unsigned long lo = ((unsigned long *) &x)[1];
172
173 /* 有効数字が全部0かどうか */
174 if (hi == 0 && lo == 0) {
175
176 /* 文字列を設定 */
177 buffer[0] = '0';
178
179 /* NULを設定 */
180 buffer[1] = '\0';
181
182 /* 小数点位置を計算 */
183 *decpt = 1;
184
185 /* 符号を計算 */
186 /* *sign = hi & 0x80000000UL; */
187 *sign = 0;
188
189 /* 確定 */
190 return;
191
192 }
193
194 }
195
196 /* 2の指数にバイアスをかけてから10の指数を概算 (approx. log10(2)) */
197 e = ((int) ((e2 - 1023) * 77)) >> 8;
198
199 /* 指数が正の場合 */
200 if (e >= 0) {
201
202 /* 指数が32より小さい場合はテーブル1から */
203 if (e < 32)
204 x *= _neg1[e];
205
206 /* 指数が32より大きい場合はテーブル1,2から */
207 else
208 x *= _neg1[e & 31] * _neg2[e >> 5];
209
210 }
211
212 /* 指数が負の場合 */
213 else {
214
215 /* 絶対値を計算 */
216 n = -e;
217
218 /* 絶対値が32より小さい場合はテーブル1から */
219 if (n < 32)
220 x *= _pos1[n];
221
222 /* 絶対値が32より大きい場合はテーブル1,2から */
223 else {
224 x *= _pos1[n & 31];
225 x *= _pos2[n >> 5];
226 }
227
228 }
229
230 /* スケーリングしすぎた場合は戻す */
231 if (_cmpd (1.0e+18, x) >= 0) {
232 e++;
233 x *= 1.0e-1;
234 }
235
236 /* スケーリングし足りない場合は追加 */
237 else if (_cmpd (1.0e+17, x) < 0) {
238 e--;
239 x *= 1.0e+1;
240 }
241
242 /* 小数点位置を計算 */
243 *decpt = e + 1;
244
245 /* 符号を計算 */
246 *sign = ((unsigned char *) &x)[0] & 0x80U;
247
248 /* 文字列に変換 */
249 _ulltoa ((unsigned long long) x, buffer);
250 }