ADMB Documentation  11.2.2853
 All Classes Files Functions Variables Typedefs Friends Defines
gradstak.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: gradstak.cpp 2817 2014-12-18 06:23:30Z johnoel $
00003  *
00004  * Author: David Fournier
00005  * Copyright (c) 2008-2012 Regents of the University of California
00006  */
00011 #include <iostream>
00012 using namespace std;
00013 #include <fcntl.h>
00014 #include "fvar.hpp"
00015 #include <adstring.hpp>
00016 
00017 #if defined (__WAT32__)
00018   #include <io.h>
00019 #endif
00020 
00021 #ifdef _MSC_VER
00022   #define lseek _lseek
00023   #define  read _read
00024   #define write _write
00025   #define open _open
00026   #define close _close
00027   #include <sys\stat.h>
00028 #else
00029   #include <sys/stat.h>
00030   #include <sys/types.h>
00031   #include <unistd.h>
00032 #endif
00033 
00034 #if defined(__TURBOC__)
00035   #pragma hdrstop
00036   #include <iostream.h>
00037   #include <iomanip.h>
00038   #include <sys\stat.h>
00039 #endif
00040 
00041 #ifdef __ZTC__
00042   #include <iostream.hpp>
00043   #define S_IREAD 0000400
00044   #define S_IWRITE 0000200
00045 #endif
00046 
00047 #ifdef __NDPX__
00048   #define O_RDONLY 0
00049   #define O_WRONLY 1
00050   #define O_RDWR 2
00051   extern "C"
00052   {
00053     int lseek(int, int, int);
00054     int open(const char*, int);
00055     int creat(const char*, int);
00056     int close(int);
00057     int write(int, char*, int);
00058   };
00059 #endif
00060 
00061 #include <stdlib.h>
00062 #include <stdio.h>
00063 #include <string.h>
00064 #include <time.h>
00065 
00066 #if !defined(OPT_LIB)
00067   #include <cassert>
00068   #include <climits>
00069 #endif
00070 #if defined(__MINGW64__) || (defined(_MSC_VER) && defined(_M_X64))
00071   #include <cassert>
00072   #include <climits>
00073 #endif
00074 
00075 #ifdef _MSC_VER
00076   #ifdef _M_X64
00077   typedef __int64 ssize_t;
00078   #else
00079   typedef int ssize_t;
00080   #endif
00081   #ifndef SSIZE_MAX
00082     #define SSIZE_MAX INT_MAX
00083   #endif
00084 #endif
00085 
00086 char lastchar(char *);
00087 char ad_random_part[6]="tmp";
00088 
00089 void fill_ad_random_part(void)
00090 {
00091 /*
00092   time_t t,tt;
00093   time(&t);
00094   tt=t;
00095   int div=1;
00096   for (int i=0;i<6;i++)
00097   {
00098     ad_random_part[i]=(tt/div)%10+48;
00099     div*=10;
00100   }
00101 */
00102 }
00106 grad_stack::grad_stack()
00107 {
00108   gradient_structure::TOTAL_BYTES = 0;
00109   gradient_structure::PREVIOUS_TOTAL_BYTES=0;
00110   true_length = gradient_structure::GRADSTACK_BUFFER_SIZE;
00111   length = true_length;
00112 
00113 #ifndef OPT_LIB
00114   assert(length > 0);
00115 #endif
00116 
00117   true_ptr_first = new grad_stack_entry[length];
00118   if (!true_ptr_first)
00119   {
00120     cerr << "Memory allocation error in grad_stack constructor\n"
00121          << " trying to allocate grad_stack_entry[" << length << "] array.\n";
00122     ad_exit(1);
00123   }
00124 
00125   test_the_pointer();
00126 
00127   ptr_first=true_ptr_first;
00128   ptr = ptr_first;
00129   ptr_last=ptr_first+(length-1);
00130   //table=new lvector(-128,250);
00131 
00132   _GRADFILE_PTR = -1; // set to illegal value for later checking
00133   end_pos  = 0;
00134   end_pos1 = 0;
00135   end_pos2 = 0;
00136 
00137   char* path = getenv("ADTMP"); // NULL if not defined
00138 
00139 #if defined(USE_ADPVM)
00140   adstring string_path;
00141   if (path) string_path=path;
00142   int on=0;
00143   int nopt=0;
00144   adstring currdir;
00145   ad_getcd(currdir);
00146   if (ad_comm::pvm_manager)
00147   {
00148     if ((on = option_match(ad_comm::argc, ad_comm::argv, "-slave", nopt)) > -1)
00149     {
00150       if (nopt ==1)
00151       {
00152         int ierr=make_sub_directory(ad_comm::argv[on+1]);
00153         ad_comm::subdir=ad_comm::argv[on+1];
00154         string_path+=ad_comm::subdir;
00155         path=(char*) string_path;
00156       }
00157       else
00158       {
00159         cerr << "Wrong number of options to -slave -- must be 1"
00160             " you have " << nopt << endl;
00161         ad_exit(1);
00162       }
00163     }
00164   }
00165 #endif
00166 
00167   if (path != NULL)
00168   {
00169 #if !defined (_WIN32)
00170     sprintf(&gradfile_name1[0],"%s/gradfil1.%s", path, ad_random_part);
00171 #else
00172     if (lastchar(path) != '\\')
00173     {
00174       sprintf(&gradfile_name1[0], "%s\\gradfil1.%s", path, ad_random_part);
00175     }
00176     else
00177     {
00178       sprintf(&gradfile_name1[0], "%sgradfil1.%s", path, ad_random_part);
00179     }
00180 #endif
00181   }
00182   else
00183   {
00184     sprintf(&gradfile_name1[0], "gradfil1.%s", ad_random_part);
00185   }
00186 
00187   path = getenv("ADTMP1"); // NULL if not defined
00188 #if defined(USE_ADPVM)
00189   adstring string_path2;
00190   if (path) string_path2=path;
00191   string_path2+=ad_comm::subdir;
00192   path=(char*) string_path2;
00193 #endif
00194   if (path != NULL)
00195   {
00196 #if !defined (_WIN32)
00197     if (strlen(path) > 0)
00198     {
00199       sprintf(&var_store_file_name[0],"%s/varssave.%s",path, ad_random_part);
00200       sprintf(&gradfile_name2[0],"%s/gradfil2.%s", path, ad_random_part);
00201     }
00202     else
00203     {
00204       sprintf(&var_store_file_name[0],"varssave.tmp");
00205       sprintf(&gradfile_name2[0],"gradfil2.tmp");
00206     }
00207 #else
00208     if (lastchar(path)!='\\')
00209     {
00210       sprintf(&gradfile_name2[0], "%s\\gradfil2.%s", path, ad_random_part);
00211       sprintf(&var_store_file_name[0], "%s\\varssave.%s", path, ad_random_part);
00212     }
00213     else
00214     {
00215       sprintf(&gradfile_name2[0], "%sgradfil2.%s", path, ad_random_part);
00216       sprintf(&var_store_file_name[0], "%svarssave.%s", path, ad_random_part);
00217     }
00218 #endif
00219   }
00220   else
00221   {
00222     sprintf(&gradfile_name2[0], "gradfil2.%s", ad_random_part);
00223     sprintf(&var_store_file_name[0], "varssave.%s", ad_random_part);
00224   }
00225 
00226   create_gradfile();
00227 
00228   strcpy(gradfile_name, gradfile_name1);
00229   _GRADFILE_PTR = _GRADFILE_PTR1;
00230 }
00234 grad_stack::~grad_stack()
00235 {
00236   const int repfs = option_match(ad_comm::argc, ad_comm::argv, "-fsize");
00237   if (ad_comm::global_logfile && repfs)
00238   {
00239      off_t pos = lseek(_GRADFILE_PTR1, 0, SEEK_END);
00240      *ad_comm::global_logfile << "size of file " << gradfile_name1
00241        << " = " << pos << endl;
00242 
00243      pos = lseek(_GRADFILE_PTR2, 0, SEEK_END);
00244      *ad_comm::global_logfile << "size of file " << gradfile_name2
00245        << " = " << pos << endl;
00246 
00247      pos = lseek(_VARSSAV_PTR, 0, SEEK_END);
00248      *ad_comm::global_logfile << "size of file " << var_store_file_name
00249        << " = " << pos << endl;
00250   }
00251   if (close(_GRADFILE_PTR1))
00252   {
00253     cerr << "Error closing file " << gradfile_name1 << "\n";
00254   }
00255   if (close(_GRADFILE_PTR2))
00256   {
00257     cerr << "Error closing file " << gradfile_name2 << "\n";
00258   }
00259   if (close(_VARSSAV_PTR))
00260   {
00261     cerr << "Error closing file " << var_store_file_name << "\n";
00262   }
00263 #if !defined (_MSC_VER)
00264   unlink(gradfile_name1);
00265   unlink(gradfile_name2);
00266   unlink(var_store_file_name);
00267 #else
00268   remove(gradfile_name1);
00269   remove(gradfile_name2);
00270   remove(var_store_file_name);
00271 #endif
00272 
00273   delete [] true_ptr_first;
00274   true_ptr_first = 0;
00275 }
00276 
00281   void  grad_stack::write_grad_stack_buffer()
00282   {
00283     #ifdef GRAD_DIAG
00284       cout << "Grad_stack size exceeded\n ";
00285       cout << "Writing to temporary file -- \n";
00286     #endif
00287 
00288     ptr--;
00289 
00290     #ifdef GRAD_DIAG
00291       {
00292       off_t lpos = lseek(_GRADFILE_PTR,0L,SEEK_CUR);
00293       cout << "Offset in file before write is " << lpos
00294                               << " bytes from the beginning\n";
00295       }
00296     #endif
00297 
00298     // if the buffer is really large only write the end of it
00299     set_gbuffer_pointers();
00300     size_t nbw = sizeof(grad_stack_entry) * length;
00301 
00302     //char * ttmp = (char *) ptr_first; ttmp--;
00303 
00304     // save the current end of file in case we can't write the whole buffer
00305     end_pos = lseek(_GRADFILE_PTR,0L,SEEK_CUR);
00306 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00307     assert(nbw <= UINT_MAX);
00308     ssize_t ierr = write(_GRADFILE_PTR, ptr_first, (unsigned int)nbw);
00309 #else
00310     ssize_t ierr = write(_GRADFILE_PTR, ptr_first, nbw);
00311 #endif
00312 
00313 #ifndef OPT_LIB
00314   assert(nbw <= SSIZE_MAX);
00315 #endif
00316 
00317     if  (ierr != (ssize_t)nbw)
00318     {
00319        cout << "Wrote " << ierr <<" not " << nbw << endl;
00320       lseek(_GRADFILE_PTR,end_pos,SEEK_SET);
00321       //save the end of file for this file so we can reposition later
00322       end_pos1 = end_pos;
00323       increment_current_gradfile_ptr();
00324 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00325       assert(nbw <= UINT_MAX);
00326       ierr = write(_GRADFILE_PTR, ptr_first, (unsigned int)nbw);
00327 #else
00328       ierr = write(_GRADFILE_PTR, ptr_first, nbw);
00329 #endif
00330 
00331       if  (ierr != (ssize_t)nbw)
00332       {
00333         perror("Error writing to temporary gradient stack file");
00334         cerr <<"   File name: " << gradfile_name << "\n";
00335 #if defined(_MSC_VER)
00336         cerr <<"   File length: "
00337              << filelength(_GRADFILE_PTR)
00338              << " bytes.\n";
00339 #endif
00340         cerr <<"   Attempting to write " << nbw <<" bytes; wrote " << ierr
00341         << ".\n";
00342         exit(1);
00343       }
00344     }
00345     else
00346     {
00347       #ifdef GRAD_DIAG
00348       cout << "Wrote " << ierr << "bytes into temp. grad. file\n";
00349       #endif
00350     }
00351 
00352     #ifdef GRAD_DIAG
00353     {
00354       off_t lpos = lseek(gradient_structure::_GRADFILE_PTR,0L,SEEK_CUR);
00355       cout << "Offset in file after write is " << lpos
00356            << " bytes from the beginning\n";
00357     }
00358     #endif
00359     //keep track of the size of the grad_stack
00360     gradient_structure::TOTAL_BYTES+=nbw;
00361     ptr = ptr_first;
00362   }
00363 
00368 void grad_stack::create_gradfile()
00369 {
00370   #if defined (__TURBOC__)
00371    _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT |
00372        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00373    _VARSSAV_PTR=open(var_store_file_name, O_RDWR | O_CREAT |
00374        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00375   #elif defined (__ZTC__)
00376     _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT |
00377       O_TRUNC , S_IREAD | S_IWRITE);
00378     _VARSSAV_PTR=open(var_store_file_name, O_RDWR | O_CREAT
00379       | O_TRUNC,  S_IREAD | S_IWRITE);
00380   #elif defined (__NDPX__)
00381     _GRADFILE_PTR1=creat(gradfile_name1, O_RDWR);
00382      _VARSSAV_PTR=creat(var_store_file_name, O_RDWR);
00383   #elif defined (__WAT32__)
00384    _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT |
00385        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00386    _VARSSAV_PTR=open(var_store_file_name, O_RDWR | O_CREAT |
00387        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00388   #else
00389     _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT | O_TRUNC |
00390       O_BINARY , 0777);
00391     _VARSSAV_PTR=open(var_store_file_name, O_RDWR |
00392       O_CREAT | O_TRUNC | O_BINARY, 0777);
00393   #endif
00394 
00395   if (_GRADFILE_PTR1 == -1)
00396   {
00397     if (ad_printf) (*ad_printf)("Error opening temporary gradient file"
00398      " %s\n",gradfile_name1);
00399     ad_exit(1);
00400   }
00401 
00402   if (_VARSSAV_PTR == -1)
00403   {
00404     perror("Error opening temporary gradient file");
00405     cerr <<"  Attempting to open " << var_store_file_name <<"\n";
00406     ad_exit(1);
00407   }
00408 
00409   #if defined (__TURBOC__)
00410     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00411       O_BINARY, S_IREAD | S_IWRITE);
00412   #elif defined (__ZTC__)
00413     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC ,
00414       S_IREAD | S_IWRITE);
00415   #elif defined (__NDPX__)
00416     _GRADFILE_PTR2=creat(gradfile_name2, O_RDWR);
00417   #elif defined (_MSC_VER)
00418     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00419       O_BINARY, S_IREAD | S_IWRITE);
00420   #elif defined (__WAT32__)
00421     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00422       O_BINARY, S_IREAD | S_IWRITE);
00423   #else
00424     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00425       O_BINARY , 0777);
00426   #endif
00427 
00428   if (_GRADFILE_PTR2 == -1)
00429   {
00430     perror("Error opening temporary gradient file");
00431     cerr <<"  Attempting to open " << gradfile_name2 <<"\n";
00432     ad_exit(1);
00433   }
00434 }
00439 void grad_stack::increment_current_gradfile_ptr()
00440 {
00441   if (_GRADFILE_PTR == _GRADFILE_PTR2)
00442   {
00443     cerr << "Attempted to open a third gradient file -- There is\n"
00444       "probably no more room on the TMP1 (if defined) device\n"
00445       "if possible set TMP1 environment string to a device with more room\n";
00446     ad_exit(1);
00447   }
00448    strcpy(gradfile_name, gradfile_name2);
00449   _GRADFILE_PTR = _GRADFILE_PTR2;
00450 }
00455 int grad_stack::decrement_current_gradfile_ptr()
00456 {
00457   if (_GRADFILE_PTR == _GRADFILE_PTR1)
00458   {
00459     return -1;
00460   }
00461 
00462   strcpy(gradfile_name, gradfile_name1);
00463   _GRADFILE_PTR = _GRADFILE_PTR1;
00464 
00465   return 0;
00466 }
00467 #ifdef _MSC_VER
00468 int grad_stack::gradfile_handle()
00469 #else
00470 int& grad_stack::gradfile_handle()
00471 #endif
00472 {
00473   return _GRADFILE_PTR;
00474 }
00479 char* grad_stack::get_gradfile_name()
00480 {
00481   return gradfile_name;
00482 }
00487 void grad_stack::set_gbuffer_pointers()
00488 {
00489   if (length > 10000L)
00490   {
00491     //make the buffer end_buf_size
00492     unsigned int end_buf_size=5000L;
00493     ptr_first+=length-end_buf_size;
00494     length=end_buf_size;
00495   }
00496 }
00501 void grad_stack::set_gradient_stack0(void (* func)(void),double * dep_addr)
00502 {
00503 #ifdef NO_DERIVS
00504   if (!gradient_structure::no_derivatives)
00505   {
00506 #endif
00507     if (ptr > ptr_last)
00508     {
00509       // current buffer is full -- write it to disk and reset pointer
00510       // and counter
00511       this->write_grad_stack_buffer();
00512     }
00513     ptr->func = func;
00514     ptr->dep_addr = dep_addr;
00515     ptr++;
00516 #ifdef NO_DERIVS
00517   }
00518 #endif
00519 }