OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libdecnumber/] [dpd/] [decimal128.c] - Blame information for rev 746

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.