// Copyright SIMetrix Technologies. 2004, All rights reserved // Module Example.cpp // created 19.5.04 // Library: // Notes: // Example of user function definition. // // You may do anything you like with this code except sell it. #include #include #include "UserFunctionInterface.h" //---------- Macro definitions ---------// //--------------------------------------// //---------- Type definitions ----------// //--------------------------------------// //--------- Extern functions -----------// //--------------------------------------// //---------- Extern data ---------------// //--------------------------------------// //--------- Local functions ------------// //--------------------------------------// //---------- Local Data-----------------// //--------------------------------------// //---------- Public data ---------------// //--------------------------------------// REGISTER_INTERFACE_DYNAMIC // A simple function that multiplies the argument by 2. This version // will not return a reference (x-values) even if supplied as an argument DEFINE_USER_FUNCTION(Times2, {DAT_Real}, 1) { // The number of elements in argument 0 // iface->data[1].length e.g. would provide the number of // elements in argument 1 etc int numElems = iface->data[0].length ; // allocate output array. You must allocate the output data // using this function. malloc or new won't work and will simply // give you a memory leak. SIMetrix will take care of freeing up the // memory allocated by this function. // // (You can of course use malloc or new to allocate temporary data for // intermediate results and the like, but you are responsible for freeing // such data) double *result = iface->makeReal(iface, numElems, iface->data[0].physType) ; int idx ; for (idx=0 ; idxdata[0].realData provides the real data for arg0. // For this function we have made arg0 compulsory and real. So // in this case we can be sure that iface->data[0].realData // will be valid. If the argument could be multiple types // or if the argument were optional, then it would be essential // to test what the user passed. iface->data[0].dataType provides // information on the type of data passed. result[idx] = 2 * iface->data[0].realData[idx] ; } } // Same as times2 but also passes "reference" data. These are the x-values if present. // For example, if a vector created by a transient run were passed, the x-values // would be the time points. Note that not all vectors have a reference and it is // essential that the presence or otherwise of a reference is tested. // The realRefData field of UserArgumentData will be non-NULL if a reference present. DEFINE_USER_FUNCTION(Times2Ref, {DAT_Real}, 1) { int numElems = iface->data[0].length ; // allocate output array double *result = iface->makeReal(iface, numElems, iface->data[0].physType) ; // allocate x-values (reference) for output double *ref ; if (iface->data[0].realRefData!=NULL) ref = iface->makeRealRef(iface, numElems, iface->data[0].refPhysType) ; else ref = NULL ; int idx ; for (idx=0 ; idxdata[0].realData[idx] ; // copy reference data if present if (ref!=NULL) ref[idx] = iface->data[0].realRefData[idx] ; } } static int comp(const void *str1, const void *str2) { const char *s1 = *((const char**)str1) ; const char *s2 = *((const char**)str2) ; return strcmp( s1, s2) ; } // An example of a string processing function. This sorts items in // alphabetical order, but unlike the built in Sort function, this one is // case sensitive DEFINE_USER_FUNCTION(SortCs, {DAT_Str}, 1) { int numElems = iface->data[0].length, idx ; // Returns an array of string pointers. Does NOT allocate the strings // themselves char **result = iface->makeString(iface, numElems) ; for (idx=0 ; idxdupString(iface->data[0].stringData[idx]) ; } qsort(result, numElems, sizeof(char*), comp) ; }