/** This function performs an aggregate calculation given by the aggregation **/ double aggregate_value(AGGREGATION *aggr) /**< the aggregation to perform */ { OBJECT *obj; double numerator=0, denominator=0, secondary=0, third=0, fourth=0; double scale = (aggr->punit ? aggr->scale : 1.0); /* non-constant groups need search program rerun */ if ((aggr->group->constflags & CF_CONSTANT) != CF_CONSTANT){ aggr->last = find_runpgm(NULL,aggr->group); /** @todo use constant part instead of NULL (ticket #3) */ } for(obj = find_first(aggr->last); obj != NULL; obj = find_next(aggr->last, obj)){ double value=0; double *pdouble = NULL; complex *pcomplex = NULL; /* add time-sensitivity to verify that we are only aggregating objects that are in-service and not out-service. */ if(obj->in_svc >= global_clock || obj->out_svc <= global_clock) continue; switch (aggr->pinfo->ptype) { case PT_complex: case PT_enduse: pcomplex = object_get_complex(obj,aggr->pinfo); if (pcomplex!=NULL) { switch (aggr->part) { case AP_REAL: value=pcomplex->r; break; case AP_IMAG: value=pcomplex->i; break; case AP_MAG: value=mag(pcomplex); break; case AP_ARG: value=arg(pcomplex); break; case AP_ANG: value=arg(pcomplex)*180/PI; break; default: pcomplex = NULL; break; /* invalidate the result */ } } break; case PT_double: case PT_loadshape: case PT_random: pdouble = object_get_double(obj,aggr->pinfo); if (pdouble!=NULL){ value = *pdouble; if(aggr->pinfo->unit != 0 && aggr->punit != 0){ int rv = unit_convert_ex(aggr->pinfo->unit, aggr->punit, &value); if(rv == 0){ // error ; } } // else don't worry } break; default: break; } if (pdouble!=NULL || pcomplex!=NULL) /* valid value */ { if ((aggr->flags&AF_ABS)==AF_ABS) value=fabs(value); switch (aggr->op) { case AGGR_MIN: if (value<numerator || denominator==0) numerator=value; denominator = 1; break; case AGGR_MAX: if (value>numerator || denominator==0) numerator=value; denominator = 1; break; case AGGR_COUNT: numerator++; denominator=1; break; case AGGR_MBE: denominator++; numerator += value; secondary += (value-secondary)/denominator; break; case AGGR_AVG: case AGGR_MEAN: numerator+=value; denominator++; break; case AGGR_SUM: numerator+=value; denominator = 1; break; case AGGR_PROD: numerator*=value; denominator = 1; break; case AGGR_GAMMA: denominator+=log(value); if (numerator==0 || secondary>value) secondary = value; numerator++; break; case AGGR_STD: case AGGR_VAR: denominator++; // note this uses a compensated on-line algorithm (see Knuth 1998) // it's better than the obvious method because it doesn't suffer from numerical instability when mean(x)-x is near zero { double delta = value-secondary; secondary += delta/denominator; numerator += delta*(value-secondary); } break; case AGGR_SKEW: case AGGR_KUR: default: break; } } } switch (aggr->op) { double v = 0.0, t = 0.0, m = 0.0; case AGGR_GAMMA: return 1 + numerator/(denominator-numerator*log(secondary)); case AGGR_STD: return sqrt(numerator/(denominator-1));// * scale; case AGGR_MBE: return numerator/denominator - secondary; case AGGR_SKEW: /** @todo implement skewness aggregate (no ticket) */ throw_exception("skewness aggregation is not implemented"); /* TROUBLESHOOT An attempt to use the skew aggregator failed because it is not implemented yet. Remove or replace the reference to the skew aggregate and try again. */ case AGGR_KUR: /** @todo implement kurtosis aggregate (no ticket) */ throw_exception("kurtosis aggregation is not implemented"); /* TROUBLESHOOT An attempt to use the kurtosis aggregator failed because it is not implemented yet. Remove or replace the reference to the */ default: return numerator/denominator;// * scale; } }
/** Convert to a \e complex_array data type Converts a string to a \e complex_array data type property. @return 1 on success, 0 on failure, -1 if conversion was incomplete **/ int convert_to_complex_array(const char *buffer, void *data, PROPERTY *prop) { complex_array *a=(complex_array*)data; unsigned row=0, col=0; const char *p = buffer; /* new array */ /* parse input */ for ( p=buffer ; *p!='\0' ; ) { char value[256]; char objectname[64], propertyname[64]; complex c; while ( *p!='\0' && isspace(*p) ) p++; /* skip spaces */ if ( *p!='\0' && sscanf(p,"%s",value)==1 ) { if ( *p==';' ) /* end row */ { row++; col=0; p++; continue; } else if ( strnicmp(p,"NAN",3)==0 ) /* NULL value */ { a->grow_to(row,col); a->clr_at(row,col); col++; } else if ( convert_to_complex(value,(void*)&c,prop) ) /* probably real value */ { a->grow_to(row,col); a->set_at(row,col,c); col++; } else if ( sscanf(value,"%[^.].%[^; \t]",objectname,propertyname)==2 ) /* object property */ { OBJECT *obj = object_find_name(objectname); PROPERTY *prop; if ( obj==NULL ) { output_error("convert_to_double_array(const char *buffer='%10s...',...): entry at row %d, col %d - object '%s' not found", buffer,row,col,objectname); return 0; } prop = object_get_property(obj,propertyname,NULL); if ( prop==NULL ) { output_error("convert_to_double_array(const char *buffer='%10s...',...): entry at row %d, col %d - property '%s' not found in object '%s'", buffer,row,col,propertyname,objectname); return 0; } a->grow_to(row,col); a->set_at(row,col,object_get_complex(obj,prop)); if ( a->is_nan(row,col) ) { output_error("convert_to_double_array(const char *buffer='%10s...',...): entry at row %d, col %d property '%s' in object '%s' is not accessible", buffer,row,col,propertyname,objectname); return 0; } col++; } else if ( sscanf(value,"%[^; \t]",propertyname)==1 ) /* object property */ { GLOBALVAR *var = global_find(propertyname); if ( var==NULL ) { output_error("convert_to_double_array(const char *buffer='%10s...',...): entry at row %d, col %d global '%s' not found", buffer,row,col,propertyname); return 0; } a->grow_to(row,col); a->set_at(row,col,(complex*)var->prop->addr); if ( a->is_nan(row,col) ) { output_error("convert_to_double_array(const char *buffer='%10s...',...): entry at row %d, col %d property '%s' in object '%s' is not accessible", buffer,row,col,propertyname,objectname); return 0; } col++; } else /* not a valid entry */ { output_error("convert_to_double_array(const char *buffer='%10s...',...): entry at row %d, col %d is not valid (value='%10s')", buffer,row,col,p); return 0; } while ( *p!='\0' && !isspace(*p) && *p!=';' ) p++; /* skip characters just parsed */ } } return 1; }
/** Fetches the property requested and uses the appropriate op on the value. @return boolean value **/ static int compare_property_alt(OBJECT *obj, char *propname, FINDOP op, void *value){ complex *complex_target = NULL; char *char_target = NULL; int16 *int16_target = NULL; int32 *int32_target = NULL; int64 *int64_target = NULL; PROPERTY *prop = object_get_property(obj, propname); if(prop == NULL){ /* property not found in object ~ normal operation */ return 0; } switch(prop->ptype){ case PT_void: return 0; /* no comparsion to be made */ case PT_double: break; case PT_complex: complex_target = object_get_complex(obj, prop); if(complex_target == NULL) return 0; /* error value */ break; case PT_enumeration: case PT_set: break; /* not 100% sure how to make these cooperate yet */ case PT_int16: int16_target = (int16 *)object_get_int16(obj, prop); if(int16_target == NULL) return 0; return compare_int16(*int16_target, op, *(int64 *)value); case PT_int32: int32_target = (int32 *)object_get_int32(obj, prop); return compare_int32(*int32_target, op, *(int64 *)value); break; case PT_int64: int64_target = (int64 *)object_get_int64(obj, prop); return compare_int64(*int64_target, op, *(int64 *)value); break; case PT_char8: case PT_char32: case PT_char256: case PT_char1024: char_target = (char *)object_get_string(obj, prop); if(char_target == NULL) return 0; return compare_string(char_target, op, value); break; case PT_object: break; case PT_bool: break; case PT_timestamp: case PT_double_array: case PT_complex_array: break; #ifdef USE_TRIPLETS case PT_triple: case PT_triplex: break; #endif default: output_error("comparison operators not supported for property type %s", class_get_property_typename(prop->ptype)); /* TROUBLESHOOT This error is caused when an object find procedure uses a comparison operator that isn't allowed on a that type of property. Make sure the property type and the comparison operator are compatible and try again. If your GLM file isn't the cause of the problem, try reducing the complexity of the GLM file you are using to isolate which module is causing the error and file a report with the GLM file attached. */ return 0; } }
static mxArray *get_object_data(OBJECT *obj) { mxArray *plhs[1]; /* set the standard info */ #define ERROR "(error)" #define NONE "(none)" char *fnames[1024] = {"id","class","parent","rank","clock","latitude","longitude","in_svc","out_svc","flags",NULL}; // }; int nFields = 0; int nData = 0; char value[1024]; PROPERTY *prop; mxArray *pId = mxCreateString(convert_from_object(value,sizeof(value),&obj,NULL)?value:ERROR); mxArray *pClass = mxCreateString(obj->oclass->name); mxArray *pParent = mxCreateString(obj->parent!=NULL&&convert_from_object(value,sizeof(value),&(obj->parent),NULL)?value:NONE); mxArray *pRank = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); mxArray *pClock = mxCreateString(convert_from_timestamp(obj->clock,value,sizeof(value))?value:ERROR); mxArray *pLatitude = mxCreateString(convert_from_latitude(obj->latitude,value,sizeof(value))?value:NONE); mxArray *pLongitude = mxCreateString(convert_from_longitude(obj->longitude,value,sizeof(value))?value:NONE); mxArray *pInSvc = mxCreateString(convert_from_timestamp(obj->in_svc,value,sizeof(value))?value:ERROR); mxArray *pOutSvc = mxCreateString(convert_from_timestamp(obj->out_svc,value,sizeof(value))?value:ERROR); mxArray *pFlags = mxCreateString(convert_from_set(value,sizeof(value),(void*)&obj->flags,object_flag_property())?value:ERROR); *(OBJECTRANK*)mxGetPr(pRank) = obj->rank; /* count the number of header items */ while (fnames[nFields]!=NULL) nFields++; /* count the number of object properties and assign the field names */ for (prop=class_get_first_property(obj->oclass); prop!=NULL; prop=class_get_next_property(prop)) /** @todo don't damage the original fieldname when making it safe for Matlab */ fnames[nFields+nData++] = make_fieldname(prop->name); /* construct the return value */ plhs[0] = mxCreateStructMatrix(1,1,nFields+nData,fnames); /* construct the header fields */ mxSetFieldByNumber(plhs[0],0,0,pId); mxSetFieldByNumber(plhs[0],0,1,pClass); mxSetFieldByNumber(plhs[0],0,2,pParent); mxSetFieldByNumber(plhs[0],0,3,pRank); mxSetFieldByNumber(plhs[0],0,4,pClock); mxSetFieldByNumber(plhs[0],0,5,pLatitude); mxSetFieldByNumber(plhs[0],0,6,pLongitude); mxSetFieldByNumber(plhs[0],0,7,pInSvc); mxSetFieldByNumber(plhs[0],0,8,pOutSvc); mxSetFieldByNumber(plhs[0],0,9,pFlags); /* construct the data fields */ for (prop=class_get_first_property(obj->oclass); prop!=NULL; nFields++,prop=class_get_next_property(prop)) { mxArray *pValue; if (prop->ptype==PT_double) { pValue = mxCreateDoubleMatrix(1,1,mxREAL); *(double*)mxGetPr(pValue) = *object_get_double(obj,prop); } else if (prop->ptype==PT_int32) { pValue = mxCreateDoubleMatrix(1,1,mxREAL); *(double*)mxGetPr(pValue) = (double)*object_get_int32(obj,prop); } else if (prop->ptype==PT_complex) { complex *pData = object_get_complex(obj,prop); pValue = mxCreateDoubleMatrix(1,1,mxCOMPLEX); *(double*)mxGetPr(pValue) = pData->r; *(double*)mxGetPi(pValue) = pData->i; } else { pValue = mxCreateString(object_get_value_by_name(obj,prop->name,value,sizeof(value))?value:ERROR); } mxSetFieldByNumber(plhs[0],0,nFields,pValue); } return plhs[0]; }