/home/coin/SVN-release/CoinAll-1.1.0/cppad/cppad/local/tape_link.hpp

Go to the documentation of this file.
00001 # ifndef CPPAD_TAPE_LINK_INCLUDED
00002 # define CPPAD_TAPE_LINK_INCLUDED
00003 
00004 /* --------------------------------------------------------------------------
00005 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-07 Bradley M. Bell
00006 
00007 CppAD is distributed under multiple licenses. This distribution is under
00008 the terms of the 
00009                     Common Public License Version 1.0.
00010 
00011 A copy of this license is included in the COPYING file of this distribution.
00012 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
00013 -------------------------------------------------------------------------- */
00014 /*
00015 $begin tape_link$$ $comment CppAD Developer Documentation$$
00016 
00017 $section Routines that Link AD<Base> and ADTape<Base> Objects$$
00018 $spell
00019         omp
00020         bool
00021         ptr
00022         const
00023         tbl
00024         atexit
00025 $$
00026 
00027 $head tape_this$$
00028 $index tape_this$$
00029 The syntax
00030 $syntax%
00031         %ptr% = %x%.tape_this()
00032 %$$
00033 returns the tape corresponding to $italic x$$
00034 where $italic x$$ and $italic ptr$$ have the prototypes
00035 $syntax%
00036         const AD<%Base%> &%x%
00037         ADTape<%Base%>  *%ptr%
00038 %$$
00039 The argument $italic x$$ must a variable.
00040 
00041 $head id_handle$$
00042 $index id_handle$$
00043 The syntax
00044 $syntax%
00045         %id% = AD<%Base%>::id_handle(%thread%)
00046 %$$
00047 returns a pointer to the currently active tape identifier
00048 for the specified OpenMP thread.
00049 
00050 $subhead thread$$
00051 The argument $italic thread$$ has prototype
00052 $syntax%
00053         size_t  %thread%
00054 %$$
00055 It must be less that $code CPPAD_MAX_NUM_THREADS$$ and
00056 specifies the OpenMP thread that the tape identifier is for.
00057 In the case where the preprocessor symbol $code _OPENMP$$ is not defined,
00058 $italic thread$$ must be zero.
00059 
00060 $subhead id$$
00061 The return value $italic id$$ has prototype
00062 $syntax%
00063         size_t *%id%
00064 %$$
00065 and is a pointer to the tape identifier for the specified thread.
00066 The initial value, for the tape identifier is zero.
00067 This way it is not equal to the default $code id_ = 1$$ value
00068 in each $syntax%AD<%Base%>%$$ object.
00069 Either $syntax%*id_handle(%thread%)%$$ is zero (its initial value) or
00070 the current thread number satisfies the equation
00071 $syntax/
00072         /thread/ == *id_handle(/thread/) % CPPAD_MAX_NUM_THREADS
00073 /$$
00074 (This is a restriction on how $syntax%*id_handle(%thread%)%$$ may be changed.)
00075 
00076 
00077 $head tape_handle$$
00078 $index tape_handle$$
00079 The syntax
00080 $syntax%
00081         %tape% = AD<%Base%>::tape_handle(%thread%)
00082 %$$
00083 returns a pointer to a pointer to the current tape
00084 for the specified OpenMP thread.
00085 
00086 $subhead thread$$
00087 The argument $italic thread$$ has prototype
00088 $syntax%
00089         size_t  %thread%
00090 %$$
00091 It must be less that $code CPPAD_MAX_NUM_THREADS$$ and
00092 specifies the OpenMP thread that the tape identifier is for.
00093 In the case where the preprocessor symbol $code _OPENMP$$ is not defined,
00094 $italic thread$$ must be zero.
00095 
00096 $subhead tape$$
00097 The return value $italic tape$$ has prototype
00098 $syntax%%
00099         ADTape<%Base%> **tape
00100 %$$.
00101 If the tape is currently active,
00102 $syntax%
00103         *%tape% != CPPAD_NULL
00104 %$$
00105 
00106 
00107 $head tape_new$$
00108 $index tape_new$$
00109 The syntax
00110 $syntax%
00111         %id% = AD<%Base%>::tape_new()
00112 %$$
00113 creates a new tape and returns the corresponding tape identifier.
00114 The resulting tape identifier is not equal to zero, one, or to any
00115 of the previous values return by $code tape_new$$.
00116 In addition, the current thread number is given by
00117 $syntax/
00118         /thread/ = /id/ % CPPAD_MAX_NUM_THREADS
00119 /$$
00120 The return value $italic id$$ has prototype
00121 $syntax%
00122         size_t %id%
00123 %$$
00124 This function is only called by the user $code Independent$$ routine
00125 and hence usage errors can be reported as coming from that routine.
00126 
00127 $head tape_delete$$
00128 $index tape_delete$$
00129 The syntax
00130 $syntax%
00131         AD<%Base%>::tape_delete(%id%)
00132 %$$
00133 deletes the tape corresponding to the tape identifier $italic id$$.
00134 The value $syntax%*id_handle(%thread%)%$$ for this thread
00135 is set to a value larger than any previous value returned by
00136 $code tape_new()$$.
00137 
00138 $head tape_ptr$$
00139 $index tape_ptr$$
00140 The syntax
00141 $syntax%
00142         %ptr% = AD<%Base%>::tape_ptr()
00143 %$$
00144 returns the a pointer to the tape corresponding to the current thread.
00145 The corresponding tape is active if and only if $syntax%%ptr% == CPPAD_NULL%$$.
00146 The syntax
00147 $syntax%
00148         %ptr% = AD<%Base%>::tape_ptr(%id%)
00149 %$$
00150 does the same thing but if NDEBUG is not defined, it also check that
00151 the $italic id$$ is the corresponding tape identifier and that $italic ptr$$
00152 is not equal to $code CPPAD_NULL$$.
00153 The argument $italic id$$ has prototype
00154 $syntax%
00155         size_t %id%
00156 %$$
00157 
00158 
00159 $end
00160 ----------------------------------------------------------------------------
00161 */
00162 
00163 # ifdef _OPENMP
00164 # include <omp.h>
00165 # endif
00166 
00167 // BEGIN CppAD namespace
00168 namespace CppAD { 
00169 
00170 // ----------------------------------------------------------------------
00171 template <class Base>
00172 inline ADTape<Base> *AD<Base>::tape_this(void) const
00173 {       
00174 
00175         size_t thread = id_ % CPPAD_MAX_NUM_THREADS;
00176         CPPAD_ASSERT_UNKNOWN( id_ == *id_handle(thread) );
00177         CPPAD_ASSERT_UNKNOWN( *tape_handle(thread) != CPPAD_NULL );
00178         return *tape_handle(thread);
00179 
00180 # if 0 // old code that did not use OpenMP 
00181         CPPAD_ASSERT_UNKNOWN( id_ == *id_handle() );
00182         CPPAD_ASSERT_UNKNOWN( *tape_handle() != CPPAD_NULL );
00183         return *tape_handle();
00184 # endif
00185 
00186 }
00187 // ----------------------------------------------------------------------
00188 // Static functions
00189 //
00190 template <class Base>
00191 inline size_t * AD<Base>::id_handle(size_t thread)
00192 {       static size_t id_table[CPPAD_MAX_NUM_THREADS];
00193         CPPAD_ASSERT_UNKNOWN( 
00194                 (id_table[thread] == 0)
00195                 | (id_table[thread] % CPPAD_MAX_NUM_THREADS == thread)
00196         ); 
00197         return id_table + thread;
00198 }
00199 template <class Base>
00200 inline ADTape<Base> ** AD<Base>::tape_handle(size_t thread)
00201 {       static ADTape<Base> *tape_table[CPPAD_MAX_NUM_THREADS];
00202         return tape_table + thread;
00203 }
00204 
00205 template <class Base>
00206 size_t  AD<Base>::tape_new(void)
00207 {
00208 # ifdef _OPENMP
00209         size_t thread = static_cast<size_t> ( omp_get_thread_num() );
00210 # else
00211         size_t thread = 0;
00212 # endif
00213         size_t *id          = id_handle(thread);
00214         ADTape<Base> **tape = tape_handle(thread);
00215 
00216         CPPAD_ASSERT_KNOWN(
00217         thread < omp_max_thread(0),
00218         "Independent: OpenMP thread number is >= omp_max_thread setting"
00219         );
00220 
00221         // initialize so that id > 1 and thread == id % CPPAD_MAX_NUM_THREADS
00222         if( *id == 0 )
00223                 *id = thread + 2 * CPPAD_MAX_NUM_THREADS;
00224 
00225         // tape for this thread must be null at the start
00226         CPPAD_ASSERT_UNKNOWN( *tape  == CPPAD_NULL );
00227         *tape = new ADTape<Base>( *id );
00228 
00229         return *id;
00230 }
00231 
00232 template <class Base>
00233 void  AD<Base>::tape_delete(size_t id_old)
00234 {
00235         size_t thread = id_old % CPPAD_MAX_NUM_THREADS;
00236 # ifdef _OPENMP
00237         CPPAD_ASSERT_KNOWN(
00238         thread == static_cast<size_t> ( omp_get_thread_num() ),
00239         "AD tape recording must stop in same thread as it started in."
00240         );
00241 # else
00242         CPPAD_ASSERT_UNKNOWN(thread == 0);
00243 # endif
00244         size_t        *id   = id_handle(thread);
00245         ADTape<Base> **tape = tape_handle(thread);
00246 
00247         CPPAD_ASSERT_UNKNOWN( *id   == id_old     );
00248         CPPAD_ASSERT_UNKNOWN( *tape != CPPAD_NULL );
00249 
00250         // increase the id for this thread in a way such that 
00251         // thread = id % CPPAD_MAX_NUM_THREADS
00252         *id  += CPPAD_MAX_NUM_THREADS;
00253 
00254         // delete the old tape for this thread
00255         delete ( *tape );
00256         *tape = CPPAD_NULL;
00257 
00258         return;
00259 }
00260 template <class Base>
00261 inline ADTape<Base> *AD<Base>::tape_ptr(void)
00262 {
00263 # ifdef _OPENMP
00264         size_t thread = static_cast<size_t> ( omp_get_thread_num() );
00265 # else
00266         size_t thread = 0;
00267 # endif
00268         return *tape_handle(thread); 
00269 }
00270 
00271 template <class Base>
00272 inline ADTape<Base> *AD<Base>::tape_ptr(size_t id)
00273 {
00274         size_t thread = id % CPPAD_MAX_NUM_THREADS;
00275 # ifdef _OPENMP
00276         CPPAD_ASSERT_KNOWN(
00277         thread == static_cast<size_t> ( omp_get_thread_num() ),
00278         "Attempt to use an AD variable in two different OpenMP threads."
00279         );
00280 # else
00281         CPPAD_ASSERT_UNKNOWN(thread == 0 );
00282 # endif
00283         CPPAD_ASSERT_UNKNOWN( id == *id_handle(thread) );
00284         CPPAD_ASSERT_UNKNOWN( *tape_handle(thread) != CPPAD_NULL );
00285         return *tape_handle(thread); 
00286 }
00287 
00288 } // END CppAD namespace
00289 
00290 # endif

Generated on Sun Nov 14 14:06:33 2010 for Coin-All by  doxygen 1.4.7