~ubuntu-branches/ubuntu/natty/libextractor/natty

« back to all changes in this revision

Viewing changes to src/plugins/convert_numeric.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-11-17 20:27:32 UTC
  • mfrom: (1.10.4 upstream) (5.2.5 sid)
  • Revision ID: james.westby@ubuntu.com-20091117202732-ipm2h3gks5bdw2vx
Tags: 0.5.23+dfsg-3
* Building against libltdl7.
* Updating to standards version 3.8.3.
* Adding maintainer homepage field to control.
* Marking maintainer homepage field to be also included in binary
  packages and changelog.
* Adding README.source.
* Simplifying autotools handling in rules.
* Updating README.source.
* Moving maintainer homepage field from control to copyright.
* Dropping la files.
* Simplyfing debhelper install files.
* Bumping versioned build-depends on debhelper.
* Adding depends to dpkg install info.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* IEEE floating point support routines, for GDB, the GNU Debugger.
2
 
   Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006
3
 
   Free Software Foundation, Inc.
4
 
 
5
 
This file is part of GDB.
6
 
 
7
 
This program is free software; you can redistribute it and/or modify
8
 
it under the terms of the GNU General Public License as published by
9
 
the Free Software Foundation; either version 2 of the License, or
10
 
(at your option) any later version.
11
 
 
12
 
This program is distributed in the hope that it will be useful,
13
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
GNU General Public License for more details.
16
 
 
17
 
You should have received a copy of the GNU General Public License
18
 
along with this program; if not, write to the Free Software
19
 
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
20
 
 
21
 
/* This is needed to pick up the NAN macro on some systems.  */
22
 
/* #define _GNU_SOURCE */
23
 
 
24
 
#ifdef HAVE_CONFIG_H
25
 
#include "config.h"
26
 
#endif
27
 
 
28
 
#include <math.h>
29
 
 
30
 
#ifdef HAVE_STRING_H
31
 
#include <string.h>
32
 
#endif
33
 
 
34
 
/* On some platforms, <float.h> provides DBL_QNAN.  */
35
 
#ifdef STDC_HEADERS
36
 
#include <float.h>
37
 
#endif
38
 
 
39
 
/*#include "ansidecl.h"*/
40
 
/*#include "libiberty.h"*/
41
 
#include "convert_numeric.h"
42
 
 
43
 
#ifndef INFINITY
44
 
#ifdef HUGE_VAL
45
 
#define INFINITY HUGE_VAL
46
 
#else
47
 
#define INFINITY (1.0 / 0.0)
48
 
#endif
49
 
#endif
50
 
 
51
 
#ifndef NAN
52
 
#ifdef DBL_QNAN
53
 
#define NAN DBL_QNAN
54
 
#else
55
 
#define NAN (0.0 / 0.0)
56
 
#endif
57
 
#endif
58
 
 
59
 
static unsigned long get_field (const unsigned char *,
60
 
                                enum floatformat_byteorders,
61
 
                                unsigned int,
62
 
                                unsigned int,
63
 
                                unsigned int);
64
 
static int floatformat_always_valid (const struct floatformat *fmt,
65
 
                                     const void *from);
66
 
 
67
 
static int
68
 
floatformat_always_valid (const struct floatformat *fmt /*ATTRIBUTE_UNUSED*/,
69
 
                          const void *from /*ATTRIBUTE_UNUSED*/)
70
 
{
71
 
  return 1;
72
 
}
73
 
 
74
 
/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
75
 
   going to bother with trying to muck around with whether it is defined in
76
 
   a system header, what we do if not, etc.  */
77
 
#define FLOATFORMAT_CHAR_BIT 8
78
 
 
79
 
/* floatformats for IEEE single and double, big and little endian.  */
80
 
const struct floatformat floatformat_ieee_single_big =
81
 
{
82
 
  floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
83
 
  floatformat_intbit_no,
84
 
  "floatformat_ieee_single_big",
85
 
  floatformat_always_valid
86
 
};
87
 
const struct floatformat floatformat_ieee_single_little =
88
 
{
89
 
  floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
90
 
  floatformat_intbit_no,
91
 
  "floatformat_ieee_single_little",
92
 
  floatformat_always_valid
93
 
};
94
 
const struct floatformat floatformat_ieee_double_big =
95
 
{
96
 
  floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
97
 
  floatformat_intbit_no,
98
 
  "floatformat_ieee_double_big",
99
 
  floatformat_always_valid
100
 
};
101
 
const struct floatformat floatformat_ieee_double_little =
102
 
{
103
 
  floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
104
 
  floatformat_intbit_no,
105
 
  "floatformat_ieee_double_little",
106
 
  floatformat_always_valid
107
 
};
108
 
 
109
 
/* floatformat for IEEE double, little endian byte order, with big endian word
110
 
   ordering, as on the ARM.  */
111
 
 
112
 
const struct floatformat floatformat_ieee_double_littlebyte_bigword =
113
 
{
114
 
  floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
115
 
  floatformat_intbit_no,
116
 
  "floatformat_ieee_double_littlebyte_bigword",
117
 
  floatformat_always_valid
118
 
};
119
 
 
120
 
/* floatformat for VAX.  Not quite IEEE, but close enough.  */
121
 
 
122
 
const struct floatformat floatformat_vax_f =
123
 
{
124
 
  floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23,
125
 
  floatformat_intbit_no,
126
 
  "floatformat_vax_f",
127
 
  floatformat_always_valid
128
 
};
129
 
const struct floatformat floatformat_vax_d =
130
 
{
131
 
  floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55,
132
 
  floatformat_intbit_no,
133
 
  "floatformat_vax_d",
134
 
  floatformat_always_valid
135
 
};
136
 
const struct floatformat floatformat_vax_g =
137
 
{
138
 
  floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52,
139
 
  floatformat_intbit_no,
140
 
  "floatformat_vax_g",
141
 
  floatformat_always_valid
142
 
};
143
 
 
144
 
static int floatformat_i387_ext_is_valid (const struct floatformat *fmt,
145
 
                                          const void *from);
146
 
 
147
 
static int
148
 
floatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
149
 
{
150
 
  /* In the i387 double-extended format, if the exponent is all ones,
151
 
     then the integer bit must be set.  If the exponent is neither 0
152
 
     nor ~0, the intbit must also be set.  Only if the exponent is
153
 
     zero can it be zero, and then it must be zero.  */
154
 
  unsigned long exponent, int_bit;
155
 
  const unsigned char *ufrom = (const unsigned char *) from;
156
 
 
157
 
  exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
158
 
                        fmt->exp_start, fmt->exp_len);
159
 
  int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
160
 
                       fmt->man_start, 1);
161
 
 
162
 
  if ((exponent == 0) != (int_bit == 0))
163
 
    return 0;
164
 
  else
165
 
    return 1;
166
 
}
167
 
 
168
 
const struct floatformat floatformat_i387_ext =
169
 
{
170
 
  floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
171
 
  floatformat_intbit_yes,
172
 
  "floatformat_i387_ext",
173
 
  floatformat_i387_ext_is_valid
174
 
};
175
 
const struct floatformat floatformat_m68881_ext =
176
 
{
177
 
  /* Note that the bits from 16 to 31 are unused.  */
178
 
  floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
179
 
  floatformat_intbit_yes,
180
 
  "floatformat_m68881_ext",
181
 
  floatformat_always_valid
182
 
};
183
 
const struct floatformat floatformat_i960_ext =
184
 
{
185
 
  /* Note that the bits from 0 to 15 are unused.  */
186
 
  floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
187
 
  floatformat_intbit_yes,
188
 
  "floatformat_i960_ext",
189
 
  floatformat_always_valid
190
 
};
191
 
const struct floatformat floatformat_m88110_ext =
192
 
{
193
 
  floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
194
 
  floatformat_intbit_yes,
195
 
  "floatformat_m88110_ext",
196
 
  floatformat_always_valid
197
 
};
198
 
const struct floatformat floatformat_m88110_harris_ext =
199
 
{
200
 
  /* Harris uses raw format 128 bytes long, but the number is just an ieee
201
 
     double, and the last 64 bits are wasted. */
202
 
  floatformat_big,128, 0, 1, 11,  0x3ff,  0x7ff, 12, 52,
203
 
  floatformat_intbit_no,
204
 
  "floatformat_m88110_ext_harris",
205
 
  floatformat_always_valid
206
 
};
207
 
const struct floatformat floatformat_arm_ext_big =
208
 
{
209
 
  /* Bits 1 to 16 are unused.  */
210
 
  floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
211
 
  floatformat_intbit_yes,
212
 
  "floatformat_arm_ext_big",
213
 
  floatformat_always_valid
214
 
};
215
 
const struct floatformat floatformat_arm_ext_littlebyte_bigword =
216
 
{
217
 
  /* Bits 1 to 16 are unused.  */
218
 
  floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
219
 
  floatformat_intbit_yes,
220
 
  "floatformat_arm_ext_littlebyte_bigword",
221
 
  floatformat_always_valid
222
 
};
223
 
const struct floatformat floatformat_ia64_spill_big =
224
 
{
225
 
  floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
226
 
  floatformat_intbit_yes,
227
 
  "floatformat_ia64_spill_big",
228
 
  floatformat_always_valid
229
 
};
230
 
const struct floatformat floatformat_ia64_spill_little =
231
 
{
232
 
  floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
233
 
  floatformat_intbit_yes,
234
 
  "floatformat_ia64_spill_little",
235
 
  floatformat_always_valid
236
 
};
237
 
const struct floatformat floatformat_ia64_quad_big =
238
 
{
239
 
  floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
240
 
  floatformat_intbit_no,
241
 
  "floatformat_ia64_quad_big",
242
 
  floatformat_always_valid
243
 
};
244
 
const struct floatformat floatformat_ia64_quad_little =
245
 
{
246
 
  floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
247
 
  floatformat_intbit_no,
248
 
  "floatformat_ia64_quad_little",
249
 
  floatformat_always_valid
250
 
};
251
 
 
252
 
 
253
 
#ifndef min
254
 
#define min(a, b) ((a) < (b) ? (a) : (b))
255
 
#endif
256
 
 
257
 
/* Extract a field which starts at START and is LEN bits long.  DATA and
258
 
   TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
259
 
static unsigned long
260
 
get_field (const unsigned char *data, enum floatformat_byteorders order,
261
 
           unsigned int total_len, unsigned int start, unsigned int len)
262
 
{
263
 
  unsigned long result = 0;
264
 
  unsigned int cur_byte;
265
 
  int lo_bit, hi_bit, cur_bitshift = 0;
266
 
  int nextbyte = (order == floatformat_little) ? 1 : -1;
267
 
 
268
 
  /* Start is in big-endian bit order!  Fix that first.  */
269
 
  start = total_len - (start + len);
270
 
 
271
 
  /* Start at the least significant part of the field.  */
272
 
  if (order == floatformat_little)
273
 
    cur_byte = start / FLOATFORMAT_CHAR_BIT;
274
 
  else
275
 
    cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
276
 
 
277
 
  lo_bit = start % FLOATFORMAT_CHAR_BIT;
278
 
  hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
279
 
  
280
 
  do
281
 
    {
282
 
      unsigned int shifted = *(data + cur_byte) >> lo_bit;
283
 
      unsigned int bits = hi_bit - lo_bit;
284
 
      unsigned int mask = (1 << bits) - 1;
285
 
      result |= (shifted & mask) << cur_bitshift;
286
 
      len -= bits;
287
 
      cur_bitshift += bits;
288
 
      cur_byte += nextbyte;
289
 
      lo_bit = 0;
290
 
      hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
291
 
    }
292
 
  while (len != 0);
293
 
 
294
 
  return result;
295
 
}
296
 
  
297
 
/* Convert from FMT to a double.
298
 
   FROM is the address of the extended float.
299
 
   Store the double in *TO.  */
300
 
 
301
 
void
302
 
floatformat_to_double (const struct floatformat *fmt,
303
 
                       const void *from, double *to)
304
 
{
305
 
  const unsigned char *ufrom = (const unsigned char *) from;
306
 
  double dto;
307
 
  long exponent;
308
 
  unsigned long mant;
309
 
  unsigned int mant_bits, mant_off;
310
 
  int mant_bits_left;
311
 
  int special_exponent;         /* It's a NaN, denorm or zero */
312
 
 
313
 
  exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
314
 
                        fmt->exp_start, fmt->exp_len);
315
 
 
316
 
  /* If the exponent indicates a NaN, we don't have information to
317
 
     decide what to do.  So we handle it like IEEE, except that we
318
 
     don't try to preserve the type of NaN.  FIXME.  */
319
 
  if ((unsigned long) exponent == fmt->exp_nan)
320
 
    {
321
 
      int nan;
322
 
 
323
 
      mant_off = fmt->man_start;
324
 
      mant_bits_left = fmt->man_len;
325
 
      nan = 0;
326
 
      while (mant_bits_left > 0)
327
 
        {
328
 
          mant_bits = min (mant_bits_left, 32);
329
 
 
330
 
          if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
331
 
                         mant_off, mant_bits) != 0)
332
 
            {
333
 
              /* This is a NaN.  */
334
 
              nan = 1;
335
 
              break;
336
 
            }
337
 
 
338
 
          mant_off += mant_bits;
339
 
          mant_bits_left -= mant_bits;
340
 
        }
341
 
 
342
 
      /* On certain systems (such as GNU/Linux), the use of the
343
 
         INFINITY macro below may generate a warning that can not be
344
 
         silenced due to a bug in GCC (PR preprocessor/11931).  The
345
 
         preprocessor fails to recognise the __extension__ keyword in
346
 
         conjunction with the GNU/C99 extension for hexadecimal
347
 
         floating point constants and will issue a warning when
348
 
         compiling with -pedantic.  */
349
 
      if (nan)
350
 
        dto = NAN;
351
 
      else
352
 
        dto = INFINITY;
353
 
 
354
 
      if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
355
 
        dto = -dto;
356
 
 
357
 
      *to = dto;
358
 
 
359
 
      return;
360
 
    }
361
 
 
362
 
  mant_bits_left = fmt->man_len;
363
 
  mant_off = fmt->man_start;
364
 
  dto = 0.0;
365
 
 
366
 
  special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;
367
 
 
368
 
  /* Don't bias zero's, denorms or NaNs.  */
369
 
  if (!special_exponent)
370
 
    exponent -= fmt->exp_bias;
371
 
 
372
 
  /* Build the result algebraically.  Might go infinite, underflow, etc;
373
 
     who cares. */
374
 
 
375
 
  /* If this format uses a hidden bit, explicitly add it in now.  Otherwise,
376
 
     increment the exponent by one to account for the integer bit.  */
377
 
 
378
 
  if (!special_exponent)
379
 
    {
380
 
      if (fmt->intbit == floatformat_intbit_no)
381
 
        dto = ldexp (1.0, exponent);
382
 
      else
383
 
        exponent++;
384
 
    }
385
 
 
386
 
  while (mant_bits_left > 0)
387
 
    {
388
 
      mant_bits = min (mant_bits_left, 32);
389
 
 
390
 
      mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
391
 
                         mant_off, mant_bits);
392
 
 
393
 
      /* Handle denormalized numbers.  FIXME: What should we do for
394
 
         non-IEEE formats?  */
395
 
      if (special_exponent && exponent == 0 && mant != 0)
396
 
        dto += ldexp ((double)mant,
397
 
                      (- fmt->exp_bias
398
 
                       - mant_bits
399
 
                       - (mant_off - fmt->man_start)
400
 
                       + 1));
401
 
      else
402
 
        dto += ldexp ((double)mant, exponent - mant_bits);
403
 
      if (exponent != 0)
404
 
        exponent -= mant_bits;
405
 
      mant_off += mant_bits;
406
 
      mant_bits_left -= mant_bits;
407
 
    }
408
 
 
409
 
  /* Negate it if negative.  */
410
 
  if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
411
 
    dto = -dto;
412
 
  *to = dto;
413
 
}
414
 
 
415
 
static void put_field (unsigned char *, enum floatformat_byteorders,
416
 
                       unsigned int,
417
 
                       unsigned int,
418
 
                       unsigned int,
419
 
                       unsigned long);
420
 
 
421
 
/* Set a field which starts at START and is LEN bits long.  DATA and
422
 
   TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
423
 
static void
424
 
put_field (unsigned char *data, enum floatformat_byteorders order,
425
 
           unsigned int total_len, unsigned int start, unsigned int len,
426
 
           unsigned long stuff_to_put)
427
 
{
428
 
  unsigned int cur_byte;
429
 
  int lo_bit, hi_bit;
430
 
  int nextbyte = (order == floatformat_little) ? 1 : -1;
431
 
 
432
 
  /* Start is in big-endian bit order!  Fix that first.  */
433
 
  start = total_len - (start + len);
434
 
 
435
 
  /* Start at the least significant part of the field.  */
436
 
  if (order == floatformat_little)
437
 
    cur_byte = start / FLOATFORMAT_CHAR_BIT;
438
 
  else
439
 
    cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
440
 
 
441
 
  lo_bit = start % FLOATFORMAT_CHAR_BIT;
442
 
  hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
443
 
  
444
 
  do
445
 
    {
446
 
      unsigned char *byte_ptr = data + cur_byte;
447
 
      unsigned int bits = hi_bit - lo_bit;
448
 
      unsigned int mask = ((1 << bits) - 1) << lo_bit;
449
 
      *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
450
 
      stuff_to_put >>= bits;
451
 
      len -= bits;
452
 
      cur_byte += nextbyte;
453
 
      lo_bit = 0;
454
 
      hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
455
 
    }
456
 
  while (len != 0);
457
 
}
458
 
 
459
 
/* The converse: convert the double *FROM to an extended float
460
 
   and store where TO points.  Neither FROM nor TO have any alignment
461
 
   restrictions.  */
462
 
 
463
 
void
464
 
floatformat_from_double (const struct floatformat *fmt,
465
 
                         const double *from, void *to)
466
 
{
467
 
  double dfrom;
468
 
  int exponent;
469
 
  double mant;
470
 
  unsigned int mant_bits, mant_off;
471
 
  int mant_bits_left;
472
 
  unsigned char *uto = (unsigned char *) to;
473
 
 
474
 
  dfrom = *from;
475
 
  memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
476
 
 
477
 
  /* If negative, set the sign bit.  */
478
 
  if (dfrom < 0)
479
 
    {
480
 
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
481
 
      dfrom = -dfrom;
482
 
    }
483
 
 
484
 
  if (dfrom == 0)
485
 
    {
486
 
      /* 0.0.  */
487
 
      return;
488
 
    }
489
 
 
490
 
  if (dfrom != dfrom)
491
 
    {
492
 
      /* NaN.  */
493
 
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
494
 
                 fmt->exp_len, fmt->exp_nan);
495
 
      /* Be sure it's not infinity, but NaN value is irrelevant.  */
496
 
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
497
 
                 32, 1);
498
 
      return;
499
 
    }
500
 
 
501
 
  if (dfrom + dfrom == dfrom)
502
 
    {
503
 
      /* This can only happen for an infinite value (or zero, which we
504
 
         already handled above).  */
505
 
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
506
 
                 fmt->exp_len, fmt->exp_nan);
507
 
      return;
508
 
    }
509
 
 
510
 
  mant = frexp (dfrom, &exponent);
511
 
  if (exponent + fmt->exp_bias - 1 > 0)
512
 
    put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
513
 
               fmt->exp_len, exponent + fmt->exp_bias - 1);
514
 
  else
515
 
    {
516
 
      /* Handle a denormalized number.  FIXME: What should we do for
517
 
         non-IEEE formats?  */
518
 
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
519
 
                 fmt->exp_len, 0);
520
 
      mant = ldexp (mant, exponent + fmt->exp_bias - 1);
521
 
    }
522
 
 
523
 
  mant_bits_left = fmt->man_len;
524
 
  mant_off = fmt->man_start;
525
 
  while (mant_bits_left > 0)
526
 
    {
527
 
      unsigned long mant_long;
528
 
      mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
529
 
 
530
 
      mant *= 4294967296.0;
531
 
      mant_long = (unsigned long)mant;
532
 
      mant -= mant_long;
533
 
 
534
 
      /* If the integer bit is implicit, and we are not creating a
535
 
         denormalized number, then we need to discard it.  */
536
 
      if ((unsigned int) mant_bits_left == fmt->man_len
537
 
          && fmt->intbit == floatformat_intbit_no
538
 
          && exponent + fmt->exp_bias - 1 > 0)
539
 
        {
540
 
          mant_long &= 0x7fffffff;
541
 
          mant_bits -= 1;
542
 
        }
543
 
      else if (mant_bits < 32)
544
 
        {
545
 
          /* The bits we want are in the most significant MANT_BITS bits of
546
 
             mant_long.  Move them to the least significant.  */
547
 
          mant_long >>= 32 - mant_bits;
548
 
        }
549
 
 
550
 
      put_field (uto, fmt->byteorder, fmt->totalsize,
551
 
                 mant_off, mant_bits, mant_long);
552
 
      mant_off += mant_bits;
553
 
      mant_bits_left -= mant_bits;
554
 
    }
555
 
}
556
 
 
557
 
/* Return non-zero iff the data at FROM is a valid number in format FMT.  */
558
 
 
559
 
int
560
 
floatformat_is_valid (const struct floatformat *fmt, const void *from)
561
 
{
562
 
  return fmt->is_valid (fmt, from);
563
 
}
564
 
 
565
 
 
566
 
#ifdef IEEE_DEBUG
567
 
 
568
 
#include <stdio.h>
569
 
 
570
 
/* This is to be run on a host which uses IEEE floating point.  */
571
 
 
572
 
void
573
 
ieee_test (double n)
574
 
{
575
 
  double result;
576
 
 
577
 
  floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
578
 
  if ((n != result && (! isnan (n) || ! isnan (result)))
579
 
      || (n < 0 && result >= 0)
580
 
      || (n >= 0 && result < 0))
581
 
    printf ("Differ(to): %.20g -> %.20g\n", n, result);
582
 
 
583
 
  floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
584
 
  if ((n != result && (! isnan (n) || ! isnan (result)))
585
 
      || (n < 0 && result >= 0)
586
 
      || (n >= 0 && result < 0))
587
 
    printf ("Differ(from): %.20g -> %.20g\n", n, result);
588
 
 
589
 
#if 0
590
 
  {
591
 
    char exten[16];
592
 
 
593
 
    floatformat_from_double (&floatformat_m68881_ext, &n, exten);
594
 
    floatformat_to_double (&floatformat_m68881_ext, exten, &result);
595
 
    if (n != result)
596
 
      printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
597
 
  }
598
 
#endif
599
 
 
600
 
#if IEEE_DEBUG > 1
601
 
  /* This is to be run on a host which uses 68881 format.  */
602
 
  {
603
 
    long double ex = *(long double *)exten;
604
 
    if (ex != n)
605
 
      printf ("Differ(from vs. extended): %.20g\n", n);
606
 
  }
607
 
#endif
608
 
}
609
 
 
610
 
int
611
 
main (void)
612
 
{
613
 
  ieee_test (0.0);
614
 
  ieee_test (0.5);
615
 
  ieee_test (256.0);
616
 
  ieee_test (0.12345);
617
 
  ieee_test (234235.78907234);
618
 
  ieee_test (-512.0);
619
 
  ieee_test (-0.004321);
620
 
  ieee_test (1.2E-70);
621
 
  ieee_test (1.2E-316);
622
 
  ieee_test (4.9406564584124654E-324);
623
 
  ieee_test (- 4.9406564584124654E-324);
624
 
  ieee_test (- 0.0);
625
 
  ieee_test (- INFINITY);
626
 
  ieee_test (- NAN);
627
 
  ieee_test (INFINITY);
628
 
  ieee_test (NAN);
629
 
  return 0;
630
 
}
631
 
#endif