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