ADMB Documentation  11.5.3259
 All Classes Files Functions Variables Typedefs Friends Defines
gradstak.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id$
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 #ifdef DIAG
00126   test_the_pointer();
00127 #endif
00128 
00129   ptr_first=true_ptr_first;
00130   ptr = ptr_first;
00131   ptr_last=ptr_first+(length-1);
00132   //table=new lvector(-128,250);
00133 
00134   _GRADFILE_PTR = -1; // set to illegal value for later checking
00135   end_pos  = 0;
00136   end_pos1 = 0;
00137   end_pos2 = 0;
00138 
00139   char* path = getenv("ADTMP"); // NULL if not defined
00140 
00141 #if defined(USE_ADPVM)
00142   adstring string_path;
00143   if (path) string_path=path;
00144   int on=0;
00145   int nopt=0;
00146   adstring currdir;
00147   ad_getcd(currdir);
00148   if (ad_comm::pvm_manager)
00149   {
00150     if ((on = option_match(ad_comm::argc, ad_comm::argv, "-slave", nopt)) > -1)
00151     {
00152       if (nopt ==1)
00153       {
00154         int ierr=make_sub_directory(ad_comm::argv[on+1]);
00155         ad_comm::subdir=ad_comm::argv[on+1];
00156         string_path+=ad_comm::subdir;
00157         path=(char*) string_path;
00158       }
00159       else
00160       {
00161         cerr << "Wrong number of options to -slave -- must be 1"
00162             " you have " << nopt << endl;
00163         ad_exit(1);
00164       }
00165     }
00166   }
00167 #endif
00168 
00169   if (path != NULL && strlen(path) <= 45)
00170   {
00171 #if !defined (_WIN32)
00172     sprintf(&gradfile_name1[0],"%s/gradfil1.%s", path, ad_random_part);
00173 #else
00174     if (lastchar(path) != '\\')
00175     {
00176       sprintf(&gradfile_name1[0], "%s\\gradfil1.%s", path, ad_random_part);
00177     }
00178     else
00179     {
00180       sprintf(&gradfile_name1[0], "%sgradfil1.%s", path, ad_random_part);
00181     }
00182 #endif
00183   }
00184   else
00185   {
00186     sprintf(&gradfile_name1[0], "gradfil1.%s", ad_random_part);
00187   }
00188 
00189   path = getenv("ADTMP1"); // NULL if not defined
00190 #if defined(USE_ADPVM)
00191   adstring string_path2;
00192   if (path) string_path2=path;
00193   string_path2+=ad_comm::subdir;
00194   path=(char*) string_path2;
00195 #endif
00196   if (path != NULL && strlen(path) <= 45)
00197   {
00198 #if !defined (_WIN32)
00199     if (strlen(path) > 0)
00200     {
00201       sprintf(&var_store_file_name[0],"%s/varssave.%s",path, ad_random_part);
00202       sprintf(&gradfile_name2[0],"%s/gradfil2.%s", path, ad_random_part);
00203     }
00204     else
00205     {
00206       sprintf(&var_store_file_name[0],"varssave.tmp");
00207       sprintf(&gradfile_name2[0],"gradfil2.tmp");
00208     }
00209 #else
00210     if (lastchar(path)!='\\')
00211     {
00212       sprintf(&gradfile_name2[0], "%s\\gradfil2.%s", path, ad_random_part);
00213       sprintf(&var_store_file_name[0], "%s\\varssave.%s", path, ad_random_part);
00214     }
00215     else
00216     {
00217       sprintf(&gradfile_name2[0], "%sgradfil2.%s", path, ad_random_part);
00218       sprintf(&var_store_file_name[0], "%svarssave.%s", path, ad_random_part);
00219     }
00220 #endif
00221   }
00222   else
00223   {
00224     sprintf(&gradfile_name2[0], "gradfil2.%s", ad_random_part);
00225     sprintf(&var_store_file_name[0], "varssave.%s", ad_random_part);
00226   }
00227 
00228   create_gradfile();
00229 
00230   strcpy(gradfile_name, gradfile_name1);
00231   _GRADFILE_PTR = _GRADFILE_PTR1;
00232 }
00236 grad_stack::~grad_stack()
00237 {
00238   const int repfs = option_match(ad_comm::argc, ad_comm::argv, "-fsize");
00239   if (ad_comm::global_logfile && repfs)
00240   {
00241      OFF_T pos = LSEEK(_GRADFILE_PTR1, 0, SEEK_END);
00242      *ad_comm::global_logfile << "size of file " << gradfile_name1
00243        << " = " << pos << endl;
00244 
00245      pos = LSEEK(_GRADFILE_PTR2, 0, SEEK_END);
00246      *ad_comm::global_logfile << "size of file " << gradfile_name2
00247        << " = " << pos << endl;
00248 
00249      pos = LSEEK(_VARSSAV_PTR, 0, SEEK_END);
00250      *ad_comm::global_logfile << "size of file " << var_store_file_name
00251        << " = " << pos << endl;
00252   }
00253   if (close(_GRADFILE_PTR1))
00254   {
00255     cerr << "Error closing file " << gradfile_name1 << "\n";
00256   }
00257   if (close(_GRADFILE_PTR2))
00258   {
00259     cerr << "Error closing file " << gradfile_name2 << "\n";
00260   }
00261   if (close(_VARSSAV_PTR))
00262   {
00263     cerr << "Error closing file " << var_store_file_name << "\n";
00264   }
00265 #if !defined (_MSC_VER)
00266   unlink(gradfile_name1);
00267   unlink(gradfile_name2);
00268   unlink(var_store_file_name);
00269 #else
00270   remove(gradfile_name1);
00271   remove(gradfile_name2);
00272   remove(var_store_file_name);
00273 #endif
00274 
00275   delete [] true_ptr_first;
00276   true_ptr_first = 0;
00277 }
00278 
00283 void  grad_stack::write_grad_stack_buffer()
00284 {
00285 #ifdef GRAD_DIAG
00286   cout << "Grad_stack size exceeded\n ";
00287   cout << "Writing to temporary file -- \n";
00288 #endif
00289 
00290   ptr--;
00291 
00292 #ifdef GRAD_DIAG
00293   {
00294     OFF_T lpos = lseek(_GRADFILE_PTR,0L,SEEK_CUR);
00295     cout << "Offset in file before write is " << lpos
00296          << " bytes from the beginning\n";
00297   }
00298 #endif
00299 
00300   // if the buffer is really large only write the end of it
00301   set_gbuffer_pointers();
00302   size_t nbw = sizeof(grad_stack_entry) * length;
00303 
00304   //char * ttmp = (char *) ptr_first; ttmp--;
00305 
00306   // save the current end of file in case we can't write the whole buffer
00307   end_pos = lseek(_GRADFILE_PTR,0L,SEEK_CUR);
00308 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00309   assert(nbw <= UINT_MAX);
00310   ssize_t ierr = write(_GRADFILE_PTR, ptr_first, (unsigned int)nbw);
00311 #else
00312   ssize_t ierr = write(_GRADFILE_PTR, ptr_first, nbw);
00313 #endif
00314 
00315 #ifndef OPT_LIB
00316   assert(nbw <= SSIZE_MAX);
00317 #endif
00318 
00319   if  (ierr != (ssize_t)nbw)
00320   {
00321     cout << "Wrote " << ierr << " not " << nbw << endl;
00322 
00323 #ifndef OPT_LIB
00324     OFF_T offset = LSEEK(_GRADFILE_PTR, end_pos, SEEK_SET);
00325     assert(offset != -1);
00326 #else
00327     LSEEK(_GRADFILE_PTR, end_pos, SEEK_SET);
00328 #endif
00329 
00330     //save the end of file for this file so we can reposition later
00331     end_pos1 = end_pos;
00332     increment_current_gradfile_ptr();
00333 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00334     assert(nbw <= UINT_MAX);
00335     ierr = write(_GRADFILE_PTR, ptr_first, (unsigned int)nbw);
00336 #else
00337     ierr = write(_GRADFILE_PTR, ptr_first, nbw);
00338 #endif
00339 
00340     if  (ierr != (ssize_t)nbw)
00341     {
00342         perror("Error writing to temporary gradient stack file");
00343         cerr <<"   File name: " << gradfile_name << "\n";
00344 #if defined(_MSC_VER)
00345         cerr <<"   File length: "
00346              << filelength(_GRADFILE_PTR)
00347              << " bytes.\n";
00348 #endif
00349       cerr << "   Attempting to write " << nbw <<" bytes; wrote "
00350            << ierr << ".\n";
00351       ad_exit(1);
00352     }
00353   }
00354 #ifdef GRAD_DIAG
00355   else
00356   {
00357     cout << "Wrote " << ierr << "bytes into temp. grad. file\n";
00358   }
00359   {
00360     OFF_T lpos = LSEEK(gradient_structure::_GRADFILE_PTR,0L,SEEK_CUR);
00361     cout << "Offset in file after write is " << lpos
00362          << " bytes from the beginning\n";
00363   }
00364 #endif
00365   //keep track of the size of the grad_stack
00366   gradient_structure::TOTAL_BYTES+=nbw;
00367   ptr = ptr_first;
00368 }
00369 
00374 void grad_stack::create_gradfile()
00375 {
00376   #if defined (__TURBOC__)
00377    _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT |
00378        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00379    _VARSSAV_PTR=open(var_store_file_name, O_RDWR | O_CREAT |
00380        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00381   #elif defined (__ZTC__)
00382     _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT |
00383       O_TRUNC , S_IREAD | S_IWRITE);
00384     _VARSSAV_PTR=open(var_store_file_name, O_RDWR | O_CREAT
00385       | O_TRUNC,  S_IREAD | S_IWRITE);
00386   #elif defined (__NDPX__)
00387     _GRADFILE_PTR1=creat(gradfile_name1, O_RDWR);
00388      _VARSSAV_PTR=creat(var_store_file_name, O_RDWR);
00389   #elif defined (__WAT32__)
00390    _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT |
00391        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00392    _VARSSAV_PTR=open(var_store_file_name, O_RDWR | O_CREAT |
00393        O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
00394   #else
00395     _GRADFILE_PTR1=open(gradfile_name1, O_RDWR | O_CREAT | O_TRUNC |
00396       O_BINARY , 0777);
00397     _VARSSAV_PTR=open(var_store_file_name, O_RDWR |
00398       O_CREAT | O_TRUNC | O_BINARY, 0777);
00399   #endif
00400 
00401   if (_GRADFILE_PTR1 == -1)
00402   {
00403     if (ad_printf) (*ad_printf)("Error opening temporary gradient file"
00404      " %s\n",gradfile_name1);
00405     ad_exit(1);
00406   }
00407 
00408   if (_VARSSAV_PTR == -1)
00409   {
00410     perror("Error opening temporary gradient file");
00411     cerr <<"  Attempting to open " << var_store_file_name <<"\n";
00412     ad_exit(1);
00413   }
00414 
00415   #if defined (__TURBOC__)
00416     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00417       O_BINARY, S_IREAD | S_IWRITE);
00418   #elif defined (__ZTC__)
00419     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC ,
00420       S_IREAD | S_IWRITE);
00421   #elif defined (__NDPX__)
00422     _GRADFILE_PTR2=creat(gradfile_name2, O_RDWR);
00423   #elif defined (_MSC_VER)
00424     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00425       O_BINARY, S_IREAD | S_IWRITE);
00426   #elif defined (__WAT32__)
00427     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00428       O_BINARY, S_IREAD | S_IWRITE);
00429   #else
00430     _GRADFILE_PTR2=open(gradfile_name2, O_RDWR | O_CREAT | O_TRUNC |
00431       O_BINARY , 0777);
00432   #endif
00433 
00434   if (_GRADFILE_PTR2 == -1)
00435   {
00436     perror("Error opening temporary gradient file");
00437     cerr <<"  Attempting to open " << gradfile_name2 <<"\n";
00438     ad_exit(1);
00439   }
00440 }
00445 void grad_stack::increment_current_gradfile_ptr()
00446 {
00447   if (_GRADFILE_PTR == _GRADFILE_PTR2)
00448   {
00449     cerr << "Attempted to open a third gradient file -- There is\n"
00450       "probably no more room on the TMP1 (if defined) device\n"
00451       "if possible set TMP1 environment string to a device with more room\n";
00452     ad_exit(1);
00453   }
00454    strcpy(gradfile_name, gradfile_name2);
00455   _GRADFILE_PTR = _GRADFILE_PTR2;
00456 }
00461 int grad_stack::decrement_current_gradfile_ptr()
00462 {
00463   if (_GRADFILE_PTR == _GRADFILE_PTR1)
00464   {
00465     return -1;
00466   }
00467 
00468   strcpy(gradfile_name, gradfile_name1);
00469   _GRADFILE_PTR = _GRADFILE_PTR1;
00470 
00471   return 0;
00472 }
00473 #ifdef _MSC_VER
00474 int grad_stack::gradfile_handle()
00475 #else
00476 int& grad_stack::gradfile_handle()
00477 #endif
00478 {
00479   return _GRADFILE_PTR;
00480 }
00485 char* grad_stack::get_gradfile_name()
00486 {
00487   return gradfile_name;
00488 }
00493 void grad_stack::set_gbuffer_pointers()
00494 {
00495   if (length > 10000L)
00496   {
00497     //make the buffer end_buf_size
00498     unsigned int end_buf_size=5000L;
00499     ptr_first+=length-end_buf_size;
00500     length=end_buf_size;
00501   }
00502 }
00507 void grad_stack::set_gradient_stack0(void (* func)(void),double * dep_addr)
00508 {
00509 #ifdef NO_DERIVS
00510   if (!gradient_structure::no_derivatives)
00511   {
00512 #endif
00513     if (ptr > ptr_last)
00514     {
00515       // current buffer is full -- write it to disk and reset pointer
00516       // and counter
00517       this->write_grad_stack_buffer();
00518     }
00519     ptr->func = func;
00520     ptr->dep_addr = dep_addr;
00521     ptr++;
00522 #ifdef NO_DERIVS
00523   }
00524 #endif
00525 }