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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [dfp-bit.c] - Blame information for rev 857

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

Line No. Rev Author Line
1 734 jeremybenn
/* This is a software decimal floating point library.
2
   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2011
3
   Free Software Foundation, Inc.
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
/* This implements IEEE 754 decimal floating point arithmetic, but
27
   does not provide a mechanism for setting the rounding mode, or for
28
   generating or handling exceptions.  Conversions between decimal
29
   floating point types and other types depend on C library functions.
30
 
31
   Contributed by Ben Elliston  <bje@au.ibm.com>.  */
32
 
33
#include <stdio.h>
34
#include <stdlib.h>
35
/* FIXME: compile with -std=gnu99 to get these from stdlib.h */
36
extern float strtof (const char *, char **);
37
extern long double strtold (const char *, char **);
38
#include <string.h>
39
#include <limits.h>
40
 
41
#include "dfp-bit.h"
42
 
43
/* Forward declarations.  */
44
#if WIDTH == 32 || WIDTH_TO == 32
45
void __host_to_ieee_32 (_Decimal32 in, decimal32 *out);
46
void __ieee_to_host_32 (decimal32 in, _Decimal32 *out);
47
#endif
48
#if WIDTH == 64 || WIDTH_TO == 64
49
void __host_to_ieee_64 (_Decimal64 in, decimal64 *out);
50
void __ieee_to_host_64 (decimal64 in, _Decimal64 *out);
51
#endif
52
#if WIDTH == 128 || WIDTH_TO == 128
53
void __host_to_ieee_128 (_Decimal128 in, decimal128 *out);
54
void __ieee_to_host_128 (decimal128 in, _Decimal128 *out);
55
#endif
56
 
57
/* A pointer to a binary decFloat operation.  */
58
typedef decFloat* (*dfp_binary_func)
59
     (decFloat *, const decFloat *, const decFloat *, decContext *);
60
 
61
/* Binary operations.  */
62
 
63
/* Use a decFloat (decDouble or decQuad) function to perform a DFP
64
   binary operation.  */
65
static inline decFloat
66
dfp_binary_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b)
67
{
68
  decFloat result;
69
  decContext context;
70
 
71
  decContextDefault (&context, CONTEXT_INIT);
72
  DFP_INIT_ROUNDMODE (context.round);
73
 
74
  /* Perform the operation.  */
75
  op (&result, &arg_a, &arg_b, &context);
76
 
77
  if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
78
    {
79
      /* decNumber exception flags we care about here.  */
80
      int ieee_flags;
81
      int dec_flags = DEC_IEEE_854_Division_by_zero | DEC_IEEE_854_Inexact
82
                      | DEC_IEEE_854_Invalid_operation | DEC_IEEE_854_Overflow
83
                      | DEC_IEEE_854_Underflow;
84
      dec_flags &= context.status;
85
      ieee_flags = DFP_IEEE_FLAGS (dec_flags);
86
      if (ieee_flags != 0)
87
        DFP_HANDLE_EXCEPTIONS (ieee_flags);
88
    }
89
 
90
  return result;
91
}
92
 
93
#if WIDTH == 32
94
/* The decNumber package doesn't provide arithmetic for decSingle (32 bits);
95
   convert to decDouble, use the operation for that, and convert back.  */
96
static inline _Decimal32
97
d32_binary_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b)
98
{
99
  union { _Decimal32 c; decSingle f; } a32, b32, res32;
100
  decDouble a, b, res;
101
  decContext context;
102
 
103
  /* Widen the operands and perform the operation.  */
104
  a32.c = arg_a;
105
  b32.c = arg_b;
106
  decSingleToWider (&a32.f, &a);
107
  decSingleToWider (&b32.f, &b);
108
  res = dfp_binary_op (op, a, b);
109
 
110
  /* Narrow the result, which might result in an underflow or overflow.  */
111
  decContextDefault (&context, CONTEXT_INIT);
112
  DFP_INIT_ROUNDMODE (context.round);
113
  decSingleFromWider (&res32.f, &res, &context);
114
  if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
115
    {
116
      /* decNumber exception flags we care about here.  */
117
      int ieee_flags;
118
      int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Overflow
119
                      | DEC_IEEE_854_Underflow;
120
      dec_flags &= context.status;
121
      ieee_flags = DFP_IEEE_FLAGS (dec_flags);
122
      if (ieee_flags != 0)
123
        DFP_HANDLE_EXCEPTIONS (ieee_flags);
124
    }
125
 
126
  return res32.c;
127
}
128
#else
129
/* decFloat operations are supported for decDouble (64 bits) and
130
   decQuad (128 bits).  The bit patterns for the types are the same.  */
131
static inline DFP_C_TYPE
132
dnn_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
133
{
134
  union { DFP_C_TYPE c; decFloat f; } a, b, result;
135
 
136
  a.c = arg_a;
137
  b.c = arg_b;
138
  result.f = dfp_binary_op (op, a.f, b.f);
139
  return result.c;
140
}
141
#endif
142
 
143
/* Comparison operations.  */
144
 
145
/* Use a decFloat (decDouble or decQuad) function to perform a DFP
146
   comparison.  */
147
static inline CMPtype
148
dfp_compare_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b)
149
{
150
  decContext context;
151
  decFloat res;
152
  int result;
153
 
154
  decContextDefault (&context, CONTEXT_INIT);
155
  DFP_INIT_ROUNDMODE (context.round);
156
 
157
  /* Perform the comparison.  */
158
  op (&res, &arg_a, &arg_b, &context);
159
 
160
  if (DEC_FLOAT_IS_SIGNED (&res))
161
    result = -1;
162
  else if (DEC_FLOAT_IS_ZERO (&res))
163
    result = 0;
164
  else if (DEC_FLOAT_IS_NAN (&res))
165
    result = -2;
166
  else
167
    result = 1;
168
 
169
  return (CMPtype) result;
170
}
171
 
172
#if WIDTH == 32
173
/* The decNumber package doesn't provide comparisons for decSingle (32 bits);
174
   convert to decDouble, use the operation for that, and convert back.  */
175
static inline CMPtype
176
d32_compare_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b)
177
{
178
  union { _Decimal32 c; decSingle f; } a32, b32;
179
  decDouble a, b;
180
 
181
  a32.c = arg_a;
182
  b32.c = arg_b;
183
  decSingleToWider (&a32.f, &a);
184
  decSingleToWider (&b32.f, &b);
185
  return dfp_compare_op (op, a, b);
186
}
187
#else
188
/* decFloat comparisons are supported for decDouble (64 bits) and
189
   decQuad (128 bits).  The bit patterns for the types are the same.  */
190
static inline CMPtype
191
dnn_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
192
{
193
  union { DFP_C_TYPE c; decFloat f; } a, b;
194
 
195
  a.c = arg_a;
196
  b.c = arg_b;
197
  return dfp_compare_op (op, a.f, b.f);
198
}
199
#endif
200
 
201
#if defined(L_conv_sd)
202
void
203
__host_to_ieee_32 (_Decimal32 in, decimal32 *out)
204
{
205
  memcpy (out, &in, 4);
206
}
207
 
208
void
209
__ieee_to_host_32 (decimal32 in, _Decimal32 *out)
210
{
211
  memcpy (out, &in, 4);
212
}
213
#endif /* L_conv_sd */
214
 
215
#if defined(L_conv_dd)
216
void
217
__host_to_ieee_64 (_Decimal64 in, decimal64 *out)
218
{
219
  memcpy (out, &in, 8);
220
}
221
 
222
void
223
__ieee_to_host_64 (decimal64 in, _Decimal64 *out)
224
{
225
  memcpy (out, &in, 8);
226
}
227
#endif /* L_conv_dd */
228
 
229
#if defined(L_conv_td)
230
void
231
__host_to_ieee_128 (_Decimal128 in, decimal128 *out)
232
{
233
  memcpy (out, &in, 16);
234
}
235
 
236
void
237
__ieee_to_host_128 (decimal128 in, _Decimal128 *out)
238
{
239
  memcpy (out, &in, 16);
240
}
241
#endif /* L_conv_td */
242
 
243
#if defined(L_addsub_sd) || defined(L_addsub_dd) || defined(L_addsub_td)
244
DFP_C_TYPE
245
DFP_ADD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
246
{
247
  return DFP_BINARY_OP (DEC_FLOAT_ADD, arg_a, arg_b);
248
}
249
 
250
DFP_C_TYPE
251
DFP_SUB (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
252
{
253
  return DFP_BINARY_OP (DEC_FLOAT_SUBTRACT, arg_a, arg_b);
254
}
255
#endif /* L_addsub */
256
 
257
#if defined(L_mul_sd) || defined(L_mul_dd) || defined(L_mul_td)
258
DFP_C_TYPE
259
DFP_MULTIPLY (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
260
{
261
  return DFP_BINARY_OP (DEC_FLOAT_MULTIPLY, arg_a, arg_b);
262
}
263
#endif /* L_mul */
264
 
265
#if defined(L_div_sd) || defined(L_div_dd) || defined(L_div_td)
266
DFP_C_TYPE
267
DFP_DIVIDE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
268
{
269
  return DFP_BINARY_OP (DEC_FLOAT_DIVIDE, arg_a, arg_b);
270
}
271
#endif /* L_div */
272
 
273
#if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
274
CMPtype
275
DFP_EQ (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
276
{
277
  CMPtype stat;
278
  stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
279
  /* For EQ return zero for true, nonzero for false.  */
280
  return stat != 0;
281
}
282
#endif /* L_eq */
283
 
284
#if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
285
CMPtype
286
DFP_NE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
287
{
288
  int stat;
289
  stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
290
  /* For NE return zero for true, nonzero for false.  */
291
  if (__builtin_expect (stat == -2, 0))  /* An operand is NaN.  */
292
    return 1;
293
  return stat != 0;
294
}
295
#endif /* L_ne */
296
 
297
#if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
298
CMPtype
299
DFP_LT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
300
{
301
  int stat;
302
  stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
303
  /* For LT return -1 (<0) for true, 1 for false.  */
304
  return (stat == -1) ? -1 : 1;
305
}
306
#endif /* L_lt */
307
 
308
#if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
309
CMPtype
310
DFP_GT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
311
{
312
  int stat;
313
  stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
314
  /* For GT return 1 (>0) for true, -1 for false.  */
315
  return (stat == 1) ? 1 : -1;
316
}
317
#endif
318
 
319
#if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
320
CMPtype
321
DFP_LE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
322
{
323
  int stat;
324
  stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
325
  /* For LE return 0 (<= 0) for true, 1 for false.  */
326
  if (__builtin_expect (stat == -2, 0))  /* An operand is NaN.  */
327
    return 1;
328
  return stat == 1;
329
}
330
#endif /* L_le */
331
 
332
#if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
333
CMPtype
334
DFP_GE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
335
{
336
  int stat;
337
  stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
338
  /* For GE return 1 (>=0) for true, -1 for false.  */
339
  if (__builtin_expect (stat == -2, 0))  /* An operand is NaN.  */
340
    return -1;
341
  return (stat != -1) ? 1 : -1;
342
}
343
#endif /* L_ge */
344
 
345
#define BUFMAX 128
346
 
347
/* Check for floating point exceptions that are relevant for conversions
348
   between decimal float values and handle them.  */
349
static inline void
350
dfp_conversion_exceptions (const int status)
351
{
352
  /* decNumber exception flags we care about here.  */
353
  int ieee_flags;
354
  int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
355
                  | DEC_IEEE_854_Overflow;
356
  dec_flags &= status;
357
  ieee_flags = DFP_IEEE_FLAGS (dec_flags);
358
  if (ieee_flags != 0)
359
    DFP_HANDLE_EXCEPTIONS (ieee_flags);
360
}
361
 
362
#if defined (L_sd_to_dd)
363
/* Use decNumber to convert directly from _Decimal32 to _Decimal64.  */
364
_Decimal64
365
DFP_TO_DFP (_Decimal32 f_from)
366
{
367
  union { _Decimal32 c; decSingle f; } from;
368
  union { _Decimal64 c; decDouble f; } to;
369
 
370
  from.c = f_from;
371
  to.f = *decSingleToWider (&from.f, &to.f);
372
  return to.c;
373
}
374
#endif
375
 
376
#if defined (L_sd_to_td)
377
/* Use decNumber to convert directly from _Decimal32 to _Decimal128.  */
378
_Decimal128
379
DFP_TO_DFP (_Decimal32 f_from)
380
{
381
  union { _Decimal32 c; decSingle f; } from;
382
  union { _Decimal128 c; decQuad f; } to;
383
  decDouble temp;
384
 
385
  from.c = f_from;
386
  temp = *decSingleToWider (&from.f, &temp);
387
  to.f = *decDoubleToWider (&temp, &to.f);
388
  return to.c;
389
}
390
#endif
391
 
392
#if defined (L_dd_to_td)
393
/* Use decNumber to convert directly from _Decimal64 to _Decimal128.  */
394
_Decimal128
395
DFP_TO_DFP (_Decimal64 f_from)
396
{
397
  union { _Decimal64 c; decDouble f; } from;
398
  union { _Decimal128 c; decQuad f; } to;
399
 
400
  from.c = f_from;
401
  to.f = *decDoubleToWider (&from.f, &to.f);
402
  return to.c;
403
}
404
#endif
405
 
406
#if defined (L_dd_to_sd)
407
/* Use decNumber to convert directly from _Decimal64 to _Decimal32.  */
408
_Decimal32
409
DFP_TO_DFP (_Decimal64 f_from)
410
{
411
  union { _Decimal32 c; decSingle f; } to;
412
  union { _Decimal64 c; decDouble f; } from;
413
  decContext context;
414
 
415
  decContextDefault (&context, CONTEXT_INIT);
416
  DFP_INIT_ROUNDMODE (context.round);
417
  from.c = f_from;
418
  to.f = *decSingleFromWider (&to.f, &from.f, &context);
419
  if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
420
    dfp_conversion_exceptions (context.status);
421
  return to.c;
422
}
423
#endif
424
 
425
#if defined (L_td_to_sd)
426
/* Use decNumber to convert directly from _Decimal128 to _Decimal32.  */
427
_Decimal32
428
DFP_TO_DFP (_Decimal128 f_from)
429
{
430
  union { _Decimal32 c; decSingle f; } to;
431
  union { _Decimal128 c; decQuad f; } from;
432
  decDouble temp;
433
  decContext context;
434
 
435
  decContextDefault (&context, CONTEXT_INIT);
436
  DFP_INIT_ROUNDMODE (context.round);
437
  from.c = f_from;
438
  temp = *decDoubleFromWider (&temp, &from.f, &context);
439
  to.f = *decSingleFromWider (&to.f, &temp, &context);
440
  if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
441
    dfp_conversion_exceptions (context.status);
442
  return to.c;
443
}
444
#endif
445
 
446
#if defined (L_td_to_dd)
447
/* Use decNumber to convert directly from _Decimal128 to _Decimal64.  */
448
_Decimal64
449
DFP_TO_DFP (_Decimal128 f_from)
450
{
451
  union { _Decimal64 c; decDouble f; } to;
452
  union { _Decimal128 c; decQuad f; } from;
453
  decContext context;
454
 
455
  decContextDefault (&context, CONTEXT_INIT);
456
  DFP_INIT_ROUNDMODE (context.round);
457
  from.c = f_from;
458
  to.f = *decDoubleFromWider (&to.f, &from.f, &context);
459
  if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
460
    dfp_conversion_exceptions (context.status);
461
  return to.c;
462
}
463
#endif
464
 
465
#if defined (L_dd_to_si) || defined (L_td_to_si) \
466
  || defined (L_dd_to_usi) || defined (L_td_to_usi)
467
/* Use decNumber to convert directly from decimal float to integer types.  */
468
INT_TYPE
469
DFP_TO_INT (DFP_C_TYPE x)
470
{
471
  union { DFP_C_TYPE c; decFloat f; } u;
472
  decContext context;
473
  INT_TYPE i;
474
 
475
  decContextDefault (&context, DEC_INIT_DECIMAL128);
476
  context.round = DEC_ROUND_DOWN;
477
  u.c = x;
478
  i = DEC_FLOAT_TO_INT (&u.f, &context, context.round);
479
  if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
480
    dfp_conversion_exceptions (context.status);
481
  return i;
482
}
483
#endif
484
 
485
#if defined (L_sd_to_si) || (L_sd_to_usi)
486
/* Use decNumber to convert directly from decimal float to integer types.  */
487
INT_TYPE
488
DFP_TO_INT (_Decimal32 x)
489
{
490
  union { _Decimal32 c; decSingle f; } u32;
491
  decDouble f64;
492
  decContext context;
493
  INT_TYPE i;
494
 
495
  decContextDefault (&context, DEC_INIT_DECIMAL128);
496
  context.round = DEC_ROUND_DOWN;
497
  u32.c = x;
498
  f64 = *decSingleToWider (&u32.f, &f64);
499
  i = DEC_FLOAT_TO_INT (&f64, &context, context.round);
500
  if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
501
    dfp_conversion_exceptions (context.status);
502
  return i;
503
}
504
#endif
505
 
506
#if defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di) \
507
  || defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
508
/* decNumber doesn't provide support for conversions to 64-bit integer
509
   types, so do it the hard way.  */
510
INT_TYPE
511
DFP_TO_INT (DFP_C_TYPE x)
512
{
513
  /* decNumber's decimal* types have the same format as C's _Decimal*
514
     types, but they have different calling conventions.  */
515
 
516
  /* TODO: Decimal float to integer conversions should raise FE_INVALID
517
     if the result value does not fit into the result type.  */
518
 
519
  IEEE_TYPE s;
520
  char buf[BUFMAX];
521
  char *pos;
522
  decNumber qval, n1, n2;
523
  decContext context;
524
 
525
  /* Use a large context to avoid losing precision.  */
526
  decContextDefault (&context, DEC_INIT_DECIMAL128);
527
  /* Need non-default rounding mode here.  */
528
  context.round = DEC_ROUND_DOWN;
529
 
530
  HOST_TO_IEEE (x, &s);
531
  TO_INTERNAL (&s, &n1);
532
  /* Rescale if the exponent is less than zero.  */
533
  decNumberToIntegralValue (&n2, &n1, &context);
534
  /* Get a value to use for the quantize call.  */
535
  decNumberFromString (&qval, "1.", &context);
536
  /* Force the exponent to zero.  */
537
  decNumberQuantize (&n1, &n2, &qval, &context);
538
  /* Get a string, which at this point will not include an exponent.  */
539
  decNumberToString (&n1, buf);
540
  /* Ignore the fractional part.  */
541
  pos = strchr (buf, '.');
542
  if (pos)
543
    *pos = 0;
544
  /* Use a C library function to convert to the integral type.  */
545
  return STR_TO_INT (buf, NULL, 10);
546
}
547
#endif
548
 
549
#if defined (L_si_to_dd) || defined (L_si_to_td) \
550
  || defined (L_usi_to_dd) || defined (L_usi_to_td)
551
/* Use decNumber to convert directly from integer to decimal float types.  */
552
DFP_C_TYPE
553
INT_TO_DFP (INT_TYPE i)
554
{
555
  union { DFP_C_TYPE c; decFloat f; } u;
556
 
557
  u.f = *DEC_FLOAT_FROM_INT (&u.f, i);
558
  return u.c;
559
}
560
#endif
561
 
562
#if defined (L_si_to_sd) || defined (L_usi_to_sd)
563
_Decimal32
564
/* Use decNumber to convert directly from integer to decimal float types.  */
565
INT_TO_DFP (INT_TYPE i)
566
{
567
  union { _Decimal32 c; decSingle f; } u32;
568
  decDouble f64;
569
  decContext context;
570
 
571
  decContextDefault (&context, DEC_INIT_DECIMAL128);
572
  f64 = *DEC_FLOAT_FROM_INT (&f64, i);
573
  u32.f = *decSingleFromWider (&u32.f, &f64, &context);
574
  if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
575
    dfp_conversion_exceptions (context.status);
576
  return u32.c;
577
}
578
#endif
579
 
580
#if defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td) \
581
  || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
582
/* decNumber doesn't provide support for conversions from 64-bit integer
583
   types, so do it the hard way.  */
584
DFP_C_TYPE
585
INT_TO_DFP (INT_TYPE i)
586
{
587
  DFP_C_TYPE f;
588
  IEEE_TYPE s;
589
  char buf[BUFMAX];
590
  decContext context;
591
 
592
  decContextDefault (&context, CONTEXT_INIT);
593
  DFP_INIT_ROUNDMODE (context.round);
594
 
595
  /* Use a C library function to get a floating point string.  */
596
  sprintf (buf, INT_FMT ".", CAST_FOR_FMT(i));
597
  /* Convert from the floating point string to a decimal* type.  */
598
  FROM_STRING (&s, buf, &context);
599
  IEEE_TO_HOST (s, &f);
600
 
601
  if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
602
    dfp_conversion_exceptions (context.status);
603
 
604
  return f;
605
}
606
#endif
607
 
608
#if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
609
 || defined (L_sd_to_df) || defined (L_dd_to_df) || defined (L_td_to_df) \
610
 || ((defined (L_sd_to_xf) || defined (L_dd_to_xf) || defined (L_td_to_xf)) \
611
     && LONG_DOUBLE_HAS_XF_MODE) \
612
 || ((defined (L_sd_to_tf) || defined (L_dd_to_tf) || defined (L_td_to_tf)) \
613
     && LONG_DOUBLE_HAS_TF_MODE)
614
BFP_TYPE
615
DFP_TO_BFP (DFP_C_TYPE f)
616
{
617
  IEEE_TYPE s;
618
  char buf[BUFMAX];
619
 
620
  HOST_TO_IEEE (f, &s);
621
  /* Write the value to a string.  */
622
  TO_STRING (&s, buf);
623
  /* Read it as the binary floating point type and return that.  */
624
  return STR_TO_BFP (buf, NULL);
625
}
626
#endif
627
 
628
#if defined (L_sf_to_sd) || defined (L_sf_to_dd) || defined (L_sf_to_td) \
629
 || defined (L_df_to_sd) || defined (L_df_to_dd) || defined (L_df_to_td) \
630
 || ((defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)) \
631
     && LONG_DOUBLE_HAS_XF_MODE) \
632
 || ((defined (L_tf_to_sd) || defined (L_tf_to_dd) || defined (L_tf_to_td)) \
633
     && LONG_DOUBLE_HAS_TF_MODE)
634
DFP_C_TYPE
635
BFP_TO_DFP (BFP_TYPE x)
636
{
637
  DFP_C_TYPE f;
638
  IEEE_TYPE s;
639
  char buf[BUFMAX];
640
  decContext context;
641
 
642
  decContextDefault (&context, CONTEXT_INIT);
643
  DFP_INIT_ROUNDMODE (context.round);
644
 
645
  /* Use a C library function to write the floating point value to a string.  */
646
  sprintf (buf, BFP_FMT, (BFP_VIA_TYPE) x);
647
 
648
  /* Convert from the floating point string to a decimal* type.  */
649
  FROM_STRING (&s, buf, &context);
650
  IEEE_TO_HOST (s, &f);
651
 
652
  if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
653
    {
654
      /* decNumber exception flags we care about here.  */
655
      int ieee_flags;
656
      int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
657
                      | DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow;
658
      dec_flags &= context.status;
659
      ieee_flags = DFP_IEEE_FLAGS (dec_flags);
660
      if (ieee_flags != 0)
661
        DFP_HANDLE_EXCEPTIONS (ieee_flags);
662
    }
663
 
664
  return f;
665
}
666
#endif
667
 
668
#if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
669
CMPtype
670
DFP_UNORD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
671
{
672
  decNumber arg1, arg2;
673
  IEEE_TYPE a, b;
674
 
675
  HOST_TO_IEEE (arg_a, &a);
676
  HOST_TO_IEEE (arg_b, &b);
677
  TO_INTERNAL (&a, &arg1);
678
  TO_INTERNAL (&b, &arg2);
679
  return (decNumberIsNaN (&arg1) || decNumberIsNaN (&arg2));
680
}
681
#endif /* L_unord_sd || L_unord_dd || L_unord_td */

powered by: WebSVN 2.1.0

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