Coverage Report

Created: 2025-08-04 07:15

/src/libxml2-2.9.7/trionan.c
Line
Count
Source (jump to first uncovered line)
1
/*************************************************************************
2
 *
3
 * $Id$
4
 *
5
 * Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
12
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
13
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
14
 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
15
 *
16
 ************************************************************************
17
 *
18
 * Functions to handle special quantities in floating-point numbers
19
 * (that is, NaNs and infinity). They provide the capability to detect
20
 * and fabricate special quantities.
21
 *
22
 * Although written to be as portable as possible, it can never be
23
 * guaranteed to work on all platforms, as not all hardware supports
24
 * special quantities.
25
 *
26
 * The approach used here (approximately) is to:
27
 *
28
 *   1. Use C99 functionality when available.
29
 *   2. Use IEEE 754 bit-patterns if possible.
30
 *   3. Use platform-specific techniques.
31
 *
32
 ************************************************************************/
33
34
/*
35
 * TODO:
36
 *  o Put all the magic into trio_fpclassify_and_signbit(), and use this from
37
 *    trio_isnan() etc.
38
 */
39
40
/*************************************************************************
41
 * Include files
42
 */
43
#include "triodef.h"
44
#include "trionan.h"
45
46
#include <math.h>
47
#include <string.h>
48
#include <limits.h>
49
#include <float.h>
50
#if defined(TRIO_PLATFORM_UNIX)
51
# include <signal.h>
52
#endif
53
#if defined(TRIO_COMPILER_DECC)
54
#  if defined(__linux__)
55
#   include <cpml.h>
56
#  else
57
#   include <fp_class.h>
58
#  endif
59
#endif
60
#include <assert.h>
61
62
#if defined(TRIO_DOCUMENTATION)
63
# include "doc/doc_nan.h"
64
#endif
65
/** @addtogroup SpecialQuantities
66
    @{
67
*/
68
69
/*************************************************************************
70
 * Definitions
71
 */
72
73
#define TRIO_TRUE (1 == 1)
74
#define TRIO_FALSE (0 == 1)
75
76
/*
77
 * We must enable IEEE floating-point on Alpha
78
 */
79
#if defined(__alpha) && !defined(_IEEE_FP)
80
# if defined(TRIO_COMPILER_DECC)
81
#  if defined(TRIO_PLATFORM_VMS)
82
#   error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE"
83
#  else
84
#   if !defined(_CFE)
85
#    error "Must be compiled with option -ieee"
86
#   endif
87
#  endif
88
# elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__))
89
#  error "Must be compiled with option -mieee"
90
# endif
91
#endif /* __alpha && ! _IEEE_FP */
92
93
/*
94
 * In ANSI/IEEE 754-1985 64-bits double format numbers have the
95
 * following properties (amoungst others)
96
 *
97
 *   o FLT_RADIX == 2: binary encoding
98
 *   o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used
99
 *     to indicate special numbers (e.g. NaN and Infinity), so the
100
 *     maximum exponent is 10 bits wide (2^10 == 1024).
101
 *   o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because
102
 *     numbers are normalized the initial binary 1 is represented
103
 *     implicitly (the so-called "hidden bit"), which leaves us with
104
 *     the ability to represent 53 bits wide mantissa.
105
 */
106
#if (FLT_RADIX == 2) && (DBL_MAX_EXP == 1024) && (DBL_MANT_DIG == 53)
107
# define USE_IEEE_754
108
#endif
109
110
111
/*************************************************************************
112
 * Constants
113
 */
114
115
static TRIO_CONST char rcsid[] = "@(#)$Id$";
116
117
#if defined(USE_IEEE_754)
118
119
/*
120
 * Endian-agnostic indexing macro.
121
 *
122
 * The value of internalEndianMagic, when converted into a 64-bit
123
 * integer, becomes 0x0706050403020100 (we could have used a 64-bit
124
 * integer value instead of a double, but not all platforms supports
125
 * that type). The value is automatically encoded with the correct
126
 * endianess by the compiler, which means that we can support any
127
 * kind of endianess. The individual bytes are then used as an index
128
 * for the IEEE 754 bit-patterns and masks.
129
 */
130
112
#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])
131
132
#if (defined(__BORLANDC__) && __BORLANDC__ >= 0x0590)
133
static TRIO_CONST double internalEndianMagic = 7.949928895127362e-275;
134
#else
135
static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275;
136
#endif
137
138
/* Mask for the exponent */
139
static TRIO_CONST unsigned char ieee_754_exponent_mask[] = {
140
  0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
141
};
142
143
/* Mask for the mantissa */
144
static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = {
145
  0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
146
};
147
148
/* Mask for the sign bit */
149
static TRIO_CONST unsigned char ieee_754_sign_mask[] = {
150
  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
151
};
152
153
/* Bit-pattern for negative zero */
154
static TRIO_CONST unsigned char ieee_754_negzero_array[] = {
155
  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
156
};
157
158
/* Bit-pattern for infinity */
159
static TRIO_CONST unsigned char ieee_754_infinity_array[] = {
160
  0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
161
};
162
163
/* Bit-pattern for quiet NaN */
164
static TRIO_CONST unsigned char ieee_754_qnan_array[] = {
165
  0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
166
};
167
168
169
/*************************************************************************
170
 * Functions
171
 */
172
173
/*
174
 * trio_make_double
175
 */
176
TRIO_PRIVATE double
177
trio_make_double
178
TRIO_ARGS1((values),
179
     TRIO_CONST unsigned char *values)
180
14
{
181
14
  TRIO_VOLATILE double result;
182
14
  int i;
183
184
126
  for (i = 0; i < (int)sizeof(double); i++) {
185
112
    ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i];
186
112
  }
187
14
  return result;
188
14
}
189
190
/*
191
 * trio_is_special_quantity
192
 */
193
TRIO_PRIVATE int
194
trio_is_special_quantity
195
TRIO_ARGS2((number, has_mantissa),
196
     double number,
197
     int *has_mantissa)
198
0
{
199
0
  unsigned int i;
200
0
  unsigned char current;
201
0
  int is_special_quantity = TRIO_TRUE;
202
0
203
0
  *has_mantissa = 0;
204
0
205
0
  for (i = 0; i < (unsigned int)sizeof(double); i++) {
206
0
    current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)];
207
0
    is_special_quantity
208
0
      &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]);
209
0
    *has_mantissa |= (current & ieee_754_mantissa_mask[i]);
210
0
  }
211
0
  return is_special_quantity;
212
0
}
213
214
/*
215
 * trio_is_negative
216
 */
217
TRIO_PRIVATE int
218
trio_is_negative
219
TRIO_ARGS1((number),
220
     double number)
221
0
{
222
0
  unsigned int i;
223
0
  int is_negative = TRIO_FALSE;
224
0
225
0
  for (i = 0; i < (unsigned int)sizeof(double); i++) {
226
0
    is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]
227
0
        & ieee_754_sign_mask[i]);
228
0
  }
229
0
  return is_negative;
230
0
}
231
232
#endif /* USE_IEEE_754 */
233
234
235
/**
236
   Generate negative zero.
237
238
   @return Floating-point representation of negative zero.
239
*/
240
TRIO_PUBLIC double
241
trio_nzero(TRIO_NOARGS)
242
14
{
243
14
#if defined(USE_IEEE_754)
244
14
  return trio_make_double(ieee_754_negzero_array);
245
#else
246
  TRIO_VOLATILE double zero = 0.0;
247
248
  return -zero;
249
#endif
250
14
}
251
252
/**
253
   Generate positive infinity.
254
255
   @return Floating-point representation of positive infinity.
256
*/
257
TRIO_PUBLIC double
258
trio_pinf(TRIO_NOARGS)
259
28
{
260
  /* Cache the result */
261
28
  static double result = 0.0;
262
263
28
  if (result == 0.0) {
264
265
14
#if defined(INFINITY) && defined(__STDC_IEC_559__)
266
14
    result = (double)INFINITY;
267
268
#elif defined(USE_IEEE_754)
269
    result = trio_make_double(ieee_754_infinity_array);
270
271
#else
272
    /*
273
     * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used
274
     * as infinity. Otherwise we have to resort to an overflow
275
     * operation to generate infinity.
276
     */
277
# if defined(TRIO_PLATFORM_UNIX)
278
    void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
279
# endif
280
281
    result = HUGE_VAL;
282
    if (HUGE_VAL == DBL_MAX) {
283
      /* Force overflow */
284
      result += HUGE_VAL;
285
    }
286
287
# if defined(TRIO_PLATFORM_UNIX)
288
    signal(SIGFPE, signal_handler);
289
# endif
290
291
#endif
292
14
  }
293
28
  return result;
294
28
}
295
296
/**
297
   Generate negative infinity.
298
299
   @return Floating-point value of negative infinity.
300
*/
301
TRIO_PUBLIC double
302
trio_ninf(TRIO_NOARGS)
303
14
{
304
14
  static double result = 0.0;
305
306
14
  if (result == 0.0) {
307
    /*
308
     * Negative infinity is calculated by negating positive infinity,
309
     * which can be done because it is legal to do calculations on
310
     * infinity (for example,  1 / infinity == 0).
311
     */
312
14
    result = -trio_pinf();
313
14
  }
314
14
  return result;
315
14
}
316
317
/**
318
   Generate NaN.
319
320
   @return Floating-point representation of NaN.
321
*/
322
TRIO_PUBLIC double
323
trio_nan(TRIO_NOARGS)
324
14
{
325
  /* Cache the result */
326
14
  static double result = 0.0;
327
328
14
  if (result == 0.0) {
329
330
14
#if defined(TRIO_COMPILER_SUPPORTS_C99)
331
14
    result = nan("");
332
333
#elif defined(NAN) && defined(__STDC_IEC_559__)
334
    result = (double)NAN;
335
336
#elif defined(USE_IEEE_754)
337
    result = trio_make_double(ieee_754_qnan_array);
338
339
#else
340
    /*
341
     * There are several ways to generate NaN. The one used here is
342
     * to divide infinity by infinity. I would have preferred to add
343
     * negative infinity to positive infinity, but that yields wrong
344
     * result (infinity) on FreeBSD.
345
     *
346
     * This may fail if the hardware does not support NaN, or if
347
     * the Invalid Operation floating-point exception is unmasked.
348
     */
349
# if defined(TRIO_PLATFORM_UNIX)
350
    void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
351
# endif
352
353
    result = trio_pinf() / trio_pinf();
354
355
# if defined(TRIO_PLATFORM_UNIX)
356
    signal(SIGFPE, signal_handler);
357
# endif
358
359
#endif
360
14
  }
361
14
  return result;
362
14
}
363
364
/**
365
   Check for NaN.
366
367
   @param number An arbitrary floating-point number.
368
   @return Boolean value indicating whether or not the number is a NaN.
369
*/
370
TRIO_PUBLIC int
371
trio_isnan
372
TRIO_ARGS1((number),
373
     double number)
374
0
{
375
0
#if (defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isnan)) \
376
0
 || defined(TRIO_COMPILER_SUPPORTS_UNIX95)
377
  /*
378
   * C99 defines isnan() as a macro. UNIX95 defines isnan() as a
379
   * function. This function was already present in XPG4, but this
380
   * is a bit tricky to detect with compiler defines, so we choose
381
   * the conservative approach and only use it for UNIX95.
382
   */
383
0
  return isnan(number);
384
385
#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
386
  /*
387
   * Microsoft Visual C++ and Borland C++ Builder have an _isnan()
388
   * function.
389
   */
390
  return _isnan(number) ? TRIO_TRUE : TRIO_FALSE;
391
392
#elif defined(USE_IEEE_754)
393
  /*
394
   * Examine IEEE 754 bit-pattern. A NaN must have a special exponent
395
   * pattern, and a non-empty mantissa.
396
   */
397
  int has_mantissa;
398
  int is_special_quantity;
399
400
  is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
401
402
  return (is_special_quantity && has_mantissa);
403
404
#else
405
  /*
406
   * Fallback solution
407
   */
408
  int status;
409
  double integral, fraction;
410
411
# if defined(TRIO_PLATFORM_UNIX)
412
  void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
413
# endif
414
415
  status = (/*
416
       * NaN is the only number which does not compare to itself
417
       */
418
      ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) ||
419
      /*
420
       * Fallback solution if NaN compares to NaN
421
       */
422
      ((number != 0.0) &&
423
       (fraction = modf(number, &integral),
424
        integral == fraction)));
425
426
# if defined(TRIO_PLATFORM_UNIX)
427
  signal(SIGFPE, signal_handler);
428
# endif
429
430
  return status;
431
432
#endif
433
0
}
434
435
/**
436
   Check for infinity.
437
438
   @param number An arbitrary floating-point number.
439
   @return 1 if positive infinity, -1 if negative infinity, 0 otherwise.
440
*/
441
TRIO_PUBLIC int
442
trio_isinf
443
TRIO_ARGS1((number),
444
     double number)
445
0
{
446
#if defined(TRIO_COMPILER_DECC) && !defined(__linux__)
447
  /*
448
   * DECC has an isinf() macro, but it works differently than that
449
   * of C99, so we use the fp_class() function instead.
450
   */
451
  return ((fp_class(number) == FP_POS_INF)
452
    ? 1
453
    : ((fp_class(number) == FP_NEG_INF) ? -1 : 0));
454
455
#elif defined(isinf)
456
  /*
457
   * C99 defines isinf() as a macro.
458
   */
459
0
  return isinf(number)
460
0
    ? ((number > 0.0) ? 1 : -1)
461
0
    : 0;
462
463
#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
464
  /*
465
   * Microsoft Visual C++ and Borland C++ Builder have an _fpclass()
466
   * function that can be used to detect infinity.
467
   */
468
  return ((_fpclass(number) == _FPCLASS_PINF)
469
    ? 1
470
    : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0));
471
472
#elif defined(USE_IEEE_754)
473
  /*
474
   * Examine IEEE 754 bit-pattern. Infinity must have a special exponent
475
   * pattern, and an empty mantissa.
476
   */
477
  int has_mantissa;
478
  int is_special_quantity;
479
480
  is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
481
482
  return (is_special_quantity && !has_mantissa)
483
    ? ((number < 0.0) ? -1 : 1)
484
    : 0;
485
486
#else
487
  /*
488
   * Fallback solution.
489
   */
490
  int status;
491
492
# if defined(TRIO_PLATFORM_UNIX)
493
  void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
494
# endif
495
496
  double infinity = trio_pinf();
497
498
  status = ((number == infinity)
499
      ? 1
500
      : ((number == -infinity) ? -1 : 0));
501
502
# if defined(TRIO_PLATFORM_UNIX)
503
  signal(SIGFPE, signal_handler);
504
# endif
505
506
  return status;
507
508
#endif
509
0
}
510
511
#if 0
512
  /* Temporary fix - this routine is not used anywhere */
513
/**
514
   Check for finity.
515
516
   @param number An arbitrary floating-point number.
517
   @return Boolean value indicating whether or not the number is a finite.
518
*/
519
TRIO_PUBLIC int
520
trio_isfinite
521
TRIO_ARGS1((number),
522
     double number)
523
{
524
#if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite)
525
  /*
526
   * C99 defines isfinite() as a macro.
527
   */
528
  return isfinite(number);
529
530
#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
531
  /*
532
   * Microsoft Visual C++ and Borland C++ Builder use _finite().
533
   */
534
  return _finite(number);
535
536
#elif defined(USE_IEEE_754)
537
  /*
538
   * Examine IEEE 754 bit-pattern. For finity we do not care about the
539
   * mantissa.
540
   */
541
  int dummy;
542
543
  return (! trio_is_special_quantity(number, &dummy));
544
545
#else
546
  /*
547
   * Fallback solution.
548
   */
549
  return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0));
550
551
#endif
552
}
553
554
#endif
555
556
/*
557
 * The sign of NaN is always false
558
 */
559
TRIO_PUBLIC int
560
trio_fpclassify_and_signbit
561
TRIO_ARGS2((number, is_negative),
562
     double number,
563
     int *is_negative)
564
0
{
565
0
#if defined(fpclassify) && defined(signbit)
566
  /*
567
   * C99 defines fpclassify() and signbit() as a macros
568
   */
569
0
  *is_negative = signbit(number);
570
0
  switch (fpclassify(number)) {
571
0
  case FP_NAN:
572
0
    return TRIO_FP_NAN;
573
0
  case FP_INFINITE:
574
0
    return TRIO_FP_INFINITE;
575
0
  case FP_SUBNORMAL:
576
0
    return TRIO_FP_SUBNORMAL;
577
0
  case FP_ZERO:
578
0
    return TRIO_FP_ZERO;
579
0
  default:
580
0
    return TRIO_FP_NORMAL;
581
0
  }
582
583
#else
584
# if defined(TRIO_COMPILER_DECC)
585
  /*
586
   * DECC has an fp_class() function.
587
   */
588
#  define TRIO_FPCLASSIFY(n) fp_class(n)
589
#  define TRIO_QUIET_NAN FP_QNAN
590
#  define TRIO_SIGNALLING_NAN FP_SNAN
591
#  define TRIO_POSITIVE_INFINITY FP_POS_INF
592
#  define TRIO_NEGATIVE_INFINITY FP_NEG_INF
593
#  define TRIO_POSITIVE_SUBNORMAL FP_POS_DENORM
594
#  define TRIO_NEGATIVE_SUBNORMAL FP_NEG_DENORM
595
#  define TRIO_POSITIVE_ZERO FP_POS_ZERO
596
#  define TRIO_NEGATIVE_ZERO FP_NEG_ZERO
597
#  define TRIO_POSITIVE_NORMAL FP_POS_NORM
598
#  define TRIO_NEGATIVE_NORMAL FP_NEG_NORM
599
600
# elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
601
  /*
602
   * Microsoft Visual C++ and Borland C++ Builder have an _fpclass()
603
   * function.
604
   */
605
#  define TRIO_FPCLASSIFY(n) _fpclass(n)
606
#  define TRIO_QUIET_NAN _FPCLASS_QNAN
607
#  define TRIO_SIGNALLING_NAN _FPCLASS_SNAN
608
#  define TRIO_POSITIVE_INFINITY _FPCLASS_PINF
609
#  define TRIO_NEGATIVE_INFINITY _FPCLASS_NINF
610
#  define TRIO_POSITIVE_SUBNORMAL _FPCLASS_PD
611
#  define TRIO_NEGATIVE_SUBNORMAL _FPCLASS_ND
612
#  define TRIO_POSITIVE_ZERO _FPCLASS_PZ
613
#  define TRIO_NEGATIVE_ZERO _FPCLASS_NZ
614
#  define TRIO_POSITIVE_NORMAL _FPCLASS_PN
615
#  define TRIO_NEGATIVE_NORMAL _FPCLASS_NN
616
617
# elif defined(FP_PLUS_NORM)
618
  /*
619
   * HP-UX 9.x and 10.x have an fpclassify() function, that is different
620
   * from the C99 fpclassify() macro supported on HP-UX 11.x.
621
   *
622
   * AIX has class() for C, and _class() for C++, which returns the
623
   * same values as the HP-UX fpclassify() function.
624
   */
625
#  if defined(TRIO_PLATFORM_AIX)
626
#   if defined(__cplusplus)
627
#    define TRIO_FPCLASSIFY(n) _class(n)
628
#   else
629
#    define TRIO_FPCLASSIFY(n) class(n)
630
#   endif
631
#  else
632
#   define TRIO_FPCLASSIFY(n) fpclassify(n)
633
#  endif
634
#  define TRIO_QUIET_NAN FP_QNAN
635
#  define TRIO_SIGNALLING_NAN FP_SNAN
636
#  define TRIO_POSITIVE_INFINITY FP_PLUS_INF
637
#  define TRIO_NEGATIVE_INFINITY FP_MINUS_INF
638
#  define TRIO_POSITIVE_SUBNORMAL FP_PLUS_DENORM
639
#  define TRIO_NEGATIVE_SUBNORMAL FP_MINUS_DENORM
640
#  define TRIO_POSITIVE_ZERO FP_PLUS_ZERO
641
#  define TRIO_NEGATIVE_ZERO FP_MINUS_ZERO
642
#  define TRIO_POSITIVE_NORMAL FP_PLUS_NORM
643
#  define TRIO_NEGATIVE_NORMAL FP_MINUS_NORM
644
# endif
645
646
# if defined(TRIO_FPCLASSIFY)
647
  switch (TRIO_FPCLASSIFY(number)) {
648
  case TRIO_QUIET_NAN:
649
  case TRIO_SIGNALLING_NAN:
650
    *is_negative = TRIO_FALSE; /* NaN has no sign */
651
    return TRIO_FP_NAN;
652
  case TRIO_POSITIVE_INFINITY:
653
    *is_negative = TRIO_FALSE;
654
    return TRIO_FP_INFINITE;
655
  case TRIO_NEGATIVE_INFINITY:
656
    *is_negative = TRIO_TRUE;
657
    return TRIO_FP_INFINITE;
658
  case TRIO_POSITIVE_SUBNORMAL:
659
    *is_negative = TRIO_FALSE;
660
    return TRIO_FP_SUBNORMAL;
661
  case TRIO_NEGATIVE_SUBNORMAL:
662
    *is_negative = TRIO_TRUE;
663
    return TRIO_FP_SUBNORMAL;
664
  case TRIO_POSITIVE_ZERO:
665
    *is_negative = TRIO_FALSE;
666
    return TRIO_FP_ZERO;
667
  case TRIO_NEGATIVE_ZERO:
668
    *is_negative = TRIO_TRUE;
669
    return TRIO_FP_ZERO;
670
  case TRIO_POSITIVE_NORMAL:
671
    *is_negative = TRIO_FALSE;
672
    return TRIO_FP_NORMAL;
673
  case TRIO_NEGATIVE_NORMAL:
674
    *is_negative = TRIO_TRUE;
675
    return TRIO_FP_NORMAL;
676
  default:
677
    /* Just in case... */
678
    *is_negative = (number < 0.0);
679
    return TRIO_FP_NORMAL;
680
  }
681
682
# else
683
  /*
684
   * Fallback solution.
685
   */
686
  int rc;
687
688
  if (number == 0.0) {
689
    /*
690
     * In IEEE 754 the sign of zero is ignored in comparisons, so we
691
     * have to handle this as a special case by examining the sign bit
692
     * directly.
693
     */
694
#  if defined(USE_IEEE_754)
695
    *is_negative = trio_is_negative(number);
696
#  else
697
    *is_negative = TRIO_FALSE; /* FIXME */
698
#  endif
699
    return TRIO_FP_ZERO;
700
  }
701
  if (trio_isnan(number)) {
702
    *is_negative = TRIO_FALSE;
703
    return TRIO_FP_NAN;
704
  }
705
  if ((rc = trio_isinf(number))) {
706
    *is_negative = (rc == -1);
707
    return TRIO_FP_INFINITE;
708
  }
709
  if ((number > 0.0) && (number < DBL_MIN)) {
710
    *is_negative = TRIO_FALSE;
711
    return TRIO_FP_SUBNORMAL;
712
  }
713
  if ((number < 0.0) && (number > -DBL_MIN)) {
714
    *is_negative = TRIO_TRUE;
715
    return TRIO_FP_SUBNORMAL;
716
  }
717
  *is_negative = (number < 0.0);
718
  return TRIO_FP_NORMAL;
719
720
# endif
721
#endif
722
0
}
723
724
/**
725
   Examine the sign of a number.
726
727
   @param number An arbitrary floating-point number.
728
   @return Boolean value indicating whether or not the number has the
729
   sign bit set (i.e. is negative).
730
*/
731
TRIO_PUBLIC int
732
trio_signbit
733
TRIO_ARGS1((number),
734
     double number)
735
0
{
736
0
  int is_negative;
737
738
0
  (void)trio_fpclassify_and_signbit(number, &is_negative);
739
0
  return is_negative;
740
0
}
741
742
#if 0
743
  /* Temporary fix - this routine is not used in libxml */
744
/**
745
   Examine the class of a number.
746
747
   @param number An arbitrary floating-point number.
748
   @return Enumerable value indicating the class of @p number
749
*/
750
TRIO_PUBLIC int
751
trio_fpclassify
752
TRIO_ARGS1((number),
753
     double number)
754
{
755
  int dummy;
756
757
  return trio_fpclassify_and_signbit(number, &dummy);
758
}
759
760
#endif
761
762
/** @} SpecialQuantities */
763
764
/*************************************************************************
765
 * For test purposes.
766
 *
767
 * Add the following compiler option to include this test code.
768
 *
769
 *  Unix : -DSTANDALONE
770
 *  VMS  : /DEFINE=(STANDALONE)
771
 */
772
#if defined(STANDALONE)
773
# include <stdio.h>
774
775
static TRIO_CONST char *
776
getClassification
777
TRIO_ARGS1((type),
778
     int type)
779
{
780
  switch (type) {
781
  case TRIO_FP_INFINITE:
782
    return "FP_INFINITE";
783
  case TRIO_FP_NAN:
784
    return "FP_NAN";
785
  case TRIO_FP_NORMAL:
786
    return "FP_NORMAL";
787
  case TRIO_FP_SUBNORMAL:
788
    return "FP_SUBNORMAL";
789
  case TRIO_FP_ZERO:
790
    return "FP_ZERO";
791
  default:
792
    return "FP_UNKNOWN";
793
  }
794
}
795
796
static void
797
print_class
798
TRIO_ARGS2((prefix, number),
799
     TRIO_CONST char *prefix,
800
     double number)
801
{
802
  printf("%-6s: %s %-15s %g\n",
803
   prefix,
804
   trio_signbit(number) ? "-" : "+",
805
   getClassification(TRIO_FPCLASSIFY(number)),
806
   number);
807
}
808
809
int main(TRIO_NOARGS)
810
{
811
  double my_nan;
812
  double my_pinf;
813
  double my_ninf;
814
# if defined(TRIO_PLATFORM_UNIX)
815
  void (*signal_handler) TRIO_PROTO((int));
816
# endif
817
818
  my_nan = trio_nan();
819
  my_pinf = trio_pinf();
820
  my_ninf = trio_ninf();
821
822
  print_class("Nan", my_nan);
823
  print_class("PInf", my_pinf);
824
  print_class("NInf", my_ninf);
825
  print_class("PZero", 0.0);
826
  print_class("NZero", -0.0);
827
  print_class("PNorm", 1.0);
828
  print_class("NNorm", -1.0);
829
  print_class("PSub", 1.01e-307 - 1.00e-307);
830
  print_class("NSub", 1.00e-307 - 1.01e-307);
831
832
  printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
833
   my_nan,
834
   ((unsigned char *)&my_nan)[0],
835
   ((unsigned char *)&my_nan)[1],
836
   ((unsigned char *)&my_nan)[2],
837
   ((unsigned char *)&my_nan)[3],
838
   ((unsigned char *)&my_nan)[4],
839
   ((unsigned char *)&my_nan)[5],
840
   ((unsigned char *)&my_nan)[6],
841
   ((unsigned char *)&my_nan)[7],
842
   trio_isnan(my_nan), trio_isinf(my_nan));
843
  printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
844
   my_pinf,
845
   ((unsigned char *)&my_pinf)[0],
846
   ((unsigned char *)&my_pinf)[1],
847
   ((unsigned char *)&my_pinf)[2],
848
   ((unsigned char *)&my_pinf)[3],
849
   ((unsigned char *)&my_pinf)[4],
850
   ((unsigned char *)&my_pinf)[5],
851
   ((unsigned char *)&my_pinf)[6],
852
   ((unsigned char *)&my_pinf)[7],
853
   trio_isnan(my_pinf), trio_isinf(my_pinf));
854
  printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
855
   my_ninf,
856
   ((unsigned char *)&my_ninf)[0],
857
   ((unsigned char *)&my_ninf)[1],
858
   ((unsigned char *)&my_ninf)[2],
859
   ((unsigned char *)&my_ninf)[3],
860
   ((unsigned char *)&my_ninf)[4],
861
   ((unsigned char *)&my_ninf)[5],
862
   ((unsigned char *)&my_ninf)[6],
863
   ((unsigned char *)&my_ninf)[7],
864
   trio_isnan(my_ninf), trio_isinf(my_ninf));
865
866
# if defined(TRIO_PLATFORM_UNIX)
867
  signal_handler = signal(SIGFPE, SIG_IGN);
868
# endif
869
870
  my_pinf = DBL_MAX + DBL_MAX;
871
  my_ninf = -my_pinf;
872
  my_nan = my_pinf / my_pinf;
873
874
# if defined(TRIO_PLATFORM_UNIX)
875
  signal(SIGFPE, signal_handler);
876
# endif
877
878
  printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
879
   my_nan,
880
   ((unsigned char *)&my_nan)[0],
881
   ((unsigned char *)&my_nan)[1],
882
   ((unsigned char *)&my_nan)[2],
883
   ((unsigned char *)&my_nan)[3],
884
   ((unsigned char *)&my_nan)[4],
885
   ((unsigned char *)&my_nan)[5],
886
   ((unsigned char *)&my_nan)[6],
887
   ((unsigned char *)&my_nan)[7],
888
   trio_isnan(my_nan), trio_isinf(my_nan));
889
  printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
890
   my_pinf,
891
   ((unsigned char *)&my_pinf)[0],
892
   ((unsigned char *)&my_pinf)[1],
893
   ((unsigned char *)&my_pinf)[2],
894
   ((unsigned char *)&my_pinf)[3],
895
   ((unsigned char *)&my_pinf)[4],
896
   ((unsigned char *)&my_pinf)[5],
897
   ((unsigned char *)&my_pinf)[6],
898
   ((unsigned char *)&my_pinf)[7],
899
   trio_isnan(my_pinf), trio_isinf(my_pinf));
900
  printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
901
   my_ninf,
902
   ((unsigned char *)&my_ninf)[0],
903
   ((unsigned char *)&my_ninf)[1],
904
   ((unsigned char *)&my_ninf)[2],
905
   ((unsigned char *)&my_ninf)[3],
906
   ((unsigned char *)&my_ninf)[4],
907
   ((unsigned char *)&my_ninf)[5],
908
   ((unsigned char *)&my_ninf)[6],
909
   ((unsigned char *)&my_ninf)[7],
910
   trio_isnan(my_ninf), trio_isinf(my_ninf));
911
912
  return 0;
913
}
914
#endif