ADMB Documentation  11.1x.2738
 All Classes Files Functions Variables Typedefs Friends Defines
gradstak.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: gradstak.cpp 2677 2014-11-17 22:40:31Z 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) || defined(__MINGW64__)
00067   #include <cassert>
00068   #include <climits>
00069 #endif
00070 
00071 #ifdef _MSC_VER
00072   #ifdef _M_X64
00073   typedef __int64 ssize_t;
00074   #else
00075   typedef int ssize_t;
00076   #endif
00077   #ifndef SSIZE_MAX
00078     #define SSIZE_MAX INT_MAX
00079   #endif
00080 #endif
00081 
00082 char lastchar(char *);
00083 char ad_random_part[6]="tmp";
00084 
00085 void fill_ad_random_part(void)
00086 {
00087 /*
00088   time_t t,tt;
00089   time(&t);
00090   tt=t;
00091   int div=1;
00092   for (int i=0;i<6;i++)
00093   {
00094     ad_random_part[i]=(tt/div)%10+48;
00095     div*=10;
00096   }
00097 */
00098 }
00102 grad_stack::grad_stack()
00103 {
00104   gradient_structure::TOTAL_BYTES = 0;
00105   gradient_structure::PREVIOUS_TOTAL_BYTES=0;
00106   true_length = gradient_structure::GRADSTACK_BUFFER_SIZE;
00107   length = true_length;
00108 
00109 #ifndef OPT_LIB
00110   assert(length > 0);
00111 #endif
00112 
00113   true_ptr_first = new grad_stack_entry[length];
00114   if (!true_ptr_first)
00115   {
00116     cerr << "Memory allocation error in grad_stack constructor\n"
00117          << " trying to allocate grad_stack_entry[" << length << "] array.\n";
00118     ad_exit(1);
00119   }
00120 
00121   test_the_pointer();
00122 
00123   ptr_first=true_ptr_first;
00124   ptr = ptr_first;
00125   ptr_last=ptr_first+(length-1);
00126   //table=new lvector(-128,250);
00127 
00128   _GRADFILE_PTR = -1; // set to illegal value for later checking
00129   end_pos  = 0;
00130   end_pos1 = 0;
00131   end_pos2 = 0;
00132 
00133   char* path = getenv("ADTMP"); // NULL if not defined
00134 
00135 #if defined(USE_ADPVM)
00136   adstring string_path;
00137   if (path) string_path=path;
00138   int on=0;
00139   int nopt=0;
00140   adstring currdir;
00141   ad_getcd(currdir);
00142   if (ad_comm::pvm_manager)
00143   {
00144     if ((on = option_match(ad_comm::argc, ad_comm::argv, "-slave", nopt)) > -1)
00145     {
00146       if (nopt ==1)
00147       {
00148         int ierr=make_sub_directory(ad_comm::argv[on+1]);
00149         ad_comm::subdir=ad_comm::argv[on+1];
00150         string_path+=ad_comm::subdir;
00151         path=(char*) string_path;
00152       }
00153       else
00154       {
00155         cerr << "Wrong number of options to -slave -- must be 1"
00156             " you have " << nopt << endl;
00157         ad_exit(1);
00158       }
00159     }
00160   }
00161 #endif
00162 
00163   if (path != NULL)
00164   {
00165 #if !defined (_WIN32)
00166     sprintf(&gradfile_name1[0],"%s/gradfil1.%s", path, ad_random_part);
00167 #else
00168     if (lastchar(path) != '\\')
00169     {
00170       sprintf(&gradfile_name1[0], "%s\\gradfil1.%s", path, ad_random_part);
00171     }
00172     else
00173     {
00174       sprintf(&gradfile_name1[0], "%sgradfil1.%s", path, ad_random_part);
00175     }
00176 #endif
00177   }
00178   else
00179   {
00180     sprintf(&gradfile_name1[0], "gradfil1.%s", ad_random_part);
00181   }
00182 
00183   path = getenv("ADTMP1"); // NULL if not defined
00184 #if defined(USE_ADPVM)
00185   adstring string_path2;
00186   if (path) string_path2=path;
00187   string_path2+=ad_comm::subdir;
00188   path=(char*) string_path2;
00189 #endif
00190   if (path != NULL)
00191   {
00192 #if !defined (_WIN32)
00193     if (strlen(path) > 0)
00194     {
00195       sprintf(&var_store_file_name[0],"%s/varssave.%s",path, ad_random_part);
00196       sprintf(&gradfile_name2[0],"%s/gradfil2.%s", path, ad_random_part);
00197     }
00198     else
00199     {
00200       sprintf(&var_store_file_name[0],"varssave.tmp");
00201       sprintf(&gradfile_name2[0],"gradfil2.tmp");
00202     }
00203 #else
00204     if (lastchar(path)!='\\')
00205     {
00206       sprintf(&gradfile_name2[0], "%s\\gradfil2.%s", path, ad_random_part);
00207       sprintf(&var_store_file_name[0], "%s\\varssave.%s", path, ad_random_part);
00208     }
00209     else
00210     {
00211       sprintf(&gradfile_name2[0], "%sgradfil2.%s", path, ad_random_part);
00212       sprintf(&var_store_file_name[0], "%svarssave.%s", path, ad_random_part);
00213     }
00214 #endif
00215   }
00216   else
00217   {
00218     sprintf(&gradfile_name2[0], "gradfil2.%s", ad_random_part);
00219     sprintf(&var_store_file_name[0], "varssave.%s", ad_random_part);
00220   }
00221 
00222   create_gradfile();
00223 
00224   strcpy(gradfile_name, gradfile_name1);
00225   _GRADFILE_PTR = _GRADFILE_PTR1;
00226 }
00230 grad_stack::~grad_stack()
00231 {
00232   const int repfs = option_match(ad_comm::argc, ad_comm::argv, "-fsize");
00233   if (ad_comm::global_logfile && repfs)
00234   {
00235      off_t pos = lseek(_GRADFILE_PTR1, 0, SEEK_END);
00236      *ad_comm::global_logfile << "size of file " << gradfile_name1
00237        << " = " << pos << endl;
00238 
00239      pos = lseek(_GRADFILE_PTR2, 0, SEEK_END);
00240      *ad_comm::global_logfile << "size of file " << gradfile_name2
00241        << " = " << pos << endl;
00242 
00243      pos = lseek(_VARSSAV_PTR, 0, SEEK_END);
00244      *ad_comm::global_logfile << "size of file " << var_store_file_name
00245        << " = " << pos << endl;
00246   }
00247   if (close(_GRADFILE_PTR1))
00248   {
00249     cerr << "Error closing file " << gradfile_name1 << "\n";
00250   }
00251   if (close(_GRADFILE_PTR2))
00252   {
00253     cerr << "Error closing file " << gradfile_name2 << "\n";
00254   }
00255   if (close(_VARSSAV_PTR))
00256   {
00257     cerr << "Error closing file " << var_store_file_name << "\n";
00258   }
00259 #if !defined (_MSC_VER)
00260   unlink(gradfile_name1);
00261   unlink(gradfile_name2);
00262   unlink(var_store_file_name);
00263 #else
00264   remove(gradfile_name1);
00265   remove(gradfile_name2);
00266   remove(var_store_file_name);
00267 #endif
00268 
00269   delete [] true_ptr_first;
00270   true_ptr_first = 0;
00271 }
00272 
00277   void  grad_stack::write_grad_stack_buffer()
00278   {
00279     #ifdef GRAD_DIAG
00280       cout << "Grad_stack size exceeded\n ";
00281       cout << "Writing to temporary file -- \n";
00282     #endif
00283 
00284     ptr--;
00285 
00286     #ifdef GRAD_DIAG
00287       {
00288       off_t lpos = lseek(_GRADFILE_PTR,0L,SEEK_CUR);
00289       cout << "Offset in file before write is " << lpos
00290                               << " bytes from the beginning\n";
00291       }
00292     #endif
00293 
00294     // if the buffer is really large only write the end of it
00295     set_gbuffer_pointers();
00296     size_t nbw = sizeof(grad_stack_entry) * length;
00297 
00298     //char * ttmp = (char *) ptr_first; ttmp--;
00299 
00300     // save the current end of file in case we can't write the whole buffer
00301     end_pos = lseek(_GRADFILE_PTR,0L,SEEK_CUR);
00302 #if defined(_MSC_VER)
00303     ssize_t ierr = write(_GRADFILE_PTR, ptr_first, nbw);
00304 #else
00305   #ifdef __MINGW64__
00306     assert(nbw <= UINT_MAX);
00307     ssize_t ierr = write(_GRADFILE_PTR, (char*)ptr_first, (unsigned int)nbw);
00308   #else
00309     ssize_t ierr = write(_GRADFILE_PTR, (char*)ptr_first, nbw);
00310   #endif
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(_MSC_VER)
00325       ierr = write(_GRADFILE_PTR, ptr_first, nbw);
00326 #else
00327   #ifdef __MINGW64__
00328       assert(nbw <= UINT_MAX);
00329       ierr = write(_GRADFILE_PTR, (char*)ptr_first, (unsigned int)nbw);
00330   #else
00331       ierr = write(_GRADFILE_PTR, (char*)ptr_first, nbw);
00332   #endif
00333 #endif
00334 
00335       if  (ierr != (ssize_t)nbw)
00336       {
00337         perror("Error writing to temporary gradient stack file");
00338         cerr <<"   File name: " << gradfile_name << "\n";
00339 #if defined(_MSC_VER)
00340         cerr <<"   File length: "
00341              << filelength(_GRADFILE_PTR)
00342              << " bytes.\n";
00343 #endif
00344         cerr <<"   Attempting to write " << nbw <<" bytes; wrote " << ierr
00345         << ".\n";
00346         exit(1);
00347       }
00348     }
00349     else
00350     {
00351       #ifdef GRAD_DIAG
00352       cout << "Wrote " << ierr << "bytes into temp. grad. file\n";
00353       #endif
00354     }
00355 
00356     #ifdef GRAD_DIAG
00357     {
00358       off_t lpos = lseek(gradient_structure::_GRADFILE_PTR,0L,SEEK_CUR);
00359       cout << "Offset in file after write is " << lpos
00360            << " bytes from the beginning\n";
00361     }
00362     #endif
00363     //keep track of the size of the grad_stack
00364     gradient_structure::TOTAL_BYTES+=nbw;
00365     ptr = ptr_first;
00366   }
00367 
00372 void grad_stack::create_gradfile()
00373 {
00374   #if defined (__TURBOC__)
00375    _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT |
00376        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00377    _VARSSAV_PTR=open(var_store_file_name, O_RDWR | O_CREAT |
00378        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00379   #elif defined (__ZTC__)
00380     _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT |
00381       O_TRUNC , S_IREAD | S_IWRITE);
00382     _VARSSAV_PTR=open(var_store_file_name, O_RDWR | O_CREAT
00383       | O_TRUNC,  S_IREAD | S_IWRITE);
00384   #elif defined (__NDPX__)
00385     _GRADFILE_PTR1=creat(gradfile_name1, O_RDWR);
00386      _VARSSAV_PTR=creat(var_store_file_name, O_RDWR);
00387   #elif defined (__WAT32__)
00388    _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT |
00389        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00390    _VARSSAV_PTR=open(var_store_file_name, O_RDWR | O_CREAT |
00391        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00392   #else
00393     _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT | O_TRUNC |
00394       O_BINARY , 0777);
00395     _VARSSAV_PTR=open(var_store_file_name, O_RDWR |
00396       O_CREAT | O_TRUNC | O_BINARY, 0777);
00397   #endif
00398 
00399   if (_GRADFILE_PTR1 == -1)
00400   {
00401     if (ad_printf) (*ad_printf)("Error opening temporary gradient file"
00402      " %s\n",gradfile_name1);
00403     ad_exit(1);
00404   }
00405 
00406   if (_VARSSAV_PTR == -1)
00407   {
00408     perror("Error opening temporary gradient file");
00409     cerr <<"  Attempting to open " << var_store_file_name <<"\n";
00410     ad_exit(1);
00411   }
00412 
00413   #if defined (__TURBOC__)
00414     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00415       O_BINARY, S_IREAD | S_IWRITE);
00416   #elif defined (__ZTC__)
00417     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC ,
00418       S_IREAD | S_IWRITE);
00419   #elif defined (__NDPX__)
00420     _GRADFILE_PTR2=creat(gradfile_name2, O_RDWR);
00421   #elif defined (_MSC_VER)
00422     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00423       O_BINARY, S_IREAD | S_IWRITE);
00424   #elif defined (__WAT32__)
00425     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00426       O_BINARY, S_IREAD | S_IWRITE);
00427   #else
00428     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00429       O_BINARY , 0777);
00430   #endif
00431 
00432   if (_GRADFILE_PTR2 == -1)
00433   {
00434     perror("Error opening temporary gradient file");
00435     cerr <<"  Attempting to open " << gradfile_name2 <<"\n";
00436     ad_exit(1);
00437   }
00438 }
00443 void grad_stack::increment_current_gradfile_ptr()
00444 {
00445   if (_GRADFILE_PTR == _GRADFILE_PTR2)
00446   {
00447     cerr << "Attempted to open a third gradient file -- There is\n"
00448       "probably no more room on the TMP1 (if defined) device\n"
00449       "if possible set TMP1 environment string to a device with more room\n";
00450     ad_exit(1);
00451   }
00452    strcpy(gradfile_name, gradfile_name2);
00453   _GRADFILE_PTR = _GRADFILE_PTR2;
00454 }
00459 int grad_stack::decrement_current_gradfile_ptr()
00460 {
00461   if (_GRADFILE_PTR == _GRADFILE_PTR1)
00462   {
00463     return -1;
00464   }
00465 
00466   strcpy(gradfile_name, gradfile_name1);
00467   _GRADFILE_PTR = _GRADFILE_PTR1;
00468 
00469   return 0;
00470 }
00471 #ifdef _MSC_VER
00472 int grad_stack::gradfile_handle()
00473 #else
00474 int& grad_stack::gradfile_handle()
00475 #endif
00476 {
00477   return _GRADFILE_PTR;
00478 }
00483 char* grad_stack::get_gradfile_name()
00484 {
00485   return gradfile_name;
00486 }
00491 void grad_stack::set_gbuffer_pointers()
00492 {
00493   if (length > 10000L)
00494   {
00495     //make the buffer end_buf_size
00496     unsigned int end_buf_size=5000L;
00497     ptr_first+=length-end_buf_size;
00498     length=end_buf_size;
00499   }
00500 }
00505 void grad_stack::set_gradient_stack0(void (* func)(void),double * dep_addr)
00506 {
00507 #ifdef NO_DERIVS
00508   if (!gradient_structure::no_derivatives)
00509   {
00510 #endif
00511     if (ptr > ptr_last)
00512     {
00513       // current buffer is full -- write it to disk and reset pointer
00514       // and counter
00515       this->write_grad_stack_buffer();
00516     }
00517     ptr->func = func;
00518     ptr->dep_addr = dep_addr;
00519     ptr++;
00520 #ifdef NO_DERIVS
00521   }
00522 #endif
00523 }