36#ifndef DOXYGEN_SKIP_THIS
39# define _INCLUDE_POSIX_SOURCE
45# define USE_ERRLOGPRINTF 1
58# define DBG_ASRT_COMP 0
61# define DBG_MSG_COMP 0
64# define DBG_TRC_COMP 0
67# define DBG_LOCAL_COMP 1
70# define DBG_ASYNC_COMP 1
77# define CSMBASE_OUT_FILE "stdout"
84# define CSMBASE_TRC_LEVEL 0
87# define CSMBASE_FLUSHMODE 1
92# define errlogPrintf printf
96# define DBG_MSG_PRINTF2(f,x) errlogPrintf(f,x)
99# define DBG_MSG_PRINTF3(f,x,y) errlogPrintf(f,x,y)
102# define DBG_MSG_PRINTF4(f,x,y,z) errlogPrintf(f,x,y,z)
105# define DBG_MSG_PRINTF5(f,x,y,z,q) errlogPrintf(f,x,y,z,q)
114# define SEMCREATE(x) 0
119# define SEM_TYPE psem_mutex
120# define SEMTAKE(x) psem_mutex_take(&(x))
121# define SEMGIVE(x) psem_mutex_give(&(x))
122# define SEMDELETE(x) psem_mutex_remove(&(x))
123# define SEMCREATE(x) (!psem_mutex_create(&(x)))
124# define epicsShareFunc
127# define SEM_TYPE epicsMutexId
129# define SEMTAKE(x) epicsMutexLock(x)
131# define SEMGIVE(x) epicsMutexUnlock(x)
133# define SEMDELETE(x) epicsMutexDestroy(x)
135# define SEMCREATE(x) (NULL==(x= epicsMutexCreate()))
157#include <epicsMutex.h>
179#define epicsExportSharedSymbols
188#define NAN (-(0.0/0.0))
208 { csm_coordinate *coordinate;
224 } csm_linear_function;
241 } csm_1d_functiontable;
260 } csm_2d_functiontable;
266#ifndef DOXYGEN_SKIP_THIS
268typedef enum { CSM_NOTHING,
277 { SEM_TYPE semaphore;
286 union { csm_linear_function lf;
287 csm_1d_functiontable tf_1;
288 csm_2d_functiontable tf_2;
323static void csm_dbg_init(
void)
330 DBG_SET_OUT(CSMBASE_OUT_FILE);
331 DBG_TRC_LEVEL= CSMBASE_TRC_LEVEL;
337 DBG_FLUSHMODE(CSMBASE_FLUSHMODE);
355static void init_coordinates(csm_coordinates *c)
371static csm_bool alloc_coordinates(csm_coordinates *c,
int elements)
375 if (c->no_of_elements==0)
376 c->coordinate= malloc(
sizeof(csm_coordinate)*elements);
378 c->coordinate= realloc(c->coordinate,
379 sizeof(csm_coordinate)*elements);
381 if (c->coordinate==NULL)
382 { DBG_MSG_PRINTF2(
"error in csm:alloc_coordinates line %d,\n"
383 "allocation failed!\n", __LINE__);
388 for(i=c->no_of_elements, co= (c->coordinate + c->no_of_elements);
395 c->no_of_elements= elements;
409static csm_bool resize_coordinates(csm_coordinates *c,
int elements)
410 {
if (elements==c->no_of_elements)
413 c->no_of_elements= elements;
414 if (NULL== (c->coordinate= realloc(c->coordinate,
415 sizeof(csm_coordinate)*elements)))
416 { DBG_MSG_PRINTF2(
"error in csm:resize_coordinates line %d,\n" \
417 "realloc failed!\n", __LINE__);
431static void reinit_coordinates(csm_coordinates *c)
432 {
if (c->no_of_elements==0)
448static csm_bool init_matrix(
double **z,
int rows,
int columns)
452 if (NULL== (zp= malloc((
sizeof(
double))*rows*columns)))
453 { DBG_MSG_PRINTF2(
"error in csm:init_matrix line %d,\n" \
454 "malloc failed!\n", __LINE__);
458 for (i= rows*columns; i>0; i--, *(zp++)=0);
475static int coordinate_cmp(
const void *t1,
const void *t2)
476 {
double x1= ((csm_coordinate *)(t1))->value;
477 double x2= ((csm_coordinate *)(t2))->value;
494static void coordinate_sort( csm_coordinates *coords)
496 qsort( coords->coordinate, coords->no_of_elements,
497 sizeof(csm_coordinate), coordinate_cmp);
515static void coordinate_update_backlinks( csm_coordinates *coords1,
516 csm_coordinates *coords2)
518 csm_coordinate *c,*d;
520 l= coords1->no_of_elements;
521 for (i=0, c= coords1->coordinate, d= coords2->coordinate; i<l; i++, c++)
522 { d[c->index].index = i; };
550#define ret(idx_a, idx_b, ret_code) \
553 coords->a_last= idx_a;\
554 coords->b_last= idx_b;\
557static int coordinate_lookup_index(csm_coordinates *coords,
double x,
567 csm_coordinate *c= coords->coordinate;
569 int last_idx= coords->no_of_elements-1;
573 if (coords->no_of_elements<2)
574 {
if (coords->no_of_elements<1)
576 DBG_MSG_PRINTF2(
"error in csm:coordinate_lookup_index %d,\n" \
577 "table has less than 1 element!\n", __LINE__);
580 coords->a_last= 0; coords->b_last= 0;
591 a_last= coords->a_last;
592 b_last= coords->b_last;
598 for(tries=1; tries<=3; tries++)
614 x_boundary= c[a_last].value;
619 ret(a_last,a_last,2);
627 for(tries=1; tries<=3; tries++)
643 x_boundary= c[b_last].value;
648 ret(b_last,b_last,2);
650 if (b_last==last_idx)
652 ret(last_idx-1,last_idx, 0);
693static double linear_get_y(csm_linear_function *p,
double x)
694 {
return( (p->a) + (p->b)*x ); }
702static double linear_get_x(csm_linear_function *p,
double y)
703 {
return( (y - (p->a))/(p->b) ); }
711static double linear_delta_get_y(csm_linear_function *p,
double x)
712 {
return( (p->b)*x ); }
720static double linear_delta_get_x(csm_linear_function *p,
double y)
721 {
return( y/(p->b) ); }
736static void init_1d_functiontable(csm_1d_functiontable *ft)
737 { init_coordinates(&(ft->x));
738 init_coordinates(&(ft->y));
750static void reinit_1d_functiontable(csm_1d_functiontable *ft)
751 { reinit_coordinates(&(ft->x));
752 reinit_coordinates(&(ft->y));
772static double lookup_1d_functiontable(csm_1d_functiontable *ft,
double x,
777 csm_coordinates *xcoords;
778 csm_coordinates *ycoords;
782 if ((ft->value_cached) && (ft->x_last==x))
789 if ((ft->value_cached) && (ft->y_last==x))
795 res= coordinate_lookup_index(xcoords, x, &a, &b);
803 if ((res== 2)||(a==b))
807 c= (xcoords->coordinate)[a];
812 return(ft->y_last= (ycoords->coordinate)[c.index].value);
817 return(ft->x_last= (ycoords->coordinate)[c.index].value);
821 c= (xcoords->coordinate)[a];
823 ya= (ycoords->coordinate)[c.index].value;
825 c= (xcoords->coordinate)[b];
827 yb= (ycoords->coordinate)[c.index].value;
835 return(ft->y_last= ya + (x-xa)/(xb-xa) * (yb-ya));
841 return(ft->x_last= ya + (x-xa)/(xb-xa) * (yb-ya));
859static void init_2d_functiontable(csm_2d_functiontable *ft)
860 { init_coordinates(&(ft->x));
861 init_coordinates(&(ft->y));
873static void reinit_2d_functiontable(csm_2d_functiontable *ft)
874 { reinit_coordinates(&(ft->x));
875 reinit_coordinates(&(ft->y));
896static double lookup_2d_functiontable(csm_2d_functiontable *ft,
898 {
int res,xia,xib,yia,yib;
900 double zaa,zab,zba,zbb;
904 csm_coordinate cxa,cxb,cya,cyb;
905 csm_coordinates *xcoords= &(ft->x);
906 csm_coordinates *ycoords= &(ft->y);
908 if (ft->value_cached)
910 if ((ft->x_last==x) && (ft->y_last==y))
914 no_of_columns= ycoords->no_of_elements;
916 res= coordinate_lookup_index(xcoords, x, &xia, &xib);
923 res= coordinate_lookup_index(ycoords, y, &yia, &yib);
932 cxa= (xcoords->coordinate)[xia];
933 cxb= (xcoords->coordinate)[xib];
934 cya= (ycoords->coordinate)[yia];
935 cyb= (ycoords->coordinate)[yib];
942 zaa= z[ cxa.index * no_of_columns + cya.index ];
943 zab= z[ cxa.index * no_of_columns + cyb.index ];
944 zba= z[ cxb.index * no_of_columns + cya.index ];
945 zbb= z[ cxb.index * no_of_columns + cyb.index ];
948printf(
"x:%f y:%f xa:%f xb:%f ya:%f yb:%f\n",x,y,xa,xb,ya,yb);
949printf(
"zaa:%f zab:%f zba:%f zbb:%f\n",zaa,zab,zba,zbb);
952 {
double alpha = (xb==xa) ? 0 : (x-xa)/(xb-xa);
953 double beta = (yb==ya) ? 0 : (y-ya)/(yb-ya);
960 return(ft->z_last= zaa);
961 return(ft->z_last= zaa+ beta *(zab-zaa) );
968 return(ft->z_last= zaa+ alpha*(zba-zaa) );
973 zaa + beta*(zab-zaa)+alpha*(zba-zaa+beta*(zbb-zba-zab+zaa)));
979 zaa + beta*(zab-zaa)+alpha*(zba-zaa+beta*(zbb-zba-zab+zaa)) );
986 double delta= (yb-ya)*(xb-xa);
991 return((zaa*yb_*xb_ + zab*y_a*xb_ + zba*yb_*x_a + zbb*y_a*x_a)/delta);
1003 SEMTAKE(func->semaphore);
1006 { ret= func->last_x;
1007 SEMGIVE(func->semaphore);
1016 func->last_x= linear_get_x(&(func->f.lf), y);
1019 func->last_x= lookup_1d_functiontable(&(func->f.tf_1),y,
1027 SEMGIVE(func->semaphore);
1034 SEMTAKE(func->semaphore);
1037 { ret= func->last_y;
1038 SEMGIVE(func->semaphore);
1047 func->last_y= linear_get_y(&(func->f.lf), x);
1050 func->last_y= lookup_1d_functiontable(&(func->f.tf_1),x,
1058 SEMGIVE(func->semaphore);
1065 SEMTAKE(func->semaphore);
1068 { ret= func->last_dx;
1069 SEMGIVE(func->semaphore);
1073 if (func->type==CSM_LINEAR)
1074 func->last_dx= linear_delta_get_x(&(func->f.lf), y);
1079 SEMGIVE(func->semaphore);
1086 SEMTAKE(func->semaphore);
1089 { ret= func->last_dy;
1090 SEMGIVE(func->semaphore);
1094 if (func->type==CSM_LINEAR)
1095 func->last_dy= linear_delta_get_y(&(func->f.lf), x);
1100 SEMGIVE(func->semaphore);
1107 SEMTAKE(func->semaphore);
1110 { ret= func->last_z;
1111 SEMGIVE(func->semaphore);
1115 if (func->type==CSM_2D_TABLE)
1116 func->last_z= lookup_2d_functiontable(&(func->f.tf_2), x, y);
1121 SEMGIVE(func->semaphore);
1139 {
if (func->type==CSM_NOTHING)
1141 if (func->type==CSM_1D_TABLE)
1142 reinit_1d_functiontable( &(func->f.tf_1) );
1143 if (func->type==CSM_2D_TABLE)
1144 reinit_2d_functiontable( &(func->f.tf_2) );
1149 func->type= CSM_NOTHING;
1162static csm_bool str_empty_or_comment(
char *st)
1163 {
for(;*st!=0; st++)
1188static int strdoublescan(
char *st,
double *d,
int no_of_cols)
1201 if ((no_of_cols<=0)||(no_of_cols>1000))
1203 for( ;NULL!=strchr(
" \t\r\n", *st); st++);
1206 strncpy(buf, st, 1023); buf[1023]=0;
1208 for(dptr= d, i=0; i<no_of_cols; i++, *(dptr++)=0 );
1209 for(p= str, dptr= d, i=0; i<no_of_cols; i++, dptr++)
1211 if (NULL== (p= strtok(str,
" \t\r\n")))
1215 {
if (1!=sscanf(p,
"%lf",dptr))
1225 { SEMTAKE(func->semaphore);
1227 SEMGIVE(func->semaphore);
1229 reinit_function(func);
1238 SEMDELETE(func->semaphore);
1246 { SEMTAKE(func->semaphore);
1248 SEMGIVE(func->semaphore);
1250 reinit_function(func);
1252 func->type= CSM_LINEAR;
1260 {
if (func->type!=CSM_LINEAR)
1261 { DBG_MSG_PRINTF2(
"error in csm_def_linear_offset line %d,\n" \
1262 "not a linear function!\n", __LINE__);
1266 SEMTAKE(func->semaphore);
1268 SEMGIVE(func->semaphore);
1278 csm_1d_functiontable *ft= &(func->f.tf_1);
1279 csm_coordinate *xc, *yc;
1282 SEMTAKE(func->semaphore);
1284 SEMGIVE(func->semaphore);
1286 reinit_function(func);
1288 init_1d_functiontable(ft);
1290 if (!alloc_coordinates(&(ft->x), len))
1292 reinit_function(func);
1297 if (!alloc_coordinates(&(ft->y), len))
1299 reinit_function(func);
1304 xc= (ft->x).coordinate;
1305 yc= (ft->y).coordinate;
1307 for(row=0; row<len; row++, xc++, yc++, x++, y++)
1315 func->type= CSM_1D_TABLE;
1317 coordinate_sort(&(ft->x));
1318 coordinate_update_backlinks(&(ft->x), &(ft->y));
1319 coordinate_sort(&(ft->y));
1320 coordinate_update_backlinks(&(ft->y), &(ft->x));
1332 csm_1d_functiontable *ft= &(func->f.tf_1);
1333 csm_coordinate *xc, *yc;
1338 if (NULL==(f=fopen(filename,
"r")))
1339 { DBG_MSG_PRINTF2(
"error in csm_read_xytable line %d,\n" \
1340 "file open error!\n", __LINE__);
1345 for(len=0; NULL!=fgets(line, 127, f); len++);
1346 if (-1==fseek(f, pos, SEEK_SET))
1351 SEMTAKE(func->semaphore);
1353 SEMGIVE(func->semaphore);
1355 reinit_function(func);
1357 init_1d_functiontable(ft);
1359 if (!alloc_coordinates(&(ft->x), len))
1361 reinit_function(func);
1366 if (!alloc_coordinates(&(ft->y), len))
1368 reinit_function(func);
1373 xc= (ft->x).coordinate;
1374 yc= (ft->y).coordinate;
1376 for(errcount=0, i=0;(len>0) && (NULL!=fgets(line, 127, f)); len--)
1377 {
if (str_empty_or_comment(line))
1379 if (2!=sscanf(line,
" %lf %lf %c",
1380 &(xc->value), &(yc->value), &dummy))
1381 { DBG_MSG_PRINTF5(
"warning[%s:%d]: the following line of the "
1382 "data-file (%s) was not understood:\n%s\n",
1383 __FILE__,__LINE__,filename,line);
1387 reinit_function(func);
1389 DBG_MSG_PRINTF3(
"error[%s:%d]: too many errors in file\n",
1399 reinit_function(func);
1401 DBG_MSG_PRINTF3(
"error[%s:%d]: no data was found at all\n",
1406 if (!resize_coordinates(&(ft->x), i))
1408 reinit_function(func);
1412 if (!resize_coordinates(&(ft->y), i))
1414 reinit_function(func);
1420 func->type= CSM_1D_TABLE;
1422 coordinate_sort(&(ft->x));
1423 coordinate_update_backlinks(&(ft->x), &(ft->y));
1424 coordinate_sort(&(ft->y));
1425 coordinate_update_backlinks(&(ft->y), &(ft->x));
1441 long i,j,lines,errcount;
1444 csm_2d_functiontable *ft= &(func->f.tf_2);
1445 csm_coordinate *xc, *yc;
1449 if (NULL==(f=fopen(filename,
"r")))
1450 { DBG_MSG_PRINTF2(
"error in csm_read_xytable line %d,\n" \
1451 "file open error!\n", __LINE__);
1455 if (NULL==fgets(line, 1024, f))
1460 columns= strdoublescan(line, NULL, 512);
1465 if (NULL==(buffer= malloc(
sizeof(
double)*(columns+1))))
1466 { DBG_MSG_PRINTF2(
"MALLOC FAILED in file %s\n",__FILE__);
1470 if (columns!= (i= strdoublescan(line, buffer, columns)))
1471 { DBG_MSG_PRINTF3(
"unexpected err in line %d in file %s\n",
1478 SEMTAKE(func->semaphore);
1480 SEMGIVE(func->semaphore);
1482 reinit_function(func);
1483 init_2d_functiontable(ft);
1485 if (!alloc_coordinates(&(ft->y), columns))
1487 reinit_function(func);
1493 yc= (ft->y).coordinate;
1496 {
double *r= buffer;
1497 csm_coordinate *c= yc;
1498 for(i=0; i< columns; i++, c++, r++ )
1505 for(lines=0; NULL!=fgets(line, 1024, f); lines++);
1506 if (-1==fseek(f, pos, SEEK_SET))
1508 reinit_function(func);
1515 if (!alloc_coordinates(&(ft->x), rows))
1517 reinit_function(func);
1523 xc= (ft->x).coordinate;
1525 if (!init_matrix(&(ft->z), rows, columns))
1527 reinit_function(func);
1535 for(errcount=0, i=0; (lines>0) && (NULL!=fgets(line, 1024, f)); lines--)
1537 if (str_empty_or_comment(line))
1539 if (columns+1 != strdoublescan(line, buffer, columns+1))
1540 { DBG_MSG_PRINTF5(
"warning[%s:%d]: the following line of the "
1541 "data-file (%s) was not understood:\n%s\n",
1542 __FILE__,__LINE__,filename,line);
1546 reinit_function(func);
1548 DBG_MSG_PRINTF3(
"error[%s:%d]: too many errors in file\n",
1553 xc->value= buffer[0];
1556 zptr= &((ft->z)[i*columns]);
1557 for (j=0; j<columns; j++)
1558 zptr[j]= buffer[j+1];
1565 reinit_function(func);
1568 DBG_MSG_PRINTF3(
"error[%s:%d]: no data was found at all\n",
1574 if (!resize_coordinates(&(ft->x), rows))
1576 reinit_function(func);
1585 func->type= CSM_2D_TABLE;
1587 coordinate_sort(&(ft->x));
1588 coordinate_sort(&(ft->y));
1615 f->type= CSM_NOTHING;
1622 if (SEMCREATE(f->semaphore))
1639static void csm_pr_coordinates(csm_coordinates *c)
1641 printf(
"no . of elements: %d\n", c->no_of_elements);
1643 printf(
"(still in initial-state)\n");
1645 { printf(
"a_last:%d b_last:%d\n",
1646 c->a_last, c->b_last);
1648 for(i=0; i< c->no_of_elements; i++)
1649 printf(
" [%03d]: %12f --> %3d\n",
1650 i,(c->coordinate)[i].value,(c->coordinate)[i].index);
1660static void csm_pr_1d_table_elm(csm_1d_functiontable *t,
int index)
1663 csm_coordinate xc= (t->x).coordinate[index];
1664 printf(
"x: %15f y: %15f\n",
1665 xc.value, ((t->y).coordinate)[xc.index].value);
1674static void csm_pr_linear(csm_linear_function *lf)
1675 { printf(
"a:%f b:%f (y=a+b*x)\n", lf->a, lf->b); }
1683static void csm_pr_1d_table(csm_1d_functiontable *tf)
1685 int l= (tf->x).no_of_elements;
1687 if (tf->x.a_last==-1)
1688 printf(
"x-coord is still in initial-state\n");
1690 printf(
"x-a_last:%d x-b_last:%d\n", tf->x.a_last, tf->x.b_last);
1691 if (tf->y.a_last==-1)
1692 printf(
"x-coord is still in initial-state\n");
1694 printf(
"y-a_last:%d y-b_last:%d\n", tf->y.a_last, tf->y.b_last);
1695 printf(
"number of elements: %d\n", l);
1697 csm_pr_1d_table_elm( tf, i);
1706static void csm_pr_2d_table(csm_2d_functiontable *ft)
1708 int rows = ft->x.no_of_elements;
1709 int columns= ft->y.no_of_elements;
1711 csm_coordinate *xc= ft->x.coordinate;
1712 csm_coordinate *yc= ft->y.coordinate;
1714 printf(
"rows:%d columns:%d\n",
1717 for (j=0; j<columns; j++)
1718 printf(
"%15f | ", yc[j].value);
1720 printf(
"------------------");
1721 for (j=0; j<columns; j++)
1722 { printf(
"---------------"); };
1723 for(i=0; i<rows; i++)
1724 { printf(
"%15f | ", xc[i].value);
1725 for (j=0; j<columns; j++)
1726 printf(
"%15f | ", z[columns*i+j]);
1732 {
if (func->on_hold)
1733 printf(
"function is on hold!\n");
1735 printf(
"function is operational\n");
1737 printf(
"Last calculated values: x:%f y:%f z:%f dx:%f dy%f\n",
1738 func->last_x, func->last_y, func->last_z,
1739 func->last_dx, func->last_dy);
1741 printf(
"function type: \n");
1744 printf(
"CSM_NOTHING\n");
1747 printf(
"CSM_LINEAR\n");
1748 csm_pr_linear(&(func->f.lf));
1751 printf(
"CSM_1D TABLE\n");
1752 printf(
"normal function:\n");
1753 csm_pr_1d_table(&(func->f.tf_1));
1756 printf(
"CSM_2D_TABLE\n");
1757 csm_pr_2d_table(&(func->f.tf_2));
1760 printf(
"%d (unknown)\n", func->type);
#define CSM_FALSE
for type csm_bool
#define CSM_TRUE
for type csm_bool
void csm_free(csm_function *func)
free a function-structure
csm_bool csm_def_linear_offset(csm_function *func, double a)
re-define the offset of a linear function
double csm_dy(csm_function *func, double x)
compute delta-y from a given delta-x
csm_bool csm_read_2d_table(char *filename, csm_function *func)
read parameters of two-dimensional function table
void csm_def_linear(csm_function *func, double a, double b)
define a linear function
double csm_x(csm_function *func, double y)
compute x from a given y
csm_function * csm_new_function(void)
create a new function object
void csm_pr_func(csm_function *func)
dump a new function object
void csm_clear(csm_function *func)
clear a function
csm_bool csm_fill_1d_table(double *x, double *y, int len, csm_function *func)
fill one-dimensional function table from double arrays.
csm_bool csm_read_1d_table(char *filename, csm_function *func)
read parameters of one-dimensional function table
double csm_dx(csm_function *func, double y)
compute delta-x from a given delta-y
double csm_z(csm_function *func, double x, double y)
compute z from a given x and y
void csm_init(void)
initialize the module
double csm_y(csm_function *func, double x)
compute y from a given x
int csm_bool
the boolean data type used in this module
struct csm_Function csm_function
the abstract csm function object