source: trunk/speed/main.cpp @ 3311

Last change on this file since 3311 was 3311, checked in by bradbell, 6 years ago

Limit boolsparsity effect to sparese tests
(prepares for more options of this nature)

speed.omh: improve section title.
main.cpp: improve section title.

  • Property svn:keywords set to Id
File size: 20.9 KB
Line 
1/* $Id: main.cpp 3311 2014-05-28 16:21:08Z bradbell $ */
2/* --------------------------------------------------------------------------
3CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell
4
5CppAD is distributed under multiple licenses. This distribution is under
6the terms of the
7                    Eclipse Public License Version 1.0.
8
9A copy of this license is included in the COPYING file of this distribution.
10Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
11-------------------------------------------------------------------------- */
12
13# include <cstring>
14# include <cstdlib>
15# include <cassert>
16# include <cstddef>
17# include <iostream>
18# include <iomanip>
19# include <cppad/vector.hpp>
20# include <cppad/speed/det_grad_33.hpp>
21# include <cppad/speed/det_33.hpp>
22# include <cppad/time_test.hpp>
23# include <cppad/speed/uniform_01.hpp>
24# include <cppad/poly.hpp>
25# include <cppad/track_new_del.hpp>
26# include <cppad/thread_alloc.hpp>
27
28# ifdef CPPAD_ADOLC_SPEED
29# define AD_PACKAGE "adolc"
30# endif
31# ifdef CPPAD_CPPAD_SPEED
32# define AD_PACKAGE "cppad"
33# endif
34# ifdef CPPAD_DOUBLE_SPEED
35# define AD_PACKAGE "double"
36# endif
37# ifdef CPPAD_FADBAD_SPEED
38# define AD_PACKAGE "fadbad"
39# endif
40# ifdef CPPAD_PROFILE_SPEED
41# define AD_PACKAGE "profile"
42# endif
43# ifdef CPPAD_SACADO_SPEED
44# define AD_PACKAGE "sacado"
45# endif
46
47/*
48$begin speed_main$$
49$spell
50        colpack
51        onetape
52        boolsparsity
53        optionlist
54        underbar
55        alloc
56        mat_mul
57        retaped
58        bool
59        ddp
60        cppad
61        adolc
62        fadbad
63        sacado
64        CppAD
65        det
66        lu
67        Jacobian
68$$
69
70$index cppad, speed test$$
71$index speed, test cppad$$
72$index test, cppad speed$$
73
74$section Running the Speed Test Program$$
75
76$head Syntax$$
77$codei%speed/%package%/speed_%package% %test% %seed% %option_list%$$
78
79$head Purpose$$
80A version of this program runs the correctness tests
81or the speed tests for one AD package identified by $icode package$$.
82
83$head package$$
84
85$subhead AD Package$$
86The command line argument
87$icode package$$ specifies one of the AD package.
88The CppAD distribution comes with support for the following packages:
89$cref/adolc/speed_adolc/$$,
90$cref/cppad/speed_cppad/$$,
91$cref/fadbad/speed_fadbad/$$,
92$cref/sacado/speed_sacado/$$.
93You can extend this program to include other package.
94Such an extension need not include all the tests.
95For example,
96$cref link_sparse_hessian$$ just returns $code false$$ for the
97$cref/fadbad/fadbad_sparse_hessian.cpp/$$ and
98$cref/sacado/sacado_sparse_hessian.cpp/$$ packages.
99
100
101$subhead double$$
102The value
103$icode package$$ can be $code double$$ in which case
104the function values (instead of derivatives) are computed
105using double precision operations.
106This enables one to compare the speed of computing function
107values in $code double$$ to the speed of the derivative computations.
108(It is often useful to divide the speed of the derivative computation by
109the speed of the function evaluation in $code double$$.)
110
111$subhead profile$$
112In the special case where $icode package$$ is $code profile$$,
113the CppAD package is compiled and run with profiling to aid in determining
114where it is spending most of its time.
115
116$head test$$
117It the argument $icode test$$ specifies which test to run
118and has the following possible values:
119$cref/correct/speed_main/test/correct/$$,
120$cref/speed/speed_main/test/speed/$$,
121$cref/det_minor/link_det_minor/$$,
122$cref/det_lu/link_det_lu/$$,
123$cref/mat_mul/link_mat_mul/$$,
124$cref/ode/link_ode/$$,
125$cref/poly/link_poly/$$,
126$cref/sparse_hessian/link_sparse_hessian/$$,
127$cref/sparse_jacobian/link_sparse_jacobian/$$.
128You can experiment with changing the implementation of a
129particular test for a particular package.
130
131$subhead correct$$
132If $icode test$$ is equal to $code correct$$,
133all of the correctness tests are run.
134
135$subhead speed$$
136If $icode test$$ is equal to $code speed$$,
137all of the speed tests are run.
138
139$head seed$$
140$index uniform_01$$
141The command line argument $icode seed$$ is a positive integer.
142The random number simulator $cref uniform_01$$ is initialized with
143the call
144$codei%
145        uniform_01(%seed%)
146%$$
147before any of the testing routines (listed above) are called.
148
149$head option_list$$
150This is a list of options that follow $icode seed$$ value.
151The order of the options does not matter and the list can be empty.
152Each option in the list, must be separate
153command line argument to the main program.
154The documentation below specifics how CppAD uses these options,
155see the examples in $cref speed_adolc$$ for how another package might
156uses these options.
157
158$subhead onetape$$
159If the option $code onetape$$ is present, the symbol
160$codep
161        extern bool global_onetape
162$$
163is true and otherwise it is false.
164If this external symbol is true,
165CppAD will use one taping of the operation
166sequence for all the repetitions of that speed test.
167Otherwise, the
168$cref/operation sequence/glossary/Operation/Sequence/$$
169will be retaped for each test repetition.
170$pre
171
172$$
173All of the tests, except $cref/det_lu/link_det_lu/$$,
174have a fixed operations sequence.
175The operation sequence for $code det_lu$$
176may be different for each repetition of the test because it
177depends on the matrix for which the determinant is being calculated.
178For this reason, the CppAD test
179$cref cppad_det_lu.cpp$$ returns false
180(indicating that the test not implemented)
181when $code global_onetape$$ is true.
182
183$subhead optimize$$
184If the option $code optimize$$ is present, the symbol
185$codep
186        extern bool global_optimize
187$$
188is true and otherwise it is false.
189If this external symbol is true,
190CppAD will optimize the operation sequence before doing computations.
191If it is false, this optimization will not be done.
192
193$subhead atomic$$
194If the option $code atomic$$ is present, the symbol
195$codep
196        extern bool global_atomic
197$$
198is true and otherwise it is false.
199If this external symbol is true, CppAD will use its user defined
200$cref/atomic/atomic_base/$$ operation is used for the test.
201If no such atomic operation exists,
202and atomic is chosen, CppAD returns false for the test.
203
204$subhead memory$$
205If the option $code memory$$ is present, the symbol
206$codep
207        extern bool global_memory
208$$
209is true and otherwise it is false.
210If it is true, the CppAD
211$cref/hold_memory/ta_hold_memory/$$ routine will be called by
212the main program before any of the tests are executed.
213This should make the CppAD $code thread_alloc$$ allocator faster.
214If it is false, CppAD will used standard memory allocation.
215
216$head Sparsity Options$$
217The following options only apply to the
218$cref/sparse_jacobian/link_sparse_jacobian/$$ and
219$cref/sparse_hessian/link_sparse_hessian/$$ tests.
220The other tests will ignore these options:
221
222$subhead boolsparsity$$
223If the option $code boolsparsity$$ is present, the symbol
224$codep
225        extern bool global_boolsparsity
226$$
227is true and otherwise it is false.
228If it is true, CppAD will use a
229$cref/vector of bool/glossary/Sparsity Pattern/Vector of Boolean/$$
230for its sparsity patterns.
231Otherwise it will use a
232$cref/vector of sets/glossary/Sparsity Pattern/Vector of Sets/$$.
233
234$subhead colpack$$
235If the option $code colpack$$ is present, the symbol
236$codep
237        extern bool global_colpack
238$$
239is true and otherwise it is false.
240If this external symbol is true,
241CppAD will use $cref/colpack/colpack_prefix/$$ to do the coloring
242for its
243Otherwise, it will use it's own coloring algorithm.
244
245$head Correctness Results$$
246One, but not both, of the following two output lines
247$codei%
248        %package%_%test%_%optionlist%_available = false
249        %package%_%test%_%optionlist%_ok = %flag%
250%$$
251is generated for each correctness test where
252$icode package$$ and $icode test$$ are as above,
253$icode optionlist$$ are the options (in $icode option_list$$)
254separated by the underbar $code _$$ character
255(whereas they are separated by spaces in $icode option_list$$),
256and $icode flag$$ is $code true$$ or $code false$$.
257
258$head Speed Results$$
259For each speed test, corresponds to three lines of the
260following form are generated:
261$codei%
262        %package%_%test%_%optionlist%_ok   = %flag%
263        %package%_%test%_size = [ %size_1%, %...%, %size_n% ]
264        %package%_%test%_rate = [ %rate_1%, %...%, %rate_n% ]
265%$$
266The values $icode package$$, $icode test$$, $icode optionlist$$,
267and $icode flag$$ are as in the correctness results above.
268The values $icode size_1$$, ..., $icode size_n$$ are the
269size arguments used for the corresponding tests.
270The values $icode rate_1$$, ..., $icode rate_n$$ are the number of times
271per second that the corresponding size problem executed.
272
273$subhead sparse_jacobian$$
274The $cref/sparse_jacobian/link_sparse_jacobian/$$ test has an extra output
275line with the following form
276$codei%
277        %package%_sparse_jacobian_n_sweep = [ %n_sweep_1%, %...%, %n_sweep_n% ]
278%$$
279The values $icode n_sweep_1$$, ..., $icode n_sweep_n$$ are the number of
280sweeps (colors) used for each sparse Jacobian calculation; see
281$cref/n_sweep/sparse_jacobian/n_sweep/$$.
282
283
284$children%
285        speed/src/link_det_lu.cpp%
286        speed/src/link_det_minor.cpp%
287        speed/src/link_mat_mul.cpp%
288        speed/src/link_ode.cpp%
289        speed/src/link_poly.cpp%
290        speed/src/link_sparse_hessian.cpp%
291        speed/src/link_sparse_jacobian.cpp%
292        speed/src/microsoft_timer.cpp
293%$$
294
295$head Link Functions$$
296Each $cref/package/speed_main/package/$$
297defines it's own version of one of the link functions listed below.
298Each of these functions links this main program to the corresponding test:
299$table
300$rref link_det_lu$$
301$rref link_det_minor$$
302$rref link_mat_mul$$
303$rref link_ode$$
304$rref link_poly$$
305$rref link_sparse_hessian$$
306$rref link_sparse_jacobian$$
307$tend
308
309
310$end
311-----------------------------------------------------------------------------
312*/
313// external routines
314
315# define CPPAD_DECLARE_SPEED(name)                       \
316     extern bool available_##name(void);                 \
317     extern bool correct_##name(bool is_package_double); \
318     extern void speed_##name(size_t size, size_t repeat)
319
320CPPAD_DECLARE_SPEED(det_lu);
321CPPAD_DECLARE_SPEED(det_minor);
322CPPAD_DECLARE_SPEED(mat_mul);
323CPPAD_DECLARE_SPEED(ode);
324CPPAD_DECLARE_SPEED(poly);
325CPPAD_DECLARE_SPEED(sparse_hessian);
326CPPAD_DECLARE_SPEED(sparse_jacobian);
327
328// info is different for each test
329extern void info_sparse_jacobian(size_t size, size_t& n_sweep);
330
331// --------------------------------------------------------------------------
332
333bool   global_onetape;
334bool   global_colpack;
335bool   global_optimize;
336bool   global_atomic;
337bool   global_memory;
338bool   global_boolsparsity;
339
340namespace {
341        using std::cout;
342        using std::endl;
343        // ----------------------------------------------------------------
344        // not available test message
345        void not_available_message(const char* test_name)
346        {       cout << AD_PACKAGE << ": " << test_name;
347                cout << " is not availabe with " << endl;
348                cout << "onetape = " << global_onetape << endl;
349                cout << "colpack = " << global_colpack << endl;
350                cout << "optimize = " << global_optimize << endl;
351                cout << "atomic = " << global_atomic << endl;
352                cout << "memory = " << global_memory << endl;
353                cout << "boolsparsity = " << global_boolsparsity << endl;
354        }
355
356        // ------------------------------------------------------
357        // output vector in form readable by octave or matlab
358        // convert size_t to int to avoid warning by MS compiler
359        void output(const CppAD::vector<size_t> &v)
360        {       size_t i= 0, n = v.size();
361                cout << "[ ";
362                while(i < n)
363                {       cout << int(v[i++]);
364                        if( i < n )
365                                cout << ", ";
366                }
367                cout << " ]";
368        }
369
370        // ----------------------------------------------------------------
371        // function that runs one correctness case
372        static size_t Run_ok_count    = 0;
373        static size_t Run_error_count = 0;
374        bool run_correct(
375                bool available_case(void) ,
376                bool correct_case(bool)   , 
377                const char *case_name     )
378        {       bool available = available_case();
379                bool ok        = true;
380                if( available ) 
381                {
382# ifdef CPPAD_DOUBLE_SPEED
383                        ok = correct_case(true);
384# else
385                        ok = correct_case(false);
386# endif
387                }
388                cout << AD_PACKAGE << "_" << case_name;
389                if( global_onetape )
390                        cout << "_onetape";
391                if( global_colpack )
392                        cout << "_colpack";
393                if( global_optimize )
394                        cout << "_optimize";
395                if( global_atomic )
396                        cout << "_atomic";
397                if( global_memory )
398                        cout << "_memory";
399                if( global_boolsparsity )
400                        cout << "_boolsparsity";
401                if( ! available )
402                {       cout << "_available = false" << endl;
403                        return ok;
404                }
405                cout << "_ok = ";
406                if( ok )
407                {       cout << " true" << endl;
408                        Run_ok_count++;
409                }
410                else
411                {       cout << " false" << endl;
412                        Run_error_count++;
413                }
414                return ok;
415        }
416        // ----------------------------------------------------------------
417        // function that runs one speed case
418        void run_speed(
419                void speed_case(size_t size, size_t repeat) , 
420                const CppAD::vector<size_t>&       size_vec ,
421                const std::string&                case_name )
422        {       double time_min = 1.;
423                cout << AD_PACKAGE << "_" << case_name << "_size = ";
424                output(size_vec);
425                cout << endl;
426                cout << AD_PACKAGE << "_" << case_name << "_rate = ";
427                cout << std::fixed;
428                for(size_t i = 0; i < size_vec.size(); i++)
429                {       if( i == 0 )
430                                cout << "[ ";
431                        else    cout << ", ";   
432                        cout << std::flush;
433                        size_t size = size_vec[i];
434                        double time = CppAD::time_test(speed_case, time_min, size);
435                        double rate = 1. / time;
436                        if( rate >= 1000 )
437                                cout << std::setprecision(0) << rate;
438                        else cout << std::setprecision(2) << rate;
439                }
440                cout << " ]" << endl;
441                return;
442        }
443}
444
445// main program that runs all the tests
446int main(int argc, char *argv[])
447{       bool ok = true;
448        enum test_enum {
449                test_correct,
450                test_speed,
451                test_det_lu,
452                test_det_minor,
453                test_mat_mul,
454                test_ode,
455                test_poly,
456                test_sparse_hessian,
457                test_sparse_jacobian,
458                test_error
459        };
460        struct test_struct {
461                const char       *name;
462                const test_enum  index;
463        }; 
464        const test_struct test_list[]= {
465                { "correct",            test_correct         }, 
466                { "speed",              test_speed           },
467                { "det_lu",             test_det_lu          },
468                { "det_minor",          test_det_minor       },
469                { "mat_mul",            test_mat_mul         },
470                { "ode",                test_ode             },
471                { "poly",               test_poly            },
472                { "sparse_hessian",     test_sparse_hessian  },
473                { "sparse_jacobian",    test_sparse_jacobian }
474        };
475        const size_t n_test  = sizeof(test_list) / sizeof(test_list[0]);
476
477        size_t i;
478        test_enum match = test_error;
479        int    iseed = 0;
480        bool   error = argc < 3;
481        if( ! error )
482        {       for(i = 0; i < n_test; i++)
483                        if( strcmp(test_list[i].name, argv[1]) == 0 )
484                                match = test_list[i].index;
485                error = match == test_error;
486                iseed = std::atoi( argv[2] );
487                error |= iseed < 0;
488                global_onetape      = false;
489                global_colpack      = false;
490                global_optimize     = false;
491                global_atomic       = false;
492                global_memory       = false;
493                global_boolsparsity = false;
494                for(i = 3; i < size_t(argc); i++)
495                {       if( strcmp(argv[i], "onetape") == 0 )
496                                global_onetape = true;
497                        else if( strcmp(argv[i], "colpack") == 0 )
498                                global_colpack = true;
499                        else if( strcmp(argv[i], "optimize") == 0 )
500                                global_optimize = true;
501                        else if( strcmp(argv[i], "atomic") == 0 )
502                                global_atomic = true;
503                        else if( strcmp(argv[i], "memory") == 0 )
504                                global_memory = true;
505                        else if( strcmp(argv[i], "boolsparsity") == 0 )
506                                global_boolsparsity = true;
507                        else
508                                error = true;
509                }
510        }
511        if( error )
512        {       cout << "usage: ./speed_" 
513                     << AD_PACKAGE << " test seed option_list" << endl;
514                cout << "test choices: " << endl;
515                for(i = 0; i < n_test; i++)
516                        cout << "\t" << test_list[i].name << endl;
517                cout << "seed choices: ";
518                cout << "a positive integer used as a random seed." << endl;
519                cout << "option choices: ";
520                cout << " \"onetape\",";
521                cout << " \"colpack\",";
522                cout << " \"optimize\",";
523                cout << " \"atomic\",";
524                cout << " \"memory\",";
525                cout << " \"boolsparsity\"." << endl << endl;
526                return 1;
527        }
528        if( global_memory )
529                CppAD::thread_alloc::hold_memory(true);
530
531        // initialize the random number simulator
532        CppAD::uniform_01(size_t(iseed));
533
534        // arguments needed for speed tests
535        size_t n_size   = 5;
536        CppAD::vector<size_t> size_det_lu(n_size);
537        CppAD::vector<size_t> size_det_minor(n_size);
538        CppAD::vector<size_t> size_mat_mul(n_size);
539        CppAD::vector<size_t> size_ode(n_size);
540        CppAD::vector<size_t> size_poly(n_size);
541        CppAD::vector<size_t> size_sparse_hessian(n_size);
542        CppAD::vector<size_t> size_sparse_jacobian(n_size);
543        for(i = 0; i < n_size; i++) 
544        {       size_det_minor[i]   = i + 1;
545                size_det_lu[i]      = 10 * i + 1;
546                size_mat_mul[i]     = 10 * i + 1;
547                size_ode[i]         = 10 * i + 1;
548                size_poly[i]        = 10 * i + 1;
549                size_sparse_hessian[i]  = 100 * (i + 1) * (i + 1);
550                size_sparse_jacobian[i] = 100 * (i + 1) * (i + 1);
551        }
552
553        switch(match)
554        {
555                // run all the correctness tests
556                case test_correct:
557                ok &= run_correct( available_det_lu, correct_det_lu, "det_lu"       
558                );
559                ok &= run_correct(
560                        available_det_minor, correct_det_minor, "det_minor"   
561                );
562                ok &= run_correct(
563                        available_mat_mul, correct_mat_mul, "mat_mul"   
564                );
565                ok &= run_correct(
566                        available_ode, correct_ode, "ode"         
567                );
568                ok &= run_correct( available_poly, correct_poly, "poly"         
569                );
570                ok &= run_correct(
571                        available_sparse_hessian, 
572                        correct_sparse_hessian,
573                        "sparse_hessian"         
574                );
575                ok &= run_correct(
576                        available_sparse_jacobian, 
577                        correct_sparse_jacobian,
578                        "sparse_jacobian"         
579                );
580                // summarize results
581                assert( ok || (Run_error_count > 0) );
582                if( ok )
583                {       cout    << "All " << int(Run_ok_count) 
584                                << " correctness tests passed." << endl;
585                }
586                else
587                {       cout    << int(Run_error_count) 
588                                << " correctness tests failed." << endl;
589                }
590                break;
591                // ---------------------------------------------------------
592                // run all the speed tests
593                case test_speed:
594                if( available_det_lu() ) run_speed(
595                speed_det_lu,          size_det_lu,          "det_lu"
596                );
597                if( available_det_minor() ) run_speed(
598                speed_det_minor,       size_det_minor,       "det_minor"
599                );
600                if( available_mat_mul() ) run_speed(
601                speed_mat_mul,           size_mat_mul,       "mat_mul"
602                );
603                if( available_ode() ) run_speed(
604                speed_ode,             size_ode,             "ode"
605                );
606                if( available_poly() ) run_speed(
607                speed_poly,            size_poly,            "poly"
608                );
609                if( available_sparse_hessian() ) run_speed(
610                speed_sparse_hessian,  size_sparse_hessian,  "sparse_hessian"
611                );
612                if( available_sparse_jacobian() ) run_speed(
613                speed_sparse_jacobian, size_sparse_jacobian, "sparse_jacobian"
614                );
615                ok = true;
616                break;
617                // ---------------------------------------------------------
618
619                case test_det_lu:
620                if( ! available_det_lu() )
621                {       not_available_message( argv[1] ); 
622                        exit(1);
623                }
624                ok &= run_correct(
625                        available_det_lu, correct_det_lu, "det_lu")
626                ;
627                run_speed(speed_det_lu,    size_det_lu,     "det_lu");
628                break;
629                // ---------------------------------------------------------
630
631                case test_det_minor:
632                if( ! available_det_minor() )
633                {       not_available_message( argv[1] ); 
634                        exit(1);
635                }
636                ok &= run_correct(
637                        available_det_minor, correct_det_minor, "det_minor"
638                );
639                run_speed(speed_det_minor, size_det_minor, "det_minor");
640                break;
641                // ---------------------------------------------------------
642
643                case test_mat_mul:
644                if( ! available_mat_mul() )
645                {       not_available_message( argv[1] ); 
646                        exit(1);
647                }
648                ok &= run_correct(
649                        available_mat_mul, correct_mat_mul, "mat_mul"
650                );
651                run_speed(speed_mat_mul, size_mat_mul, "mat_mul");
652                break;
653                // ---------------------------------------------------------
654
655                case test_ode:
656                if( ! available_ode() )
657                {       not_available_message( argv[1] ); 
658                        exit(1);
659                }
660                ok &= run_correct(
661                        available_ode, correct_ode, "ode"
662                );
663                run_speed(speed_ode,      size_ode,      "ode");
664                break;
665                // ---------------------------------------------------------
666
667                case test_poly:
668                if( ! available_poly() )
669                {       not_available_message( argv[1] ); 
670                        exit(1);
671                }
672                ok &= run_correct(
673                        available_poly, correct_poly, "poly"
674                );
675                run_speed(speed_poly,      size_poly,      "poly");
676                break;
677                // ---------------------------------------------------------
678
679                case test_sparse_hessian:
680                if( ! available_sparse_hessian() )
681                {       not_available_message( argv[1] ); 
682                        exit(1);
683                }
684                ok &= run_correct(
685                        available_sparse_hessian,
686                        correct_sparse_hessian,
687                        "sparse_hessian"
688                );
689                run_speed(
690                speed_sparse_hessian, size_sparse_hessian,  "sparse_hessian");
691                break;
692                // ---------------------------------------------------------
693
694                case test_sparse_jacobian:
695                if( ! available_sparse_jacobian() )
696                {       not_available_message( argv[1] ); 
697                        exit(1);
698                }
699                ok &= run_correct(
700                        available_sparse_jacobian,
701                        correct_sparse_jacobian,
702                        "sparse_jacobian"
703                );
704                run_speed(
705                speed_sparse_jacobian, size_sparse_jacobian, "sparse_jacobian"
706                );
707                cout << AD_PACKAGE << "_sparse_jacobian_n_sweep = ";
708                for(size_t i = 0; i < size_sparse_jacobian.size(); i++)
709                {       if( i == 0 )
710                                cout << "[ ";
711                        else    cout << ", ";   
712                        size_t n_sweep;
713                        info_sparse_jacobian(size_sparse_jacobian[i], n_sweep);
714                        cout << n_sweep;
715                }
716                cout << " ]" << endl;
717                break;
718                // ---------------------------------------------------------
719               
720                default:
721                assert(0);
722        }
723# ifndef NDEBUG
724        // return memory for vectors that are still in scope
725        size_det_lu.clear();
726        size_det_minor.clear();
727        size_mat_mul.clear();
728        size_ode.clear();
729        size_poly.clear();
730        size_sparse_hessian.clear();
731        size_sparse_jacobian.clear();
732        // check for memory leak
733        if( CppAD::thread_alloc::free_all() )
734        {       Run_ok_count++;
735                cout << "No memory leak detected" << endl;
736        }
737        else
738        {       ok = false;
739                Run_error_count++;
740                cout << "Memory leak detected" << endl;
741        }
742# endif
743        return static_cast<int>( ! ok );
744}
Note: See TracBrowser for help on using the repository browser.