decimal32.c revision 1.1.1.7 1 1.1 mrg /* Decimal 32-bit format module for the decNumber C Library.
2 1.1.1.7 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 32-bit format module */
28 1.1 mrg /* ------------------------------------------------------------------ */
29 1.1 mrg /* This module comprises the routines for decimal32 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 7 /* make decNumbers with space for 7 */
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 "decimal32.h" /* our primary include */
45 1.1 mrg
46 1.1 mrg /* Utility tables and routines [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];
50 1.1 mrg extern const uByte BIN2CHAR[4001];
51 1.1 mrg
52 1.1 mrg extern void decDigitsToDPD(const decNumber *, uInt *, Int);
53 1.1 mrg extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
54 1.1 mrg
55 1.1 mrg #if DECTRACE || DECCHECK
56 1.1 mrg void decimal32Show(const decimal32 *); /* 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 /* decimal32FromNumber -- convert decNumber to decimal32 */
66 1.1 mrg /* */
67 1.1 mrg /* ds is the target decimal32 */
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 DECIMAL32_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 decimal32 * decimal32FromNumber(decimal32 *d32, 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 targ=0; /* target 32-bit */
90 1.1 mrg
91 1.1 mrg /* If the number has too many digits, or the exponent could be */
92 1.1 mrg /* out of range then reduce the number under the appropriate */
93 1.1 mrg /* constraints. This could push the number to Infinity or zero, */
94 1.1 mrg /* so this check and rounding must be done before generating the */
95 1.1 mrg /* decimal32] */
96 1.1 mrg ae=dn->exponent+dn->digits-1; /* [0 if special] */
97 1.1 mrg if (dn->digits>DECIMAL32_Pmax /* too many digits */
98 1.1 mrg || ae>DECIMAL32_Emax /* likely overflow */
99 1.1 mrg || ae<DECIMAL32_Emin) { /* likely underflow */
100 1.1 mrg decContextDefault(&dc, DEC_INIT_DECIMAL32); /* [no traps] */
101 1.1 mrg dc.round=set->round; /* use supplied rounding */
102 1.1 mrg decNumberPlus(&dw, dn, &dc); /* (round and check) */
103 1.1 mrg /* [this changes -0 to 0, so enforce the sign...] */
104 1.1 mrg dw.bits|=dn->bits&DECNEG;
105 1.1 mrg status=dc.status; /* save status */
106 1.1 mrg dn=&dw; /* use the work number */
107 1.1 mrg } /* maybe out of range */
108 1.1 mrg
109 1.1 mrg if (dn->bits&DECSPECIAL) { /* a special value */
110 1.1 mrg if (dn->bits&DECINF) targ=DECIMAL_Inf<<24;
111 1.1 mrg else { /* sNaN or qNaN */
112 1.1 mrg if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */
113 1.1 mrg && (dn->digits<DECIMAL32_Pmax)) { /* coefficient fits */
114 1.1 mrg decDigitsToDPD(dn, &targ, 0);
115 1.1 mrg }
116 1.1 mrg if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24;
117 1.1 mrg else targ|=DECIMAL_sNaN<<24;
118 1.1 mrg } /* a NaN */
119 1.1 mrg } /* special */
120 1.1 mrg
121 1.1 mrg else { /* is finite */
122 1.1 mrg if (decNumberIsZero(dn)) { /* is a zero */
123 1.1 mrg /* set and clamp exponent */
124 1.1 mrg if (dn->exponent<-DECIMAL32_Bias) {
125 1.1 mrg exp=0; /* low clamp */
126 1.1 mrg status|=DEC_Clamped;
127 1.1 mrg }
128 1.1 mrg else {
129 1.1 mrg exp=dn->exponent+DECIMAL32_Bias; /* bias exponent */
130 1.1 mrg if (exp>DECIMAL32_Ehigh) { /* top clamp */
131 1.1 mrg exp=DECIMAL32_Ehigh;
132 1.1 mrg status|=DEC_Clamped;
133 1.1 mrg }
134 1.1 mrg }
135 1.1 mrg comb=(exp>>3) & 0x18; /* msd=0, exp top 2 bits .. */
136 1.1 mrg }
137 1.1 mrg else { /* non-zero finite number */
138 1.1 mrg uInt msd; /* work */
139 1.1 mrg Int pad=0; /* coefficient pad digits */
140 1.1 mrg
141 1.1 mrg /* the dn is known to fit, but it may need to be padded */
142 1.1 mrg exp=(uInt)(dn->exponent+DECIMAL32_Bias); /* bias exponent */
143 1.1 mrg if (exp>DECIMAL32_Ehigh) { /* fold-down case */
144 1.1 mrg pad=exp-DECIMAL32_Ehigh;
145 1.1 mrg exp=DECIMAL32_Ehigh; /* [to maximum] */
146 1.1 mrg status|=DEC_Clamped;
147 1.1 mrg }
148 1.1 mrg
149 1.1 mrg /* fastpath common case */
150 1.1 mrg if (DECDPUN==3 && pad==0) {
151 1.1 mrg targ=BIN2DPD[dn->lsu[0]];
152 1.1 mrg if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10;
153 1.1 mrg msd=(dn->digits==7 ? dn->lsu[2] : 0);
154 1.1 mrg }
155 1.1 mrg else { /* general case */
156 1.1 mrg decDigitsToDPD(dn, &targ, pad);
157 1.1 mrg /* save and clear the top digit */
158 1.1 mrg msd=targ>>20;
159 1.1 mrg targ&=0x000fffff;
160 1.1 mrg }
161 1.1 mrg
162 1.1 mrg /* create the combination field */
163 1.1 mrg if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01);
164 1.1 mrg else comb=((exp>>3) & 0x18) | msd;
165 1.1 mrg }
166 1.1 mrg targ|=comb<<26; /* add combination field .. */
167 1.1 mrg targ|=(exp&0x3f)<<20; /* .. and exponent continuation */
168 1.1 mrg } /* finite */
169 1.1 mrg
170 1.1 mrg if (dn->bits&DECNEG) targ|=0x80000000; /* add sign bit */
171 1.1 mrg
172 1.1 mrg /* now write to storage; this is endian */
173 1.1 mrg UBFROMUI(d32->bytes, targ); /* directly store the int */
174 1.1 mrg
175 1.1 mrg if (status!=0) decContextSetStatus(set, status); /* pass on status */
176 1.1 mrg /* decimal32Show(d32); */
177 1.1 mrg return d32;
178 1.1 mrg } /* decimal32FromNumber */
179 1.1 mrg
180 1.1 mrg /* ------------------------------------------------------------------ */
181 1.1 mrg /* decimal32ToNumber -- convert decimal32 to decNumber */
182 1.1 mrg /* d32 is the source decimal32 */
183 1.1 mrg /* dn is the target number, with appropriate space */
184 1.1 mrg /* No error is possible. */
185 1.1 mrg /* ------------------------------------------------------------------ */
186 1.1 mrg decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
187 1.1 mrg uInt msd; /* coefficient MSD */
188 1.1 mrg uInt exp; /* exponent top two bits */
189 1.1 mrg uInt comb; /* combination field */
190 1.1 mrg uInt sour; /* source 32-bit */
191 1.1 mrg uInt uiwork; /* for macros */
192 1.1 mrg
193 1.1 mrg /* load source from storage; this is endian */
194 1.1 mrg sour=UBTOUI(d32->bytes); /* directly load the int */
195 1.1 mrg
196 1.1 mrg comb=(sour>>26)&0x1f; /* combination field */
197 1.1 mrg
198 1.1 mrg decNumberZero(dn); /* clean number */
199 1.1 mrg if (sour&0x80000000) dn->bits=DECNEG; /* set sign if negative */
200 1.1 mrg
201 1.1 mrg msd=COMBMSD[comb]; /* decode the combination field */
202 1.1 mrg exp=COMBEXP[comb]; /* .. */
203 1.1 mrg
204 1.1 mrg if (exp==3) { /* is a special */
205 1.1 mrg if (msd==0) {
206 1.1 mrg dn->bits|=DECINF;
207 1.1 mrg return dn; /* no coefficient needed */
208 1.1 mrg }
209 1.1 mrg else if (sour&0x02000000) dn->bits|=DECSNAN;
210 1.1 mrg else dn->bits|=DECNAN;
211 1.1 mrg msd=0; /* no top digit */
212 1.1 mrg }
213 1.1 mrg else { /* is a finite number */
214 1.1 mrg dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */
215 1.1 mrg }
216 1.1 mrg
217 1.1 mrg /* get the coefficient */
218 1.1 mrg sour&=0x000fffff; /* clean coefficient continuation */
219 1.1 mrg if (msd) { /* non-zero msd */
220 1.1 mrg sour|=msd<<20; /* prefix to coefficient */
221 1.1 mrg decDigitsFromDPD(dn, &sour, 3); /* process 3 declets */
222 1.1 mrg return dn;
223 1.1 mrg }
224 1.1 mrg /* msd=0 */
225 1.1 mrg if (!sour) return dn; /* easy: coefficient is 0 */
226 1.1 mrg if (sour&0x000ffc00) /* need 2 declets? */
227 1.1 mrg decDigitsFromDPD(dn, &sour, 2); /* process 2 declets */
228 1.1 mrg else
229 1.1 mrg decDigitsFromDPD(dn, &sour, 1); /* process 1 declet */
230 1.1 mrg return dn;
231 1.1 mrg } /* decimal32ToNumber */
232 1.1 mrg
233 1.1 mrg /* ------------------------------------------------------------------ */
234 1.1 mrg /* to-scientific-string -- conversion to numeric string */
235 1.1 mrg /* to-engineering-string -- conversion to numeric string */
236 1.1 mrg /* */
237 1.1 mrg /* decimal32ToString(d32, string); */
238 1.1 mrg /* decimal32ToEngString(d32, string); */
239 1.1 mrg /* */
240 1.1 mrg /* d32 is the decimal32 format number to convert */
241 1.1 mrg /* string is the string where the result will be laid out */
242 1.1 mrg /* */
243 1.1 mrg /* string must be at least 24 characters */
244 1.1 mrg /* */
245 1.1 mrg /* No error is possible, and no status can be set. */
246 1.1 mrg /* ------------------------------------------------------------------ */
247 1.1 mrg char * decimal32ToEngString(const decimal32 *d32, char *string){
248 1.1 mrg decNumber dn; /* work */
249 1.1 mrg decimal32ToNumber(d32, &dn);
250 1.1 mrg decNumberToEngString(&dn, string);
251 1.1 mrg return string;
252 1.1 mrg } /* decimal32ToEngString */
253 1.1 mrg
254 1.1 mrg char * decimal32ToString(const decimal32 *d32, char *string){
255 1.1 mrg uInt msd; /* coefficient MSD */
256 1.1 mrg Int exp; /* exponent top two bits or full */
257 1.1 mrg uInt comb; /* combination field */
258 1.1 mrg char *cstart; /* coefficient start */
259 1.1 mrg char *c; /* output pointer in string */
260 1.1 mrg const uByte *u; /* work */
261 1.1 mrg char *s, *t; /* .. (source, target) */
262 1.1 mrg Int dpd; /* .. */
263 1.1 mrg Int pre, e; /* .. */
264 1.1 mrg uInt uiwork; /* for macros */
265 1.1 mrg uInt sour; /* source 32-bit */
266 1.1 mrg
267 1.1 mrg /* load source from storage; this is endian */
268 1.1 mrg sour=UBTOUI(d32->bytes); /* directly load the int */
269 1.1 mrg
270 1.1 mrg c=string; /* where result will go */
271 1.1 mrg if (((Int)sour)<0) *c++='-'; /* handle sign */
272 1.1 mrg
273 1.1 mrg comb=(sour>>26)&0x1f; /* combination field */
274 1.1 mrg msd=COMBMSD[comb]; /* decode the combination field */
275 1.1 mrg exp=COMBEXP[comb]; /* .. */
276 1.1 mrg
277 1.1 mrg if (exp==3) {
278 1.1 mrg if (msd==0) { /* infinity */
279 1.1 mrg strcpy(c, "Inf");
280 1.1 mrg strcpy(c+3, "inity");
281 1.1 mrg return string; /* easy */
282 1.1 mrg }
283 1.1 mrg if (sour&0x02000000) *c++='s'; /* sNaN */
284 1.1 mrg strcpy(c, "NaN"); /* complete word */
285 1.1 mrg c+=3; /* step past */
286 1.1 mrg if ((sour&0x000fffff)==0) return string; /* zero payload */
287 1.1 mrg /* otherwise drop through to add integer; set correct exp */
288 1.1 mrg exp=0; msd=0; /* setup for following code */
289 1.1 mrg }
290 1.1 mrg else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */
291 1.1 mrg
292 1.1 mrg /* convert 7 digits of significand to characters */
293 1.1 mrg cstart=c; /* save start of coefficient */
294 1.1 mrg if (msd) *c++='0'+(char)msd; /* non-zero most significant digit */
295 1.1 mrg
296 1.1 mrg /* Now decode the declets. After extracting each one, it is */
297 1.1 mrg /* decoded to binary and then to a 4-char sequence by table lookup; */
298 1.1 mrg /* the 4-chars are a 1-char length (significant digits, except 000 */
299 1.1 mrg /* has length 0). This allows us to left-align the first declet */
300 1.1 mrg /* with non-zero content, then remaining ones are full 3-char */
301 1.1 mrg /* length. We use fixed-length memcpys because variable-length */
302 1.1 mrg /* causes a subroutine call in GCC. (These are length 4 for speed */
303 1.1 mrg /* and are safe because the array has an extra terminator byte.) */
304 1.1 mrg #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
305 1.1 mrg if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
306 1.1 mrg else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
307 1.1 mrg
308 1.1 mrg dpd=(sour>>10)&0x3ff; /* declet 1 */
309 1.1 mrg dpd2char;
310 1.1 mrg dpd=(sour)&0x3ff; /* declet 2 */
311 1.1 mrg dpd2char;
312 1.1 mrg
313 1.1 mrg if (c==cstart) *c++='0'; /* all zeros -- make 0 */
314 1.1 mrg
315 1.1 mrg if (exp==0) { /* integer or NaN case -- easy */
316 1.1 mrg *c='\0'; /* terminate */
317 1.1 mrg return string;
318 1.1 mrg }
319 1.1 mrg
320 1.1 mrg /* non-0 exponent */
321 1.1 mrg e=0; /* assume no E */
322 1.1 mrg pre=c-cstart+exp;
323 1.1 mrg /* [here, pre-exp is the digits count (==1 for zero)] */
324 1.1 mrg if (exp>0 || pre<-5) { /* need exponential form */
325 1.1 mrg e=pre-1; /* calculate E value */
326 1.1 mrg pre=1; /* assume one digit before '.' */
327 1.1 mrg } /* exponential form */
328 1.1 mrg
329 1.1 mrg /* modify the coefficient, adding 0s, '.', and E+nn as needed */
330 1.1 mrg s=c-1; /* source (LSD) */
331 1.1 mrg if (pre>0) { /* ddd.ddd (plain), perhaps with E */
332 1.1 mrg char *dotat=cstart+pre;
333 1.1 mrg if (dotat<c) { /* if embedded dot needed... */
334 1.1 mrg t=c; /* target */
335 1.1 mrg for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
336 1.1 mrg *t='.'; /* insert the dot */
337 1.1 mrg c++; /* length increased by one */
338 1.1 mrg }
339 1.1 mrg
340 1.1 mrg /* finally add the E-part, if needed; it will never be 0, and has */
341 1.1 mrg /* a maximum length of 3 digits (E-101 case) */
342 1.1 mrg if (e!=0) {
343 1.1 mrg *c++='E'; /* starts with E */
344 1.1 mrg *c++='+'; /* assume positive */
345 1.1 mrg if (e<0) {
346 1.1 mrg *(c-1)='-'; /* oops, need '-' */
347 1.1 mrg e=-e; /* uInt, please */
348 1.1 mrg }
349 1.1 mrg u=&BIN2CHAR[e*4]; /* -> length byte */
350 1.1 mrg memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */
351 1.1 mrg c+=*u; /* bump pointer appropriately */
352 1.1 mrg }
353 1.1 mrg *c='\0'; /* add terminator */
354 1.1 mrg /*printf("res %s\n", string); */
355 1.1 mrg return string;
356 1.1 mrg } /* pre>0 */
357 1.1 mrg
358 1.1 mrg /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
359 1.1 mrg t=c+1-pre;
360 1.1 mrg *(t+1)='\0'; /* can add terminator now */
361 1.1 mrg for (; s>=cstart; s--, t--) *t=*s; /* shift whole coefficient right */
362 1.1 mrg c=cstart;
363 1.1 mrg *c++='0'; /* always starts with 0. */
364 1.1 mrg *c++='.';
365 1.1 mrg for (; pre<0; pre++) *c++='0'; /* add any 0's after '.' */
366 1.1 mrg /*printf("res %s\n", string); */
367 1.1 mrg return string;
368 1.1 mrg } /* decimal32ToString */
369 1.1 mrg
370 1.1 mrg /* ------------------------------------------------------------------ */
371 1.1 mrg /* to-number -- conversion from numeric string */
372 1.1 mrg /* */
373 1.1 mrg /* decimal32FromString(result, string, set); */
374 1.1 mrg /* */
375 1.1 mrg /* result is the decimal32 format number which gets the result of */
376 1.1 mrg /* the conversion */
377 1.1 mrg /* *string is the character string which should contain a valid */
378 1.1 mrg /* number (which may be a special value) */
379 1.1 mrg /* set is the context */
380 1.1 mrg /* */
381 1.1 mrg /* The context is supplied to this routine is used for error handling */
382 1.1 mrg /* (setting of status and traps) and for the rounding mode, only. */
383 1.1 mrg /* If an error occurs, the result will be a valid decimal32 NaN. */
384 1.1 mrg /* ------------------------------------------------------------------ */
385 1.1 mrg decimal32 * decimal32FromString(decimal32 *result, const char *string,
386 1.1 mrg decContext *set) {
387 1.1 mrg decContext dc; /* work */
388 1.1 mrg decNumber dn; /* .. */
389 1.1 mrg
390 1.1 mrg decContextDefault(&dc, DEC_INIT_DECIMAL32); /* no traps, please */
391 1.1 mrg dc.round=set->round; /* use supplied rounding */
392 1.1 mrg
393 1.1 mrg decNumberFromString(&dn, string, &dc); /* will round if needed */
394 1.1 mrg decimal32FromNumber(result, &dn, &dc);
395 1.1 mrg if (dc.status!=0) { /* something happened */
396 1.1 mrg decContextSetStatus(set, dc.status); /* .. pass it on */
397 1.1 mrg }
398 1.1 mrg return result;
399 1.1 mrg } /* decimal32FromString */
400 1.1 mrg
401 1.1 mrg /* ------------------------------------------------------------------ */
402 1.1 mrg /* decimal32IsCanonical -- test whether encoding is canonical */
403 1.1 mrg /* d32 is the source decimal32 */
404 1.1 mrg /* returns 1 if the encoding of d32 is canonical, 0 otherwise */
405 1.1 mrg /* No error is possible. */
406 1.1 mrg /* ------------------------------------------------------------------ */
407 1.1 mrg uInt decimal32IsCanonical(const decimal32 *d32) {
408 1.1 mrg decNumber dn; /* work */
409 1.1 mrg decimal32 canon; /* .. */
410 1.1 mrg decContext dc; /* .. */
411 1.1 mrg decContextDefault(&dc, DEC_INIT_DECIMAL32);
412 1.1 mrg decimal32ToNumber(d32, &dn);
413 1.1 mrg decimal32FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
414 1.1 mrg return memcmp(d32, &canon, DECIMAL32_Bytes)==0;
415 1.1 mrg } /* decimal32IsCanonical */
416 1.1 mrg
417 1.1 mrg /* ------------------------------------------------------------------ */
418 1.1 mrg /* decimal32Canonical -- copy an encoding, ensuring it is canonical */
419 1.1 mrg /* d32 is the source decimal32 */
420 1.1 mrg /* result is the target (may be the same decimal32) */
421 1.1 mrg /* returns result */
422 1.1 mrg /* No error is possible. */
423 1.1 mrg /* ------------------------------------------------------------------ */
424 1.1 mrg decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) {
425 1.1 mrg decNumber dn; /* work */
426 1.1 mrg decContext dc; /* .. */
427 1.1 mrg decContextDefault(&dc, DEC_INIT_DECIMAL32);
428 1.1 mrg decimal32ToNumber(d32, &dn);
429 1.1 mrg decimal32FromNumber(result, &dn, &dc);/* result will now be canonical */
430 1.1 mrg return result;
431 1.1 mrg } /* decimal32Canonical */
432 1.1 mrg
433 1.1 mrg #if DECTRACE || DECCHECK
434 1.1 mrg /* Macros for accessing decimal32 fields. These assume the argument
435 1.1 mrg is a reference (pointer) to the decimal32 structure, and the
436 1.1 mrg decimal32 is in network byte order (big-endian) */
437 1.1 mrg /* Get sign */
438 1.1 mrg #define decimal32Sign(d) ((unsigned)(d)->bytes[0]>>7)
439 1.1 mrg
440 1.1 mrg /* Get combination field */
441 1.1 mrg #define decimal32Comb(d) (((d)->bytes[0] & 0x7c)>>2)
442 1.1 mrg
443 1.1 mrg /* Get exponent continuation [does not remove bias] */
444 1.1 mrg #define decimal32ExpCon(d) ((((d)->bytes[0] & 0x03)<<4) \
445 1.1 mrg | ((unsigned)(d)->bytes[1]>>4))
446 1.1 mrg
447 1.1 mrg /* Set sign [this assumes sign previously 0] */
448 1.1 mrg #define decimal32SetSign(d, b) { \
449 1.1 mrg (d)->bytes[0]|=((unsigned)(b)<<7);}
450 1.1 mrg
451 1.1 mrg /* Set exponent continuation [does not apply bias] */
452 1.1 mrg /* This assumes range has been checked and exponent previously 0; */
453 1.1 mrg /* type of exponent must be unsigned */
454 1.1 mrg #define decimal32SetExpCon(d, e) { \
455 1.1 mrg (d)->bytes[0]|=(uByte)((e)>>4); \
456 1.1 mrg (d)->bytes[1]|=(uByte)(((e)&0x0F)<<4);}
457 1.1 mrg
458 1.1 mrg /* ------------------------------------------------------------------ */
459 1.1 mrg /* decimal32Show -- display a decimal32 in hexadecimal [debug aid] */
460 1.1 mrg /* d32 -- the number to show */
461 1.1 mrg /* ------------------------------------------------------------------ */
462 1.1 mrg /* Also shows sign/cob/expconfields extracted - valid bigendian only */
463 1.1 mrg void decimal32Show(const decimal32 *d32) {
464 1.1 mrg char buf[DECIMAL32_Bytes*2+1];
465 1.1 mrg Int i, j=0;
466 1.1 mrg
467 1.1 mrg if (DECLITEND) {
468 1.1 mrg for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
469 1.1 mrg sprintf(&buf[j], "%02x", d32->bytes[3-i]);
470 1.1 mrg }
471 1.1 mrg printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
472 1.1 mrg d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f,
473 1.1 mrg ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4));
474 1.1 mrg }
475 1.1 mrg else {
476 1.1 mrg for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
477 1.1 mrg sprintf(&buf[j], "%02x", d32->bytes[i]);
478 1.1 mrg }
479 1.1 mrg printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
480 1.1 mrg decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32));
481 1.1 mrg }
482 1.1 mrg } /* decimal32Show */
483 1.1 mrg #endif
484