1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if ! defined (octave_lo_ieee_h)
27 #define octave_lo_ieee_h 1
28 
29 #include <cmath>
30 
31 #include "octave-config.h"
32 
33 #if defined (__cplusplus)
34 extern "C" {
35 #endif
36 
37 /*  Octave's idea of infinity.  */
38 #define octave_Inf (lo_ieee_inf_value ())
39 
40 /* Octave's idea of a missing value.  */
41 #define octave_NA (lo_ieee_na_value ())
42 
43 /* Octave's idea of not a number.  */
44 #define octave_NaN (lo_ieee_nan_value ())
45 
46 /*  Octave's idea of infinity.  */
47 #define octave_Float_Inf (lo_ieee_float_inf_value ())
48 
49 /* Octave's idea of a missing value.  */
50 #define octave_Float_NA (lo_ieee_float_na_value ())
51 
52 /* Octave's idea of not a number.  */
53 #define octave_Float_NaN (lo_ieee_float_nan_value ())
54 
55 /* FIXME: This code assumes that a double has twice the
56           number of bits as an int */
57 
58 typedef union
59 {
60   double value;
61   unsigned int word[2];
62 } lo_ieee_double;
63 
64 typedef union
65 {
66   float value;
67   unsigned int word;
68 } lo_ieee_float;
69 
70 #define LO_IEEE_NA_HW_OLD 0x7ff00000
71 #define LO_IEEE_NA_LW_OLD 1954
72 #if defined (HAVE_MIPS_NAN)
73   #define LO_IEEE_NA_HW 0x7FF040F4
74 #else
75   #define LO_IEEE_NA_HW 0x7FF840F4
76 #endif
77 #define LO_IEEE_NA_LW 0x40000000
78 #define LO_IEEE_NA_FLOAT   0x7FC207A2
79 
80 extern OCTAVE_API void octave_ieee_init (void);
81 
__lo_ieee_isnan(double x)82 inline int __lo_ieee_isnan (double x) { return std::isnan (x); }
__lo_ieee_finite(double x)83 inline int __lo_ieee_finite (double x) { return std::isfinite (x); }
__lo_ieee_isinf(double x)84 inline int __lo_ieee_isinf (double x) { return std::isinf (x); }
85 
86 extern OCTAVE_API int __lo_ieee_is_NA (double);
87 extern OCTAVE_API int __lo_ieee_is_old_NA (double);
88 extern OCTAVE_API double __lo_ieee_replace_old_NA (double);
89 
90 extern OCTAVE_API double lo_ieee_inf_value (void);
91 extern OCTAVE_API double lo_ieee_na_value (void);
92 extern OCTAVE_API double lo_ieee_nan_value (void);
93 
__lo_ieee_signbit(double x)94 inline int __lo_ieee_signbit (double x) { return std::signbit (x); }
95 
__lo_ieee_float_isnan(float x)96 inline int __lo_ieee_float_isnan (float x) { return std::isnan (x); }
__lo_ieee_float_finite(float x)97 inline int __lo_ieee_float_finite (float x) { return std::isfinite (x); }
__lo_ieee_float_isinf(float x)98 inline int __lo_ieee_float_isinf (float x) { return std::isinf (x); }
99 
100 extern OCTAVE_API int __lo_ieee_float_is_NA (float);
101 
102 extern OCTAVE_API float lo_ieee_float_inf_value (void);
103 extern OCTAVE_API float lo_ieee_float_na_value (void);
104 extern OCTAVE_API float lo_ieee_float_nan_value (void);
105 
__lo_ieee_float_signbit(float x)106 inline int __lo_ieee_float_signbit (float x) { return std::signbit (x); }
107 
108 #if defined (__cplusplus)
109 }
110 #endif
111 
112 #define lo_ieee_isnan(x)                                \
113   (sizeof (x) == sizeof (float)                         \
114    ? __lo_ieee_float_isnan (x) : __lo_ieee_isnan (x))
115 
116 #define lo_ieee_finite(x)                               \
117   (sizeof (x) == sizeof (float)                         \
118    ? __lo_ieee_float_finite (x) : __lo_ieee_finite (x))
119 
120 #define lo_ieee_isinf(x)                                \
121   (sizeof (x) == sizeof (float)                         \
122    ? __lo_ieee_float_isinf (x) : __lo_ieee_isinf (x))
123 
124 #define lo_ieee_is_NA(x)                                \
125   (sizeof (x) == sizeof (float)                         \
126    ? __lo_ieee_float_is_NA (x) : __lo_ieee_is_NA (x))
127 
128 #define lo_ieee_is_NaN_or_NA(x)                                         \
129   (sizeof (x) == sizeof (float)                                         \
130    ? __lo_ieee_float_is_NaN_or_NA (x) : __lo_ieee_is_NaN_or_NA (x))
131 
132 #define lo_ieee_signbit(x)                                      \
133   (sizeof (x) == sizeof (float)                                 \
134    ? __lo_ieee_float_signbit (x) : __lo_ieee_signbit (x))
135 
136 #if defined (__cplusplus)
137 
138 namespace octave
139 {
140   template <typename T>
141   struct numeric_limits
142   {
NAnumeric_limits143     static T NA (void) { return static_cast<T> (0); }
NaNnumeric_limits144     static T NaN (void) { return static_cast<T> (0); }
Infnumeric_limits145     static T Inf (void) { return static_cast<T> (0); }
146   };
147 
148   template <>
149   struct numeric_limits<double>
150   {
151     static double NA (void) { return octave_NA; }
152     static double NaN (void) { return octave_NaN; }
153     static double Inf (void) { return octave_Inf; }
154   };
155 
156   template <>
157   struct numeric_limits<float>
158   {
159     static float NA (void) { return octave_Float_NA; }
160     static float NaN (void) { return octave_Float_NaN; }
161     static float Inf (void) { return octave_Float_Inf; }
162   };
163 }
164 
165 #endif
166 
167 #endif
168