GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/air/754.c Lines: 47 131 35.9 %
Date: 2017-05-26 Branches: 32 100 32.0 %

Line Branch Exec Source
1
/*
2
  Teem: Tools to process and visualize scientific data and images             .
3
  Copyright (C) 2013, 2012, 2011, 2010, 2009  University of Chicago
4
  Copyright (C) 2008, 2007, 2006, 2005  Gordon Kindlmann
5
  Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998  University of Utah
6
7
  This library is free software; you can redistribute it and/or
8
  modify it under the terms of the GNU Lesser General Public License
9
  (LGPL) as published by the Free Software Foundation; either
10
  version 2.1 of the License, or (at your option) any later version.
11
  The terms of redistributing and/or modifying this software also
12
  include exceptions to the LGPL that facilitate static linking.
13
14
  This library is distributed in the hope that it will be useful,
15
  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
  Lesser General Public License for more details.
18
19
  You should have received a copy of the GNU Lesser General Public License
20
  along with this library; if not, write to Free Software Foundation, Inc.,
21
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
*/
23
24
#include "air.h"
25
#include "privateAir.h"
26
#include <teemQnanhibit.h>
27
28
/*
29
** all this is based on a reading of
30
** Hennessy + Patterson "Computer Architecture, A Quantitative Approach"
31
** pages A-13 - A-17
32
**
33
** and some assorted web pages, such as:
34
** http://en.wikipedia.org/wiki/NaN#Encoding
35
** which explains what Teem calls qnanhibit, and
36
** http://grouper.ieee.org/groups/754/email/msg04192.html
37
** which includes some discussion on signal-vs-quiet nan
38
*/
39
40
/*
41
** _airFloatEndian{Little,Big}, _airDoubleEndian{Little,Big}
42
**
43
** these unions facilitate converting amongst
44
** i: unsigned integral type
45
** c: (sign,exp,frac) triples of unsigned integral components
46
** v: the floating point numbers these bit-patterns represent
47
*/
48
typedef union {
49
  unsigned int i;
50
  struct {
51
    unsigned int mant : 23;
52
    unsigned int expo : 8;
53
    unsigned int sign : 1;
54
  } c;
55
  float v;
56
} _airFloatEndianLittle;
57
/* HEY COPY AND PASTE */
58
typedef union {
59
  unsigned int i;
60
  struct {
61
    unsigned int sign : 1;
62
    unsigned int expo : 8;
63
    unsigned int mant : 23;
64
  } c;
65
  float v;
66
} _airFloatEndianBig;
67
68
typedef union {
69
  airULLong i;
70
  /* these next two members are used for printing in airFPFprintf_d */
71
  struct { /* access to whole double as two unsigned ints */
72
    unsigned int half0 : 32;
73
    unsigned int half1 : 32;
74
  } h;
75
  struct { /* access to fraction with two unsigned ints */
76
    unsigned int mant1 : 32;
77
    unsigned int mant0 : 20;
78
    unsigned int expo : 11;
79
    unsigned int sign : 1;
80
  } c;
81
  double v;
82
} _airDoubleEndianLittle;
83
/* HEY COPY AND PASTE */
84
typedef union {
85
  airULLong i;
86
  /* these next two members are used for printing in airFPFprintf_d */
87
  struct { /* access to whole double as two unsigned ints */
88
    unsigned int half1 : 32;
89
    unsigned int half0 : 32;
90
  } h;
91
  struct { /* access to fraction with two unsigned ints */
92
    unsigned int sign : 1;
93
    unsigned int expo : 11;
94
    unsigned int mant0 : 20;
95
    unsigned int mant1 : 32;
96
  } c;
97
  double v;
98
} _airDoubleEndianBig;
99
100
/*
101
** The hex numbers in braces are examples of C's "initial member of a union"
102
** aggregate initialization.
103
*/
104
105
#if TEEM_QNANHIBIT == 1
106
const int airMyQNaNHiBit = 1;
107
const airFloat airFloatQNaN = {0x7fffffff};
108
const airFloat airFloatSNaN = {0x7fbfffff};
109
#else
110
const int airMyQNaNHiBit = 0;
111
const airFloat airFloatQNaN = {0x7fbfffff};
112
const airFloat airFloatSNaN = {0x7fffffff};
113
#endif
114
115
const airFloat airFloatPosInf = {0x7f800000};
116
const airFloat airFloatNegInf = {0xff800000}; /* why does solaris whine? */
117
118
/*
119
** these shouldn't be needed, but here they are if need be:
120
121
in this file:
122
const airFloat airFloatMax = {0x7f7fffff};
123
const airFloat airFloatMin = {0x00800000};
124
const airDouble airDoubleMax = {AIR_ULLONG(0x7fefffffffffffff)};
125
const airDouble airDoubleMin = {AIR_ULLONG(0x0010000000000000)};
126
127
in air.h:
128
extern air_export const airFloat airFloatMax;
129
extern air_export const airFloat airFloatMin;
130
extern air_export const airDouble airDoubleMax;
131
extern air_export const airDouble airDoubleMin;
132
#define AIR_FLT_MIN (airFloatMin.f)
133
#define AIR_FLT_MAX (airFloatMax.f)
134
#define AIR_DBL_MIN (airDoubleMin.d)
135
#define AIR_DBL_MAX (airDoubleMax.d)
136
*/
137
138
/* the bit-masking done here quiets gcc -Wconversion warnings */
139
#define FP_SET_F(flit, fbig, s, e, m)          \
140
  flit.c.sign = 1u & (s);                      \
141
  flit.c.expo = ((1u<8)-1) & (e);              \
142
  flit.c.mant = ((1u<23)-1) & (m);             \
143
  fbig.c.sign = 1u & (s);                      \
144
  fbig.c.expo = ((1u<8)-1) & (e);              \
145
  fbig.c.mant = ((1u<23)-1) & (m)
146
147
#define FP_GET_F(s, e, m, flit, fbig)            \
148
  if (airEndianLittle == airMyEndian()) {        \
149
    (s) = flit.c.sign;                           \
150
    (e) = flit.c.expo;                           \
151
    (m) = flit.c.mant;                           \
152
  } else {                                       \
153
    (s) = fbig.c.sign;                           \
154
    (e) = fbig.c.expo;                           \
155
    (m) = fbig.c.mant;                           \
156
  }
157
158
#define FP_SET_D(dlit, dbig, s, e, m0, m1)     \
159
  dlit.c.sign = 1u & (s);                      \
160
  dlit.c.expo = ((1u<<11)-1) & (e);            \
161
  dlit.c.mant0 = ((1u<<20)-1) & (m0);          \
162
  dlit.c.mant1 = (m1);                         \
163
  dbig.c.sign = 1u & (s);                      \
164
  dbig.c.expo = ((1u<<11)-1) & (e);            \
165
  dbig.c.mant0 = ((1u<<20)-1) & (m0);          \
166
  dbig.c.mant1 = (m1)
167
168
#define FP_GET_D(s, e, m0, m1, dlit, dbig)       \
169
  if (airEndianLittle == airMyEndian()) {        \
170
    (s) = dlit.c.sign;                           \
171
    (e) = dlit.c.expo;                           \
172
    (m0) = dlit.c.mant0;                         \
173
    (m1) = dlit.c.mant1;                         \
174
  } else {                                       \
175
    (s) = dbig.c.sign;                           \
176
    (e) = dbig.c.expo;                           \
177
    (m0) = dbig.c.mant0;                         \
178
    (m1) = dbig.c.mant1;                         \
179
  }
180
181
182
float
183
airFPPartsToVal_f(unsigned int sign,
184
                  unsigned int expo,
185
                  unsigned int mant) {
186
  _airFloatEndianLittle flit;
187
  _airFloatEndianBig fbig;
188
189
  FP_SET_F(flit, fbig, sign, expo, mant);
190
  return (airEndianLittle == airMyEndian()
191
          ? flit.v
192
          : fbig.v);
193
}
194
195
void
196
airFPValToParts_f(unsigned int *signP,
197
                  unsigned int *expoP,
198
                  unsigned int *mantP, float v) {
199
  _airFloatEndianLittle flit;
200
  _airFloatEndianBig fbig;
201
202
40
  flit.v = fbig.v = v;
203
40
  FP_GET_F(*signP, *expoP, *mantP, flit, fbig);
204
20
}
205
206
double
207
airFPPartsToVal_d(unsigned int sign,
208
                  unsigned int expo,
209
                  unsigned int mant0,
210
                  unsigned int mant1) {
211
  _airDoubleEndianLittle dlit;
212
  _airDoubleEndianBig dbig;
213
214
  FP_SET_D(dlit, dbig, sign, expo, mant0, mant1);
215
  return (airEndianLittle == airMyEndian()
216
          ? dlit.v
217
          : dbig.v);
218
}
219
220
/*
221
** Disable the 'local variable used without having been initialized'
222
** warning produced by the MSVC compiler
223
*/
224
#ifdef _MSC_VER
225
#pragma warning(push)
226
#pragma warning(disable : 4700)
227
#endif
228
void
229
airFPValToParts_d(unsigned int *signP,
230
                  unsigned int *expoP,
231
                  unsigned int *mant0P,
232
                  unsigned int *mant1P, double v) {
233
  _airDoubleEndianLittle dlit;
234
  _airDoubleEndianBig dbig;
235
236
  dlit.v = dbig.v = v;
237
  FP_GET_D(*signP, *expoP, *mant0P, *mant1P, dlit, dbig);
238
}
239
#ifdef _MSC_VER
240
#pragma warning(pop)
241
#endif
242
243
/*
244
******** airFPGen_f()
245
**
246
** generates a floating point value which is a member of the given class
247
*/
248
float
249
airFPGen_f(int cls) {
250
  _airFloatEndianLittle flit;
251
  _airFloatEndianBig fbig;
252
253


16656
  switch(cls) {
254
  case airFP_SNAN:
255
    /* sgn: anything, mant: anything non-zero with high bit !TEEM_QNANHIBIT */
256
    FP_SET_F(flit, fbig, 0, 0xff, (!TEEM_QNANHIBIT << 22) | 0x3fffff);
257
    break;
258
  case airFP_QNAN:
259
    /* sgn: anything, mant: anything non-zero with high bit TEEM_QNANHIBIT */
260
    FP_SET_F(flit, fbig, 0, 0xff, (TEEM_QNANHIBIT << 22) | 0x3fffff);
261
8328
    break;
262
  case airFP_POS_INF:
263
    FP_SET_F(flit, fbig, 0, 0xff, 0);
264
    break;
265
  case airFP_NEG_INF:
266
    FP_SET_F(flit, fbig, 1, 0xff, 0);
267
    break;
268
  case airFP_POS_NORM:
269
    /* exp: anything non-zero but < 0xff, mant: anything */
270
    FP_SET_F(flit, fbig, 0, 0x80, 0x7ff000);
271
    break;
272
  case airFP_NEG_NORM:
273
    /* exp: anything non-zero but < 0xff, mant: anything */
274
    FP_SET_F(flit, fbig, 1, 0x80, 0x7ff000);
275
    break;
276
  case airFP_POS_DENORM:
277
    /* mant: anything non-zero */
278
    FP_SET_F(flit, fbig, 0, 0, 0xff);
279
    break;
280
  case airFP_NEG_DENORM:
281
    /* mant: anything non-zero */
282
    FP_SET_F(flit, fbig, 1, 0, 0xff);
283
    break;
284
  case airFP_NEG_ZERO:
285
    FP_SET_F(flit, fbig, 1, 0, 0);
286
    break;
287
  case airFP_POS_ZERO:
288
  default:
289
    FP_SET_F(flit, fbig, 0, 0, 0);
290
    break;
291
  }
292
16656
  return (airEndianLittle == airMyEndian()
293
8328
          ? flit.v
294
8328
          : fbig.v);
295
}
296
297
/*
298
******** airFPGen_d()
299
**
300
** generates a floating point value which is a member of the given class
301
*/
302
double
303
airFPGen_d(int cls) {
304
  _airDoubleEndianLittle dlit;
305
  _airDoubleEndianBig dbig;
306
307
  switch(cls) {
308
  case airFP_SNAN:
309
    /* sgn: anything, mant: anything non-zero with high bit !TEEM_QNANHIBIT */
310
    FP_SET_D(dlit, dbig,  0, 0x7ff, (!TEEM_QNANHIBIT << 19) | 0x7ffff, 0xffffffff);
311
    break;
312
  case airFP_QNAN:
313
    /* sgn: anything, mant anything non-zero with high bit TEEM_QNANHIBIT */
314
    FP_SET_D(dlit, dbig,  0, 0x7ff, (TEEM_QNANHIBIT << 19) | 0x7ffff, 0xffffffff);
315
    break;
316
  case airFP_POS_INF:
317
    FP_SET_D(dlit, dbig,  0, 0x7ff, 0, 0);
318
    break;
319
  case airFP_NEG_INF:
320
    FP_SET_D(dlit, dbig,  1, 0x7ff, 0, 0);
321
    break;
322
  case airFP_POS_NORM:
323
    /* exp: anything non-zero but < 0xff, mant: anything */
324
    FP_SET_D(dlit, dbig,  0, 0x400, 0x0ff00, 0);
325
    break;
326
  case airFP_NEG_NORM:
327
    /* exp: anything non-zero but < 0xff, mant: anything */
328
    FP_SET_D(dlit, dbig,  1, 0x400, 0x0ff00, 0);
329
    break;
330
  case airFP_POS_DENORM:
331
    /* mant: anything non-zero */
332
    FP_SET_D(dlit, dbig,  0, 0, 0xff, 0);
333
    break;
334
  case airFP_NEG_DENORM:
335
    /* mant: anything non-zero */
336
    FP_SET_D(dlit, dbig,  1, 0, 0xff, 0);
337
    break;
338
  case airFP_NEG_ZERO:
339
    FP_SET_D(dlit, dbig,  1, 0, 0, 0);
340
    break;
341
  case airFP_POS_ZERO:
342
  default:
343
    FP_SET_D(dlit, dbig,  0, 0, 0, 0);
344
    break;
345
  }
346
  return (airEndianLittle == airMyEndian()
347
          ? dlit.v
348
          : dbig.v);
349
}
350
351
/*
352
******** airFPClass_f()
353
**
354
** given a floating point number, tells which class its in
355
*/
356
int
357
airFPClass_f(float val) {
358
  _airFloatEndianLittle flit;
359
  _airFloatEndianBig fbig;
360
  unsigned int sign, expv, mant;
361
  int indexv, ret = 0;
362
363
200
  flit.v = fbig.v = val;
364
200
  FP_GET_F(sign, expv, mant, flit, fbig);
365
200
  indexv = ((!!sign) << 2) | ((!!expv) << 1) | (!!mant);
366


200
  switch(indexv) {
367
  case 0:
368
    /* all fields are zero */
369
    ret = airFP_POS_ZERO;
370
    break;
371
  case 1:
372
    /* only mantissa is non-zero */
373
    ret = airFP_POS_DENORM;
374
    break;
375
  case 2:
376
    /* only exponent field is non-zero */
377
20
    if (0xff == expv) {
378
      ret = airFP_POS_INF;
379
20
    } else {
380
      ret = airFP_POS_NORM;
381
    }
382
    break;
383
  case 3:
384
    /* exponent and mantissa fields are non-zero */
385
40
    if (0xff == expv) {
386
40
      if (TEEM_QNANHIBIT == mant >> 22) {
387
        ret = airFP_QNAN;
388
40
      } else {
389
        ret = airFP_SNAN;
390
      }
391
    } else {
392
      ret = airFP_POS_NORM;
393
    }
394
    break;
395
  case 4:
396
    /* only sign field is non-zero */
397
    ret = airFP_NEG_ZERO;
398
    break;
399
  case 5:
400
    /* sign and mantissa fields are non-zero */
401
    ret = airFP_NEG_DENORM;
402
    break;
403
  case 6:
404
    /* sign and exponent fields are non-zero */
405
20
    if (0xff > expv) {
406
      ret = airFP_NEG_NORM;
407
    } else {
408
      ret = airFP_NEG_INF;
409
    }
410
    break;
411
  case 7:
412
    /* all fields are non-zero */
413
20
    if (0xff > expv) {
414
      ret = airFP_NEG_NORM;
415
    } else {
416
20
      if (TEEM_QNANHIBIT == mant >> 22) {
417
        ret = airFP_QNAN;
418
20
      } else {
419
        ret = airFP_SNAN;
420
      }
421
    }
422
    break;
423
  }
424
100
  return ret;
425
}
426
427
/*
428
** Disable the 'local variable used without having been initialized'
429
** warning produced by the MSVC compiler
430
*/
431
#ifdef _MSC_VER
432
#pragma warning(push)
433
#pragma warning(disable : 4700)
434
#endif
435
/*
436
******** airFPClass_d()
437
**
438
** given a double, tells which class its in
439
*/
440
int
441
airFPClass_d(double val) {
442
  _airDoubleEndianLittle dlit;
443
  _airDoubleEndianBig dbig;
444
  unsigned int sign, expo, mant0, mant1;
445
  int indexv, ret=0;
446
  unsigned char hibit;
447
448
94248
  dlit.v = dbig.v = val;
449
  /* "expo = d.c.expo" had been annotated with: "this seems to be a
450
     WIN32 bug: on a quiet-NaN, d.c.exp should be non-zero, but it was
451
     completely zero, so that this function returned airFP_NEG_DENORM
452
     instead of airFP_QNAN" */
453
94248
  FP_GET_D(sign, expo, mant0, mant1, dlit, dbig);
454
47124
  hibit = AIR_CAST(unsigned char, mant0 >> 19); /* mant0 20 bits wide: ok */
455
456
141518
  indexv = ((!!sign) << 2) | ((!!expo) << 1) | (!!mant0 || !!mant1);
457


94248
  switch(indexv) {
458
  case 0:
459
    /* all fields are zero */
460
    ret = airFP_POS_ZERO;
461
119
    break;
462
  case 1:
463
    /* only fractional field is non-zero */
464
    ret = airFP_POS_DENORM;
465
    break;
466
  case 2:
467
    /* only exponent field is non-zero */
468
24
    if (0x7ff > expo) {
469
      ret = airFP_POS_NORM;
470
24
    } else {
471
      ret = airFP_POS_INF;
472
    }
473
    break;
474
  case 3:
475
    /* exponent and fractional fields are non-zero */
476
46028
    if (0x7ff > expo) {
477
      ret = airFP_POS_NORM;
478
974
    } else {
479
45054
      if (TEEM_QNANHIBIT == hibit) {
480
        ret = airFP_QNAN;
481
45054
      } else {
482
        ret = airFP_SNAN;
483
      }
484
    }
485
    break;
486
  case 4:
487
    /* only sign field is non-zero */
488
    ret = airFP_NEG_ZERO;
489
    break;
490
  case 5:
491
    /* sign and fractional fields are non-zero */
492
    ret = airFP_NEG_DENORM;
493
    break;
494
  case 6:
495
    /* sign and exponent fields are non-zero */
496
3
    if (0x7ff > expo) {
497
      ret = airFP_NEG_NORM;
498
3
    } else {
499
      ret = airFP_NEG_INF;
500
    }
501
    break;
502
  case 7:
503
    /* all fields are non-zero */
504
950
    if (0x7ff > expo)
505
950
      ret = airFP_NEG_NORM;
506
    else {
507
      if (TEEM_QNANHIBIT == hibit) {
508
        ret = airFP_QNAN;
509
      } else {
510
        ret = airFP_SNAN;
511
      }
512
    }
513
    break;
514
  }
515
47124
  return ret;
516
}
517
#ifdef _MSC_VER
518
#pragma warning(pop)
519
#endif
520
521
/*
522
******** airIsNaN()
523
**
524
** returns 1 if input is either kind of NaN, 0 otherwise.  It is okay
525
** to only have a double version of this function, as opposed to
526
** having one for float and one for double, because Section 6.2 of the
527
** 754 spec tells us that that NaN is to be preserved across precision
528
** changes (and airSanity() explicitly checks for this).
529
*/
530
int
531
airIsNaN(double g) {
532
  _airFloatEndianLittle flit;
533
  _airFloatEndianBig fbig;
534
  unsigned int sign, expo, mant;
535
536
43988
  flit.v = fbig.v = AIR_CAST(float, g);
537
43988
  FP_GET_F(sign, expo, mant, flit, fbig);
538
  AIR_UNUSED(sign);
539
21994
  return (0xff == expo && mant);
540
}
541
542
/*
543
******** airIsInf_f(), airIsInf_d()
544
**
545
** returns 1 if input is positive infinity,
546
** -1 if negative infinity,
547
** or 0 otherwise (including NaN)
548
**
549
** thus the non-zero-ness of the return is an easy way to do a
550
** boolean check of whether the value is infinite
551
*/
552
int
553
airIsInf_f(float f) {
554
  int c, ret;
555
556
  c = airFPClass_f(f);
557
  if (airFP_POS_INF == c) {
558
    ret = 1;
559
  } else if (airFP_NEG_INF == c) {
560
    ret = -1;
561
  } else {
562
    ret = 0;
563
  }
564
  return ret;
565
}
566
int
567
airIsInf_d(double d) {
568
  int c, ret;
569
570
94136
  c = airFPClass_d(d);
571
47068
  if (airFP_POS_INF == c) {
572
    ret = 1;
573
47068
  } else if (airFP_NEG_INF == c) {
574
    ret = -1;
575
  } else {
576
    ret = 0;
577
  }
578
47068
  return ret;
579
}
580
581
/* airExists_f() airExists_d() were nixed because they weren't used-
582
  you can just use AIR_EXISTS_F and AIR_EXISTS_D directly */
583
584
/*
585
******** airExists()
586
**
587
** an optimization-proof alternative to AIR_EXISTS
588
*/
589
int
590
airExists(double val) {
591
  _airDoubleEndianLittle dlit;
592
  _airDoubleEndianBig dbig;
593
594
  dbig.v = dlit.v = val;
595
  return (airEndianLittle == airMyEndian()
596
          ? 0x7ff != dlit.c.expo
597
          : 0x7ff != dbig.c.expo);
598
}
599
600
/*
601
******** airNaN()
602
**
603
** returns a float quiet NaN
604
*/
605
float
606
airNaN(void) {
607
608
16656
  return airFPGen_f(airFP_QNAN);
609
}
610
611
/*
612
******** airFPFprintf_f()
613
**
614
** prints out the bits of a "float", indicating the three different fields
615
*/
616
void
617
airFPFprintf_f(FILE *file, float val) {
618
  int i;
619
  unsigned int sign, expo, mant;
620
  _airFloatEndianLittle flit;
621
  _airFloatEndianBig fbig;
622
623
  if (file) {
624
    flit.v = fbig.v = val;
625
    FP_GET_F(sign, expo, mant, flit, fbig);
626
    fprintf(file, "%f: class %d; 0x%08x = ",val, airFPClass_f(val),
627
            airEndianLittle == airMyEndian() ? flit.i : fbig.i);
628
    fprintf(file, "sign:0x%x, expo:0x%02x, mant:0x%06x = \n",
629
            sign, expo, mant);
630
    fprintf(file, " S [ . . Exp . . ] "
631
            "[ . . . . . . . . . Mant. . . . . . . . . . ]\n");
632
    fprintf(file, " %d ", sign);
633
    for (i=7; i>=0; i--) {
634
      fprintf(file, "%d ", (expo >> i) & 1);
635
    }
636
    for (i=22; i>=0; i--) {
637
      fprintf(file, "%d ", (mant >> i) & 1);
638
    }
639
    fprintf(file, "\n");
640
  }
641
}
642
643
/*
644
******** airFPFprintf_d()
645
**
646
** prints out the bits of a "double", indicating the three different fields
647
*/
648
void
649
airFPFprintf_d(FILE *file, double val) {
650
  int i;
651
  _airDoubleEndianLittle dlit;
652
  _airDoubleEndianBig dbig;
653
  unsigned int sign, expo, mant0, mant1;
654
655
  if (file) {
656
    dlit.v = dbig.v = val;
657
    fprintf(file, "%f: class %d; 0x%08x %08x = \n",
658
            val, airFPClass_d(val),
659
            (airEndianLittle == airMyEndian() ? dlit.h.half1 : dbig.h.half1),
660
            (airEndianLittle == airMyEndian() ? dlit.h.half0 : dbig.h.half0));
661
    FP_GET_D(sign, expo, mant0, mant1, dlit, dbig);
662
    fprintf(file, "sign:0x%x, expo:0x%03x, mant:0x%05x %08x = \n",
663
            sign, expo, mant0, mant1);
664
    fprintf(file, "S[...Exp...][.......................Mant.......................]\n");
665
    fprintf(file, "%d", sign);
666
    for (i=10; i>=0; i--) {
667
      fprintf(file, "%d", (expo >> i) & 1);
668
    }
669
    for (i=19; i>=0; i--) {
670
      fprintf(file, "%d", (mant0 >> i) & 1);
671
    }
672
    for (i=31; i>=0; i--) {
673
      fprintf(file, "%d", (mant1 >> i) & 1);
674
    }
675
    fprintf(file, "\n");
676
  }
677
}
678