00001
00002
00003
00004
00005
00006
00007
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <errno.h>
00011 #include <math.h>
00012 #include <complex.h>
00013
00014 #include "double_assert.h"
00015
00016 EXPORT_CREATE(double_assert);
00017 EXPORT_INIT(double_assert);
00018 EXPORT_COMMIT(double_assert);
00019 EXPORT_NOTIFY(double_assert);
00020
00021 CLASS *double_assert::oclass = NULL;
00022 double_assert *double_assert::defaults = NULL;
00023
00024 double_assert::double_assert(MODULE *module)
00025 {
00026 if (oclass==NULL)
00027 {
00028
00029 oclass = gl_register_class(module,"double_assert",sizeof(double_assert),PC_AUTOLOCK|PC_OBSERVER);
00030 if (oclass==NULL)
00031 throw "unable to register class double_assert";
00032 else
00033 oclass->trl = TRL_PROVEN;
00034
00035 if (gl_publish_variable(oclass,
00036
00037 PT_enumeration,"status",get_status_offset(),PT_DESCRIPTION,"Conditions for the assert checks",
00038 PT_KEYWORD,"ASSERT_TRUE",(enumeration)ASSERT_TRUE,
00039 PT_KEYWORD,"ASSERT_FALSE",(enumeration)ASSERT_FALSE,
00040 PT_KEYWORD,"ASSERT_NONE",(enumeration)ASSERT_NONE,
00041 PT_enumeration, "once", get_once_offset(),PT_DESCRIPTION,"Conditions for a single assert check",
00042 PT_KEYWORD,"ONCE_FALSE",(enumeration)ONCE_FALSE,
00043 PT_KEYWORD,"ONCE_TRUE",(enumeration)ONCE_TRUE,
00044 PT_KEYWORD,"ONCE_DONE",(enumeration)ONCE_DONE,
00045 PT_enumeration, "within_mode", get_within_mode_offset(),PT_DESCRIPTION,"Method of applying tolerance",
00046 PT_KEYWORD,"WITHIN_VALUE",(enumeration)IN_ABS,
00047 PT_KEYWORD,"WITHIN_RATIO",(enumeration)IN_RATIO,
00048 PT_double, "value", get_value_offset(),PT_DESCRIPTION,"Value to assert",
00049 PT_double, "within", get_within_offset(),PT_DESCRIPTION,"Tolerance for a successful assert",
00050 PT_char1024, "target", get_target_offset(),PT_DESCRIPTION,"Property to perform the assert upon",
00051 NULL)<1){
00052 char msg[256];
00053 sprintf(msg, "unable to publish properties in %s",__FILE__);
00054 throw msg;
00055 }
00056
00057 defaults = this;
00058 status = ASSERT_TRUE;
00059 within = 0.0;
00060 within_mode = IN_ABS;
00061 value = 0.0;
00062 once = ONCE_FALSE;
00063 once_value = 0;
00064 }
00065 }
00066
00067
00068 int double_assert::create(void)
00069 {
00070 memcpy(this,defaults,sizeof(*this));
00071
00072 return 1;
00073 }
00074
00075 int double_assert::init(OBJECT *parent)
00076 {
00077 char *msg = "A non-positive value has been specified for within.";
00078 if (within <= 0.0)
00079 throw msg;
00080
00081
00082
00083
00084 return 1;
00085 }
00086
00087 TIMESTAMP double_assert::commit(TIMESTAMP t1, TIMESTAMP t2)
00088 {
00089
00090 if ( once==ONCE_TRUE )
00091 {
00092 once_value = value;
00093 once = ONCE_DONE;
00094 }
00095 else if ( once == ONCE_DONE )
00096 {
00097 if ( once_value==value )
00098 {
00099 gl_verbose("Assert skipped with ONCE logic");
00100 return TS_NEVER;
00101 }
00102 else
00103 {
00104 once_value = value;
00105 }
00106 }
00107
00108
00109 gld_property target_prop(get_parent(),get_target());
00110 if ( !target_prop.is_valid() || target_prop.get_type()!=PT_double )
00111 {
00112 gl_error("Specified target %s for %s is not valid.",get_target(),get_parent()->get_name());
00113
00114
00115
00116
00117
00118
00119 return 0;
00120 }
00121
00122
00123 double range = 0.0;
00124 if ( within_mode == IN_RATIO )
00125 {
00126 range = value * within;
00127 if ( range<0.001 )
00128 {
00129 range = 0.001;
00130 }
00131 }
00132 else if ( within_mode== IN_ABS )
00133 {
00134 range = within;
00135 }
00136
00137
00138 double x; target_prop.getp(x);
00139 if ( status == ASSERT_TRUE )
00140 {
00141 double m = fabs(x-value);
00142 if ( _isnan(m) || m>range )
00143 {
00144 gl_error("Assert failed on %s: %s %g not within %f of given value %g",
00145 get_parent()->get_name(), get_target(), x, range, value);
00146 return 0;
00147 }
00148 gl_verbose("Assert passed on %s", get_parent()->get_name());
00149 return TS_NEVER;
00150 }
00151 else if ( status == ASSERT_FALSE )
00152 {
00153 double m = fabs(x-value);
00154 if ( _isnan(m) || m<range )
00155 {
00156 gl_error("Assert failed on %s: %s %g is within %f of given value %g",
00157 get_parent()->get_name(), get_target(), x, range, value);
00158 return 0;
00159 }
00160 gl_verbose("Assert passed on %s", get_parent()->get_name());
00161 return TS_NEVER;
00162 }
00163 else
00164 {
00165 gl_verbose("Assert test is not being run on %s", get_parent()->get_name());
00166 return TS_NEVER;
00167 }
00168
00169 }
00170
00171 int double_assert::postnotify(PROPERTY *prop, char *value)
00172 {
00173 if ( once==ONCE_DONE && strcmp(prop->name, "value")==0 )
00174 {
00175 once = ONCE_TRUE;
00176 }
00177 return 1;
00178 }
00179
00180
00181 EXPORT SIMULATIONMODE update_double_assert(OBJECT *obj, TIMESTAMP t0, unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val)
00182 {
00183 char buff[64];
00184 char dateformat[8]="";
00185 char error_output_buff[1024];
00186 char datebuff[64];
00187 double_assert *da = OBJECTDATA(obj,double_assert);
00188 DATETIME delta_dt_val;
00189 double del_clock;
00190 TIMESTAMP del_clock_int;
00191 int del_microseconds;
00192 double *x;
00193
00194 if(da->get_once() == da->ONCE_TRUE){
00195 da->set_once_value(da->get_value());
00196 da->set_once(da->ONCE_DONE);
00197 } else if (da->get_once() == da->ONCE_DONE){
00198 if(da->get_once_value() == da->get_value()){
00199 gl_verbose("Assert skipped with ONCE logic");
00200 return SM_EVENT;
00201 } else {
00202 da->set_once_value(da->get_value());
00203 }
00204 }
00205
00206
00207 double range = 0.0;
00208 if ( da->get_within_mode() == da->IN_RATIO )
00209 {
00210 range = da->get_value() * da->get_within();
00211
00212
00213
00214
00215
00216 }
00217 else if ( da->get_within_mode()== da->IN_ABS )
00218 {
00219 range = da->get_within();
00220 }
00221
00222
00223 if (iteration_count_val == 0)
00224 {
00225
00226 if (delta_time>=dt)
00227 {
00228
00229 x = (double*)gl_get_double_by_name(obj->parent,da->get_target());
00230
00231 if (x==NULL)
00232 {
00233 gl_error("Specified target %s for %s is not valid.",da->get_target(),gl_name(obj->parent,buff,64));
00234
00235
00236
00237
00238
00239
00240 return SM_ERROR;
00241 }
00242 else if (da->get_status() == da->ASSERT_TRUE)
00243 {
00244 double m = fabs(*x-da->get_value());
00245 if (_isnan(m) || m>range)
00246 {
00247
00248 if (delta_time>=dt)
00249 del_clock = (double)t0 + (double)(delta_time-dt)/(double)DT_SECOND;
00250 else
00251 del_clock = (double)t0 + (double)(delta_time)/(double)DT_SECOND;
00252
00253 del_clock_int = (TIMESTAMP)del_clock;
00254 del_microseconds = (int)((del_clock-(int)(del_clock))*1000000+0.5);
00255
00256
00257 gl_localtime(del_clock_int,&delta_dt_val);
00258
00259
00260 gl_global_getvar("dateformat",dateformat,sizeof(dateformat));
00261
00262
00263 if ( strcmp(dateformat,"ISO")==0)
00264 sprintf(datebuff,"ERROR [%04d-%02d-%02d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.year,delta_dt_val.month,delta_dt_val.day,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
00265 else if ( strcmp(dateformat,"US")==0)
00266 sprintf(datebuff,"ERROR [%02d-%02d-%04d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.month,delta_dt_val.day,delta_dt_val.year,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
00267 else if ( strcmp(dateformat,"EURO")==0)
00268 sprintf(datebuff,"ERROR [%02d-%02d-%04d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.day,delta_dt_val.month,delta_dt_val.year,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
00269 else
00270 sprintf(datebuff,"ERROR .09f : ",del_clock);
00271
00272
00273 sprintf(error_output_buff,"Assert failed on %s - %s (%g) not within %f of given value %g",gl_name(obj->parent, buff, 64),da->get_target(), *x, da->get_within(), da->get_value());
00274
00275
00276 gl_output("%s%s",datebuff,error_output_buff);
00277
00278 return SM_ERROR;
00279 }
00280 gl_verbose("Assert passed on %s", gl_name(obj->parent, buff, 64));
00281 return SM_EVENT;
00282 }
00283 else if (da->get_status() == da->ASSERT_FALSE)
00284 {
00285 double m = fabs(*x-da->get_value());
00286 if (_isnan(m) || m<range)
00287 {
00288
00289 if (delta_time>=dt)
00290 del_clock = (double)t0 + (double)(delta_time-dt)/(double)DT_SECOND;
00291 else
00292 del_clock = (double)t0 + (double)(delta_time)/(double)DT_SECOND;
00293
00294 del_clock_int = (TIMESTAMP)del_clock;
00295 del_microseconds = (int)((del_clock-(int)(del_clock))*1000000+0.5);
00296
00297
00298 gl_localtime(del_clock_int,&delta_dt_val);
00299
00300
00301 gl_global_getvar("dateformat",dateformat,sizeof(dateformat));
00302
00303
00304 if ( strcmp(dateformat,"ISO")==0)
00305 sprintf(datebuff,"ERROR [%04d-%02d-%02d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.year,delta_dt_val.month,delta_dt_val.day,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
00306 else if ( strcmp(dateformat,"US")==0)
00307 sprintf(datebuff,"ERROR [%02d-%02d-%04d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.month,delta_dt_val.day,delta_dt_val.year,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
00308 else if ( strcmp(dateformat,"EURO")==0)
00309 sprintf(datebuff,"ERROR [%02d-%02d-%04d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.day,delta_dt_val.month,delta_dt_val.year,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
00310 else
00311 sprintf(datebuff,"ERROR .09f : ",del_clock);
00312
00313
00314 sprintf(error_output_buff,"Assert failed on %s - %s (%g) not within %f of given value %g",gl_name(obj->parent, buff, 64),da->get_target(), *x, da->get_within(), da->get_value());
00315
00316
00317 gl_output("%s%s",datebuff,error_output_buff);
00318
00319 return SM_ERROR;
00320 }
00321 gl_verbose("Assert passed on %s", gl_name(obj->parent, buff, 64));
00322 return SM_EVENT;
00323 }
00324 else
00325 {
00326 gl_verbose("Assert test is not being run on %s", gl_name(obj->parent, buff, 64));
00327 return SM_EVENT;
00328 }
00329 }
00330 else
00331 return SM_EVENT;
00332 }
00333 else
00334 return SM_EVENT;
00335 }