1 /* --------------------------------------------------------------------------
2 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
3 
4 CppAD is distributed under the terms of the
5              Eclipse Public License Version 2.0.
6 
7 This Source Code may also be made available under the following
8 Secondary License when the conditions for such availability set forth
9 in the Eclipse Public License, Version 2.0 are satisfied:
10       GNU General Public License, Version 2.0 or later.
11 ---------------------------------------------------------------------------- */
12 
13 /*
14 old num_limits.cpp example / test
15 $spell
16 $$
17 
18 $section Numeric Limits: Example and Test$$
19 $index limits$$
20 $index example, limits$$
21 $index test, limits$$
22 
23 $head Assumption$$
24 This code assumes that the decimal point is infront of the mantissa.
25 Hence dividing the minimum normalized value looses precision,
26 while multiplying the maximum normalized value results in infinity.
27 
28 $head Externals$$
29 This example using external routines to get and set values
30 so that the complier does not set the correspdong code and optimize
31 it out.
32 
33 $code
34 old verbatim%example/num_limits.cpp%0%// BEGIN C++%// END C++%1%$$
35 $$
36 
37 $end
38 */
39 // BEGIN C++
40 // Complex examples should supppress conversion warnings
41 # include <cppad/wno_conversion.hpp>
42 
43 # ifdef _MSC_VER
44 // Supress Microsoft compiler warning about possible loss of precision,
45 // in the constructors (when converting to std::complex<float>)
46 //    Type one = 1
47 //    Type two = 2
48 // 1 and 2 are small enough so no loss of precision when converting to float.
49 # pragma warning(disable:4244)
50 # endif
51 
52 # include <cppad/cppad.hpp>
53 # include <complex>
54 # include "extern_value.hpp"
55 
56 namespace {
57     using CppAD::vector;
58     using CppAD::abs_geq;
59 
60     template <class Type>
add_one(const Type & value)61     Type add_one(const Type& value)
62     {   return( Type(1) + value ); }
63     // -----------------------------------------------------------------
64     template <class Type>
check_epsilon(void)65     bool check_epsilon(void)
66     {   bool ok    = true;
67         typedef extern_value<Type> value;
68         value eps( CppAD::numeric_limits<Type>::epsilon() );
69         value one( Type(1) );
70         value two( Type(2) );
71         value tmp( Type(0) );
72         //
73         tmp.set( add_one( eps.get() / two.get() ) );
74         ok        &= one.get() == tmp.get();
75         //
76         tmp.set( add_one( eps.get() ) );
77         ok        &= one.get() != tmp.get();
78         return ok;
79     }
80     // -----------------------------------------------------------------
81     template <class Type>
check_min(void)82     bool check_min(void)
83     {   bool ok    = true;
84         typedef extern_value<Type> value;
85         value min( CppAD::numeric_limits<Type>::min() );
86         value eps3( Type(3) * CppAD::numeric_limits<Type>::epsilon() );
87         value one( Type(1) );
88         value hun( Type(100) );
89         value tmp( Type(0) );
90         //
91         tmp.set( min.get() / hun.get() );
92         tmp.set( tmp.get() * hun.get() );
93         ok        &= abs_geq(tmp.get()/min.get() - one.get(), eps3.get());
94         //
95         tmp.set( min.get() * hun.get() );
96         tmp.set( tmp.get() / hun.get() );
97         ok        &= ! abs_geq(tmp.get()/min.get() - one.get(), eps3.get());
98         return ok;
99     }
100 
101     // -----------------------------------------------------------------
102     template <class Type>
check_max(void)103     bool check_max(void)
104     {   bool ok    = true;
105         typedef extern_value<Type> value;
106         value max2( CppAD::numeric_limits<Type>::max() / Type(2) );
107         value eps3( Type(3) * CppAD::numeric_limits<Type>::epsilon() );
108         value one( Type(1) );
109         value hun( Type(100) );
110         value tmp( Type(0) );
111 
112         // In complex case, this operaiton can result in (inf, 0)
113         tmp.set( max2.get() * hun.get() );
114 
115         // In complex case, this operaiotn can result in (inf,-nan)
116         // (where nan corresponds to inf * 0)
117         tmp.set( tmp.get() / hun.get() );
118 
119         if( ! CppAD::isnan( tmp.get() ) ) ok &= abs_geq(
120             tmp.get() / max2.get() - one.get(), eps3.get()
121         );
122         //
123         tmp.set( max2.get() / hun.get() );
124         tmp.set( tmp.get() * hun.get() );
125         ok        &= ! abs_geq(tmp.get() / max2.get() - one.get(), eps3.get() );
126         return ok;
127     }
128     // -----------------------------------------------------------------
129     template <class Type>
check_quiet_NaN(void)130     bool check_quiet_NaN(void)
131     {   bool ok    = true;
132         typedef extern_value<Type> value;
133         value nan( CppAD::numeric_limits<Type>::quiet_NaN() );
134         value same( nan.get() );
135         //
136         ok &= nan.get() != same.get();
137         ok &= ! (nan.get() == same.get() );
138         //
139         return ok;
140     }
141 }
142 
num_limits(void)143 bool num_limits(void)
144 {   bool ok = true;
145     using CppAD::AD;
146 
147     // -------------------------------------------------------------------
148     // epsilon for Base types defined by CppAD
149     ok &= check_epsilon<float>();
150     ok &= check_epsilon<double>();
151     ok &= check_epsilon< std::complex<float> >();
152     ok &= check_epsilon< std::complex<double> >();
153 
154     // epsilon for some AD types.
155     ok &= check_epsilon< AD<float> >();
156     ok &= check_epsilon< AD<double> >();
157     ok &= check_epsilon<  AD<std::complex<float> > >();
158     ok &= check_epsilon<  AD<std::complex<double> > >();
159 
160     // -------------------------------------------------------------------
161     // min for Base types defined by CppAD
162     ok &= check_min<float>();
163     ok &= check_min<double>();
164     ok &= check_min< std::complex<float> >();
165     ok &= check_min< std::complex<double> >();
166 
167     // min for some AD types.
168     ok &= check_min< AD<float> >();
169     ok &= check_min< AD<double> >();
170     ok &= check_min<  AD<std::complex<float> > >();
171     ok &= check_min<  AD<std::complex<double> > >();
172 
173     // -------------------------------------------------------------------
174     // max for Base types defined by CppAD
175     ok &= check_max<float>();
176     ok &= check_max<double>();
177     ok &= check_max< std::complex<float> >();
178     ok &= check_max< std::complex<double> >();
179 
180     // max for some AD types.
181     ok &= check_max< AD<float> >();
182     ok &= check_max< AD<double> >();
183     ok &= check_max< AD< std::complex<float> > >();
184     ok &= check_max< AD< std::complex<double> > >();
185     // -------------------------------------------------------------------
186     // quiet_NaN for Base types defined by CppAD
187     ok &= check_quiet_NaN<float>();
188     ok &= check_quiet_NaN<double>();
189     ok &= check_quiet_NaN< std::complex<float> >();
190     ok &= check_quiet_NaN< std::complex<double> >();
191 
192     // quiet_NaN for some AD types.
193     ok &= check_quiet_NaN< AD<float> >();
194     ok &= check_quiet_NaN< AD<double> >();
195     ok &= check_quiet_NaN< AD< std::complex<float> > >();
196     ok &= check_quiet_NaN< AD< std::complex<double> > >();
197 
198     return ok;
199 }
200 // END C++
201