00001 #include <eh_utils.h>
00002
00005 CLASS( Eh_input_val )
00006 {
00007 Eh_input_val_type type;
00008 FILE* fp;
00009 gchar* file;
00010 double* x;
00011 double* y;
00012 double len;
00013 GRand* rand;
00014 double data[2];
00015 double val;
00016 };
00017
00018 GQuark
00019 eh_input_val_error_quark( void )
00020 {
00021 return g_quark_from_static_string( "eh-input-val-error-quark" );
00022 }
00023
00030 Eh_input_val
00031 eh_input_val_new( )
00032 {
00033 Eh_input_val val;
00034
00035 NEW_OBJECT( Eh_input_val , val );
00036
00037 if ( val )
00038 {
00039 val->fp = NULL;
00040 val->file = NULL;
00041 val->x = NULL;
00042 val->y = NULL;
00043 val->len = 0;
00044 val->val = G_MINDOUBLE;
00045 val->rand = g_rand_new();
00046 }
00047
00048 return val;
00049 }
00050
00057 Eh_input_val
00058 eh_input_val_destroy( Eh_input_val val )
00059 {
00060 if ( val )
00061 {
00062 eh_free( val->x );
00063 eh_free( val->y );
00064 eh_free( val->file );
00065 g_rand_free( val->rand );
00066 eh_free( val );
00067 }
00068 return NULL;
00069 }
00070
00095 Eh_input_val
00096 eh_input_val_set( const char *input_str , GError** err )
00097 {
00098 Eh_input_val val = NULL;
00099
00100 eh_return_val_if_fail( err==NULL || *err==NULL , NULL );
00101
00102 eh_require( input_str );
00103
00104
00105
00106
00107
00108
00109 if ( strchr( input_str , '=' ) == NULL )
00110 {
00111 val = eh_input_val_new();
00112
00113 val->type = EH_INPUT_VAL_SCALAR;
00114 val->val = g_ascii_strtod( input_str , NULL );
00115 }
00116 else
00117 {
00118 GError* tmp_error = NULL;
00119 char **equal_split = g_strsplit( input_str , "=" , 2 );
00120
00121 if ( g_ascii_strcasecmp( equal_split[0] , "FILE" ) == 0
00122 || g_ascii_strcasecmp( equal_split[0] , "USER" ) == 0 )
00123 {
00124 double** data;
00125 gint n_rows, n_cols;
00126 Eh_input_val_type type;
00127 gchar* file;
00128
00129 if ( g_ascii_strcasecmp( equal_split[0] , "FILE" ) == 0 )
00130 type = EH_INPUT_VAL_FILE;
00131 else
00132 type = EH_INPUT_VAL_RAND_USER;
00133
00134 file = g_strdup( equal_split[1] );
00135
00136 data = eh_dlm_read_swap( file , ";," , &n_rows , &n_cols , &tmp_error );
00137
00138 if ( !tmp_error )
00139 {
00140 if ( n_rows!=2 )
00141 g_set_error( &tmp_error ,
00142 EH_INPUT_VAL_ERROR ,
00143 EH_INPUT_VAL_ERROR_NOT_TWO_COLUMNS ,
00144 "%s: Input file does not contain 2 columns (found %d)\n" ,
00145 file , n_rows );
00146 else if ( !eh_dbl_array_is_monotonic_up( data[0] , n_cols ) )
00147 g_set_error( &tmp_error ,
00148 EH_INPUT_VAL_ERROR ,
00149 EH_INPUT_VAL_ERROR_X_NOT_MONOTONIC ,
00150 "%s: The first column must be monotonically increasing\n" ,
00151 file );
00152 else if ( type == EH_INPUT_VAL_RAND_USER
00153 && !eh_dbl_array_is_monotonic_up( data[1] , n_cols ) )
00154 g_set_error( &tmp_error ,
00155 EH_INPUT_VAL_ERROR ,
00156 EH_INPUT_VAL_ERROR_F_NOT_MONOTONIC ,
00157 "%s: The second column must be monotonically increasing\n" ,
00158 file );
00159 else if ( type == EH_INPUT_VAL_RAND_USER
00160 && !(data[1][0]<=0 && data[1][n_cols-1]>=1. ) )
00161 g_set_error( &tmp_error ,
00162 EH_INPUT_VAL_ERROR ,
00163 EH_INPUT_VAL_ERROR_BAD_F_RANGE ,
00164 "%s: CDF data must range from 0 to 1 (found [%f,%f]).\n" ,
00165 file , data[1][0] , data[1][n_cols-1] );
00166 else
00167 {
00168 val = eh_input_val_new();
00169
00170 val->type = type;
00171 val->file = file;
00172 val->len = n_cols;
00173 val->x = g_memdup( data[0] , sizeof(double)*n_cols );
00174 val->y = g_memdup( data[1] , sizeof(double)*n_cols );
00175 }
00176 }
00177
00178 eh_free_2( data );
00179 }
00180 else if ( g_ascii_strcasecmp( equal_split[0] , "UNIFORM" ) == 0
00181 || g_ascii_strcasecmp( equal_split[0] , "NORMAL" ) == 0
00182 || g_ascii_strcasecmp( equal_split[0] , "WEIBULL" ) == 0 )
00183 {
00184 char** comma_split = g_strsplit( equal_split[1] , "," , -1 );
00185 gint n_vals = g_strv_length( comma_split );
00186
00187 if ( n_vals != 2 )
00188 g_set_error( &tmp_error ,
00189 EH_INPUT_VAL_ERROR ,
00190 EH_INPUT_VAL_ERROR_NOT_TWO_DIST_VALS ,
00191 "%s: Two values are required to define a distribution (found %d)." ,
00192 equal_split[1], n_vals );
00193 else
00194 {
00195 val = eh_input_val_new();
00196
00197 val->data[0] = g_ascii_strtod( comma_split[0] , NULL );
00198 val->data[1] = g_ascii_strtod( comma_split[1] , NULL );
00199
00200 if ( g_ascii_strcasecmp( equal_split[0] , "UNIFORM" ) == 0 )
00201 val->type = EH_INPUT_VAL_RAND_UNIFORM;
00202 else if ( g_ascii_strcasecmp( equal_split[0] , "NORMAL" ) == 0 )
00203 val->type = EH_INPUT_VAL_RAND_NORMAL;
00204 else if ( g_ascii_strcasecmp( equal_split[0] , "WEIBULL" ) == 0 )
00205 val->type = EH_INPUT_VAL_RAND_WEIBULL;
00206 else
00207 eh_require_not_reached();
00208
00209 }
00210 g_strfreev( comma_split );
00211 }
00212 else
00213 {
00214 g_set_error( &tmp_error ,
00215 EH_INPUT_VAL_ERROR ,
00216 EH_INPUT_VAL_ERROR_BAD_DIST_KEY ,
00217 "%s: Bad input val key (valid keys are %s).\n" ,
00218 equal_split[0] , "Uniform, Normal, Weibull, User, and File" );
00219 }
00220
00221 g_strfreev( equal_split );
00222
00223 if ( tmp_error )
00224 g_propagate_error( err , tmp_error );
00225 }
00226
00227 return val;
00228 }
00229
00238 double
00239 eh_input_val_eval( Eh_input_val val , ... )
00240 {
00241 va_list args;
00242 double data;
00243
00244 if ( val->type == EH_INPUT_VAL_RAND_NORMAL )
00245 val->val = eh_rand_normal( val->rand , val->data[0] , val->data[1] );
00246 else if ( val->type == EH_INPUT_VAL_RAND_UNIFORM )
00247 val->val = g_rand_double_range( val->rand , val->data[0] , val->data[1] );
00248 else if ( val->type == EH_INPUT_VAL_RAND_WEIBULL )
00249 val->val = eh_rand_weibull( val->rand , val->data[0] , val->data[1] );
00250 else if ( val->type == EH_INPUT_VAL_RAND_USER )
00251 val->val = eh_rand_user( val->rand , val->x , val->y , val->len );
00252 else if ( val->type == EH_INPUT_VAL_FILE )
00253 {
00254
00255 eh_require( val->x );
00256 eh_require( val->y );
00257
00258 va_start( args , val );
00259 data = va_arg( args , double );
00260
00261 interpolate( val->x , val->y , val->len , &data , &(val->val) , 1 );
00262
00263 va_end( args );
00264 }
00265
00266 return val->val;
00267 }
00268
00269