Ignore:
Timestamp:
Feb 27, 2013 1:49:28 PM (7 years ago)
Author:
bradbell
Message:

Make testing of numeric limits more robust by
using external functions, instead of arrays, for storing temporary values.

extern_value.cpp: external functions for getting and setting values.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/test_more/limits.cpp

    r2722 r2756  
    2121$index test, limits$$
    2222
     23$head Assumption$$
     24This code assumes that the decimal point is infront of the mantissa.
     25Hence dividing the minimum normalized value looses precision,
     26while multiplying the maximum normalized value results in infinity.
     27
     28$head Externals$$
     29This example using external routines to get and set values
     30so that the complier does not set the correspdong code and optimize
     31it out.
     32
    2333$code
    2434$verbatim%example/limits.cpp%0%// BEGIN C++%// END C++%1%$$
     
    4050# include <cppad/cppad.hpp>
    4151# include <complex>
     52# include "extern_value.hpp"
    4253
    4354namespace {
     
    5263        bool check_epsilon(void)
    5364        {       bool ok    = true;
    54                 vector<Type> eps(1), one(1), two(1), eps2(1), check(1);
    55                 eps[0]     = CppAD::numeric_limits<Type>::epsilon();
    56                 one[0]     = 1;
    57                 two[0]     = 2;
    58                 eps2[0]    = eps[0] / two[0];
    59                 check[0]   = add_one(eps[0]);
    60                 ok        &= one[0] != check[0];
    61                 check[0]   = add_one(eps2[0]);
    62                 ok        &= one[0] == check[0];
     65                typedef extern_value<Type> value;
     66                value eps( CppAD::numeric_limits<Type>::epsilon() );
     67                value one( Type(1) );
     68                value two( Type(2) );
     69                value tmp( Type(0) );
     70                //
     71                tmp.set( add_one( eps.get() / two.get() ) );
     72                ok        &= one.get() == tmp.get();
     73                //
     74                tmp.set( add_one( eps.get() ) );
     75                ok        &= one.get() != tmp.get();
    6376                return ok;
    6477        }
     
    6780        bool check_min(void)
    6881        {       bool ok    = true;
    69                 vector<Type> min(1),eps(1),one(1),three(1),hun(1),tmp(1),match(1);
    70                 min[0]     = CppAD::numeric_limits<Type>::min();
    71                 eps[0]     = CppAD::numeric_limits<Type>::epsilon();
    72                 one[0]     = Type(1);
    73                 three[0]   = Type(3);
    74                 hun[0]     = Type(100);
     82                typedef extern_value<Type> value;
     83                value min( CppAD::numeric_limits<Type>::min() );
     84                value eps3( Type(3) * CppAD::numeric_limits<Type>::epsilon() );
     85                value one( Type(1) );
     86                value hun( Type(100) );
     87                value tmp( Type(0) );
    7588                //
    76                 tmp[0]     = min[0] / hun[0];
    77                 match[0]   = tmp[0] * hun[0];
    78                 ok        &= abs_geq(match[0]/min[0] - one[0], three[0]*eps[0]);
     89                tmp.set( min.get() / hun.get() );
     90                tmp.set( tmp.get() * hun.get() );
     91                ok        &= abs_geq(tmp.get()/min.get() - one.get(), eps3.get());
    7992                //
    80                 tmp[0]     = min[0] * hun[0];
    81                 match[0]   = tmp[0] / (hun[0] * (Type(1) - eps[0]) );
    82                 ok        &= ! abs_geq(match[0]/min[0] - one[0], three[0]*eps[0]);
     93                tmp.set( min.get() * hun.get() );
     94                tmp.set( tmp.get() / hun.get() );
     95                ok        &= ! abs_geq(tmp.get()/min.get() - one.get(), eps3.get());
    8396                return ok;
    8497        }
     98
    8599        // -----------------------------------------------------------------
    86100        template <class Type>
    87101        bool check_max(void)
    88102        {       bool ok    = true;
    89                 vector<Type> max(1),eps(1),one(1),three(1),hun(1),tmp(1),match(1);
    90                 max[0]     = CppAD::numeric_limits<Type>::max();
    91                 eps[0]     = CppAD::numeric_limits<Type>::epsilon();
    92                 one[0]     = Type(1);
    93                 three[0]   = Type(3);
    94                 hun[0]     = Type(100);
     103                typedef extern_value<Type> value;
     104                value max2( CppAD::numeric_limits<Type>::max() / Type(2) );
     105                value eps3( Type(3) * CppAD::numeric_limits<Type>::epsilon() );
     106                value one( Type(1) );
     107                value hun( Type(100) );
     108                value tmp( Type(0) );
    95109                //
    96                 tmp[0]     = max[0] * hun[0];
    97                 match[0]   = tmp[0] / hun[0];
    98                 ok        &= abs_geq(match[0]/max[0] - one[0],  three[0]*eps[0]);
     110                tmp.set( max2.get() * hun.get() );
     111                tmp.set( tmp.get() / hun.get() );
     112                // tmp is infinite
     113                ok        &= abs_geq(tmp.get() / max2.get() - one.get(), eps3.get() );
    99114                //
    100                 tmp[0]     = max[0] / hun[0];
    101                 match[0]   = tmp[0] * (hun[0] * (Type(1) - eps[0]) );
    102                 ok        &= ! abs_geq(match[0]/max[0] - one[0], three[0]*eps[0]);
    103                 return ok;
    104         }
    105         // ---------------------------------------------------------------------
    106         template <class Type>
    107         bool check_max_complex(void)
    108         {       typedef std::complex<Type> Complex;
    109                 bool ok    = true;
    110                 vector<Complex> c_max(1), c_eps(1);
    111                 vector<Type> max(1),eps(1),one(1),three(1),hun(1),tmp(1),match(1);
    112                 c_max[0]   = CppAD::numeric_limits<Complex>::max();
    113                 c_eps[0]   = CppAD::numeric_limits<Type>::epsilon();
    114                 ok        &= c_eps[0].imag() == Type(0);
    115                 ok        &= c_max[0].imag() == Type(0);
    116                 max[0]    = c_max[0].real();
    117                 eps[0]    = c_eps[0].real();
    118                 one[0]    = Type(1);
    119                 three[0]  = Type(3);
    120                 hun[0]    = Type(100);
    121                 //
    122                 tmp[0]     = max[0] * hun[0];
    123                 match[0]   = tmp[0] / hun[0];
    124                 ok  &= CppAD::abs(match[0]/max[0] - one[0]) > three[0] * eps[0];
    125                 //
    126                 tmp[0]     = max[0] / hun[0];
    127                 match[0]   = tmp[0] * (hun[0] * (Type(1) - eps[0]));
    128                 ok  &= CppAD::abs(match[0]/max[0] - one[0]) < three[0] * eps[0];
    129                 return ok;
    130         }
    131         //
    132         template <class Base>
    133         bool check_max_ad_complex()
    134         {       using CppAD::AD;
    135                 bool ok    = true;
    136                 AD<Base> c_max   = CppAD::numeric_limits< AD<Base> >::max();
    137                 ok &= Value(c_max).imag() == Base(0);
    138                 ok &= Value(c_max).real() == CppAD::numeric_limits<Base>::max();
    139 
     115                tmp.set( max2.get() / hun.get() );
     116                tmp.set( tmp.get() * hun.get() );
     117                ok        &= ! abs_geq(tmp.get() / max2.get() - one.get(), eps3.get() );
    140118                return ok;
    141119        }
     
    176154        ok &= check_max<float>();
    177155        ok &= check_max<double>();
    178         ok &= check_max_complex<float>();
    179         ok &= check_max_complex<double>();
     156        ok &= check_max< std::complex<float> >();
     157        ok &= check_max< std::complex<double> >();
    180158
    181159        // max for some AD types.
    182160        ok &= check_max< AD<float> >();
    183161        ok &= check_max< AD<double> >();
    184         ok &= check_max_ad_complex< std::complex<float> >();
    185         ok &= check_max_ad_complex< std::complex<double> >();
     162        ok &= check_max< AD< std::complex<float> > >();
     163        ok &= check_max< AD< std::complex<double> > >();
    186164
    187165        return ok;
Note: See TracChangeset for help on using the changeset viewer.