summaryrefslogtreecommitdiff
path: root/impl/OPTUtils.h
diff options
context:
space:
mode:
Diffstat (limited to 'impl/OPTUtils.h')
-rwxr-xr-ximpl/OPTUtils.h475
1 files changed, 475 insertions, 0 deletions
diff --git a/impl/OPTUtils.h b/impl/OPTUtils.h
new file mode 100755
index 0000000..66ad4af
--- /dev/null
+++ b/impl/OPTUtils.h
@@ -0,0 +1,475 @@
+/*--------------------------------------------------------------------------*/
+/*--------------------------- File OPTutils.h ------------------------------*/
+/*--------------------------------------------------------------------------*/
+/** @file
+ * Small classes are provided for:
+ * - reading the time of a code;
+ * - generating random numbers.
+ *
+ * The classes can be adapted to different environments setting a
+ * compile-time switch in this file.
+ *
+ * Additionally, a function is provided for safely reading parameters
+ * out of a stream.
+ *
+ * \version 1.00
+ *
+ * \date 04 - 10 - 2010
+ *
+ * \author Antonio Frangioni \n
+ * Operations Research Group \n
+ * Dipartimento di Informatica \n
+ * Universita' di Pisa \n
+ *
+ * Copyright &copy 1994 - 2010 by Antonio Frangioni
+ */
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+#ifndef __OPTutils
+ #define __OPTutils /* self-identification: #endif at the end of the file */
+
+/*--------------------------------------------------------------------------*/
+/*----------------------------- MACROS -------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/** @defgroup OPTUTILS_MACROS Compile-time switches in OPTutils.h
+ These macros control how the classes OPTTimers and OPTrand are
+ implemented; choose the appropriate value for your environment,
+ or program a new version if no value suits you.
+ Also, namespaces can be eliminated if they create problems.
+ @{ */
+
+
+/*----------------------- OPT_USE_NAMESPACES -------------------------------*/
+
+#define OPT_USE_NAMESPACES 0
+
+/**< Setting OPT_USE_NAMESPACES == 0 should instruct all codes that use
+ OPTutils stuff to avoid using namespaces; to start with, the common
+ namespace OPTutils_di_unipi_it, that contains all the types defined
+ herein, is *not* defined. */
+
+/*---------------------------- OPT_TIMERS ----------------------------------*/
+
+#define OPT_TIMERS 5
+
+/**< The class OPTtimers is defined below to give an abstract interface to the
+ different timing routines that are used in different platforms. This is
+ needed since time-related functions are one of the less standard parts of
+ the C[++] library. The value of the OPT_TIMERS constant selects among the
+ different timing routines:
+
+ - 1 = Use the Unix times() routine in sys/times.h
+
+ - 2 = As 1 but uses sys/timeb.h (typical for Microsoft(TM) compilers)
+
+ - 3 = Still use times() of sys/times.h, but return wallclock time
+ rather than CPU time
+
+ - 4 = As 3 but uses sys/timeb.h (typical for Microsoft(TM) compilers)
+
+ - 5 = return the user time obtained with ANSI C clock() function; this
+ may result in more accurate running times w.r.t. but may be limited
+ to ~ 72 hours on systems where ints are 32bits.
+
+ - 6 = Use the Unix gettimeofday() routine of sys/time.h.
+
+ Any unsupported value would simply make the class to report constant
+ zero as the time.
+
+ The values 1 .. 4 rely on the constant CLK_TCK for converting between
+ clock ticks and seconds; for the case where the constant is not defined by
+ the compiler -- should not happen, but it does -- or it is defined in a
+ wrong way, the constant is re-defined below. */
+
+/*---------------------------- OPT_RANDOM ---------------------------------*/
+
+#define OPT_RANDOM 1
+
+/**< The class OPTrand is defined below to give an abstract interface to the
+ different random generators that are used in different platforms. This is
+ needed since random generators are one of the less standard parts of the
+ C[++] library. The value of the OPT_RANDOM constant selects among the
+ different timing routines:
+
+ - 0 = an hand-made implementation of a rather good random number generator
+ is used; note that this assumes that long ints >= 32 bits
+
+ - 1 = standard rand() / srand() pair, common to all C libreries but not
+ very sophisticated
+
+ - 2 = drand48() / srand48(), common on Unix architectures and pretty good.
+
+ Any unsupported value would simply make the functions to report constant
+ zero, which is not nice but useful to quickly fix problems if you don't
+ use random numbers at all. */
+
+/*@} -----------------------------------------------------------------------*/
+/*------------------------------ INCLUDES ----------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+#if( OPT_RANDOM )
+ #include <stdlib.h>
+
+ /* For random routines, see OPTrand() below. */
+#endif
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+#if( OPT_TIMERS <= 4 )
+ #if( ( OPT_TIMERS == 1 ) || ( OPT_TIMERS == 3 ) )
+ #include <sys/times.h>
+ #else
+ #include <sys/timeb.h>
+ #endif
+ #include <limits.h>
+#elif( OPT_TIMERS == 5 )
+ #include <time.h>
+#elif( OPT_TIMERS == 6 )
+ #include <sys/time.h>
+#endif
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+#include <iostream>
+#include <sstream>
+
+/* For istream and the >> operator, used in DfltdSfInpt(). */
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------- NAMESPACE ------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+#if( OPT_USE_NAMESPACES )
+namespace OPTtypes_di_unipi_it
+{
+ /** @namespace OPTtypes_di_unipi_it
+ The namespace OPTtypes_di_unipi_it is defined to hold all the data
+ types, constants, classes and functions defined here. It also
+ comprises the namespace std. */
+#endif
+
+ using namespace std; // I know it's not elegant, but ...
+
+/*--------------------------------------------------------------------------*/
+/*----------------------------- NULL ---------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+/* Curiously enough, some compilers do not always define NULL; for instance,
+ sometimes it is defined in stdlib.h. */
+
+/*--------------------------------------------------------------------------*/
+/*---------------------------- CLK_TCK -------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+#ifndef CLK_TCK
+ #define CLK_TCK 100
+#endif
+
+/* CLK_TCK is the constant used to transform (integer) time values in seconds
+ for times()-based routines. Its normal value is 100. */
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------- OPT_TIMERS -----------------------------------*/
+/*--------------------------------------------------------------------------*/
+/** @defgroup OPTtypes_CLASSES Classes in OPTutils.h
+ @{ */
+
+#if( OPT_TIMERS )
+
+/** Provides a common interface to the different timing routines that are
+ available in different platforms. */
+
+class OPTtimers {
+
+ public: //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ /// constructor of the class
+ OPTtimers( void )
+ {
+ ReSet();
+ }
+
+ /// start the timer
+ void Start( void )
+ {
+ if( ! ticking ) {
+ #if( ( OPT_TIMERS == 1 ) || ( OPT_TIMERS == 2 ) )
+ times( &buff );
+ t_u = buff.tms_utime;
+ t_s = buff.tms_stime;
+ #elif( ( OPT_TIMERS == 3 ) || ( OPT_TIMERS == 4 ) )
+ t_u = times( &buff );
+ #elif( OPT_TIMERS == 5 )
+ t_u = clock();
+ #elif( OPT_TIMERS == 6 )
+ struct timeval t;
+ gettimeofday( &t , NULL );
+ t_u = double( t.tv_sec + t.tv_usec * 1e-6 );
+ #endif
+
+ ticking = 1;
+ }
+ }
+
+ /// stop the timer
+ void Stop( void )
+ {
+ if( ticking ) {
+ Read( u , s );
+ ticking = 0;
+ }
+ }
+
+ /** Return the elapsed time. If the clock is ticking, return the *total*
+ time since the last Start() without stopping the clock; otherwise,
+ return the total elapsed time of all the past runs of the clock since
+ the last ReSet() [see below]. */
+
+ double Read( void )
+ {
+ double tu = 0;
+ double ts = 0;
+ Read( tu , ts );
+ return( tu + ts );
+ }
+
+ /// As Read( void ) but *adds* user and system time to tu and ts.
+ void Read( double &tu , double &ts )
+ {
+ if( ticking ) {
+ #if( ( OPT_TIMERS == 1 ) || ( OPT_TIMERS == 2 ) )
+ times( &buff );
+ tu += ( double( buff.tms_utime - t_u ) ) / double( CLK_TCK );
+ ts += ( double( buff.tms_stime - t_s ) ) / double( CLK_TCK );
+ #elif( ( OPT_TIMERS == 3 ) || ( OPT_TIMERS == 4 ) )
+ tu += ( double( times( &buff ) - t_u ) ) / double( CLK_TCK );
+ #elif( OPT_TIMERS == 5 )
+ tu += ( double( clock() - t_u ) ) / double( CLOCKS_PER_SEC );
+ #elif( OPT_TIMERS == 6 )
+ struct timeval t;
+ gettimeofday( &t , NULL );
+ tu += double( t.tv_sec + t.tv_usec * 1e-6 ) - t_u;
+ #endif
+ }
+ else { tu += u; ts += s; }
+ }
+
+ /// reset the timer
+ void ReSet( void )
+ {
+ u = s = 0; ticking = 0;
+ }
+
+ private: //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ double u; // elapsed *user* time, in seconds
+ double s; // elapsed *system* time, in seconds
+ char ticking; // 1 if the clock is ticking
+
+ #if( ( OPT_TIMERS > 0 ) && ( OPT_TIMERS <= 5 ) )
+ clock_t t_u;
+
+ #if( OPT_TIMERS <= 4 )
+ struct tms buff;
+
+ #if( ( OPT_TIMERS == 1 ) || ( OPT_TIMERS == 3 ) )
+ clock_t t_s;
+ #endif
+ #endif
+ #elif( OPT_TIMERS == 6 )
+ double t_u;
+ #endif
+
+ }; // end( class OPTtimers );
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+/*------------------------------ OPTrand() ---------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+/** Provide a common interface to the different random generators that are
+ available in different platforms. */
+
+class OPTrand {
+
+ public: //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ /// constructor of the class
+ OPTrand( void )
+ {
+ #if( OPT_RANDOM == 0 )
+ A[ 0 ] = -1;
+ srand( long( 123456789 ) );
+ #else
+ OPTrand::srand( long( 1 ) );
+ #endif
+ }
+
+ /** Returns a random number uniformly distributed in [0, 1).
+ \note each object of class OPTrand has its own sequence, so that
+ multiple OPTrand objects being used within the same program do not
+ interfere with each other (as opposed to what C random routines
+ would do). */
+
+ double rand( void )
+ {
+ #if( OPT_RANDOM == 0 )
+ long nmbr = *(gb_fptr--);
+ if( nmbr < 0 )
+ nmbr = gb_flip_cycle();
+ return( double( nmbr ) / double( (unsigned long)0x80000000 ) );
+ #elif( OPT_RANDOM == 1 )
+ ::srand( myseed );
+ myseed = ::rand();
+ return( double( myseed ) / double( RAND_MAX ) );
+ #elif( OPT_RANDOM == 2 )
+ return( erand48( myseed ) );
+ #else
+ return( 0 ); // random, eh?
+ #endif
+ }
+
+ /// Seeds the random generator for this instance of OPTrand.
+ void srand( long seed )
+ {
+ #if( OPT_RANDOM == 0 )
+ long prev = seed , next = 1;
+ seed = prev = mod_diff( prev , 0 );
+ A[ 55 ] = prev;
+
+ for( long i = 21 ; i ; i = ( i + 21 ) % 55 ) {
+ A[ i ] = next;
+ next = mod_diff( prev , next );
+ if( seed & 1 )
+ seed = 0x40000000 + ( seed >> 1 );
+ else
+ seed >>= 1;
+
+ next = mod_diff( next , seed );
+ prev = A[ i ];
+ }
+
+ gb_flip_cycle();
+ gb_flip_cycle();
+ gb_flip_cycle();
+ gb_flip_cycle();
+ gb_flip_cycle();
+ #elif( OPT_RANDOM == 1 )
+ myseed = int( seed );
+ #elif( OPT_RANDOM == 2 )
+ long *sp = (long*)( &myseed );
+ *sp = seed; // copy higher 32 bits
+ myseed[ 2 ] = 0x330E; // initialize lower 16 bits
+ #endif
+ }
+
+ private: //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ #if( OPT_RANDOM == 0 )
+ long A[ 56 ];
+ long *gb_fptr;
+
+ long mod_diff( long x , long y )
+ {
+ return( ( ( x ) - ( y ) ) & 0x7fffffff );
+ }
+
+ long gb_flip_cycle( void )
+ {
+ long *ii, *jj;
+ for( ii = &A[ 1 ] , jj = &A[ 32 ] ; jj <= &A[ 55 ] ; ii++ , jj++ )
+ *ii = mod_diff( *ii , *jj );
+
+ for( jj = &A[ 1 ] ; ii <= &A[ 55 ] ; ii++ , jj++ )
+ *ii = mod_diff( *ii , *jj );
+
+ gb_fptr = &A[ 54 ];
+
+ return A[ 55 ];
+ }
+ #elif( OPT_RANDOM == 1 )
+ int myseed;
+ #elif( OPT_RANDOM == 2 )
+ unsigned short int myseed[ 3 ];
+ #endif
+
+ }; // end( class( OPTrand ) )
+
+/* @} end( group( OPTtypes_CLASSES ) ) */
+/*--------------------------------------------------------------------------*/
+/*--------------------------- DfltdSfInpt() --------------------------------*/
+/*--------------------------------------------------------------------------*/
+/** @defgroup OPTtypes_FUNCTIONS Functions in OPTutils.h
+ @{ */
+
+/** Template function for reading parameters from a istream. The function is
+ "safe" because it works also if the istream is not given, is not be long
+ enough or contains erroneous things.
+
+ Given a &istream (possibly NULL), DfltdSfInpt() attempts to read Param out
+ of it, skipping any line that begins with the comment carachter (defaulted
+ to '#'), any blank line and any line starting with anything that can not
+ be interpreted as a `T'. If, for any reason, the read operation fails,
+ then the parameter is given the default value `Dflt'. Otherwise, all the
+ rest of the line up to the nearest newline ('\n') carachter is flushed. */
+
+template<class T>
+inline void DfltdSfInpt( istream *iStrm , T &Param , const T Dflt ,
+ const char cmntc = '#' )
+{
+ string comm( 1 , cmntc );
+
+ // the "! ! stream" trick is there to force the compiler to apply the
+ // stream -> bool conversion, in case it is too dumb to do it by itself
+ if( iStrm && ( ! ( ! (*iStrm) ) ) ) {
+ string buf;
+
+ for( ;; ) {
+ if( ! ( (*iStrm) >> ws ) ) // skip whitespace
+ break;
+
+ if( ! (*iStrm).good() ) // check stream is OK
+ break;
+
+ getline( *iStrm , buf );
+
+ if( ! buf.empty() )
+ if( buf.substr( 0 , 1 ).compare( comm ) ) {
+ stringstream ss;
+ ss << buf;
+ if( ! ( ss >> Param ) )
+ break;
+
+ return;
+ }
+ }
+ }
+
+ Param = Dflt;
+
+ } // end( DfltdSfInpt )
+
+/* @} end( group( OPTtypes_FUNCTIONS ) ) */
+/*--------------------------------------------------------------------------*/
+
+#if( OPT_USE_NAMESPACES )
+ }; // end( namespace OPTtypes_di_unipi_it )
+#endif
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+#endif /* OPTutils.h included */
+
+/*--------------------------------------------------------------------------*/
+/*---------------------- End File OPTutils.h -------------------------------*/
+/*--------------------------------------------------------------------------*/