Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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