decimal128.c revision 1.1.1.5 1 1.1 mrg /* Decimal 128-bit format module for the decNumber C Library.
2 1.1.1.5 mrg Copyright (C) 2005-2017 Free Software Foundation, Inc.
3 1.1 mrg Contributed by IBM Corporation. Author Mike Cowlishaw.
4 1.1 mrg
5 1.1 mrg This file is part of GCC.
6 1.1 mrg
7 1.1 mrg GCC is free software; you can redistribute it and/or modify it under
8 1.1 mrg the terms of the GNU General Public License as published by the Free
9 1.1 mrg Software Foundation; either version 3, or (at your option) any later
10 1.1 mrg version.
11 1.1 mrg
12 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 1.1 mrg for more details.
16 1.1 mrg
17 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
18 1.1 mrg permissions described in the GCC Runtime Library Exception, version
19 1.1 mrg 3.1, as published by the Free Software Foundation.
20 1.1 mrg
21 1.1 mrg You should have received a copy of the GNU General Public License and
22 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
23 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 1.1 mrg <http://www.gnu.org/licenses/>. */
25 1.1 mrg
26 1.1 mrg /* ------------------------------------------------------------------ */
27 1.1 mrg /* Decimal 128-bit format module */
28 1.1 mrg /* ------------------------------------------------------------------ */
29 1.1 mrg /* This module comprises the routines for decimal128 format numbers. */
30 1.1 mrg /* Conversions are supplied to and from decNumber and String. */
31 1.1 mrg /* */
32 1.1 mrg /* This is used when decNumber provides operations, either for all */
33 1.1 mrg /* operations or as a proxy between decNumber and decSingle. */
34 1.1 mrg /* */
35 1.1 mrg /* Error handling is the same as decNumber (qv.). */
36 1.1 mrg /* ------------------------------------------------------------------ */
37 1.1 mrg #include <string.h> /* [for memset/memcpy] */
38 1.1 mrg #include <stdio.h> /* [for printf] */
39 1.1 mrg
40 1.1 mrg #include "dconfig.h" /* GCC definitions */
41 1.1 mrg #define DECNUMDIGITS 34 /* make decNumbers with space for 34 */
42 1.1 mrg #include "decNumber.h" /* base number library */
43 1.1 mrg #include "decNumberLocal.h" /* decNumber local types, etc. */
44 1.1 mrg #include "decimal128.h" /* our primary include */
45 1.1 mrg
46 1.1 mrg /* Utility routines and tables [in decimal64.c] */
47 1.1 mrg extern const uInt COMBEXP[32], COMBMSD[32];
48 1.1 mrg extern const uShort DPD2BIN[1024];
49 1.1 mrg extern const uShort BIN2DPD[1000]; /* [not used] */
50 1.1 mrg extern const uByte BIN2CHAR[4001];
51 1.1 mrg
52 1.1 mrg extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
53 1.1 mrg extern void decDigitsToDPD(const decNumber *, uInt *, Int);
54 1.1 mrg
55 1.1 mrg #if DECTRACE || DECCHECK
56 1.1 mrg void decimal128Show(const decimal128 *); /* for debug */
57 1.1 mrg extern void decNumberShow(const decNumber *); /* .. */
58 1.1 mrg #endif
59 1.1 mrg
60 1.1 mrg /* Useful macro */
61 1.1 mrg /* Clear a structure (e.g., a decNumber) */
62 1.1 mrg #define DEC_clear(d) memset(d, 0, sizeof(*d))
63 1.1 mrg
64 1.1 mrg /* ------------------------------------------------------------------ */
65 1.1 mrg /* decimal128FromNumber -- convert decNumber to decimal128 */
66 1.1 mrg /* */
67 1.1 mrg /* ds is the target decimal128 */
68 1.1 mrg /* dn is the source number (assumed valid) */
69 1.1 mrg /* set is the context, used only for reporting errors */
70 1.1 mrg /* */
71 1.1 mrg /* The set argument is used only for status reporting and for the */
72 1.1 mrg /* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/
73 1.1 mrg /* digits or an overflow is detected). If the exponent is out of the */
74 1.1 mrg /* valid range then Overflow or Underflow will be raised. */
75 1.1 mrg /* After Underflow a subnormal result is possible. */
76 1.1 mrg /* */
77 1.1 mrg /* DEC_Clamped is set if the number has to be 'folded down' to fit, */
78 1.1 mrg /* by reducing its exponent and multiplying the coefficient by a */
79 1.1 mrg /* power of ten, or if the exponent on a zero had to be clamped. */
80 1.1 mrg /* ------------------------------------------------------------------ */
81 1.1 mrg decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
82 1.1 mrg decContext *set) {
83 1.1 mrg uInt status=0; /* status accumulator */
84 1.1 mrg Int ae; /* adjusted exponent */
85 1.1 mrg decNumber dw; /* work */
86 1.1 mrg decContext dc; /* .. */
87 1.1 mrg uInt comb, exp; /* .. */
88 1.1 mrg uInt uiwork; /* for macros */
89 1.1 mrg uInt targar[4]={0,0,0,0}; /* target 128-bit */
90 1.1 mrg #define targhi targar[3] /* name the word with the sign */
91 1.1 mrg #define targmh targar[2] /* name the words */
92 1.1 mrg #define targml targar[1] /* .. */
93 1.1 mrg #define targlo targar[0] /* .. */
94 1.1 mrg
95 1.1 mrg /* If the number has too many digits, or the exponent could be */
96 1.1 mrg /* out of range then reduce the number under the appropriate */
97 1.1 mrg /* constraints. This could push the number to Infinity or zero, */
98 1.1 mrg /* so this check and rounding must be done before generating the */
99 1.1 mrg /* decimal128] */
100 1.1 mrg ae=dn->exponent+dn->digits-1; /* [0 if special] */
101 1.1 mrg if (dn->digits>DECIMAL128_Pmax /* too many digits */
102 1.1 mrg || ae>DECIMAL128_Emax /* likely overflow */
103 1.1 mrg || ae<DECIMAL128_Emin) { /* likely underflow */
104 1.1 mrg decContextDefault(&dc, DEC_INIT_DECIMAL128); /* [no traps] */
105 1.1 mrg dc.round=set->round; /* use supplied rounding */
106 1.1 mrg decNumberPlus(&dw, dn, &dc); /* (round and check) */
107 1.1 mrg /* [this changes -0 to 0, so enforce the sign...] */
108 1.1 mrg dw.bits|=dn->bits&DECNEG;
109 1.1 mrg status=dc.status; /* save status */
110 1.1 mrg dn=&dw; /* use the work number */
111 1.1 mrg } /* maybe out of range */
112 1.1 mrg
113 1.1 mrg if (dn->bits&DECSPECIAL) { /* a special value */
114 1.1 mrg if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
115 1.1 mrg else { /* sNaN or qNaN */
116 1.1 mrg if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */
117 1.1 mrg && (dn->digits<DECIMAL128_Pmax)) { /* coefficient fits */
118 1.1 mrg decDigitsToDPD(dn, targar, 0);
119 1.1 mrg }
120 1.1 mrg if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
121 1.1 mrg else targhi|=DECIMAL_sNaN<<24;
122 1.1 mrg } /* a NaN */
123 1.1 mrg } /* special */
124 1.1 mrg
125 1.1 mrg else { /* is finite */
126 1.1 mrg if (decNumberIsZero(dn)) { /* is a zero */
127 1.1 mrg /* set and clamp exponent */
128 1.1 mrg if (dn->exponent<-DECIMAL128_Bias) {
129 1.1 mrg exp=0; /* low clamp */
130 1.1 mrg status|=DEC_Clamped;
131 1.1 mrg }
132 1.1 mrg else {
133 1.1 mrg exp=dn->exponent+DECIMAL128_Bias; /* bias exponent */
134 1.1 mrg if (exp>DECIMAL128_Ehigh) { /* top clamp */
135 1.1 mrg exp=DECIMAL128_Ehigh;
136 1.1 mrg status|=DEC_Clamped;
137 1.1 mrg }
138 1.1 mrg }
139 1.1 mrg comb=(exp>>9) & 0x18; /* msd=0, exp top 2 bits .. */
140 1.1 mrg }
141 1.1 mrg else { /* non-zero finite number */
142 1.1 mrg uInt msd; /* work */
143 1.1 mrg Int pad=0; /* coefficient pad digits */
144 1.1 mrg
145 1.1 mrg /* the dn is known to fit, but it may need to be padded */
146 1.1 mrg exp=(uInt)(dn->exponent+DECIMAL128_Bias); /* bias exponent */
147 1.1 mrg if (exp>DECIMAL128_Ehigh) { /* fold-down case */
148 1.1 mrg pad=exp-DECIMAL128_Ehigh;
149 1.1 mrg exp=DECIMAL128_Ehigh; /* [to maximum] */
150 1.1 mrg status|=DEC_Clamped;
151 1.1 mrg }
152 1.1 mrg
153 1.1 mrg /* [fastpath for common case is not a win, here] */
154 1.1 mrg decDigitsToDPD(dn, targar, pad);
155 1.1 mrg /* save and clear the top digit */
156 1.1 mrg msd=targhi>>14;
157 1.1 mrg targhi&=0x00003fff;
158 1.1 mrg
159 1.1 mrg /* create the combination field */
160 1.1 mrg if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01);
161 1.1 mrg else comb=((exp>>9) & 0x18) | msd;
162 1.1 mrg }
163 1.1 mrg targhi|=comb<<26; /* add combination field .. */
164 1.1 mrg targhi|=(exp&0xfff)<<14; /* .. and exponent continuation */
165 1.1 mrg } /* finite */
166 1.1 mrg
167 1.1 mrg if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */
168 1.1 mrg
169 1.1 mrg /* now write to storage; this is endian */
170 1.1 mrg if (DECLITEND) {
171 1.1 mrg /* lo -> hi */
172 1.1 mrg UBFROMUI(d128->bytes, targlo);
173 1.1 mrg UBFROMUI(d128->bytes+4, targml);
174 1.1 mrg UBFROMUI(d128->bytes+8, targmh);
175 1.1 mrg UBFROMUI(d128->bytes+12, targhi);
176 1.1 mrg }
177 1.1 mrg else {
178 1.1 mrg /* hi -> lo */
179 1.1 mrg UBFROMUI(d128->bytes, targhi);
180 1.1 mrg UBFROMUI(d128->bytes+4, targmh);
181 1.1 mrg UBFROMUI(d128->bytes+8, targml);
182 1.1 mrg UBFROMUI(d128->bytes+12, targlo);
183 1.1 mrg }
184 1.1 mrg
185 1.1 mrg if (status!=0) decContextSetStatus(set, status); /* pass on status */
186 1.1 mrg /* decimal128Show(d128); */
187 1.1 mrg return d128;
188 1.1 mrg } /* decimal128FromNumber */
189 1.1 mrg
190 1.1 mrg /* ------------------------------------------------------------------ */
191 1.1 mrg /* decimal128ToNumber -- convert decimal128 to decNumber */
192 1.1 mrg /* d128 is the source decimal128 */
193 1.1 mrg /* dn is the target number, with appropriate space */
194 1.1 mrg /* No error is possible. */
195 1.1 mrg /* ------------------------------------------------------------------ */
196 1.1 mrg decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
197 1.1 mrg uInt msd; /* coefficient MSD */
198 1.1 mrg uInt exp; /* exponent top two bits */
199 1.1 mrg uInt comb; /* combination field */
200 1.1 mrg Int need; /* work */
201 1.1 mrg uInt uiwork; /* for macros */
202 1.1 mrg uInt sourar[4]; /* source 128-bit */
203 1.1 mrg #define sourhi sourar[3] /* name the word with the sign */
204 1.1 mrg #define sourmh sourar[2] /* and the mid-high word */
205 1.1 mrg #define sourml sourar[1] /* and the mod-low word */
206 1.1 mrg #define sourlo sourar[0] /* and the lowest word */
207 1.1 mrg
208 1.1 mrg /* load source from storage; this is endian */
209 1.1 mrg if (DECLITEND) {
210 1.1 mrg sourlo=UBTOUI(d128->bytes ); /* directly load the low int */
211 1.1 mrg sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
212 1.1 mrg sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
213 1.1 mrg sourhi=UBTOUI(d128->bytes+12); /* then the high int */
214 1.1 mrg }
215 1.1 mrg else {
216 1.1 mrg sourhi=UBTOUI(d128->bytes ); /* directly load the high int */
217 1.1 mrg sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
218 1.1 mrg sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
219 1.1 mrg sourlo=UBTOUI(d128->bytes+12); /* then the low int */
220 1.1 mrg }
221 1.1 mrg
222 1.1 mrg comb=(sourhi>>26)&0x1f; /* combination field */
223 1.1 mrg
224 1.1 mrg decNumberZero(dn); /* clean number */
225 1.1 mrg if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */
226 1.1 mrg
227 1.1 mrg msd=COMBMSD[comb]; /* decode the combination field */
228 1.1 mrg exp=COMBEXP[comb]; /* .. */
229 1.1 mrg
230 1.1 mrg if (exp==3) { /* is a special */
231 1.1 mrg if (msd==0) {
232 1.1 mrg dn->bits|=DECINF;
233 1.1 mrg return dn; /* no coefficient needed */
234 1.1 mrg }
235 1.1 mrg else if (sourhi&0x02000000) dn->bits|=DECSNAN;
236 1.1 mrg else dn->bits|=DECNAN;
237 1.1 mrg msd=0; /* no top digit */
238 1.1 mrg }
239 1.1 mrg else { /* is a finite number */
240 1.1 mrg dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
241 1.1 mrg }
242 1.1 mrg
243 1.1 mrg /* get the coefficient */
244 1.1 mrg sourhi&=0x00003fff; /* clean coefficient continuation */
245 1.1 mrg if (msd) { /* non-zero msd */
246 1.1 mrg sourhi|=msd<<14; /* prefix to coefficient */
247 1.1 mrg need=12; /* process 12 declets */
248 1.1 mrg }
249 1.1 mrg else { /* msd=0 */
250 1.1 mrg if (sourhi) need=11; /* declets to process */
251 1.1 mrg else if (sourmh) need=10;
252 1.1 mrg else if (sourml) need=7;
253 1.1 mrg else if (sourlo) need=4;
254 1.1 mrg else return dn; /* easy: coefficient is 0 */
255 1.1 mrg } /*msd=0 */
256 1.1 mrg
257 1.1 mrg decDigitsFromDPD(dn, sourar, need); /* process declets */
258 1.1 mrg /* decNumberShow(dn); */
259 1.1 mrg return dn;
260 1.1 mrg } /* decimal128ToNumber */
261 1.1 mrg
262 1.1 mrg /* ------------------------------------------------------------------ */
263 1.1 mrg /* to-scientific-string -- conversion to numeric string */
264 1.1 mrg /* to-engineering-string -- conversion to numeric string */
265 1.1 mrg /* */
266 1.1 mrg /* decimal128ToString(d128, string); */
267 1.1 mrg /* decimal128ToEngString(d128, string); */
268 1.1 mrg /* */
269 1.1 mrg /* d128 is the decimal128 format number to convert */
270 1.1 mrg /* string is the string where the result will be laid out */
271 1.1 mrg /* */
272 1.1 mrg /* string must be at least 24 characters */
273 1.1 mrg /* */
274 1.1 mrg /* No error is possible, and no status can be set. */
275 1.1 mrg /* ------------------------------------------------------------------ */
276 1.1 mrg char * decimal128ToEngString(const decimal128 *d128, char *string){
277 1.1 mrg decNumber dn; /* work */
278 1.1 mrg decimal128ToNumber(d128, &dn);
279 1.1 mrg decNumberToEngString(&dn, string);
280 1.1 mrg return string;
281 1.1 mrg } /* decimal128ToEngString */
282 1.1 mrg
283 1.1 mrg char * decimal128ToString(const decimal128 *d128, char *string){
284 1.1 mrg uInt msd; /* coefficient MSD */
285 1.1 mrg Int exp; /* exponent top two bits or full */
286 1.1 mrg uInt comb; /* combination field */
287 1.1 mrg char *cstart; /* coefficient start */
288 1.1 mrg char *c; /* output pointer in string */
289 1.1 mrg const uByte *u; /* work */
290 1.1 mrg char *s, *t; /* .. (source, target) */
291 1.1 mrg Int dpd; /* .. */
292 1.1 mrg Int pre, e; /* .. */
293 1.1 mrg uInt uiwork; /* for macros */
294 1.1 mrg
295 1.1 mrg uInt sourar[4]; /* source 128-bit */
296 1.1 mrg #define sourhi sourar[3] /* name the word with the sign */
297 1.1 mrg #define sourmh sourar[2] /* and the mid-high word */
298 1.1 mrg #define sourml sourar[1] /* and the mod-low word */
299 1.1 mrg #define sourlo sourar[0] /* and the lowest word */
300 1.1 mrg
301 1.1 mrg /* load source from storage; this is endian */
302 1.1 mrg if (DECLITEND) {
303 1.1 mrg sourlo=UBTOUI(d128->bytes ); /* directly load the low int */
304 1.1 mrg sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
305 1.1 mrg sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
306 1.1 mrg sourhi=UBTOUI(d128->bytes+12); /* then the high int */
307 1.1 mrg }
308 1.1 mrg else {
309 1.1 mrg sourhi=UBTOUI(d128->bytes ); /* directly load the high int */
310 1.1 mrg sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
311 1.1 mrg sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
312 1.1 mrg sourlo=UBTOUI(d128->bytes+12); /* then the low int */
313 1.1 mrg }
314 1.1 mrg
315 1.1 mrg c=string; /* where result will go */
316 1.1 mrg if (((Int)sourhi)<0) *c++='-'; /* handle sign */
317 1.1 mrg
318 1.1 mrg comb=(sourhi>>26)&0x1f; /* combination field */
319 1.1 mrg msd=COMBMSD[comb]; /* decode the combination field */
320 1.1 mrg exp=COMBEXP[comb]; /* .. */
321 1.1 mrg
322 1.1 mrg if (exp==3) {
323 1.1 mrg if (msd==0) { /* infinity */
324 1.1 mrg strcpy(c, "Inf");
325 1.1 mrg strcpy(c+3, "inity");
326 1.1 mrg return string; /* easy */
327 1.1 mrg }
328 1.1 mrg if (sourhi&0x02000000) *c++='s'; /* sNaN */
329 1.1 mrg strcpy(c, "NaN"); /* complete word */
330 1.1 mrg c+=3; /* step past */
331 1.1 mrg if (sourlo==0 && sourml==0 && sourmh==0
332 1.1 mrg && (sourhi&0x0003ffff)==0) return string; /* zero payload */
333 1.1 mrg /* otherwise drop through to add integer; set correct exp */
334 1.1 mrg exp=0; msd=0; /* setup for following code */
335 1.1 mrg }
336 1.1 mrg else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
337 1.1 mrg
338 1.1 mrg /* convert 34 digits of significand to characters */
339 1.1 mrg cstart=c; /* save start of coefficient */
340 1.1 mrg if (msd) *c++='0'+(char)msd; /* non-zero most significant digit */
341 1.1 mrg
342 1.1 mrg /* Now decode the declets. After extracting each one, it is */
343 1.1 mrg /* decoded to binary and then to a 4-char sequence by table lookup; */
344 1.1 mrg /* the 4-chars are a 1-char length (significant digits, except 000 */
345 1.1 mrg /* has length 0). This allows us to left-align the first declet */
346 1.1 mrg /* with non-zero content, then remaining ones are full 3-char */
347 1.1 mrg /* length. We use fixed-length memcpys because variable-length */
348 1.1 mrg /* causes a subroutine call in GCC. (These are length 4 for speed */
349 1.1 mrg /* and are safe because the array has an extra terminator byte.) */
350 1.1 mrg #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
351 1.1 mrg if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
352 1.1 mrg else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
353 1.1 mrg dpd=(sourhi>>4)&0x3ff; /* declet 1 */
354 1.1 mrg dpd2char;
355 1.1 mrg dpd=((sourhi&0xf)<<6) | (sourmh>>26); /* declet 2 */
356 1.1 mrg dpd2char;
357 1.1 mrg dpd=(sourmh>>16)&0x3ff; /* declet 3 */
358 1.1 mrg dpd2char;
359 1.1 mrg dpd=(sourmh>>6)&0x3ff; /* declet 4 */
360 1.1 mrg dpd2char;
361 1.1 mrg dpd=((sourmh&0x3f)<<4) | (sourml>>28); /* declet 5 */
362 1.1 mrg dpd2char;
363 1.1 mrg dpd=(sourml>>18)&0x3ff; /* declet 6 */
364 1.1 mrg dpd2char;
365 1.1 mrg dpd=(sourml>>8)&0x3ff; /* declet 7 */
366 1.1 mrg dpd2char;
367 1.1 mrg dpd=((sourml&0xff)<<2) | (sourlo>>30); /* declet 8 */
368 1.1 mrg dpd2char;
369 1.1 mrg dpd=(sourlo>>20)&0x3ff; /* declet 9 */
370 1.1 mrg dpd2char;
371 1.1 mrg dpd=(sourlo>>10)&0x3ff; /* declet 10 */
372 1.1 mrg dpd2char;
373 1.1 mrg dpd=(sourlo)&0x3ff; /* declet 11 */
374 1.1 mrg dpd2char;
375 1.1 mrg
376 1.1 mrg if (c==cstart) *c++='0'; /* all zeros -- make 0 */
377 1.1 mrg
378 1.1 mrg if (exp==0) { /* integer or NaN case -- easy */
379 1.1 mrg *c='\0'; /* terminate */
380 1.1 mrg return string;
381 1.1 mrg }
382 1.1 mrg
383 1.1 mrg /* non-0 exponent */
384 1.1 mrg e=0; /* assume no E */
385 1.1 mrg pre=c-cstart+exp;
386 1.1 mrg /* [here, pre-exp is the digits count (==1 for zero)] */
387 1.1 mrg if (exp>0 || pre<-5) { /* need exponential form */
388 1.1 mrg e=pre-1; /* calculate E value */
389 1.1 mrg pre=1; /* assume one digit before '.' */
390 1.1 mrg } /* exponential form */
391 1.1 mrg
392 1.1 mrg /* modify the coefficient, adding 0s, '.', and E+nn as needed */
393 1.1 mrg s=c-1; /* source (LSD) */
394 1.1 mrg if (pre>0) { /* ddd.ddd (plain), perhaps with E */
395 1.1 mrg char *dotat=cstart+pre;
396 1.1 mrg if (dotat<c) { /* if embedded dot needed... */
397 1.1 mrg t=c; /* target */
398 1.1 mrg for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
399 1.1 mrg *t='.'; /* insert the dot */
400 1.1 mrg c++; /* length increased by one */
401 1.1 mrg }
402 1.1 mrg
403 1.1 mrg /* finally add the E-part, if needed; it will never be 0, and has */
404 1.1 mrg /* a maximum length of 4 digits */
405 1.1 mrg if (e!=0) {
406 1.1 mrg *c++='E'; /* starts with E */
407 1.1 mrg *c++='+'; /* assume positive */
408 1.1 mrg if (e<0) {
409 1.1 mrg *(c-1)='-'; /* oops, need '-' */
410 1.1 mrg e=-e; /* uInt, please */
411 1.1 mrg }
412 1.1 mrg if (e<1000) { /* 3 (or fewer) digits case */
413 1.1 mrg u=&BIN2CHAR[e*4]; /* -> length byte */
414 1.1 mrg memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */
415 1.1 mrg c+=*u; /* bump pointer appropriately */
416 1.1 mrg }
417 1.1 mrg else { /* 4-digits */
418 1.1 mrg Int thou=((e>>3)*1049)>>17; /* e/1000 */
419 1.1 mrg Int rem=e-(1000*thou); /* e%1000 */
420 1.1 mrg *c++='0'+(char)thou;
421 1.1 mrg u=&BIN2CHAR[rem*4]; /* -> length byte */
422 1.1 mrg memcpy(c, u+1, 4); /* copy fixed 3+1 characters [is safe] */
423 1.1 mrg c+=3; /* bump pointer, always 3 digits */
424 1.1 mrg }
425 1.1 mrg }
426 1.1 mrg *c='\0'; /* add terminator */
427 1.1 mrg /*printf("res %s\n", string); */
428 1.1 mrg return string;
429 1.1 mrg } /* pre>0 */
430 1.1 mrg
431 1.1 mrg /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
432 1.1 mrg t=c+1-pre;
433 1.1 mrg *(t+1)='\0'; /* can add terminator now */
434 1.1 mrg for (; s>=cstart; s--, t--) *t=*s; /* shift whole coefficient right */
435 1.1 mrg c=cstart;
436 1.1 mrg *c++='0'; /* always starts with 0. */
437 1.1 mrg *c++='.';
438 1.1 mrg for (; pre<0; pre++) *c++='0'; /* add any 0's after '.' */
439 1.1 mrg /*printf("res %s\n", string); */
440 1.1 mrg return string;
441 1.1 mrg } /* decimal128ToString */
442 1.1 mrg
443 1.1 mrg /* ------------------------------------------------------------------ */
444 1.1 mrg /* to-number -- conversion from numeric string */
445 1.1 mrg /* */
446 1.1 mrg /* decimal128FromString(result, string, set); */
447 1.1 mrg /* */
448 1.1 mrg /* result is the decimal128 format number which gets the result of */
449 1.1 mrg /* the conversion */
450 1.1 mrg /* *string is the character string which should contain a valid */
451 1.1 mrg /* number (which may be a special value) */
452 1.1 mrg /* set is the context */
453 1.1 mrg /* */
454 1.1 mrg /* The context is supplied to this routine is used for error handling */
455 1.1 mrg /* (setting of status and traps) and for the rounding mode, only. */
456 1.1 mrg /* If an error occurs, the result will be a valid decimal128 NaN. */
457 1.1 mrg /* ------------------------------------------------------------------ */
458 1.1 mrg decimal128 * decimal128FromString(decimal128 *result, const char *string,
459 1.1 mrg decContext *set) {
460 1.1 mrg decContext dc; /* work */
461 1.1 mrg decNumber dn; /* .. */
462 1.1 mrg
463 1.1 mrg decContextDefault(&dc, DEC_INIT_DECIMAL128); /* no traps, please */
464 1.1 mrg dc.round=set->round; /* use supplied rounding */
465 1.1 mrg
466 1.1 mrg decNumberFromString(&dn, string, &dc); /* will round if needed */
467 1.1 mrg decimal128FromNumber(result, &dn, &dc);
468 1.1 mrg if (dc.status!=0) { /* something happened */
469 1.1 mrg decContextSetStatus(set, dc.status); /* .. pass it on */
470 1.1 mrg }
471 1.1 mrg return result;
472 1.1 mrg } /* decimal128FromString */
473 1.1 mrg
474 1.1 mrg /* ------------------------------------------------------------------ */
475 1.1 mrg /* decimal128IsCanonical -- test whether encoding is canonical */
476 1.1 mrg /* d128 is the source decimal128 */
477 1.1 mrg /* returns 1 if the encoding of d128 is canonical, 0 otherwise */
478 1.1 mrg /* No error is possible. */
479 1.1 mrg /* ------------------------------------------------------------------ */
480 1.1 mrg uInt decimal128IsCanonical(const decimal128 *d128) {
481 1.1 mrg decNumber dn; /* work */
482 1.1 mrg decimal128 canon; /* .. */
483 1.1 mrg decContext dc; /* .. */
484 1.1 mrg decContextDefault(&dc, DEC_INIT_DECIMAL128);
485 1.1 mrg decimal128ToNumber(d128, &dn);
486 1.1 mrg decimal128FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
487 1.1 mrg return memcmp(d128, &canon, DECIMAL128_Bytes)==0;
488 1.1 mrg } /* decimal128IsCanonical */
489 1.1 mrg
490 1.1 mrg /* ------------------------------------------------------------------ */
491 1.1 mrg /* decimal128Canonical -- copy an encoding, ensuring it is canonical */
492 1.1 mrg /* d128 is the source decimal128 */
493 1.1 mrg /* result is the target (may be the same decimal128) */
494 1.1 mrg /* returns result */
495 1.1 mrg /* No error is possible. */
496 1.1 mrg /* ------------------------------------------------------------------ */
497 1.1 mrg decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
498 1.1 mrg decNumber dn; /* work */
499 1.1 mrg decContext dc; /* .. */
500 1.1 mrg decContextDefault(&dc, DEC_INIT_DECIMAL128);
501 1.1 mrg decimal128ToNumber(d128, &dn);
502 1.1 mrg decimal128FromNumber(result, &dn, &dc);/* result will now be canonical */
503 1.1 mrg return result;
504 1.1 mrg } /* decimal128Canonical */
505 1.1 mrg
506 1.1 mrg #if DECTRACE || DECCHECK
507 1.1 mrg /* Macros for accessing decimal128 fields. These assume the argument
508 1.1 mrg is a reference (pointer) to the decimal128 structure, and the
509 1.1 mrg decimal128 is in network byte order (big-endian) */
510 1.1 mrg /* Get sign */
511 1.1 mrg #define decimal128Sign(d) ((unsigned)(d)->bytes[0]>>7)
512 1.1 mrg
513 1.1 mrg /* Get combination field */
514 1.1 mrg #define decimal128Comb(d) (((d)->bytes[0] & 0x7c)>>2)
515 1.1 mrg
516 1.1 mrg /* Get exponent continuation [does not remove bias] */
517 1.1 mrg #define decimal128ExpCon(d) ((((d)->bytes[0] & 0x03)<<10) \
518 1.1 mrg | ((unsigned)(d)->bytes[1]<<2) \
519 1.1 mrg | ((unsigned)(d)->bytes[2]>>6))
520 1.1 mrg
521 1.1 mrg /* Set sign [this assumes sign previously 0] */
522 1.1 mrg #define decimal128SetSign(d, b) { \
523 1.1 mrg (d)->bytes[0]|=((unsigned)(b)<<7);}
524 1.1 mrg
525 1.1 mrg /* Set exponent continuation [does not apply bias] */
526 1.1 mrg /* This assumes range has been checked and exponent previously 0; */
527 1.1 mrg /* type of exponent must be unsigned */
528 1.1 mrg #define decimal128SetExpCon(d, e) { \
529 1.1 mrg (d)->bytes[0]|=(uByte)((e)>>10); \
530 1.1 mrg (d)->bytes[1] =(uByte)(((e)&0x3fc)>>2); \
531 1.1 mrg (d)->bytes[2]|=(uByte)(((e)&0x03)<<6);}
532 1.1 mrg
533 1.1 mrg /* ------------------------------------------------------------------ */
534 1.1 mrg /* decimal128Show -- display a decimal128 in hexadecimal [debug aid] */
535 1.1 mrg /* d128 -- the number to show */
536 1.1 mrg /* ------------------------------------------------------------------ */
537 1.1 mrg /* Also shows sign/cob/expconfields extracted */
538 1.1 mrg void decimal128Show(const decimal128 *d128) {
539 1.1 mrg char buf[DECIMAL128_Bytes*2+1];
540 1.1 mrg Int i, j=0;
541 1.1 mrg
542 1.1 mrg if (DECLITEND) {
543 1.1 mrg for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
544 1.1 mrg sprintf(&buf[j], "%02x", d128->bytes[15-i]);
545 1.1 mrg }
546 1.1 mrg printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
547 1.1 mrg d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f,
548 1.1 mrg ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)|
549 1.1 mrg (d128->bytes[13]>>6));
550 1.1 mrg }
551 1.1 mrg else {
552 1.1 mrg for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
553 1.1 mrg sprintf(&buf[j], "%02x", d128->bytes[i]);
554 1.1 mrg }
555 1.1 mrg printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
556 1.1 mrg decimal128Sign(d128), decimal128Comb(d128),
557 1.1 mrg decimal128ExpCon(d128));
558 1.1 mrg }
559 1.1 mrg } /* decimal128Show */
560 1.1 mrg #endif
561