File: check_for_nan.cpp

package info (click to toggle)
cppad 2025.00.00.2-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 11,552 kB
  • sloc: cpp: 112,594; sh: 5,972; ansic: 179; python: 71; sed: 12; makefile: 10
file content (112 lines) | stat: -rw-r--r-- 2,999 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
// SPDX-FileContributor: 2003-22 Bradley M. Bell
// ----------------------------------------------------------------------------

/*
{xrst_begin check_for_nan.cpp}

ADFun Checking For Nan: Example and Test
########################################

{xrst_literal
   // BEGIN C++
   // END C++
}

{xrst_end check_for_nan.cpp}
*/
// BEGIN C++
# include <cppad/cppad.hpp>
# include <cctype>

namespace {
   void myhandler(
      bool known       ,
      int  line        ,
      const char *file ,
      const char *exp  ,
      const char *msg  )
   {  // error handler must not return, so throw an exception
      std::string message = msg;
      throw message;
   }
}

bool check_for_nan(void)
{  bool ok = true;
   using CppAD::AD;
   using std::string;
   double eps = 10. * std::numeric_limits<double>::epsilon();

   // replace the default CppAD error handler
   CppAD::ErrorHandler info(myhandler);

   CPPAD_TESTVECTOR(AD<double>) ax(2), ay(2);
   ax[0] = 2.0;
   ax[1] = 1.0;
   CppAD::Independent(ax);
   ay[0] = sqrt( ax[0] );
   ay[1] = sqrt( ax[1] );
   CppAD::ADFun<double> f(ax, ay);

   CPPAD_TESTVECTOR(double) x(2), y(2);
   x[0] = 2.0;
   x[1] = -1.0;

   // use try / catch because this causes an exception
   // (assuming that NDEBUG is not defined)
   f.check_for_nan(true);
   try {
      y = f.Forward(0, x);

# ifndef NDEBUG
      // When compiled with NDEBUG defined,
      // CppAD does not spend time checking for nan.
      ok = false;
# endif
   }
   catch(std::string msg)
   {
      // get and check size of the independent variable vector
      string pattern = "vector_size = ";
      size_t start   = msg.find(pattern) + pattern.size();
      string number;
      for(size_t i = start; msg[i] != '\n'; i++)
         number += msg[i];
      size_t vector_size = size_t( std::atoi(number.c_str()) );
      ok &= vector_size == 2;

      // get and check first dependent variable index that is nan
      pattern = "index = ";
      start   = msg.find(pattern) + pattern.size();
      number  = "";
      for(size_t i = start; msg[i] != '\n'; i++)
         number += msg[i];
      size_t index = size_t( std::atoi(number.c_str()) );
      ok &= index == 1;

      // get the name of the file
      pattern = "file_name = ";
      start   = msg.find(pattern) + pattern.size();
      string file_name;
      for(size_t i = start; msg[i] != '\n'; i++)
         file_name += msg[i];

      // get and check independent variable vector that resulted in the nan
      CppAD::vector<double> vec(vector_size);
      CppAD::get_check_for_nan(vec, file_name);
      for(size_t i = 0; i < vector_size; i++)
         ok &= vec[i] == x[i];
   }

   // now do calculation without an exception
   f.check_for_nan(false);
   y = f.Forward(0, x);
   ok &= CppAD::NearEqual(y[0], std::sqrt(x[0]), eps, eps);
   ok &= CppAD::isnan( y[1] );

   return ok;
}

// END C++