1 /*----------------------------------------------------------------------------
2  ADOL-C -- Automatic Differentiation by Overloading in C++
3  File:     tape_handling.cpp
4  Revision: $Id: tape_handling.cpp 764 2019-01-30 14:44:40Z mbanovic $
5  Contents: management of tape infos
6 
7  Copyright (c) Andreas Kowarz, Andrea Walther, Kshitij Kulshreshtha,
8                Benjamin Letschert, Jean Utke
9 
10  This file is part of ADOL-C. This software is provided as open source.
11  Any use, reproduction, or distribution of the software constitutes
12  recipient's acceptance of the terms of the accompanying license file.
13 
14 ---------------------------------------------------------------------------*/
15 #include "taping_p.h"
16 #include "checkpointing_p.h"
17 #include "dvlparms.h"
18 #include <adolc/revolve.h>
19 #include <adolc/adalloc.h>
20 
21 #ifdef ADOLC_MEDIPACK_SUPPORT
22 #include "medipacksupport_p.h"
23 #endif
24 
25 #include <cassert>
26 #include <limits>
27 #include <iostream>
28 #include <string.h>
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 #include <vector>
33 #include <stack>
34 #include <errno.h>
35 
36 using namespace std;
37 
38 #ifdef SPARSE
39 BEGIN_C_DECLS
40 extern void freeSparseJacInfos(double *y, double **B, unsigned int **JP, void *g,
41 			       void *jr1d, int seed_rows, int seed_clms, int depen);
42 extern void freeSparseHessInfos(double **Hcomp, double ***Xppp, double ***Yppp, double ***Zppp,
43 				double **Upp, unsigned int **HP,
44 				void *g, void *hr, int p, int indep);
45 END_C_DECLS
46 #endif
47 
GlobalTapeVarsCL()48 GlobalTapeVarsCL::GlobalTapeVarsCL() {
49   store = NULL;
50 #if defined(ADOLC_TRACK_ACTIVITY)
51   actStore = NULL;
52 #endif
53   storeSize = 0;
54   numLives = 0;
55   nominmaxFlag = 0;
56   pStore = NULL;
57   numparam = 0;
58   maxparam = 0;
59   initialStoreSize = 0;
60 #if defined(ADOLC_TRACK_ACTIVITY)
61   storeManagerPtr = new StoreManagerLocintBlock(store, actStore, storeSize, numLives);
62 #else
63   storeManagerPtr = new StoreManagerLocintBlock(store, storeSize, numLives);
64 #endif
65   paramStoreMgrPtr = new StoreManagerLocintBlock(pStore, maxparam, numparam);
66 }
67 
~GlobalTapeVarsCL()68 GlobalTapeVarsCL::~GlobalTapeVarsCL() {
69   if (storeManagerPtr != NULL) {
70     delete storeManagerPtr;
71     storeManagerPtr = NULL;
72   }
73   if (paramStoreMgrPtr != NULL) {
74       delete paramStoreMgrPtr;
75       paramStoreMgrPtr = NULL;
76   }
77 }
78 
operator =(const GlobalTapeVarsCL & gtv)79 const GlobalTapeVarsCL& GlobalTapeVarsCL::operator=(const GlobalTapeVarsCL& gtv) {
80     storeSize = gtv.storeSize;
81     numLives = gtv.numLives;
82     maxLoc = gtv.maxLoc;
83     operationBufferSize = gtv.operationBufferSize;
84     locationBufferSize = gtv.locationBufferSize;
85     valueBufferSize = gtv.valueBufferSize;
86     taylorBufferSize = gtv.taylorBufferSize;
87     maxNumberTaylorBuffers = gtv.maxNumberTaylorBuffers;
88     inParallelRegion = gtv.inParallelRegion;
89     newTape = gtv.newTape;
90     branchSwitchWarning = gtv.branchSwitchWarning;
91     currentTapeInfosPtr = gtv.currentTapeInfosPtr;
92     initialStoreSize = gtv.initialStoreSize;
93     store = new double[storeSize];
94     memcpy(store, gtv.store, storeSize*sizeof(double));
95 #if defined(ADOLC_TRACK_ACTIVITY)
96     actStore = new char[storeSize];
97     memcpy(actStore, gtv.actStore, storeSize*sizeof(char));
98 #endif
99     storeManagerPtr = new
100         StoreManagerLocintBlock(
101             dynamic_cast<StoreManagerLocintBlock*>(gtv.storeManagerPtr),
102             store,
103 #if defined(ADOLC_TRACK_ACTIVITY)
104             actStore,
105 #endif
106             storeSize, numLives);
107     paramStoreMgrPtr = new
108         StoreManagerLocintBlock(
109             dynamic_cast<StoreManagerLocintBlock*>(gtv.paramStoreMgrPtr),
110             pStore, maxparam, numparam);
111     return *this;
112 }
113 
114 #if defined(ADOLC_TRACK_ACTIVITY)
115 
116 char const* const StoreManagerLocint::nowhere = NULL;
117 
StoreManagerLocint(double * & storePtr,char * & actStorePtr,size_t & size,size_t & numlives)118 StoreManagerLocint::StoreManagerLocint(double * &storePtr, char* &actStorePtr, size_t &size, size_t &numlives) :
119     storePtr(storePtr),
120     activityTracking(1),
121     actStorePtr(actStorePtr),
122     indexFree(0),
123     head(0),
124     maxsize(size), currentfill(numlives)
125 {
126 #ifdef ADOLC_DEBUG
127     std::cerr << "StoreManagerInteger::StoreManagerInteger()\n";
128 #endif
129 }
130 
StoreManagerLocint(const StoreManagerLocint * const stm,double * & storePtr,char * & actStorePtr,size_t & size,size_t & numlives)131 StoreManagerLocint::StoreManagerLocint(const StoreManagerLocint *const stm,
132 				       double * &storePtr, char* &actStorePtr, size_t &size, size_t &numlives) :
133     storePtr(storePtr),
134     actStorePtr(actStorePtr),
135     activityTracking(1),
136     maxsize(size), currentfill(numlives)
137 {
138 #ifdef ADOLC_DEBUG
139     std::cerr << "StoreManagerInteger::StoreManagerInteger()\n";
140 #endif
141     head = stm->head;
142     indexFree = new locint[maxsize];
143     for (size_t i = 0; i < maxsize; i++)
144 	indexFree[i] = stm->indexFree[i];
145 }
146 #endif
147 
StoreManagerLocint(double * & storePtr,size_t & size,size_t & numlives)148 StoreManagerLocint::StoreManagerLocint(double * &storePtr, size_t &size, size_t &numlives) :
149     storePtr(storePtr),
150 #if defined(ADOLC_TRACK_ACTIVITY)
151     activityTracking(0),
152     actStorePtr(const_cast<char*&>(nowhere)),
153 #endif
154     indexFree(0),
155     head(0),
156     maxsize(size), currentfill(numlives)
157 {
158 #ifdef ADOLC_DEBUG
159     std::cerr << "StoreManagerInteger::StoreManagerInteger()\n";
160 #endif
161 }
162 
~StoreManagerLocint()163 StoreManagerLocint::~StoreManagerLocint()
164 {
165 #ifdef ADOLC_DEBUG
166     std::cerr << "StoreManagerInteger::~StoreManagerInteger()\n";
167 #endif
168     if (storePtr) {
169 	delete[] storePtr;
170 	storePtr = 0;
171     }
172     if (indexFree) {
173 	delete[] indexFree;
174 	indexFree = 0;
175     }
176 #if defined(ADOLC_TRACK_ACTIVITY)
177     if (activityTracking && actStorePtr) {
178 	delete[] actStorePtr;
179     }
180 #endif
181     maxsize = 0;
182     currentfill = 0;
183     head = 0;
184 }
185 
StoreManagerLocint(const StoreManagerLocint * const stm,double * & storePtr,size_t & size,size_t & numlives)186 StoreManagerLocint::StoreManagerLocint(const StoreManagerLocint *const stm,
187 				       double * &storePtr, size_t &size, size_t &numlives) :
188     storePtr(storePtr),
189 #if defined(ADOLC_TRACK_ACTIVITY)
190     activityTracking(0),
191     actStorePtr(const_cast<char*&>(nowhere)),
192 #endif
193     maxsize(size), currentfill(numlives)
194 {
195 #ifdef ADOLC_DEBUG
196     std::cerr << "StoreManagerInteger::StoreManagerInteger()\n";
197 #endif
198     head = stm->head;
199     indexFree = new locint[maxsize];
200     for (size_t i = 0; i < maxsize; i++)
201 	indexFree[i] = stm->indexFree[i];
202 }
203 
next_loc()204 locint StoreManagerLocint::next_loc() {
205     if (head == 0) {
206       grow();
207     }
208     assert(head);
209     locint const result = head;
210     head = indexFree[head];
211     ++currentfill;
212 #ifdef ADOLC_DEBUG
213     std::cerr << "next_loc: " << result << " fill: " << size() << "max: " << maxSize() << endl;
214 #endif
215     return result;
216 }
217 
free_loc(locint loc)218 void StoreManagerLocint::free_loc(locint loc) {
219     assert(0 < loc && loc < maxsize);
220     indexFree[loc] = head;
221     head = loc;
222     --currentfill;
223 #ifdef ADOLC_DEBUG
224     std::cerr << "free_loc: " << loc << " fill: " << size() << "max: " << maxSize() << endl;
225 #endif
226 }
227 
ensure_block(size_t n)228 void StoreManagerLocint::ensure_block(size_t n) {
229     fprintf(DIAG_OUT,"ADOL-C error: Location block required from singleton location store");
230     adolc_exit(-4,"ADOL-C error: Location blocks not alowed",__func__,__FILE__,__LINE__);
231 }
232 
grow(size_t mingrow)233 void StoreManagerLocint::grow(size_t mingrow) {
234     if (maxsize == 0) maxsize += initialSize;
235     size_t const oldMaxsize = maxsize;
236     maxsize *= 2;
237     if (maxsize < mingrow) maxsize = mingrow;
238 
239     if (maxsize > std::numeric_limits<locint>::max()) {
240       // encapsulate this error message
241       fprintf(DIAG_OUT,"\nADOL-C error:\n");
242       fprintf(DIAG_OUT,"maximal number (%d) of live active variables exceeded\n\n",
243 	      std::numeric_limits<locint>::max());
244       adolc_exit(-3,"",__func__,__FILE__,__LINE__);
245     }
246 
247 #ifdef ADOLC_DEBUG
248     std::cerr << "StoreManagerInteger::grow(): increase size from " << oldMaxsize
249 	 << " to " << maxsize << " entries (currently " << size() << " entries used)\n";
250     assert(oldMaxsize == initialSize or size() == oldMaxsize);
251 #endif
252 
253     double *const oldStore = storePtr;
254     locint *const oldIndex = indexFree;
255 #if defined(ADOLC_TRACK_ACTIVITY)
256     char * oldactStore;
257     if (activityTracking) {
258 	oldactStore = actStorePtr;
259     }
260 #endif
261 
262 #if defined(ADOLC_DEBUG)
263     std::cerr << "StoreManagerInteger::grow(): allocate " << maxsize * sizeof(double) << " B doubles "
264 	 << "and " << maxsize * sizeof(locint) << " B locints\n";
265 #endif
266     storePtr = new double[maxsize];
267     indexFree = new locint[maxsize];
268 #if defined(ADOLC_TRACK_ACTIVITY)
269     if (activityTracking)
270 	actStorePtr = new char[maxsize];
271 #endif
272     // we use index 0 as end-of-list marker
273     size_t i = 1;
274     storePtr[0] =  std::numeric_limits<double>::quiet_NaN();
275 
276     if (oldMaxsize != initialSize) { // not the first time
277 #if defined(ADOLC_DEBUG)
278       std::cerr << "StoreManagerInteger::grow(): copy values\n";
279 #endif
280       for (size_t j = i; j < oldMaxsize; ++j) {
281 	indexFree[j] = oldIndex[j];
282       }
283       for (size_t j = i; j < oldMaxsize; ++j) {
284 	storePtr[j] = oldStore[j];
285       }
286 #if defined(ADOLC_TRACK_ACTIVITY)
287       if (activityTracking) {
288 	  for (size_t j = i; j < oldMaxsize; ++j) {
289 	      actStorePtr[j] = oldactStore[j];
290 	  }
291       }
292 #endif
293       // reset i to start of new slots (upper half)
294       i = oldMaxsize;
295 
296 #if defined(ADOLC_DEBUG)
297       std::cerr << "StoreManagerInteger::grow(): free " << oldMaxsize * sizeof(double)
298 		<< " + " << oldMaxsize * sizeof(locint) << " B\n";
299 #endif
300       delete [] oldStore;
301       delete [] oldIndex;
302 #if defined(ADOLC_TRACK_ACTIVITY)
303       if (activityTracking)
304 	  delete [] oldactStore;
305 #endif
306     }
307 
308     head = i;
309     // create initial linked list for new slots
310     for ( ; i < maxsize-1; ++i) {
311       indexFree[i] = i + 1;
312     }
313     indexFree[i] = 0; // end marker
314     assert(i == maxsize-1);
315 }
316 
317 
318 /****************************************************************************/
319 /* Returns the next free location in "adouble" memory.                      */
320 /****************************************************************************/
next_loc()321 locint next_loc() {
322   ADOLC_OPENMP_THREAD_NUMBER;
323   ADOLC_OPENMP_GET_THREAD_NUMBER;
324   return ADOLC_GLOBAL_TAPE_VARS.storeManagerPtr->next_loc();
325 }
326 
327 /****************************************************************************/
328 /* frees the specified location in "adouble" memory                         */
329 /****************************************************************************/
free_loc(locint loc)330 void free_loc(locint loc) {
331   ADOLC_OPENMP_THREAD_NUMBER;
332   ADOLC_OPENMP_GET_THREAD_NUMBER;
333   ADOLC_GLOBAL_TAPE_VARS.storeManagerPtr->free_loc(loc);
334 }
335 
336 /* vector of tape infos for all tapes in use */
337 vector<TapeInfos *> ADOLC_TAPE_INFOS_BUFFER_DECL;
338 
339 /* stack of pointers to tape infos
340  * represents the order of tape usage when doing nested taping */
341 stack<TapeInfos *> ADOLC_TAPE_STACK_DECL;
342 
343 /* the main tape info buffer and its fallback */
344 TapeInfos ADOLC_CURRENT_TAPE_INFOS_DECL;
345 TapeInfos ADOLC_CURRENT_TAPE_INFOS_FALLBACK_DECL;
346 
347 /* global tapeing variables */
348 GlobalTapeVars ADOLC_GLOBAL_TAPE_VARS_DECL;
349 
350 #if defined(_OPENMP)
351 static vector<TapeInfos *> *tapeInfosBuffer_s;
352 static stack<TapeInfos *>  *tapeStack_s;
353 static TapeInfos           *currentTapeInfos_s;
354 static TapeInfos           *currentTapeInfos_fallBack_s;
355 static GlobalTapeVars      *globalTapeVars_s;
356 static ADOLC_BUFFER_TYPE   *ADOLC_extDiffFctsBuffer_s;
357 static stack<StackElement> *ADOLC_checkpointsStack_s;
358 static revolve_nums        *revolve_numbers_s;
359 
360 static vector<TapeInfos *> *tapeInfosBuffer_p;
361 static stack<TapeInfos *>  *tapeStack_p;
362 static TapeInfos           *currentTapeInfos_p;
363 static TapeInfos           *currentTapeInfos_fallBack_p;
364 static GlobalTapeVars      *globalTapeVars_p;
365 static ADOLC_BUFFER_TYPE   *ADOLC_extDiffFctsBuffer_p;
366 static stack<StackElement> *ADOLC_checkpointsStack_p;
367 static revolve_nums        *revolve_numbers_p;
368 #endif
369 
370 /*--------------------------------------------------------------------------*/
371 /* This function sets the flag "newTape" if either a taylor buffer has been */
372 /* created or a taping process has been performed. Calling the function is  */
373 /* also useful to "convince" the linker of including the cleaner part into  */
374 /* the binary when linking statically!                                      */
375 /*--------------------------------------------------------------------------*/
markNewTape()376 void markNewTape() {
377     ADOLC_OPENMP_THREAD_NUMBER;
378     ADOLC_OPENMP_GET_THREAD_NUMBER;
379     ADOLC_GLOBAL_TAPE_VARS.newTape = 1;
380 }
381 
382 /* inits the struct for the new tape */
initTapeInfos(TapeInfos * newTapeInfos)383 void initTapeInfos(TapeInfos *newTapeInfos) {
384     char *ptr, *end;
385 
386     ptr = (char *)(&newTapeInfos->tapeID);
387     end = (char *)(&newTapeInfos->pTapeInfos);
388     for ( ; ptr != end ; ptr++ )
389         *ptr = 0;
390 }
391 
392 /* as above but keep allocated buffers if possible */
initTapeInfos_keep(TapeInfos * newTapeInfos)393 void initTapeInfos_keep(TapeInfos *newTapeInfos) {
394     unsigned char *opBuffer = newTapeInfos->opBuffer;
395     locint *locBuffer = newTapeInfos->locBuffer;
396     double *valBuffer = newTapeInfos->valBuffer;
397     revreal *tayBuffer = newTapeInfos->tayBuffer;
398     double *signature = newTapeInfos->signature;
399     FILE *tay_file = newTapeInfos->tay_file;
400 
401     initTapeInfos(newTapeInfos);
402 
403     newTapeInfos->opBuffer = opBuffer;
404     newTapeInfos->locBuffer = locBuffer;
405     newTapeInfos->valBuffer = valBuffer;
406     newTapeInfos->tayBuffer = tayBuffer;
407     newTapeInfos->signature = signature;
408     newTapeInfos->tay_file = tay_file;
409 }
410 
411 /* inits a new tape and updates the tape stack (called from start_trace)
412  * - returns 0 without error
413  * - returns 1 if tapeID was already/still in use */
initNewTape(short tapeID)414 int initNewTape(short tapeID) {
415     TapeInfos *newTapeInfos = NULL;
416     bool newTI = false;
417     int retval = 0;
418 
419     ADOLC_OPENMP_THREAD_NUMBER;
420     ADOLC_OPENMP_GET_THREAD_NUMBER;
421 
422     /* check if tape is in use */
423     vector<TapeInfos *>::iterator tiIter;
424     if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
425         for (tiIter=ADOLC_TAPE_INFOS_BUFFER.begin();
426                 tiIter!=ADOLC_TAPE_INFOS_BUFFER.end();
427                 ++tiIter) {
428             if ((*tiIter)->tapeID==tapeID) {
429                 newTapeInfos=*tiIter;
430                 if ((*tiIter)->inUse != 0) {
431                     if ((*tiIter)->tapingComplete == 0)
432                         fail(ADOLC_TAPING_TAPE_STILL_IN_USE);
433                     if ( (*tiIter)->stats[OP_FILE_ACCESS]  == 0 &&
434                             (*tiIter)->stats[LOC_FILE_ACCESS] == 0 &&
435                             (*tiIter)->stats[VAL_FILE_ACCESS] == 0  ) {
436 #              if defined(ADOLC_DEBUG)
437                         fprintf(DIAG_OUT, "\nADOL-C warning: Tape %d existed in main memory"
438                                 " only and gets overwritten!\n\n", tapeID);
439 #              endif
440                         /* free associated resources */
441                         retval = 1;
442                     }
443                 }
444                 if ((*tiIter)->tay_file != NULL)
445                     rewind((*tiIter)->tay_file);
446                 initTapeInfos_keep(*tiIter);
447                 (*tiIter)->tapeID = tapeID;
448 #ifdef SPARSE
449 		freeSparseJacInfos(newTapeInfos->pTapeInfos.sJinfos.y,
450 				   newTapeInfos->pTapeInfos.sJinfos.B,
451 				   newTapeInfos->pTapeInfos.sJinfos.JP,
452 				   newTapeInfos->pTapeInfos.sJinfos.g,
453 				   newTapeInfos->pTapeInfos.sJinfos.jr1d,
454 				   newTapeInfos->pTapeInfos.sJinfos.seed_rows,
455 				   newTapeInfos->pTapeInfos.sJinfos.seed_clms,
456 				   newTapeInfos->pTapeInfos.sJinfos.depen);
457 		freeSparseHessInfos(newTapeInfos->pTapeInfos.sHinfos.Hcomp,
458 				    newTapeInfos->pTapeInfos.sHinfos.Xppp,
459 				    newTapeInfos->pTapeInfos.sHinfos.Yppp,
460 				    newTapeInfos->pTapeInfos.sHinfos.Zppp,
461 				    newTapeInfos->pTapeInfos.sHinfos.Upp,
462 				    newTapeInfos->pTapeInfos.sHinfos.HP,
463 				    newTapeInfos->pTapeInfos.sHinfos.g,
464 				    newTapeInfos->pTapeInfos.sHinfos.hr,
465 				    newTapeInfos->pTapeInfos.sHinfos.p,
466 				    newTapeInfos->pTapeInfos.sHinfos.indep);
467 		newTapeInfos->pTapeInfos.sJinfos.B=NULL;
468 		newTapeInfos->pTapeInfos.sJinfos.y=NULL;
469 		newTapeInfos->pTapeInfos.sJinfos.g=NULL;
470 		newTapeInfos->pTapeInfos.sJinfos.jr1d=NULL;
471 		newTapeInfos->pTapeInfos.sJinfos.Seed=NULL;
472 		newTapeInfos->pTapeInfos.sJinfos.JP=NULL;
473 		newTapeInfos->pTapeInfos.sJinfos.depen=0;
474 		newTapeInfos->pTapeInfos.sJinfos.nnz_in=0;
475 		newTapeInfos->pTapeInfos.sJinfos.seed_rows=0;
476 		newTapeInfos->pTapeInfos.sJinfos.seed_clms=0;
477 		newTapeInfos->pTapeInfos.sHinfos.Zppp=NULL;
478 		newTapeInfos->pTapeInfos.sHinfos.Yppp=NULL;
479 		newTapeInfos->pTapeInfos.sHinfos.Xppp=NULL;
480 		newTapeInfos->pTapeInfos.sHinfos.Upp=NULL;
481 		newTapeInfos->pTapeInfos.sHinfos.Hcomp=NULL;
482 		newTapeInfos->pTapeInfos.sHinfos.HP=NULL;
483 		newTapeInfos->pTapeInfos.sHinfos.g=NULL;
484 		newTapeInfos->pTapeInfos.sHinfos.hr=NULL;
485 		newTapeInfos->pTapeInfos.sHinfos.nnz_in=0;
486 		newTapeInfos->pTapeInfos.sHinfos.indep=0;
487 		newTapeInfos->pTapeInfos.sHinfos.p=0;
488 #endif
489                 break;
490             }
491         }
492     }
493 
494     /* create new info struct and initialize it */
495     if (newTapeInfos == NULL) {
496         newTapeInfos = new TapeInfos(tapeID);
497         newTI = true;
498     }
499     newTapeInfos->traceFlag=1;
500     newTapeInfos->inUse=1;
501 
502     newTapeInfos->stats[OP_BUFFER_SIZE] =
503         ADOLC_GLOBAL_TAPE_VARS.operationBufferSize;
504     newTapeInfos->stats[LOC_BUFFER_SIZE] =
505         ADOLC_GLOBAL_TAPE_VARS.locationBufferSize;
506     newTapeInfos->stats[VAL_BUFFER_SIZE] =
507         ADOLC_GLOBAL_TAPE_VARS.valueBufferSize;
508     newTapeInfos->stats[TAY_BUFFER_SIZE] =
509         ADOLC_GLOBAL_TAPE_VARS.taylorBufferSize;
510 
511     /* update tapeStack and save tapeInfos */
512     if (ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr != NULL) {
513         ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr->copy(
514             ADOLC_CURRENT_TAPE_INFOS);
515         ADOLC_TAPE_STACK.push(ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr);
516     } else {
517         ADOLC_CURRENT_TAPE_INFOS_FALLBACK.copy(
518                 ADOLC_CURRENT_TAPE_INFOS);
519         ADOLC_TAPE_STACK.push(&ADOLC_CURRENT_TAPE_INFOS_FALLBACK);
520     }
521     if (newTI) ADOLC_TAPE_INFOS_BUFFER.push_back(newTapeInfos);
522 
523     newTapeInfos->pTapeInfos.skipFileCleanup=0;
524 
525     /* set the new tape infos as current */
526     ADOLC_CURRENT_TAPE_INFOS.copy(*newTapeInfos);
527     ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr = newTapeInfos;
528 
529     return retval;
530 }
531 
532 /* opens an existing tape or creates a new handle for a tape on hard disk
533  * - called from init_for_sweep and init_rev_sweep */
openTape(short tapeID,char mode)534 void openTape(short tapeID, char mode) {
535     TapeInfos *tempTapeInfos=NULL;
536 
537     ADOLC_OPENMP_THREAD_NUMBER;
538     ADOLC_OPENMP_GET_THREAD_NUMBER;
539 
540     /* check if tape information exist in memory */
541     vector<TapeInfos *>::iterator tiIter;
542     if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
543         for (tiIter=ADOLC_TAPE_INFOS_BUFFER.begin();
544                 tiIter!=ADOLC_TAPE_INFOS_BUFFER.end();
545                 ++tiIter) {
546             if ((*tiIter)->tapeID == tapeID) {
547                 /* tape has been used before (in the current program) */
548                 if ((*tiIter)->inUse == 0) {
549                     /* forward sweep */
550                     if ((*tiIter)->tay_file != NULL)
551                         rewind((*tiIter)->tay_file);
552                     initTapeInfos_keep(*tiIter);
553                     (*tiIter)->traceFlag=1;
554                     (*tiIter)->tapeID = tapeID;
555                     (*tiIter)->tapingComplete = 1;
556                     (*tiIter)->inUse = 1;
557                     read_tape_stats(*tiIter);
558                }
559                 if (ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr != NULL) {
560                     ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr->copy(
561                             ADOLC_CURRENT_TAPE_INFOS);
562                     ADOLC_TAPE_STACK.push(
563                             ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr);
564                 } else {
565                     ADOLC_CURRENT_TAPE_INFOS_FALLBACK.copy(
566                             ADOLC_CURRENT_TAPE_INFOS);
567                     ADOLC_TAPE_STACK.push(&ADOLC_CURRENT_TAPE_INFOS_FALLBACK);
568                 }
569                 ADOLC_CURRENT_TAPE_INFOS.copy(**tiIter);
570                 ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr = *tiIter;
571                 return;
572             }
573         }
574     }
575 
576     /* tapeID not used so far */
577     if (mode == ADOLC_REVERSE) {
578         failAdditionalInfo1 = tapeID;
579         fail(ADOLC_REVERSE_NO_TAYLOR_STACK);
580     }
581 
582     /* create new info struct and initialize it */
583     tempTapeInfos = new TapeInfos(tapeID);
584     tempTapeInfos->traceFlag=1;
585     tempTapeInfos->inUse = 1;
586     tempTapeInfos->tapingComplete = 1;
587     ADOLC_TAPE_INFOS_BUFFER.push_back(tempTapeInfos);
588 
589     read_tape_stats(tempTapeInfos);
590     /* update tapeStack and save tapeInfos */
591     if (ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr != NULL) {
592         ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr->copy(
593                 ADOLC_CURRENT_TAPE_INFOS);
594         ADOLC_TAPE_STACK.push(ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr);
595     } else {
596         ADOLC_CURRENT_TAPE_INFOS_FALLBACK.copy(
597                 ADOLC_CURRENT_TAPE_INFOS);
598         ADOLC_TAPE_STACK.push(&ADOLC_CURRENT_TAPE_INFOS_FALLBACK);
599     }
600 
601     /* set the new tape infos as current */
602     ADOLC_CURRENT_TAPE_INFOS.copy(*tempTapeInfos);
603     ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr = tempTapeInfos;
604 }
605 
606 /* release the current tape and give control to the previous one */
releaseTape()607 void releaseTape() {
608     ADOLC_OPENMP_THREAD_NUMBER;
609     ADOLC_OPENMP_GET_THREAD_NUMBER;
610 
611     /* if operations, locations and constants tapes have been written and value
612      * stack information have not been created tapeInfos are no longer needed*/
613     if (ADOLC_CURRENT_TAPE_INFOS.keepTaylors            == 0 &&
614             ADOLC_CURRENT_TAPE_INFOS.stats[OP_FILE_ACCESS]  == 1 &&
615             ADOLC_CURRENT_TAPE_INFOS.stats[LOC_FILE_ACCESS] == 1 &&
616             ADOLC_CURRENT_TAPE_INFOS.stats[VAL_FILE_ACCESS] == 1 ) {
617         ADOLC_CURRENT_TAPE_INFOS.inUse = 0;
618     }
619 
620     ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr->copy(
621             ADOLC_CURRENT_TAPE_INFOS);
622     ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr = ADOLC_TAPE_STACK.top();
623     ADOLC_CURRENT_TAPE_INFOS.copy(
624             *ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr);
625     ADOLC_TAPE_STACK.pop();
626     if (ADOLC_TAPE_STACK.empty())
627         ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr = NULL;
628 }
629 
630 /* updates the tape infos for the given ID - a tapeInfos struct is created
631  * and registered if non is found but its state will remain "not in use" */
getTapeInfos(short tapeID)632 TapeInfos *getTapeInfos(short tapeID) {
633     TapeInfos *tapeInfos;
634     vector<TapeInfos *>::iterator tiIter;
635 
636     ADOLC_OPENMP_THREAD_NUMBER;
637     ADOLC_OPENMP_GET_THREAD_NUMBER;
638 
639     /* check if TapeInfos for tapeID exist */
640     if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
641         for (tiIter=ADOLC_TAPE_INFOS_BUFFER.begin();
642                 tiIter!=ADOLC_TAPE_INFOS_BUFFER.end();
643                 ++tiIter) {
644             if ((*tiIter)->tapeID==tapeID) {
645                 tapeInfos=*tiIter;
646                 if (tapeInfos->inUse==0) read_tape_stats(tapeInfos);
647                 return tapeInfos;
648             }
649         }
650     }
651     /* create new TapeInfos, initialize and update tapeInfosBuffer */
652     tapeInfos = new TapeInfos(tapeID);
653     ADOLC_TAPE_INFOS_BUFFER.push_back(tapeInfos);
654     tapeInfos->traceFlag=1;
655     tapeInfos->inUse=0;
656     tapeInfos->tapingComplete = 1;
657     read_tape_stats(tapeInfos);
658     return tapeInfos;
659 }
660 
661 /****************************************************************************/
662 /* Set a trace to nested_ctx                                                */
663 /****************************************************************************/
set_nested_ctx(short tag,char nested)664 void set_nested_ctx(short tag, char nested) {
665     TapeInfos* tiInfos = getTapeInfos(tag);
666     tiInfos->in_nested_ctx = nested;
667 }
668 /****************************************************************************/
669 /* Check whether a tape has been set to nested_ctx                          */
670 /****************************************************************************/
currently_nested(short tag)671 char currently_nested(short tag) {
672     TapeInfos* tiInfos = getTapeInfos(tag);
673     return tiInfos->in_nested_ctx;
674 }
675 
676 
cachedTraceTags(std::vector<short> & result)677 void cachedTraceTags(std::vector<short>& result) {
678     vector<TapeInfos *>::const_iterator tiIter;
679     vector<short>::iterator tIdIter;
680     ADOLC_OPENMP_THREAD_NUMBER;
681     ADOLC_OPENMP_GET_THREAD_NUMBER;
682 
683     result.resize(ADOLC_TAPE_INFOS_BUFFER.size());
684     if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
685         for(tiIter=ADOLC_TAPE_INFOS_BUFFER.begin(), tIdIter=result.begin();
686             tiIter!=ADOLC_TAPE_INFOS_BUFFER.end();
687             ++tiIter, ++tIdIter) {
688             *tIdIter = (*tiIter)->tapeID;
689         }
690     }
691 }
692 
693 #ifdef SPARSE
694 /* updates the tape infos on sparse Jac for the given ID  */
setTapeInfoJacSparse(short tapeID,SparseJacInfos sJinfos)695 void setTapeInfoJacSparse(short tapeID, SparseJacInfos sJinfos) {
696     TapeInfos *tapeInfos;
697     vector<TapeInfos *>::iterator tiIter;
698 
699     ADOLC_OPENMP_THREAD_NUMBER;
700     ADOLC_OPENMP_GET_THREAD_NUMBER;
701 
702     /* check if TapeInfos for tapeID exist */
703     if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
704         for (tiIter=ADOLC_TAPE_INFOS_BUFFER.begin();
705                 tiIter!=ADOLC_TAPE_INFOS_BUFFER.end();
706                 ++tiIter) {
707             if ((*tiIter)->tapeID==tapeID) {
708                 tapeInfos=*tiIter;
709 		// free memory of tape entry that had been used previously
710 		freeSparseJacInfos(tapeInfos->pTapeInfos.sJinfos.y,
711                         tapeInfos->pTapeInfos.sJinfos.B,
712                         tapeInfos->pTapeInfos.sJinfos.JP,
713                         tapeInfos->pTapeInfos.sJinfos.g,
714 			tapeInfos->pTapeInfos.sJinfos.jr1d,
715 			tapeInfos->pTapeInfos.sJinfos.seed_rows,
716 			tapeInfos->pTapeInfos.sJinfos.seed_clms,
717 			tapeInfos->pTapeInfos.sJinfos.depen);
718 		tapeInfos->pTapeInfos.sJinfos.y=sJinfos.y;
719 		tapeInfos->pTapeInfos.sJinfos.Seed=sJinfos.Seed;
720 		tapeInfos->pTapeInfos.sJinfos.B=sJinfos.B;
721 		tapeInfos->pTapeInfos.sJinfos.JP=sJinfos.JP;
722 		tapeInfos->pTapeInfos.sJinfos.depen=sJinfos.depen;
723 		tapeInfos->pTapeInfos.sJinfos.nnz_in=sJinfos.nnz_in;
724 		tapeInfos->pTapeInfos.sJinfos.seed_clms=sJinfos.seed_clms;
725 		tapeInfos->pTapeInfos.sJinfos.seed_rows=sJinfos.seed_rows;
726 		tapeInfos->pTapeInfos.sJinfos.g=sJinfos.g;
727 		tapeInfos->pTapeInfos.sJinfos.jr1d=sJinfos.jr1d;
728             }
729         }
730     }
731 }
732 #endif
733 
734 #ifdef SPARSE
735 /* updates the tape infos on sparse Hess for the given ID  */
setTapeInfoHessSparse(short tapeID,SparseHessInfos sHinfos)736 void setTapeInfoHessSparse(short tapeID, SparseHessInfos sHinfos) {
737     TapeInfos *tapeInfos;
738     vector<TapeInfos *>::iterator tiIter;
739 
740     ADOLC_OPENMP_THREAD_NUMBER;
741     ADOLC_OPENMP_GET_THREAD_NUMBER;
742 
743     /* check if TapeInfos for tapeID exist */
744     if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
745         for (tiIter=ADOLC_TAPE_INFOS_BUFFER.begin();
746                 tiIter!=ADOLC_TAPE_INFOS_BUFFER.end();
747                 ++tiIter) {
748             if ((*tiIter)->tapeID==tapeID) {
749                 tapeInfos=*tiIter;
750 		// free memory of tape entry that had been used previously
751                     freeSparseHessInfos(tapeInfos->pTapeInfos.sHinfos.Hcomp,
752                                         tapeInfos->pTapeInfos.sHinfos.Xppp,
753                                         tapeInfos->pTapeInfos.sHinfos.Yppp,
754                                         tapeInfos->pTapeInfos.sHinfos.Zppp,
755                                         tapeInfos->pTapeInfos.sHinfos.Upp,
756                                         tapeInfos->pTapeInfos.sHinfos.HP,
757 					tapeInfos->pTapeInfos.sHinfos.g,
758                                         tapeInfos->pTapeInfos.sHinfos.hr,
759                                         tapeInfos->pTapeInfos.sHinfos.p,
760                                         tapeInfos->pTapeInfos.sHinfos.indep);
761 		    tapeInfos->pTapeInfos.sHinfos.Hcomp=sHinfos.Hcomp;
762 		    tapeInfos->pTapeInfos.sHinfos.Xppp=sHinfos.Xppp;
763 		    tapeInfos->pTapeInfos.sHinfos.Yppp=sHinfos.Yppp;
764 		    tapeInfos->pTapeInfos.sHinfos.Zppp=sHinfos.Zppp;
765 		    tapeInfos->pTapeInfos.sHinfos.Upp=sHinfos.Upp;
766 		    tapeInfos->pTapeInfos.sHinfos.HP=sHinfos.HP;
767 		    tapeInfos->pTapeInfos.sHinfos.indep=sHinfos.indep;
768 		    tapeInfos->pTapeInfos.sHinfos.nnz_in=sHinfos.nnz_in;
769 		    tapeInfos->pTapeInfos.sHinfos.p=sHinfos.p;
770 		    tapeInfos->pTapeInfos.sHinfos.g=sHinfos.g;
771 		    tapeInfos->pTapeInfos.sHinfos.hr=sHinfos.hr;
772             }
773         }
774     }
775 }
776 #endif
777 
init_lib()778 static void init_lib() {
779     ADOLC_OPENMP_THREAD_NUMBER;
780     errno = 0;
781     ADOLC_OPENMP_GET_THREAD_NUMBER;
782 
783 #if defined(_OPENMP)
784     tapeInfosBuffer = new vector<TapeInfos *>;
785     tapeStack = new stack<TapeInfos *>;
786     currentTapeInfos = new TapeInfos;
787     currentTapeInfos->tapingComplete = 1;
788     currentTapeInfos_fallBack = new TapeInfos;
789     globalTapeVars = new GlobalTapeVars;
790     ADOLC_extDiffFctsBuffer = new ADOLC_BUFFER_TYPE;
791     ADOLC_checkpointsStack = new stack<StackElement>;
792     revolve_numbers = new revolve_nums;
793 #endif /* _OPENMP */
794 
795     ADOLC_CURRENT_TAPE_INFOS.traceFlag = 0;
796     ADOLC_CURRENT_TAPE_INFOS.keepTaylors = 0;
797 
798     ADOLC_GLOBAL_TAPE_VARS.maxLoc=1;
799     for (uint i=0; i<sizeof(locint)*8-1; ++i) {
800         ADOLC_GLOBAL_TAPE_VARS.maxLoc<<=1;
801         ++ADOLC_GLOBAL_TAPE_VARS.maxLoc;
802     }
803     ADOLC_GLOBAL_TAPE_VARS.inParallelRegion = 0;
804     ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr = NULL;
805     ADOLC_GLOBAL_TAPE_VARS.branchSwitchWarning = 1;
806 
807     adolc_id.adolc_ver    = ADOLC_VERSION;
808     adolc_id.adolc_sub    = ADOLC_SUBVERSION;
809     adolc_id.adolc_lvl    = ADOLC_PATCHLEVEL;
810     adolc_id.locint_size  = sizeof(locint);
811     adolc_id.revreal_size = sizeof(revreal);
812     adolc_id.address_size = sizeof(size_t);
813 
814     ADOLC_EXT_DIFF_FCTS_BUFFER.init(init_CpInfos);
815     readConfigFile();
816 }
817 
clearCurrentTape()818 static void clearCurrentTape() {
819     ADOLC_OPENMP_THREAD_NUMBER;
820     ADOLC_OPENMP_GET_THREAD_NUMBER;
821     TapeInfos* tmpTapeInfos = new TapeInfos;
822 
823     ADOLC_CURRENT_TAPE_INFOS.copy(*tmpTapeInfos);
824     ADOLC_CURRENT_TAPE_INFOS_FALLBACK.copy(*tmpTapeInfos);
825     delete tmpTapeInfos;
826 }
827 
828 /* does things like closing/removing temporary files, ... */
cleanUp()829 void cleanUp() {
830     ADOLC_OPENMP_THREAD_NUMBER;
831     ADOLC_OPENMP_GET_THREAD_NUMBER;
832 
833     TapeInfos** tiIter;
834     clearCurrentTape();
835     while (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
836         tiIter = &ADOLC_TAPE_INFOS_BUFFER.back();
837         ADOLC_TAPE_INFOS_BUFFER.pop_back();
838         {
839             /* close open files though they may be incomplete */
840             if ((*tiIter)->op_file!=NULL)
841             {
842                 fclose((*tiIter)->op_file);
843                 (*tiIter)->op_file = NULL;
844             }
845             if ((*tiIter)->val_file!=NULL)
846             {
847                 fclose((*tiIter)->val_file);
848                 (*tiIter)->val_file = NULL;
849             }
850             if ((*tiIter)->loc_file!=NULL)
851             {
852                 fclose((*tiIter)->loc_file);
853                 (*tiIter)->loc_file = NULL;
854             }
855             if ((*tiIter)->tay_file!=NULL && (*tiIter)->pTapeInfos.skipFileCleanup==0 ) {
856                 fclose((*tiIter)->tay_file);
857                 (*tiIter)->tay_file = NULL;
858                 remove((*tiIter)->pTapeInfos.tay_fileName);
859             }
860             if ((*tiIter)->opBuffer != NULL)
861             {
862                 free((*tiIter)->opBuffer);
863                 (*tiIter)->opBuffer = NULL;
864             }
865             if ((*tiIter)->valBuffer != NULL)
866             {
867                 free((*tiIter)->valBuffer);
868                 (*tiIter)->valBuffer = NULL;
869             }
870             if ((*tiIter)->locBuffer != NULL)
871             {
872                 free((*tiIter)->locBuffer);
873                 (*tiIter)->locBuffer = NULL;
874             }
875 	    if ((*tiIter)->signature != NULL)
876 	    {
877 		free((*tiIter)->signature);
878 		(*tiIter)->signature = NULL;
879 	    }
880             if ((*tiIter)->tayBuffer != NULL)
881             {
882                 free((*tiIter)->tayBuffer);
883                 (*tiIter)->tayBuffer = NULL;
884             }
885 
886 #ifdef SPARSE
887 	    freeSparseJacInfos((*tiIter)->pTapeInfos.sJinfos.y,
888 			       (*tiIter)->pTapeInfos.sJinfos.B,
889 			       (*tiIter)->pTapeInfos.sJinfos.JP,
890 			       (*tiIter)->pTapeInfos.sJinfos.g,
891 			       (*tiIter)->pTapeInfos.sJinfos.jr1d,
892 			       (*tiIter)->pTapeInfos.sJinfos.seed_rows,
893 			       (*tiIter)->pTapeInfos.sJinfos.seed_clms,
894 			       (*tiIter)->pTapeInfos.sJinfos.depen);
895 	    freeSparseHessInfos((*tiIter)->pTapeInfos.sHinfos.Hcomp,
896 				(*tiIter)->pTapeInfos.sHinfos.Xppp,
897 				(*tiIter)->pTapeInfos.sHinfos.Yppp,
898 				(*tiIter)->pTapeInfos.sHinfos.Zppp,
899 				(*tiIter)->pTapeInfos.sHinfos.Upp,
900 				(*tiIter)->pTapeInfos.sHinfos.HP,
901 				(*tiIter)->pTapeInfos.sHinfos.g,
902 				(*tiIter)->pTapeInfos.sHinfos.hr,
903 				(*tiIter)->pTapeInfos.sHinfos.p,
904 				(*tiIter)->pTapeInfos.sHinfos.indep);
905 #endif
906 
907             /* remove "main" tape files if not all three have been written */
908             int filesWritten = (*tiIter)->stats[OP_FILE_ACCESS] +
909                 (*tiIter)->stats[LOC_FILE_ACCESS] +
910                 (*tiIter)->stats[VAL_FILE_ACCESS];
911             if ( (filesWritten > 0) && ((*tiIter)->pTapeInfos.keepTape == 0) && (*tiIter)->pTapeInfos.skipFileCleanup==0 )
912             {
913                 /* try to remove all tapes (even those not written by this
914                  * run) => this ensures that there is no mixture of tapes from
915                  * different ADOLC runs */
916                 if ( (*tiIter)->stats[OP_FILE_ACCESS] == 1 )
917                     remove((*tiIter)->pTapeInfos.op_fileName);
918                 if ( (*tiIter)->stats[LOC_FILE_ACCESS] == 1 )
919                     remove((*tiIter)->pTapeInfos.loc_fileName);
920                 if ( (*tiIter)->stats[VAL_FILE_ACCESS] == 1 )
921                     remove((*tiIter)->pTapeInfos.val_fileName);
922             }
923             if ((*tiIter)->pTapeInfos.op_fileName != NULL)
924             {
925                 free((*tiIter)->pTapeInfos.op_fileName);
926                 (*tiIter)->pTapeInfos.op_fileName = NULL;
927             }
928             if ((*tiIter)->pTapeInfos.val_fileName != NULL)
929             {
930                 free((*tiIter)->pTapeInfos.val_fileName);
931                 (*tiIter)->pTapeInfos.val_fileName = NULL;
932             }
933             if ((*tiIter)->pTapeInfos.loc_fileName != NULL)
934             {
935                 free((*tiIter)->pTapeInfos.loc_fileName);
936                 (*tiIter)->pTapeInfos.loc_fileName = NULL;
937             }
938             if ((*tiIter)->pTapeInfos.tay_fileName != NULL)
939             {
940                 free((*tiIter)->pTapeInfos.tay_fileName);
941                 (*tiIter)->pTapeInfos.tay_fileName = NULL;
942             }
943 
944             delete *tiIter;
945             *tiIter = NULL;
946         }
947     }
948 
949     cp_clearStack();
950 
951     if (ADOLC_GLOBAL_TAPE_VARS.store != NULL) {
952         delete[] ADOLC_GLOBAL_TAPE_VARS.store;
953         ADOLC_GLOBAL_TAPE_VARS.store = NULL;
954     }
955     if (ADOLC_GLOBAL_TAPE_VARS.pStore != NULL) {
956         delete[] ADOLC_GLOBAL_TAPE_VARS.pStore;
957         ADOLC_GLOBAL_TAPE_VARS.pStore = NULL;
958     }
959 
960 #if defined(_OPENMP)
961     if (ADOLC_GLOBAL_TAPE_VARS.inParallelRegion == 0) {
962         /* cleanup on program exit */
963         delete revolve_numbers;
964         delete ADOLC_checkpointsStack;
965         delete ADOLC_extDiffFctsBuffer;
966         delete globalTapeVars;
967         delete currentTapeInfos;
968         delete currentTapeInfos_fallBack;
969         delete tapeStack;
970         delete tapeInfosBuffer;
971     }
972 #endif
973 
974     ADOLC_OPENMP_RESTORE_THREAD_NUMBER;
975     clearTapeBaseNames();
976 }
977 
removeTape(short tapeID,short type)978 int removeTape(short tapeID, short type) {
979     TapeInfos *tapeInfos = NULL;
980     vector<TapeInfos *>::iterator tiIter;
981     ADOLC_OPENMP_THREAD_NUMBER;
982     ADOLC_OPENMP_GET_THREAD_NUMBER;
983 
984     /* check if TapeInfos for tapeID exist */
985     if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
986         for (tiIter = ADOLC_TAPE_INFOS_BUFFER.begin();
987                 tiIter != ADOLC_TAPE_INFOS_BUFFER.end();
988                 ++tiIter)
989         {
990             if ((*tiIter)->tapeID == tapeID) {
991                 tapeInfos = *tiIter;
992                 if (tapeInfos->tapingComplete == 0) return -1;
993                 ADOLC_TAPE_INFOS_BUFFER.erase(tiIter);
994                 break;
995             }
996         }
997     }
998 
999     if (tapeInfos == NULL) { // might be on disk only
1000         tapeInfos = new TapeInfos(tapeID);
1001         tapeInfos->tapingComplete = 1;
1002     }
1003 
1004     freeTapeResources(tapeInfos);
1005 #ifdef SPARSE
1006     freeSparseJacInfos(tapeInfos->pTapeInfos.sJinfos.y,
1007 		       tapeInfos->pTapeInfos.sJinfos.B,
1008 		       tapeInfos->pTapeInfos.sJinfos.JP,
1009 		       tapeInfos->pTapeInfos.sJinfos.g,
1010 		       tapeInfos->pTapeInfos.sJinfos.jr1d,
1011 		       tapeInfos->pTapeInfos.sJinfos.seed_rows,
1012 		       tapeInfos->pTapeInfos.sJinfos.seed_clms,
1013 		       tapeInfos->pTapeInfos.sJinfos.depen);
1014     freeSparseHessInfos(tapeInfos->pTapeInfos.sHinfos.Hcomp,
1015 			tapeInfos->pTapeInfos.sHinfos.Xppp,
1016 			tapeInfos->pTapeInfos.sHinfos.Yppp,
1017 			tapeInfos->pTapeInfos.sHinfos.Zppp,
1018 			tapeInfos->pTapeInfos.sHinfos.Upp,
1019 			tapeInfos->pTapeInfos.sHinfos.HP,
1020 			tapeInfos->pTapeInfos.sHinfos.g,
1021 			tapeInfos->pTapeInfos.sHinfos.hr,
1022 			tapeInfos->pTapeInfos.sHinfos.p,
1023 			tapeInfos->pTapeInfos.sHinfos.indep);
1024 #endif
1025     ADOLC_OPENMP_RESTORE_THREAD_NUMBER;
1026 
1027     if (type == ADOLC_REMOVE_COMPLETELY) {
1028         remove(tapeInfos->pTapeInfos.op_fileName);
1029         remove(tapeInfos->pTapeInfos.loc_fileName);
1030         remove(tapeInfos->pTapeInfos.val_fileName);
1031     }
1032 
1033     free(tapeInfos->pTapeInfos.op_fileName);
1034     free(tapeInfos->pTapeInfos.val_fileName);
1035     free(tapeInfos->pTapeInfos.loc_fileName);
1036     if (tapeInfos->pTapeInfos.tay_fileName != NULL)
1037         free(tapeInfos->pTapeInfos.tay_fileName);
1038 
1039     delete tapeInfos;
1040 
1041     return 0;
1042 }
1043 
1044 /****************************************************************************/
1045 /* Initialization for the taping process. Creates buffers for this tape,    */
1046 /* sets files names, and calls appropriate setup routines.                  */
1047 /****************************************************************************/
trace_on(short tnum,int keepTaylors)1048 int trace_on(short tnum, int keepTaylors) {
1049     int retval = 0;
1050     ADOLC_OPENMP_THREAD_NUMBER;
1051     ADOLC_OPENMP_GET_THREAD_NUMBER;
1052 
1053     /* allocate memory for TapeInfos and update tapeStack */
1054     retval = initNewTape(tnum);
1055 #ifdef ADOLC_MEDIPACK_SUPPORT
1056     mediInitTape(tnum);
1057 #endif
1058     ADOLC_CURRENT_TAPE_INFOS.keepTaylors=keepTaylors;
1059     ADOLC_CURRENT_TAPE_INFOS.stats[NO_MIN_MAX] =
1060 	ADOLC_GLOBAL_TAPE_VARS.nominmaxFlag;
1061     if (keepTaylors!=0) ADOLC_CURRENT_TAPE_INFOS.deg_save=1;
1062     start_trace();
1063     take_stock();               /* record all existing adoubles on the tape */
1064     return retval;
1065 }
1066 
trace_on(short tnum,int keepTaylors,uint obs,uint lbs,uint vbs,uint tbs,int skipFileCleanup)1067 int trace_on(short tnum, int keepTaylors,
1068         uint obs, uint lbs, uint vbs, uint tbs, int skipFileCleanup)
1069 {
1070     int retval = 0;
1071     ADOLC_OPENMP_THREAD_NUMBER;
1072     ADOLC_OPENMP_GET_THREAD_NUMBER;
1073 
1074     /* allocate memory for TapeInfos and update tapeStack */
1075     retval = initNewTape(tnum);
1076 #ifdef ADOLC_MEDIPACK_SUPPORT
1077     mediInitTape(tnum);
1078 #endif
1079     freeTapeResources(&ADOLC_CURRENT_TAPE_INFOS);
1080     ADOLC_CURRENT_TAPE_INFOS.stats[OP_BUFFER_SIZE] = obs;
1081     ADOLC_CURRENT_TAPE_INFOS.stats[LOC_BUFFER_SIZE] = lbs;
1082     ADOLC_CURRENT_TAPE_INFOS.stats[VAL_BUFFER_SIZE] = vbs;
1083     ADOLC_CURRENT_TAPE_INFOS.stats[TAY_BUFFER_SIZE] = tbs;
1084     ADOLC_CURRENT_TAPE_INFOS.keepTaylors=keepTaylors;
1085     ADOLC_CURRENT_TAPE_INFOS.stats[NO_MIN_MAX] =
1086 	ADOLC_GLOBAL_TAPE_VARS.nominmaxFlag;
1087     ADOLC_CURRENT_TAPE_INFOS.pTapeInfos.skipFileCleanup=skipFileCleanup;
1088     if (keepTaylors!=0) ADOLC_CURRENT_TAPE_INFOS.deg_save=1;
1089     start_trace();
1090     take_stock();               /* record all existing adoubles on the tape */
1091     return retval;
1092 }
1093 
1094 /****************************************************************************/
1095 /* Stop Tracing. Cleans up, and turns off trace_flag. Flag not equal zero   */
1096 /* enforces writing of the three main tape files (op+loc+val).              */
1097 /****************************************************************************/
trace_off(int flag)1098 void trace_off(int flag) {
1099     ADOLC_OPENMP_THREAD_NUMBER;
1100     ADOLC_OPENMP_GET_THREAD_NUMBER;
1101     if (ADOLC_CURRENT_TAPE_INFOS.workMode != ADOLC_TAPING) {
1102 	failAdditionalInfo1 = ADOLC_CURRENT_TAPE_INFOS.tapeID;
1103 	fail(ADOLC_TAPING_NOT_ACTUALLY_TAPING);
1104     }
1105     ADOLC_CURRENT_TAPE_INFOS.pTapeInfos.keepTape = flag;
1106     keep_stock();         /* copy remaining live variables + trace_flag = 0 */
1107     stop_trace(flag);
1108     cout.flush();
1109     ADOLC_CURRENT_TAPE_INFOS.tapingComplete = 1;
1110     ADOLC_CURRENT_TAPE_INFOS.workMode = ADOLC_NO_MODE;
1111     releaseTape();
1112 }
1113 
isTaping()1114 bool isTaping() {
1115     ADOLC_OPENMP_THREAD_NUMBER;
1116     ADOLC_OPENMP_GET_THREAD_NUMBER;
1117     return ADOLC_CURRENT_TAPE_INFOS.traceFlag != 0;
1118 }
1119 
checkInitialStoreSize(GlobalTapeVars * gtv)1120 void checkInitialStoreSize(GlobalTapeVars *gtv) {
1121     if (gtv->initialStoreSize >
1122         gtv->storeManagerPtr->initialSize)
1123         gtv->storeManagerPtr->grow(
1124             gtv->initialStoreSize);
1125 }
1126 
1127 /****************************************************************************/
1128 /* A class for initialization/finalization and OpenMP handling              */
1129 /****************************************************************************/
1130 class Keeper {
1131     public:
Keeper()1132         inline Keeper() {
1133             dummy = 0;
1134             init_lib();
1135         }
~Keeper()1136         inline ~Keeper() {
1137             cleanUp();
1138         }
1139 
touch()1140         inline void touch() {
1141             dummy = 1;
1142         }
1143 
1144     private:
1145         int dummy;
1146 };
1147 
1148 /* a static instance that does all work */
1149 static Keeper theKeeper;
1150 
1151 /**
1152  * Hope to convince the linker to link the keeper code into the executable. */
initADOLC()1153 void initADOLC() {
1154     theKeeper.touch();
1155 }
1156 
1157 /****************************************************************************/
1158 /****************************************************************************/
1159 /* The following is necessary to provide a separate ADOL-C environment for  */
1160 /* each OpenMP worker.                                                      */
1161 /****************************************************************************/
1162 /****************************************************************************/
1163 #if defined(_OPENMP)
1164 #include <adolc/adolc_openmp.h>
1165 
1166 ADOLC_OpenMP ADOLC_OpenMP_Handler;
1167 ADOLC_OpenMP_NC ADOLC_OpenMP_Handler_NC;
1168 int ADOLC_parallel_doCopy;
1169 
1170 static bool waitForMaster_begin = true;
1171 static bool waitForMaster_end   = true;
1172 static bool firstParallel       = true;
1173 
1174 /****************************************************************************/
1175 /* Used by OpenMP to create a separate environment for every worker thread. */
1176 /****************************************************************************/
beginParallel()1177 void beginParallel() {
1178     ADOLC_OPENMP_THREAD_NUMBER;
1179 #if defined(ADOLC_THREADSAVE_ERRNO)
1180     errno = omp_get_thread_num();
1181 #endif
1182     ADOLC_OPENMP_GET_THREAD_NUMBER;
1183 
1184     if (ADOLC_threadNumber == 0) { /* master only */
1185         int numThreads = omp_get_num_threads();
1186 
1187         tapeInfosBuffer_s           = tapeInfosBuffer;
1188         tapeStack_s                 = tapeStack;
1189         currentTapeInfos_s          = currentTapeInfos;
1190         currentTapeInfos_fallBack_s = currentTapeInfos_fallBack;
1191         globalTapeVars_s            = globalTapeVars;
1192         ADOLC_extDiffFctsBuffer_s   = ADOLC_extDiffFctsBuffer;
1193         ADOLC_checkpointsStack_s    = ADOLC_checkpointsStack;
1194         revolve_numbers_s           = revolve_numbers;
1195 
1196         if (firstParallel) {
1197             tapeInfosBuffer           = new vector<TapeInfos *>[numThreads];
1198             tapeStack                 = new stack<TapeInfos *>[numThreads];
1199             currentTapeInfos          = new TapeInfos[numThreads];
1200             currentTapeInfos_fallBack = new TapeInfos[numThreads];
1201             globalTapeVars            = new GlobalTapeVars[numThreads];
1202             ADOLC_extDiffFctsBuffer   = new ADOLC_BUFFER_TYPE[numThreads];
1203             ADOLC_checkpointsStack    = new stack<StackElement>[numThreads];
1204             revolve_numbers           = new revolve_nums[numThreads];
1205         } else {
1206             tapeInfosBuffer           = tapeInfosBuffer_p;
1207             tapeStack                 = tapeStack_p;
1208             currentTapeInfos          = currentTapeInfos_p;
1209             currentTapeInfos_fallBack = currentTapeInfos_fallBack_p;
1210             globalTapeVars            = globalTapeVars_p;
1211             ADOLC_extDiffFctsBuffer   = ADOLC_extDiffFctsBuffer_p;
1212             ADOLC_checkpointsStack    = ADOLC_checkpointsStack_p;
1213             revolve_numbers         = revolve_numbers_p;
1214         }
1215 
1216         /* - set inParallelRegion for tmpGlobalTapeVars because it is source
1217          *   for initializing the parallel globalTapeVars structs
1218          * - inParallelRegion has to be set to one for all workers by master.
1219          *   This is necessary, to deter a speedy master from assuming all
1220          *   workers are done, in endParallel, before they even leaved
1221          *   beginParallel. */
1222         globalTapeVars_s[0].inParallelRegion = 1;
1223         for (int i = 0; i < numThreads; ++i)
1224             globalTapeVars[i].inParallelRegion = 1;
1225 
1226         waitForMaster_end = true;
1227         waitForMaster_begin = false;
1228     } else
1229         while (waitForMaster_begin) {
1230             usleep(1000); /* if anyone knows a better value, ... :-) */
1231         }
1232 
1233     if (firstParallel) {
1234         ADOLC_EXT_DIFF_FCTS_BUFFER.init(init_CpInfos);
1235 
1236 	/* Use assignment operator instead of open coding
1237 	 * this copies the store and the storemanager too
1238 	 */
1239 	ADOLC_GLOBAL_TAPE_VARS = *globalTapeVars_s;
1240 
1241         ADOLC_GLOBAL_TAPE_VARS.newTape = 0;
1242         ADOLC_CURRENT_TAPE_INFOS.tapingComplete = 1;
1243         ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr = NULL;
1244     } else {
1245         if (ADOLC_parallel_doCopy) {
1246             ADOLC_GLOBAL_TAPE_VARS.storeSize = globalTapeVars_s->storeSize;
1247             ADOLC_GLOBAL_TAPE_VARS.numLives = globalTapeVars_s->numLives;
1248 
1249             ADOLC_GLOBAL_TAPE_VARS.branchSwitchWarning = globalTapeVars_s->branchSwitchWarning;
1250 
1251 	    /* deleting the storemanager deletes the store too */
1252 	    delete ADOLC_GLOBAL_TAPE_VARS.storeManagerPtr;
1253 
1254             ADOLC_GLOBAL_TAPE_VARS.store = new
1255                 double[ADOLC_GLOBAL_TAPE_VARS.storeSize];
1256             memcpy(ADOLC_GLOBAL_TAPE_VARS.store, globalTapeVars_s->store,
1257                     ADOLC_GLOBAL_TAPE_VARS.storeSize * sizeof(double));
1258 	    ADOLC_GLOBAL_TAPE_VARS.storeManagerPtr = new
1259 		StoreManagerLocintBlock(
1260 		    dynamic_cast<StoreManagerLocintBlock*>(globalTapeVars_s->storeManagerPtr),
1261 		    ADOLC_GLOBAL_TAPE_VARS.store,
1262 		    ADOLC_GLOBAL_TAPE_VARS.storeSize,
1263 		    ADOLC_GLOBAL_TAPE_VARS.numLives);
1264         }
1265     }
1266 }
1267 
1268 /****************************************************************************/
1269 /* Used by OpenMP to destroy the separate environment of every worker.      */
1270 /****************************************************************************/
1271 /* There are n+1 instances of ADOLC_OpenMP => n within the parallel region
1272  * and one in the serial part! */
endParallel()1273 void endParallel() {
1274     ADOLC_OPENMP_THREAD_NUMBER;
1275     ADOLC_OPENMP_GET_THREAD_NUMBER;
1276 
1277     /* do nothing if called at program exit (serial part) */
1278     if (ADOLC_threadNumber == 0 &&
1279             ADOLC_GLOBAL_TAPE_VARS.inParallelRegion == 0) return;
1280 
1281     ADOLC_GLOBAL_TAPE_VARS.inParallelRegion = 0;
1282 
1283     if (ADOLC_threadNumber == 0) { /* master only */
1284         int num;
1285         int numThreads = omp_get_num_threads();
1286         bool firstIt = true;
1287         do { /* wait until all slaves have left the parallel part */
1288             if (firstIt) firstIt = false;
1289             else usleep(1000); /* no busy waiting */
1290             num = 1;
1291             for (int i = 1; i < numThreads; ++i)
1292                 if (globalTapeVars[i].inParallelRegion == 0) ++num;
1293         } while (num != numThreads);
1294 
1295         firstParallel = false;
1296 
1297         revolve_numbers_p           = revolve_numbers;
1298         ADOLC_checkpointsStack_p    = ADOLC_checkpointsStack;
1299         ADOLC_extDiffFctsBuffer_p   = ADOLC_extDiffFctsBuffer;
1300         globalTapeVars_p            = globalTapeVars;
1301         currentTapeInfos_p          = currentTapeInfos;
1302         currentTapeInfos_fallBack_p = currentTapeInfos_fallBack;
1303         tapeStack_p                 = tapeStack;
1304         tapeInfosBuffer_p           = tapeInfosBuffer;
1305 
1306         revolve_numbers           = revolve_numbers_s;
1307         ADOLC_checkpointsStack    = ADOLC_checkpointsStack_s;
1308         ADOLC_extDiffFctsBuffer   = ADOLC_extDiffFctsBuffer_s;
1309         globalTapeVars            = globalTapeVars_s;
1310         currentTapeInfos          = currentTapeInfos_s;
1311         currentTapeInfos_fallBack = currentTapeInfos_fallBack_s;
1312         tapeStack                 = tapeStack_s;
1313         tapeInfosBuffer           = tapeInfosBuffer_s;
1314 
1315         ADOLC_GLOBAL_TAPE_VARS.inParallelRegion = 0;
1316         waitForMaster_begin = true;
1317         waitForMaster_end = false;
1318     } else
1319         while (waitForMaster_end) {
1320             usleep(1000); // no busy waiting
1321         }
1322 }
1323 
1324 #endif /* _OPENMP */
1325 
TapeInfos()1326 TapeInfos::TapeInfos() : pTapeInfos() {
1327     initTapeInfos(this);
1328 }
1329 
TapeInfos(short _tapeID)1330 TapeInfos::TapeInfos(short _tapeID) : pTapeInfos() {
1331     initTapeInfos(this);
1332     tapeID = _tapeID;
1333     pTapeInfos.op_fileName = createFileName(tapeID, OPERATIONS_TAPE);
1334     pTapeInfos.loc_fileName = createFileName(tapeID, LOCATIONS_TAPE);
1335     pTapeInfos.val_fileName = createFileName(tapeID, VALUES_TAPE);
1336     pTapeInfos.tay_fileName = NULL;
1337 }
1338 
copy(const TapeInfos & tInfos)1339 void TapeInfos::copy(const TapeInfos& tInfos) {
1340     char *ptr, *end;
1341     char const* tIptr = (char const*)(&tInfos.tapeID);
1342 
1343     ptr = (char *)(&this->tapeID);
1344     end = (char *)(&this->pTapeInfos);
1345     for ( ; ptr != end ; ptr++, tIptr++ )
1346         *ptr = *tIptr;
1347     this->pTapeInfos.copy(tInfos.pTapeInfos);
1348 }
1349 
PersistantTapeInfos()1350 PersistantTapeInfos::PersistantTapeInfos() {
1351     char *ptr = (char*)(&forodec_nax), *end = (char*)(&paramstore);
1352     for (; ptr != end ; ptr++ )
1353         *ptr = 0;
1354     paramstore = NULL;
1355 }
1356 
copy(const PersistantTapeInfos & pTInfos)1357 void PersistantTapeInfos::copy(const PersistantTapeInfos& pTInfos) {
1358     char *ptr = (char*)(&this->forodec_nax), *end = (char*)(&this->paramstore);
1359     char const* pTIptr = (char const*)(&pTInfos.forodec_nax);
1360     for (; ptr != end ; ptr++, pTIptr++ )
1361         *ptr = *pTIptr;
1362     paramstore = pTInfos.paramstore;
1363 }
1364 
~PersistantTapeInfos()1365 PersistantTapeInfos::~PersistantTapeInfos() {
1366     if (jacSolv_nax) {
1367         free(jacSolv_ci);
1368         free(jacSolv_ri);
1369         myfree1(jacSolv_xold);
1370         myfreeI2(jacSolv_nax, jacSolv_I);
1371         myfree2(jacSolv_J);
1372         jacSolv_nax = 0;
1373     }
1374     if (forodec_nax) {
1375         myfree1(forodec_y);
1376         myfree1(forodec_z);
1377         myfree2(forodec_Z);
1378         forodec_nax = 0;
1379     }
1380     if (paramstore != NULL) {
1381         free(paramstore);
1382         paramstore = NULL;
1383     }
1384 }
1385 
1386 #if defined(ADOLC_TRACK_ACTIVITY)
1387 
1388 char const* const StoreManagerLocintBlock::nowhere = NULL;
1389 
StoreManagerLocintBlock(double * & storePtr,char * & actStorePtr,size_t & size,size_t & numlives)1390 StoreManagerLocintBlock::StoreManagerLocintBlock(double * &storePtr, char* &actStorePtr, size_t &size, size_t &numlives) :
1391     storePtr(storePtr),
1392     actStorePtr(actStorePtr),
1393     activityTracking(1),
1394     maxsize(size),
1395     currentfill(numlives)
1396 #ifdef ADOLC_LOCDEBUG
1397     ,ensure_blockCallsSinceLastConsolidateBlocks(0)
1398 #endif
1399   {
1400     indexFree.clear();
1401 #ifdef ADOLC_LOCDEBUG
1402     std::cerr << "StoreManagerIntegerBlock::StoreManagerIntegerBlock()\n";
1403 #endif
1404 }
1405 
StoreManagerLocintBlock(const StoreManagerLocintBlock * const stm,double * & storePtr,char * & actStorePtr,size_t & size,size_t & numlives)1406 StoreManagerLocintBlock::StoreManagerLocintBlock(
1407     const StoreManagerLocintBlock *const stm,
1408     double * &storePtr, char * &actStorePtr, size_t &size, size_t &numlives) :
1409     storePtr(storePtr),
1410 #if defined(ADOLC_TRACK_ACTIVITY)
1411     actStorePtr(actStorePtr),
1412     activityTracking(1),
1413 #endif
1414     maxsize(size),
1415     currentfill(numlives)
1416 #ifdef ADOLC_LOCDEBUG
1417     ,ensure_blockCallsSinceLastConsolidateBlocks(0)
1418 #endif
1419   {
1420 #ifdef ADOLC_LOCDEBUG
1421     std::cerr << "StoreManagerInteger::StoreManagerInteger()\n";
1422 #endif
1423     indexFree.clear();
1424     forward_list<struct FreeBlock>::const_iterator iter = stm->indexFree.begin();
1425     for (; iter != stm->indexFree.end(); iter++)
1426 	indexFree.emplace_front( *iter );
1427 }
1428 #endif
1429 
StoreManagerLocintBlock(double * & storePtr,size_t & size,size_t & numlives)1430 StoreManagerLocintBlock::StoreManagerLocintBlock(double * &storePtr, size_t &size, size_t &numlives) :
1431     storePtr(storePtr),
1432 #if defined(ADOLC_TRACK_ACTIVITY)
1433     activityTracking(0),
1434     actStorePtr(const_cast<char*&>(nowhere)),
1435 #endif
1436     maxsize(size),
1437     currentfill(numlives)
1438 #ifdef ADOLC_LOCDEBUG
1439     ,ensure_blockCallsSinceLastConsolidateBlocks(0)
1440 #endif
1441   {
1442     indexFree.clear();
1443 #ifdef ADOLC_LOCDEBUG
1444     std::cerr << "StoreManagerIntegerBlock::StoreManagerIntegerBlock()\n";
1445 #endif
1446 }
1447 
~StoreManagerLocintBlock()1448 StoreManagerLocintBlock::~StoreManagerLocintBlock()
1449 {
1450 #ifdef ADOLC_LOCDEBUG
1451     std::cerr << "StoreManagerIntegerBlock::~StoreManagerIntegerBlock()\n";
1452 #endif
1453     if (storePtr != NULL) {
1454      delete[] storePtr;
1455      storePtr = NULL;
1456     }
1457     if (!indexFree.empty() ) {
1458 	indexFree.clear();
1459     }
1460 #if defined(ADOLC_TRACK_ACTIVITY)
1461     if (activityTracking && actStorePtr) {
1462 	delete[] actStorePtr;
1463     }
1464 #endif
1465     maxsize = 0;
1466     currentfill = 0;
1467 }
1468 
StoreManagerLocintBlock(const StoreManagerLocintBlock * const stm,double * & storePtr,size_t & size,size_t & numlives)1469 StoreManagerLocintBlock::StoreManagerLocintBlock(
1470     const StoreManagerLocintBlock *const stm,
1471     double * &storePtr, size_t &size, size_t &numlives) :
1472     storePtr(storePtr),
1473 #if defined(ADOLC_TRACK_ACTIVITY)
1474     activityTracking(0),
1475     actStorePtr(const_cast<char*&>(nowhere)),
1476 #endif
1477     maxsize(size),
1478     currentfill(numlives)
1479 #ifdef ADOLC_LOCDEBUG
1480     ,ensure_blockCallsSinceLastConsolidateBlocks(0)
1481 #endif
1482   {
1483 #ifdef ADOLC_LOCDEBUG
1484     std::cerr << "StoreManagerInteger::StoreManagerInteger()\n";
1485 #endif
1486     indexFree.clear();
1487     forward_list<struct FreeBlock>::const_iterator iter = stm->indexFree.begin();
1488     for (; iter != stm->indexFree.end(); iter++)
1489 	indexFree.emplace_front( *iter );
1490 }
1491 
1492 
next_loc()1493 locint StoreManagerLocintBlock::next_loc() {
1494     if ( indexFree.empty() )
1495 	grow();
1496 
1497     struct FreeBlock &front = indexFree.front();
1498     locint const result = front.next;
1499     if (--front.size == 0) {
1500 	if (next(indexFree.cbegin()) == indexFree.cend()) {
1501             front.next++;
1502 	    grow();
1503 	} else
1504           indexFree.pop_front();
1505     } else
1506         front.next++;
1507 
1508     ++currentfill;
1509 
1510 #ifdef ADOLC_LOCDEBUG
1511     std::cerr << "StoreManagerLocintBlock::next_loc: result: " << result << " fill: " << size() << "max: " << maxSize() << endl;
1512     forward_list<struct FreeBlock>::iterator iter = indexFree.begin();
1513     for( ; iter != indexFree.end(); iter++ )
1514        std::cerr << "INDEXFELD ( " << iter->next << " , " << iter->size << ")" << endl;
1515 #endif
1516 
1517     return result;
1518 }
1519 
ensure_block(size_t n)1520 void StoreManagerLocintBlock::ensure_block(size_t n) {
1521     bool found = false;
1522 #ifdef ADOLC_LOCDEBUG
1523     ++ensure_blockCallsSinceLastConsolidateBlocks;
1524     std::cerr << "StoreManagerLocintBlock::ensure_Block: required " << n << " ... ";
1525     std::cerr << "searching for big enough block " << endl;
1526 #endif
1527     if (maxSize()-size()>n) {
1528       if (indexFree.front().size>=n) found = true;
1529       if ((!found) && ((double(maxSize())/double(size()))>gcTriggerRatio() || maxSize()>gcTriggerMaxSize())) {
1530         consolidateBlocks();
1531 #ifdef ADOLC_LOCDEBUG
1532         std::cerr << "ADOLC: GC called consolidateBlocks because " << maxSize() << "/" << size() << ">" << gcTriggerRatio() << " or " << maxSize() << ">" << gcTriggerMaxSize() << " after " << ensure_blockCallsSinceLastConsolidateBlocks << std::endl;
1533         ensure_blockCallsSinceLastConsolidateBlocks=0;
1534 #endif
1535         forward_list<struct FreeBlock>::iterator
1536             biter = indexFree.before_begin(),
1537             iter = indexFree.begin();
1538         for (; iter != indexFree.end() ; biter++, iter++ ) {
1539           if ( iter->size >= n) {
1540             if (iter != indexFree.begin() ) {
1541               indexFree.emplace_front(*iter);
1542               indexFree.erase_after(biter);
1543             }
1544             found = true;
1545             break;
1546           }
1547         }
1548       }
1549     }
1550     if (!found) {
1551 #ifdef ADOLC_LOCDEBUG
1552 	std::cerr << "no big enough block...growing " << endl;
1553 #endif
1554 	grow(n);
1555     }
1556 
1557 #ifdef ADOLC_LOCDEBUG
1558     std::cerr << "StoreManagerLocintBlock::ensure_Block: " << " fill: " << size() << "max: " << maxSize() <<  " ensure_Block (" << n << ")" << endl;
1559     forward_list<struct FreeBlock>::iterator iter = indexFree.begin();
1560     for( ; iter != indexFree.end(); iter++ )
1561 	std::cerr << "INDEXFELD ( " << iter->next << " , " << iter->size << ")" << endl;
1562 #endif
1563 }
1564 
grow(size_t minGrow)1565 void StoreManagerLocintBlock::grow(size_t minGrow) {
1566     // first figure out what eventual size we want
1567     size_t const oldMaxsize = maxsize;
1568 
1569     if (maxsize == 0){
1570         maxsize = initialSize;
1571     } else {
1572 	maxsize *= 2;
1573     }
1574 
1575     if (minGrow > 0) {
1576 	while (maxsize - oldMaxsize < minGrow) {
1577 	    maxsize *= 2;
1578 	}
1579     }
1580 
1581     if (maxsize > std::numeric_limits<locint>::max()) {
1582       // encapsulate this error message
1583       fprintf(DIAG_OUT,"\nADOL-C error:\n");
1584       fprintf(DIAG_OUT,"maximal number (%u) of live active variables exceeded\n\n",
1585            std::numeric_limits<locint>::max());
1586       adolc_exit(-3,"",__func__,__FILE__,__LINE__);
1587     }
1588 
1589 #ifdef ADOLC_LOCDEBUG
1590     // index 0 is not used, means one slot less
1591     std::cerr << "StoreManagerIntegerBlock::grow(): increase size from " << oldMaxsize
1592       << " to " << maxsize << " entries (currently " << size() << " entries used)\n";
1593 #endif
1594 
1595     double *const oldStore = storePtr;
1596 #if defined(ADOLC_TRACK_ACTIVITY)
1597     char * oldactStore;
1598     if (activityTracking)
1599 	oldactStore = actStorePtr;
1600 #endif
1601 #if defined(ADOLC_LOCDEBUG)
1602     std::cerr << "StoreManagerInteger::grow(): allocate " << maxsize * sizeof(double) << " B doubles\n";
1603 #endif
1604     storePtr = new double[maxsize];
1605     assert(storePtr);
1606     memset(storePtr, 0, maxsize*sizeof(double));
1607 #if defined(ADOLC_TRACK_ACTIVITY)
1608     if (activityTracking) {
1609 	actStorePtr = new char[maxsize];
1610 	memset(actStorePtr,0,maxsize*sizeof(char));
1611     }
1612 #endif
1613 
1614     if (oldStore != NULL) { // not the first time
1615 #if defined(ADOLC_LOCDEBUG)
1616       std::cerr << "StoreManagerInteger::grow(): copy values\n";
1617 #endif
1618 
1619       memcpy(storePtr, oldStore, oldMaxsize*sizeof(double));
1620 #if defined(ADOLC_TRACK_ACTIVITY)
1621       if (activityTracking) {
1622 	  memcpy(actStorePtr, oldactStore, oldMaxsize*sizeof(char));
1623       }
1624 #endif
1625 
1626 #if defined(ADOLC_LOCDEBUG)
1627       std::cerr << "StoreManagerInteger::grow(): free " << oldMaxsize * sizeof(double) << "\n";
1628 #endif
1629       delete [] oldStore;
1630 #if defined(ADOLC_TRACK_ACTIVITY)
1631       if (activityTracking) {
1632 	  delete[] oldactStore;
1633       }
1634 #endif
1635 
1636     }
1637 
1638     bool foundTail = false;
1639     forward_list<struct FreeBlock>::iterator
1640         biter = indexFree.before_begin(),
1641         iter = indexFree.begin();
1642     for (; iter != indexFree.end() ; biter++,iter++ ) {
1643          if (iter->next + iter->size == oldMaxsize ) {
1644 	     iter->size += (maxsize - oldMaxsize);
1645 	      indexFree.emplace_front(*iter);
1646 	      indexFree.erase_after(biter);
1647 	      foundTail = true;
1648 	      break;
1649          }
1650     }
1651 
1652     if (! foundTail) {
1653 	indexFree.emplace_front(
1654 #if defined(_MSC_VER) && _MSC_VER <= 1800
1655 		FreeBlock(
1656 #endif
1657 		oldMaxsize,(maxsize - oldMaxsize)
1658 #if defined(_MSC_VER) && _MSC_VER <= 1800
1659 		)
1660 #endif
1661 		);
1662     }
1663 
1664     biter = indexFree.before_begin();
1665     iter = indexFree.begin();
1666     while (iter != indexFree.end()) {
1667          if (iter->size == 0) {
1668              indexFree.erase_after(biter); // don't leave 0 blocks around
1669              iter = next(biter);
1670          }
1671 	 else {
1672              biter++;
1673 	     iter++;
1674          }
1675     }
1676 #ifdef ADOLC_LOCDEBUG
1677     std::cerr << "Growing:" << endl;
1678     iter = indexFree.begin();
1679     for( ; iter != indexFree.end(); iter++ )
1680        std::cerr << "INDEXFELD ( " << iter->next << " , " << iter->size << ")" << endl;
1681 #endif
1682 }
1683 
free_loc(locint loc)1684 void StoreManagerLocintBlock::free_loc(locint loc) {
1685     assert( loc < maxsize);
1686 
1687     struct FreeBlock &front = indexFree.front();
1688     if ((loc+1 == front.next)
1689         || (front.next + front.size == loc)) {
1690 	front.size++;
1691 	if (loc + 1 == front.next)
1692 	    front.next = loc;
1693     }
1694     else {
1695          indexFree.emplace_front(
1696 #if defined(_MSC_VER) && _MSC_VER <= 1800
1697 		FreeBlock(
1698 #endif
1699 			 loc,1
1700 #if defined(_MSC_VER) && _MSC_VER <= 1800
1701 			 )
1702 #endif
1703 			 );
1704     }
1705 
1706     --currentfill;
1707 #ifdef ADOLC_LOCDEBUG
1708     std::cerr << "free_loc: " << loc << " fill: " << size() << "max: " << maxSize() << endl;
1709     forward_list<struct FreeBlock>::iterator iter = indexFree.begin();
1710     for( ; iter != indexFree.end(); iter++ )
1711        std::cerr << "INDEXFELD ( " << iter->next << " , " << iter->size << ")" << endl;
1712 #endif
1713 }
1714 
ensureContiguousLocations(size_t n)1715 void ensureContiguousLocations(size_t n) {
1716     ADOLC_OPENMP_THREAD_NUMBER;
1717     ADOLC_OPENMP_GET_THREAD_NUMBER;
1718     ADOLC_GLOBAL_TAPE_VARS.storeManagerPtr->ensure_block(n);
1719 }
1720 
setStoreManagerControl(double gcTriggerRatio,size_t gcTriggerMaxSize)1721 void setStoreManagerControl(double gcTriggerRatio, size_t gcTriggerMaxSize) {
1722   ADOLC_OPENMP_THREAD_NUMBER;
1723   ADOLC_OPENMP_GET_THREAD_NUMBER;
1724   ADOLC_GLOBAL_TAPE_VARS.storeManagerPtr->setStoreManagerControl(gcTriggerRatio,gcTriggerMaxSize);
1725 }
1726 
consolidateBlocks()1727 void StoreManagerLocintBlock::consolidateBlocks() {
1728     indexFree.sort();
1729     forward_list<struct FreeBlock>::iterator
1730         iter = indexFree.begin(),
1731         niter = iter++;
1732     while (iter != indexFree.end()) {
1733 	if (niter->next + niter->size == iter->next) {
1734 	    niter->size += iter->size;
1735 	    indexFree.erase_after(niter);
1736 	    iter = next(niter);
1737 	} else {
1738 	    niter++;
1739 	    iter++;
1740 	}
1741     }
1742 #ifdef ADOLC_LOCDEBUG
1743     std::cerr << "StoreManagerLocintBlock::consolidateBlocks: " << " fill: " << size() << "max: " << maxSize() << endl;
1744     iter = indexFree.begin();
1745     for( ; iter != indexFree.end(); iter++ )
1746 	std::cerr << "INDEXFELD ( " << iter->next << " , " << iter->size << ")" << endl;
1747 #endif
1748 }
1749 
enableMinMaxUsingAbs()1750 void enableMinMaxUsingAbs() {
1751     ADOLC_OPENMP_THREAD_NUMBER;
1752     ADOLC_OPENMP_GET_THREAD_NUMBER;
1753 
1754     if (!isTaping())
1755 	ADOLC_GLOBAL_TAPE_VARS.nominmaxFlag = 1;
1756     else
1757 	fprintf(DIAG_OUT, "ADOL-C warning: "
1758 		"change from native Min/Max to using Abs during tracing "
1759 		"will lead to inconsistent results, not changing behaviour now\n"
1760 		"                "
1761 		"call %s before trace_on(tape_id) for the correct behaviour\n"
1762 		,__FUNCTION__);
1763 }
1764 
disableMinMaxUsingAbs()1765 void disableMinMaxUsingAbs() {
1766     ADOLC_OPENMP_THREAD_NUMBER;
1767     ADOLC_OPENMP_GET_THREAD_NUMBER;
1768 
1769     if (!isTaping())
1770 	ADOLC_GLOBAL_TAPE_VARS.nominmaxFlag = 0;
1771     else
1772 	fprintf(DIAG_OUT, "ADOL-C warning: "
1773 		"change from native Min/Max to using Abs during tracing "
1774 		"will lead to inconsistent results, not changing behaviour now\n"
1775 		"                "
1776 		"call %s after trace_off() for the correct behaviour\n"
1777 		,__FUNCTION__);
1778 }
1779 
1780 #include <adolc/adolc_fatalerror.h>
1781 
adolc_exit(int errorcode,const char * what,const char * function,const char * file,int line)1782 void adolc_exit(int errorcode, const char *what, const char* function, const char *file, int line) {
1783     throw FatalError(errorcode, what, function, file, line);
1784 }
1785 
1786 /* Only called during stop_trace() via save_params() */
free_all_taping_params()1787 void free_all_taping_params() {
1788     size_t np;
1789     ADOLC_OPENMP_THREAD_NUMBER;
1790     ADOLC_OPENMP_GET_THREAD_NUMBER;
1791 
1792     np = ADOLC_CURRENT_TAPE_INFOS.stats[NUM_PARAM];
1793     while ( np > 0 )
1794         ADOLC_GLOBAL_TAPE_VARS.paramStoreMgrPtr->free_loc(--np);
1795 }
1796 
setStoreManagerType(unsigned char type)1797 void setStoreManagerType(unsigned char type) {
1798     ADOLC_OPENMP_THREAD_NUMBER;
1799     ADOLC_OPENMP_GET_THREAD_NUMBER;
1800 
1801     if (ADOLC_GLOBAL_TAPE_VARS.storeManagerPtr->storeType() != type) {
1802         if (ADOLC_GLOBAL_TAPE_VARS.numLives == 0) {
1803             ADOLC_GLOBAL_TAPE_VARS.reallocStore(type);
1804         } else {
1805             fprintf(DIAG_OUT,"ADOL-C-warning: called %s after allocating %d active variables\n"
1806                     "***  WILL NOT CHANGE ***\nto change type deallocate all active variables\n"
1807                     "continuing ...\n"
1808                     , __func__, ADOLC_GLOBAL_TAPE_VARS.numLives);
1809         }
1810     } else {
1811             fprintf(DIAG_OUT,"ADOL-C-warning: called %s with same type as before\n"
1812                     "***  NO CHANGE ***\ncontinuing ...\n",__func__);
1813     }
1814 }
1815 
reallocStore(unsigned char type)1816 void GlobalTapeVarsCL::reallocStore(unsigned char type) {
1817     if (storeManagerPtr != NULL)
1818         delete storeManagerPtr;
1819 
1820     store = NULL;
1821 #if defined(ADOLC_TRACK_ACTIVITY)
1822     actStore = NULL;
1823 #endif
1824     storeSize = 0;
1825     numLives = 0;
1826     switch (type) {
1827         case ADOLC_LOCATION_BLOCKS:
1828 #if defined(ADOLC_TRACK_ACTIVITY)
1829             storeManagerPtr = new StoreManagerLocintBlock(store, actStore, storeSize, numLives);
1830 #else
1831             storeManagerPtr = new StoreManagerLocintBlock(store, storeSize, numLives);
1832 #endif
1833             break;
1834         case ADOLC_LOCATION_SINGLETONS:
1835 #if defined(ADOLC_TRACK_ACTIVITY)
1836             storeManagerPtr = new StoreManagerLocint(store, actStore, storeSize, numLives);
1837 #else
1838             storeManagerPtr = new StoreManagerLocint(store, storeSize, numLives);
1839 #endif
1840             break;
1841     }
1842 }
1843