Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 1
/* ieeefloat.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS                                                                        */
6
/*                                                                           */
7
/* IEEE Floating Point Handling                                              */
8
/*                                                                           */
9
/*****************************************************************************/
10
 
11
#include "stdinc.h"
12
#include <float.h>
13
#include <math.h>
14
#include <errno.h>
15
#include <string.h>
16
 
17
#include "be_le.h"
18
#include "as_float.h"
19
#ifdef HOST_DECFLOAT
20
# include "decfloat.h"
21
#endif
22
#include "ieeefloat.h"
23
 
24
#define DBG_FLOAT 0
25
 
26
#ifdef IEEEFLOAT_8_DOUBLE
27
/*!------------------------------------------------------------------------
28
 * \fn     as_float_dissect(as_float_dissect_t *p_dest, as_float_t num)
29
 * \brief  dissect float into components - version if as_float_t is IEEE Double
30
 * \param  p_dest result buffer
31
 * \param  num number to dissect
32
 * ------------------------------------------------------------------------ */
33
 
34
void as_float_dissect(as_float_dissect_t *p_dest, as_float_t num)
35
{
36
  Byte buf[8];
37
  LongWord mant_h, mant_l;
38
 
39
  as_float_zero(p_dest);
40
 
41
  /* binary representation, little endian: */
42
 
43
  memcpy(buf, &num, 8);
44
  if (HostBigEndian)
45
    QSwap(buf, 8);
46
 
47
#if DBG_FLOAT
48
  fprintf(stdout, "%0.15f\n", num);
49
#endif
50
 
51
  /* (a) Sign is MSB of highest byte: */
52
 
53
  p_dest->negative = !!(buf[7] & 0x80);
54
 
55
  /* (b) Exponent is stored in the following 11 bits, with a bias of 1023: */
56
 
57
  p_dest->exponent = (buf[7] & 0x7f);
58
  p_dest->exponent = (p_dest->exponent << 4) | ((buf[6] >> 4) & 15);
59
  switch (p_dest->exponent)
60
  {
61
    case 0:
62
      p_dest->fp_class = AS_FP_SUBNORMAL;
63
      break;
64
    case 2047:
65
      p_dest->fp_class = AS_FP_INFINITE;
66
      break;
67
    default:
68
      p_dest->fp_class = AS_FP_NORMAL;
69
  }
70
  p_dest->exponent -= 1023;
71
 
72
  /* (c) Make leading one explicit (if not denormal) */
73
 
74
  as_float_append_mantissa_bits(p_dest, p_dest->fp_class == AS_FP_NORMAL, 1);
75
 
76
  /* (d) Extract 52 bits of mantissa: */
77
 
78
  mant_h = buf[6] & 15;
79
  mant_h = (mant_h << 8) | buf[5];
80
  mant_h = (mant_h << 8) | buf[4];
81
  as_float_append_mantissa_bits(p_dest, mant_h, 20);
82
  mant_l = buf[3];
83
  mant_l = (mant_l << 8) | buf[2];
84
  mant_l = (mant_l << 8) | buf[1];
85
  mant_l = (mant_l << 8) | buf[0];
86
  as_float_append_mantissa_bits(p_dest, mant_l, 32);
87
 
88
  /* Distinguish NaN and Infinite */
89
 
90
  if ((p_dest->fp_class == AS_FP_INFINITE)
91
   && (mant_h || mant_l))
92
    p_dest->fp_class = AS_FP_NAN;
93
#if DBG_FLOAT
94
  as_float_dump(stdout, "0", p_dest);
95
#endif
96
}
97
#endif /* IEEEFLOAT_8_DOUBLE */
98
 
99
/* x86 80 bit float format is just extended with two or six padding bytes
100
   on i386 resp. x86-64, which can be ignored for dissection: */
101
 
102
#if (defined IEEEFLOAT_10_10_LONG_DOUBLE) || (defined IEEEFLOAT_10_12_LONG_DOUBLE) || (defined IEEEFLOAT_10_16_LONG_DOUBLE)
103
/*!------------------------------------------------------------------------
104
 * \fn     as_float_dissect(as_float_dissect_t *p_dest, as_float_t num)
105
 * \brief  dissect float into components - version if as_float_t is x86 extended 80 Bit
106
 * \param  p_dest result buffer
107
 * \param  num number to dissect
108
 * ------------------------------------------------------------------------ */
109
 
110
void as_float_dissect(as_float_dissect_t *p_dest, as_float_t num)
111
{
112
  Byte buf[16];
113
  LongWord mant_h, mant_l;
114
 
115
  as_float_zero(p_dest);
116
 
117
  /* binary representation, little endian: */
118
 
119
  memcpy(buf, &num, 10);
120
  if (HostBigEndian)
121
    TSwap(buf, 10);
122
 
123
#if DBG_FLOAT
124
  fprintf(stdout, "%0.15Lf\n", num);
125
#endif
126
 
127
  /* (a) Sign is MSB of highest byte: */
128
 
129
  p_dest->negative = !!(buf[9] & 0x80);
130
 
131
  /* (b) Exponent is stored in the following 15 bits, with a bias of 16383:
132
         Note special case for denormal numbers, which is due to the
133
         explicit leading mantissa bit: */
134
 
135
  p_dest->exponent = (buf[9] & 0x7f);
136
  p_dest->exponent = (p_dest->exponent << 8) | buf[8];
137
  switch (p_dest->exponent)
138
  {
139
    case 0:
140
      p_dest->fp_class = AS_FP_SUBNORMAL;
141
      p_dest->exponent = -16382;
142
      break;
143
    case 32767:
144
      p_dest->fp_class = AS_FP_INFINITE;
145
      p_dest->exponent -= 16383;
146
      break;
147
    default:
148
      p_dest->fp_class = AS_FP_NORMAL;
149
      p_dest->exponent -= 16383;
150
  }
151
 
152
  /* (c) leading one is *not* implicit */
153
 
154
  /* (d) Extract 64 bits of mantissa: */
155
 
156
  mant_h = buf[7];
157
  mant_h = (mant_h << 8) | buf[6];
158
  mant_h = (mant_h << 8) | buf[5];
159
  mant_h = (mant_h << 8) | buf[4];
160
  as_float_append_mantissa_bits(p_dest, mant_h, 32);
161
  mant_l = buf[3];
162
  mant_l = (mant_l << 8) | buf[3];
163
  mant_l = (mant_l << 8) | buf[2];
164
  mant_l = (mant_l << 8) | buf[1];
165
  mant_l = (mant_l << 8) | buf[0];
166
  as_float_append_mantissa_bits(p_dest, mant_l, 32);
167
 
168
  /* Distinguish NaN and Infinite */
169
 
170
  if ((p_dest->fp_class == AS_FP_INFINITE)
171
   && !as_float_mantissa_is_zero_from(p_dest, 1))
172
      p_dest->fp_class = AS_FP_NAN;
173
 
174
#if DBG_FLOAT
175
  as_float_dump(stdout, "0", p_dest);
176
#endif
177
}
178
#endif /* IEEEFLOAT_10_10_LONG_DOUBLE || IEEEFLOAT_10_12_LONG_DOUBLE || IEEEFLOAT_10_16_LONG_DOUBLE */
179
 
180
#ifdef IEEEFLOAT_10_2P8_LONG_DOUBLE
181
/*!------------------------------------------------------------------------
182
 * \fn     as_float_dissect(as_float_dissect_t *p_dest, as_float_t num)
183
 * \brief  dissect float into components - version if as_float_t is 68K extended 96/80 Bit
184
 * \param  p_dest result buffer
185
 * \param  num number to dissect
186
 * ------------------------------------------------------------------------ */
187
 
188
void as_float_dissect(as_float_dissect_t *p_dest, as_float_t num)
189
{
190
  Byte buf[12];
191
  LongWord mant_h, mant_l;
192
 
193
  as_float_zero(p_dest);
194
 
195
  /* binary representation, big endian: */
196
 
197
  memcpy(buf, &num, 12);
198
 
199
  /* (a) Sign is MSB of highest byte: */
200
 
201
  p_dest->negative = !!(buf[0] & 0x80);
202
 
203
  /* (b) Exponent is stored in the following 15 bits, with a bias of 16383:
204
         Note special case for denormal numbers, which is due to the
205
         explicit leading mantissa bit: */
206
 
207
  p_dest->exponent = (buf[0] & 0x7f);
208
  p_dest->exponent = (p_dest->exponent << 8) | buf[1];
209
  switch (p_dest->exponent)
210
  {
211
    case 0:
212
      p_dest->fp_class = AS_FP_SUBNORMAL;
213
      p_dest->exponent = -16382;
214
      break;
215
    case 32767:
216
      p_dest->fp_class = AS_FP_INFINITE;
217
      p_dest->exponent -= 16383;
218
      break;
219
    default:
220
      p_dest->fp_class = AS_FP_NORMAL;
221
      p_dest->exponent -= 16383;
222
  }
223
 
224
  /* (c) leading one is *not* implicit */
225
 
226
  /* (d) Extract 64 bits of mantissa: */
227
 
228
  mant_h = buf[4];
229
  mant_h = (mant_h << 8) | buf[5];
230
  mant_h = (mant_h << 8) | buf[6];
231
  mant_h = (mant_h << 8) | buf[7];
232
  as_float_append_mantissa_bits(p_dest, mant_h, 32);
233
  mant_l = buf[8];
234
  mant_l = (mant_l << 8) | buf[9];
235
  mant_l = (mant_l << 8) | buf[10];
236
  mant_l = (mant_l << 8) | buf[11];
237
  as_float_append_mantissa_bits(p_dest, mant_l, 32);
238
 
239
  /* Distinguish NaN and Infinite */
240
 
241
  if ((p_dest->fp_class == AS_FP_INFINITE)
242
   && !as_float_mantissa_is_zero_from(p_dest, 1))
243
      p_dest->fp_class = AS_FP_NAN;
244
}
245
#endif /* IEEEFLOAT_10_12_LONG_DOUBLE */
246
 
247
/*!------------------------------------------------------------------------
248
 * \fn     as_float_2_ieee4(as_float_t inp, Byte *pDest, Boolean NeedsBig)
249
 * \brief  convert float to IEEE single (32 bit) float binary representation
250
 * \param  inp input number
251
 * \param  pDest where to write binary data
252
 * \param  NeedsBig req's big endian?
253
 * \return >=0 if conversion was successful, <0 for error
254
 * ------------------------------------------------------------------------ */
255
 
256
int as_float_2_ieee4(as_float_t inp, Byte *pDest, Boolean NeedsBig)
257
{
258
  as_float_dissect_t dissect;
259
#if (defined IEEEFLOAT_8_DOUBLE) || (defined IEEEFLOAT_10_LONG_DOUBLE)
260
 
261
  float tmp;
262
  as_float_dissect(&dissect, inp);
263
  if ((dissect.fp_class != AS_FP_NAN)
264
   && (dissect.fp_class != AS_FP_INFINITE)
265
   && (as_fabs(inp) > FLT_MAX))
266
    return -E2BIG;
267
  tmp = inp;
268
  memcpy(pDest, &tmp, 4);
269
  if (HostBigEndian != NeedsBig)
270
    DSwap(pDest, 4);
271
 
272
#else
273
 
274
  as_float_round_t round_type;
275
  unsigned mask = NeedsBig ? 3 : 0;
276
 
277
  /* (1) Dissect IEEE number */
278
 
279
  as_float_dissect(&dissect, inp);
280
 
281
  /* Infinity/NaN: */
282
 
283
  if ((dissect.fp_class == AS_FP_NAN)
284
   || (dissect.fp_class == AS_FP_INFINITE))
285
  {
286
    pDest[3 ^ mask] = (dissect.negative << 7) | 0x7f;
287
    pDest[2 ^ mask] = 0x80;
288
    pDest[1 ^ mask] =
289
    pDest[0 ^ mask] = 0;
290
 
291
    /* clone all-ones mantissa for NaN: */
292
 
293
    if (as_float_mantissa_is_allones(&dissect))
294
    {
295
      pDest[2 ^ mask] |= 0x7f;
296
      pDest[1 ^ mask] |= 0xff;
297
      pDest[0 ^ mask] |= 0xff;
298
    }
299
 
300
    /* otherwise clone MSB+LSB of mantissa: */
301
 
302
    else
303
    {
304
      if (as_float_get_mantissa_bit(dissect.mantissa, dissect.mantissa_bits, 1))
305
        pDest[2 ^ mask] |= 0x40;
306
      if (as_float_get_mantissa_bit(dissect.mantissa, dissect.mantissa_bits, dissect.mantissa_bits - 1))
307
        pDest[0 ^ mask] |= 0x01;
308
    }
309
    return 2;
310
  }
311
 
312
  /* (2) Round to target precision: */
313
 
314
  round_type = as_float_round(&dissect, 24);
315
 
316
  /* (3a) Overrange? */
317
 
318
  if (dissect.exponent > 127)
319
    return -E2BIG;
320
  else if ((dissect.exponent == 127)
321
        && as_float_mantissa_is_allones(&dissect)
322
        && (round_type == e_round_down))
323
    return -E2BIG;
324
 
325
  /* (3b) number that is too small may degenerate to 0: */
326
 
327
  while ((dissect.exponent < -127) && !as_float_mantissa_is_zero(&dissect))
328
  {
329
    dissect.exponent++;
330
    as_float_mantissa_shift_right(dissect.mantissa, 0, dissect.mantissa_bits);
331
  }
332
 
333
  /* numbers too small to represent degenerate to 0 (mantissa was shifted out) */
334
 
335
  if (dissect.exponent < -127)
336
    dissect.exponent = -127;
337
 
338
  /* For denormal numbers, exponent is 2^(-126) and not 2^(-127)!
339
     So if we end up with an exponent of 2^(-127), convert
340
     mantissa so it corresponds to 2^(-127): */
341
 
342
  else if (dissect.exponent == -127)
343
    as_float_mantissa_shift_right(dissect.mantissa, 0, dissect.mantissa_bits);
344
 
345
  /* (3c) add bias to exponent */
346
 
347
  dissect.exponent += 127;
348
 
349
  /* (3d) store result */
350
 
351
  pDest[3 ^ mask] = (dissect.negative << 7)
352
                  | ((dissect.exponent >> 1) & 0x7f);
353
  pDest[2 ^ mask] = ((dissect.exponent & 1) << 7)
354
                  | as_float_mantissa_extract(&dissect, 1, 7);
355
  pDest[1 ^ mask] = as_float_mantissa_extract(&dissect, 8, 8);
356
  pDest[0 ^ mask] = as_float_mantissa_extract(&dissect, 16, 8);
357
 
358
#endif
359
  return 4;
360
}
361
 
362
/*!------------------------------------------------------------------------
363
 * \fn     as_float_2_ieee8(as_float_t inp, Byte *pDest, Boolean NeedsBig)
364
 * \brief  convert float to IEEE double (64 bit) float binary representation
365
 * \param  inp input number
366
 * \param  pDest where to write binary data
367
 * \param  NeedsBig req's big endian?
368
 * \return >=0 if conversion was successful, <0 for error
369
 * ------------------------------------------------------------------------ */
370
 
371
int as_float_2_ieee8(as_float_t inp, Byte *pDest, Boolean NeedsBig)
372
{
373
  as_float_dissect_t dissect;
374
#if (defined IEEEFLOAT_8_DOUBLE) || (defined IEEEFLOAT_10_LONG_DOUBLE)
375
 
376
  double tmp;
377
  as_float_dissect(&dissect, inp);
378
  if ((dissect.fp_class != AS_FP_NAN)
379
   && (dissect.fp_class != AS_FP_INFINITE)
380
   && (as_fabs(inp) > DBL_MAX))
381
    return -E2BIG;
382
  tmp = inp;
383
  memcpy(pDest, &tmp, 8);
384
  if (HostBigEndian != NeedsBig)
385
    QSwap(pDest, 8);
386
 
387
#else
388
 
389
  as_float_round_t round_type;
390
  unsigned mask = NeedsBig ? 7 : 0;
391
 
392
  /* (1) Dissect IEEE number */
393
 
394
  as_float_dissect(&dissect, inp);
395
 
396
  /* Infinity/NaN: */
397
 
398
  if ((dissect.fp_class == AS_FP_NAN)
399
   || (dissect.fp_class == AS_FP_INFINITE))
400
  {
401
    pDest[7 ^ mask] = (dissect.negative << 7) | 0x7f;
402
    pDest[6 ^ mask] = 0xf0;
403
    pDest[5 ^ mask] =
404
    pDest[4 ^ mask] =
405
    pDest[3 ^ mask] =
406
    pDest[2 ^ mask] =
407
    pDest[1 ^ mask] =
408
    pDest[0 ^ mask] = 0;
409
 
410
    /* clone all-ones mantissa for NaN: */
411
 
412
    if (as_float_mantissa_is_allones(&dissect))
413
    {
414
      pDest[6 ^ mask] |= 0x0f;
415
      pDest[5 ^ mask] |= 0xff;
416
      pDest[4 ^ mask] |= 0xff;
417
      pDest[3 ^ mask] |= 0xff;
418
      pDest[2 ^ mask] |= 0xff;
419
      pDest[1 ^ mask] |= 0xff;
420
      pDest[0 ^ mask] |= 0xff;
421
    }
422
 
423
    /* otherwise clone MSB+LSB of mantissa: */
424
 
425
    else
426
    {
427
      if (as_float_get_mantissa_bit(dissect.mantissa, dissect.mantissa_bits, 1))
428
        pDest[6 ^ mask] |= 0x08;
429
      if (as_float_get_mantissa_bit(dissect.mantissa, dissect.mantissa_bits, dissect.mantissa_bits - 1))
430
        pDest[0 ^ mask] |= 0x01;
431
    }
432
    return 2;
433
  }
434
 
435
  /* (2) Round to target precision: */
436
 
437
  round_type = as_float_round(&dissect, 53);
438
 
439
  /* (3a) Overrange? */
440
 
441
  if (dissect.exponent > 1023)
442
    return -E2BIG;
443
  else if ((dissect.exponent == 1023)
444
        && as_float_mantissa_is_allones(&dissect)
445
        && (round_type == e_round_down))
446
    return -E2BIG;
447
 
448
  /* (3b) number that is too small may degenerate to 0: */
449
 
450
  while ((dissect.exponent < -1023) && !as_float_mantissa_is_zero(&dissect))
451
  {
452
    dissect.exponent++;
453
    as_float_mantissa_shift_right(dissect.mantissa, 0, dissect.mantissa_bits);
454
  }
455
 
456
  /* TODO: This is needed to get a correct exponent value (0) for 0.0,
457
     if the host format has smaller exponent that IEEE64.
458
     Ultimately, as_float_dissect() should return an exponent
459
     of zero. */
460
 
461
  if (as_float_mantissa_is_zero(&dissect))
462
    dissect.exponent = -1023;
463
 
464
  /* numbers too small to represent degenerate to 0 (mantissa was shifted out) */
465
 
466
  if (dissect.exponent < -1023)
467
    dissect.exponent = -1023;
468
 
469
  /* For denormal numbers, exponent is 2^(-1022) and not 2^(-1023)!
470
     So if we end up with an exponent of 2^(-1023), convert
471
     mantissa so it corresponds to 2^(-1023): */
472
 
473
  else if (dissect.exponent == -1023)
474
    as_float_mantissa_shift_right(dissect.mantissa, 0, dissect.mantissa_bits);
475
 
476
  /* (3c) add bias to exponent */
477
 
478
  dissect.exponent += 1023;
479
 
480
  /* (3d) store result */
481
 
482
  pDest[7 ^ mask] = (dissect.negative << 7)
483
                  | ((dissect.exponent >> 4) & 0x7f);
484
  pDest[6 ^ mask] = ((dissect.exponent & 15) << 4)
485
                  | as_float_mantissa_extract(&dissect, 1, 4);
486
  pDest[5 ^ mask] = as_float_mantissa_extract(&dissect, 5, 8);
487
  pDest[4 ^ mask] = as_float_mantissa_extract(&dissect, 13, 8);
488
  pDest[3 ^ mask] = as_float_mantissa_extract(&dissect, 21, 8);
489
  pDest[2 ^ mask] = as_float_mantissa_extract(&dissect, 29, 8);
490
  pDest[1 ^ mask] = as_float_mantissa_extract(&dissect, 37, 8);
491
  pDest[0 ^ mask] = as_float_mantissa_extract(&dissect, 45, 8);
492
 
493
#endif
494
  return 8;
495
}
496
 
497
/*!------------------------------------------------------------------------
498
 * \fn     as_float_2_ieee10(as_float_t inp, Byte *pDest, Boolean NeedsBig)
499
 * \brief  convert float to non-IEEE extended (80 bit) float binary representation
500
 * \param  inp input number
501
 * \param  pDest where to write binary data
502
 * \param  NeedsBig req's big endian?
503
 * \return >=0 if conversion was successful, <0 for error
504
 * ------------------------------------------------------------------------ */
505
 
506
int as_float_2_ieee10(as_float_t inp, Byte *pDest, Boolean NeedsBig)
507
{
508
#if (defined IEEEFLOAT_10_10_LONG_DOUBLE) || (defined IEEEFLOAT_10_12_LONG_DOUBLE) || (defined IEEEFLOAT_10_16_LONG_DOUBLE)
509
  memcpy(pDest, &inp, 10);
510
  if (HostBigEndian != NeedsBig)
511
    TSwap(pDest, 10);
512
 
513
#else
514
 
515
  as_float_dissect_t dissect;
516
 
517
  /* (1) Dissect IEEE number */
518
 
519
  as_float_dissect(&dissect, inp);
520
 
521
  /* Infinity/NaN: Note that for IEEEFLOAT_10_2P8_LONG_DOUBLE (M68K Extended float),
522
     the mantissa's MSB of infinities and NANs may be 1 or 0.  We want the 1-version,
523
     to be consistent with x86: */
524
 
525
  if ((dissect.fp_class == AS_FP_NAN)
526
   || (dissect.fp_class == AS_FP_INFINITE))
527
  {
528
    pDest[9] = (dissect.negative << 7) | 0x7f;
529
    pDest[8] = 0xff;
530
 
531
    /* clone all-ones mantissa for NaN: */
532
 
533
    if (as_float_mantissa_is_allones(&dissect))
534
      memset(&pDest[0], 8, 0xff);
535
 
536
    /* otherwise clone MSB+LSB of mantissa: */
537
 
538
    else
539
    {
540
      memset(&pDest[0], 0x00, 8);
541
      pDest[7] |= 0x80;
542
      if (as_float_get_mantissa_bit(dissect.mantissa, dissect.mantissa_bits, dissect.mantissa_bits - 1))
543
        pDest[0] |= 0x01;
544
    }
545
 
546
    if (NeedsBig)
547
      TSwap(pDest, 10);
548
 
549
    return 10;
550
  }
551
 
552
# ifdef IEEEFLOAT_10_2P8_LONG_DOUBLE
553
 
554
  Byte *p_src = (Byte*)&inp;
555
  pDest[NeedsBig ? 0 : 9] = p_src[0];
556
  pDest[NeedsBig ? 1 : 8] = p_src[1];
557
  pDest[NeedsBig ? 2 : 7] = p_src[4];
558
  pDest[NeedsBig ? 3 : 6] = p_src[5];
559
  pDest[NeedsBig ? 4 : 5] = p_src[6];
560
  pDest[NeedsBig ? 5 : 4] = p_src[7];
561
  pDest[NeedsBig ? 6 : 3] = p_src[8];
562
  pDest[NeedsBig ? 7 : 2] = p_src[9];
563
  pDest[NeedsBig ? 8 : 1] = p_src[10];
564
  pDest[NeedsBig ? 9 : 0] = p_src[11];
565
 
566
# else /* !IEEEFLOAT_10_2P8_LONG_DOUBLE */
567
 
568
  as_float_dissect(&dissect, inp);
569
  /* (2) Round to target precision: */
570
 
571
  as_float_round(&dissect, 64);
572
 
573
  /* (3a) Overrange? */
574
 
575
  if (dissect.exponent > 16383)
576
    return -E2BIG;
577
 
578
  /* (3b) number that is too small may degenerate to 0: */
579
 
580
  while ((dissect.exponent < -16383) && !as_float_mantissa_is_zero(&dissect))
581
  {
582
    dissect.exponent++;
583
    as_float_mantissa_shift_right(dissect.mantissa, 0, dissect.mantissa_bits);
584
  }
585
 
586
  /* TODO: This is needed to get a correct exponent value (0) for 0.0.
587
     The old routine just added the difference of the 64-bit ad 80-bit
588
     biases, which resulted in an exponent of 0x3c00 (-1023) in the
589
     final value.  Ultimately, as_float_dissect() should return an exponent
590
     of zero. */
591
 
592
  if (as_float_mantissa_is_zero(&dissect))
593
    dissect.exponent = -16383;
594
 
595
  /* numbers too small to represent degenerate to 0 (mantissa was shifted out) */
596
 
597
  if (dissect.exponent < -16383)
598
    dissect.exponent = -16383;
599
 
600
  /* For denormal numbers, exponent is 2^(-16382) and not 2^(-16383)!
601
     So if we end up with an exponent of 2^(-16383), convert
602
     mantissa so it corresponds to 2^(-16382): */
603
 
604
  else if (dissect.exponent == -16383)
605
    as_float_mantissa_shift_right(dissect.mantissa, 0, dissect.mantissa_bits);
606
 
607
  /* (3c) add bias to exponent */
608
 
609
  dissect.exponent += 16383;
610
 
611
  /* (3d) store result */
612
 
613
  pDest[9] = (dissect.negative << 7)
614
           | ((dissect.exponent >> 8) & 0x7f);
615
  pDest[8] = ((dissect.exponent >> 0) & 0xff);
616
  pDest[7] = as_float_mantissa_extract(&dissect,  0, 8); /* leading one is explicit! */
617
  pDest[6] = as_float_mantissa_extract(&dissect,  8, 8);
618
  pDest[5] = as_float_mantissa_extract(&dissect, 16, 8);
619
  pDest[4] = as_float_mantissa_extract(&dissect, 24, 8);
620
  pDest[3] = as_float_mantissa_extract(&dissect, 32, 8);
621
  pDest[2] = as_float_mantissa_extract(&dissect, 40, 8);
622
  pDest[1] = as_float_mantissa_extract(&dissect, 48, 8);
623
  pDest[0] = as_float_mantissa_extract(&dissect, 56, 8);
624
 
625
  if (NeedsBig)
626
    TSwap(pDest, 10);
627
# endif /* IEEEFLOAT_10_2P8_LONG_DOUBLE */
628
#endif /* IEEEFLOAT_10_1?_LONG_DOUBLE */
629
  return 10;
630
}
631
 
632
/*!------------------------------------------------------------------------
633
 * \fn     as_float_2_ieee16(as_float_t inp, Byte *pDest, Boolean NeedsBig)
634
 * \brief  convert float to IEEE quad (128 bit) float binary representation
635
 * \param  inp input number
636
 * \param  pDest where to write binary data
637
 * \param  NeedsBig req's big endian?
638
 * \return >=0 if conversion was successful, <0 for error
639
 * ------------------------------------------------------------------------ */
640
 
641
int as_float_2_ieee16(as_float_t inp, Byte *pDest, Boolean NeedsBig)
642
{
643
  as_float_dissect_t dissect;
644
 
645
  /* (1) Dissect IEEE number */
646
 
647
  as_float_dissect(&dissect, inp);
648
 
649
  /* Infinity/NaN: */
650
 
651
  if ((dissect.fp_class == AS_FP_NAN)
652
   || (dissect.fp_class == AS_FP_INFINITE))
653
  {
654
    pDest[15] = (dissect.negative << 7) | 0x7f;
655
    pDest[14] = 0xff;
656
 
657
    /* clone all-ones mantissa for NaN: */
658
 
659
    if (as_float_mantissa_is_allones(&dissect))
660
      memset(&pDest[0], 14, 0xff);
661
 
662
    /* otherwise clone MSB+LSB of mantissa: */
663
 
664
    else
665
    {
666
      memset(&pDest[0], 0x00, 14);
667
      if (as_float_get_mantissa_bit(dissect.mantissa, dissect.mantissa_bits, 1))
668
        pDest[13] |= 0x80;
669
      if (as_float_get_mantissa_bit(dissect.mantissa, dissect.mantissa_bits, dissect.mantissa_bits - 1))
670
        pDest[0] |= 0x01;
671
    }
672
    if (NeedsBig)
673
      OSwap(pDest, 16);
674
    return 16;
675
  }
676
 
677
  /* (2) Round to target precision: */
678
 
679
  as_float_round(&dissect, 113);
680
 
681
  /* (3a) Overrange? */
682
 
683
  if (dissect.exponent > 16383)
684
    return -E2BIG;
685
 
686
  /* (3b) number that is too small may degenerate to 0: */
687
 
688
  while ((dissect.exponent < -16383) && !as_float_mantissa_is_zero(&dissect))
689
  {
690
    dissect.exponent++;
691
    as_float_mantissa_shift_right(dissect.mantissa, 0, dissect.mantissa_bits);
692
  }
693
 
694
  /* TODO: This is needed to get a correct exponent value (0) for 0.0.
695
     The old routine just added the difference of the 64-bit ad 80-bit
696
     biases, which resulted in an exponent of 0x3c00 (-1023) in the
697
     final value.  Ultimately, as_float_dissect() should return an exponent
698
     of zero. */
699
 
700
  if (as_float_mantissa_is_zero(&dissect))
701
    dissect.exponent = -16383;
702
 
703
  /* numbers too small to represent degenerate to 0 (mantissa was shifted out) */
704
 
705
  if (dissect.exponent < -16383)
706
    dissect.exponent = -16383;
707
 
708
  /* For denormal numbers, exponent is 2^(-16382) and not 2^(-16383)!
709
     So if we end up with an exponent of 2^(-16383), convert
710
     mantissa so it corresponds to 2^(-16382): */
711
 
712
  else if (dissect.exponent == -16383)
713
    as_float_mantissa_shift_right(dissect.mantissa, 0, dissect.mantissa_bits);
714
 
715
  /* (3c) add bias to exponent */
716
 
717
  dissect.exponent += 16383;
718
 
719
  /* (3d) store result */
720
 
721
  pDest[15] = (dissect.negative << 7)
722
            | ((dissect.exponent >> 8) & 0x7f);
723
  pDest[14] = ((dissect.exponent >> 0) & 0xff);
724
  pDest[13] = as_float_mantissa_extract(&dissect,  1, 8);
725
  pDest[12] = as_float_mantissa_extract(&dissect,  9, 8);
726
  pDest[11] = as_float_mantissa_extract(&dissect, 17, 8);
727
  pDest[10] = as_float_mantissa_extract(&dissect, 25, 8);
728
  pDest[ 9] = as_float_mantissa_extract(&dissect, 33, 8);
729
  pDest[ 8] = as_float_mantissa_extract(&dissect, 41, 8);
730
  pDest[ 7] = as_float_mantissa_extract(&dissect, 49, 8);
731
  pDest[ 6] = as_float_mantissa_extract(&dissect, 57, 8);
732
  pDest[ 5] = as_float_mantissa_extract(&dissect, 65, 8);
733
  pDest[ 4] = as_float_mantissa_extract(&dissect, 73, 8);
734
  pDest[ 3] = as_float_mantissa_extract(&dissect, 81, 8);
735
  pDest[ 2] = as_float_mantissa_extract(&dissect, 89, 8);
736
  pDest[ 1] = as_float_mantissa_extract(&dissect, 97, 8);
737
  pDest[ 0] = as_float_mantissa_extract(&dissect,105, 8);
738
 
739
  if (NeedsBig)
740
    OSwap(pDest, 16);
741
 
742
  return 16;
743
}
744
 
745
/*!------------------------------------------------------------------------
746
 * \fn     as_float_2_ieee2(as_float_t inp, Byte *pDest, Boolean NeedsBig)
747
 * \brief  convert floating point number to IEEE half size (16 bit) format
748
 * \param  inp floating point number to store
749
 * \param  pDest where to write result (2 bytes)
750
 * \param  NeedsBig req's big endian?
751
 * \return >=0 if conversion was successful, <0 for error
752
 * ------------------------------------------------------------------------ */
753
 
754
int as_float_2_ieee2(as_float_t inp, Byte *pDest, Boolean NeedsBig)
755
{
756
  as_float_dissect_t dissect;
757
  as_float_round_t round_type;
758
 
759
  /* (1) Dissect IEEE number */
760
 
761
  as_float_dissect(&dissect, inp);
762
 
763
  /* Infinity/NaN: */
764
 
765
  if ((dissect.fp_class == AS_FP_NAN)
766
   || (dissect.fp_class == AS_FP_INFINITE))
767
  {
768
    pDest[1 ^ !!NeedsBig] = (dissect.negative << 7) | 0x7c;
769
    pDest[0 ^ !!NeedsBig] = 0;
770
 
771
    /* clone all-ones mantissa for NaN: */
772
 
773
    if (as_float_mantissa_is_allones(&dissect))
774
    {
775
      pDest[1 ^ !!NeedsBig] |= 0x03;
776
      pDest[0 ^ !!NeedsBig] = 0xff;
777
    }
778
 
779
    /* otherwise clone MSB+LSB of mantissa: */
780
 
781
    else
782
    {
783
      if (as_float_get_mantissa_bit(dissect.mantissa, dissect.mantissa_bits, 1))
784
        pDest[1 ^ !!NeedsBig] |= 0x02;
785
      if (as_float_get_mantissa_bit(dissect.mantissa, dissect.mantissa_bits, dissect.mantissa_bits - 1))
786
        pDest[0 ^ !!NeedsBig] |= 0x01;
787
    }
788
    return 2;
789
  }
790
 
791
  /* (2) Round to target precision: */
792
 
793
  round_type = as_float_round(&dissect, 11);
794
 
795
  /* (3a) Overrange? */
796
 
797
  if (dissect.exponent > 15)
798
    return -E2BIG;
799
  else if ((dissect.exponent == 15)
800
        && as_float_mantissa_is_allones(&dissect)
801
        && (round_type == e_round_down))
802
    return -E2BIG;
803
 
804
  /* (3b) number that is too small may degenerate to 0: */
805
 
806
  while ((dissect.exponent < -15) && !as_float_mantissa_is_zero(&dissect))
807
  {
808
    dissect.exponent++;
809
    as_float_mantissa_shift_right(dissect.mantissa, 0, dissect.mantissa_bits);
810
  }
811
 
812
  /* numbers too small to represent degenerate to 0 (mantissa was shifted out) */
813
 
814
  if (dissect.exponent < -15)
815
    dissect.exponent = -15;
816
 
817
  /* For denormal numbers, exponent is 2^(-14) and not 2^(-15)!
818
     So if we end up with an exponent of 2^(-15), convert
819
     mantissa so it corresponds to 2^(-14): */
820
 
821
  else if (dissect.exponent == -15)
822
    as_float_mantissa_shift_right(dissect.mantissa, 0, dissect.mantissa_bits);
823
 
824
  /* (3c) add bias to exponent */
825
 
826
  dissect.exponent += 15;
827
 
828
  /* (3d) store result */
829
 
830
  pDest[1 ^ !!NeedsBig] = (dissect.negative << 7)
831
                        | ((dissect.exponent << 2) & 0x7c)
832
                        | as_float_mantissa_extract(&dissect, 1, 2);
833
  pDest[0 ^ !!NeedsBig] = as_float_mantissa_extract(&dissect, 3, 8);
834
  return 2;
835
}