TPCCLIB
Loading...
Searching...
No Matches
units.c
Go to the documentation of this file.
1
4/*****************************************************************************/
5#include "tpcclibConfig.h"
6/*****************************************************************************/
7#include "tpcextensions.h"
8/*****************************************************************************/
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <strings.h>
13#include <ctype.h>
14#include <math.h>
15#include <time.h>
16/*****************************************************************************/
17
18/*****************************************************************************/
22typedef struct TPC_UNIT {
24 char name[MAX_UNITS_LEN];
26 int u1;
28 int u2;
30 int v1;
32 int v2;
33} TPC_UNIT;
34
36static TPC_UNIT tpc_unit[]={
98 {"sec*kBq/mL", UNIT_KBQ, UNIT_SEC, UNIT_ML, UNIT_UNITLESS},
99 {"min*kBq/mL", UNIT_KBQ, UNIT_MIN, UNIT_ML, UNIT_UNITLESS},
100 {"sec*Bq/mL", UNIT_BQ, UNIT_SEC, UNIT_ML, UNIT_UNITLESS},
101 {"min*Bq/mL", UNIT_BQ, UNIT_MIN, UNIT_ML, UNIT_UNITLESS},
110 {"mL/(mL*sec)", UNIT_ML, UNIT_UNITLESS, UNIT_ML, UNIT_SEC},
111 {"mL/(mL*min)", UNIT_ML, UNIT_UNITLESS, UNIT_ML, UNIT_MIN},
112 {"mL/(dL*min)", UNIT_ML, UNIT_UNITLESS, UNIT_DL, UNIT_MIN},
113 {"mL/(g*min)", UNIT_ML, UNIT_UNITLESS, UNIT_G, UNIT_MIN},
114 {"mL/(100g*min)", UNIT_ML, UNIT_UNITLESS, UNIT_100G, UNIT_MIN},
115 {"umol/(mL*min)", UNIT_UMOL, UNIT_UNITLESS, UNIT_ML, UNIT_MIN},
116 {"umol/(dL*min)", UNIT_UMOL, UNIT_UNITLESS, UNIT_DL, UNIT_MIN},
117 {"umol/(g*min)", UNIT_UMOL, UNIT_UNITLESS, UNIT_G, UNIT_MIN},
118 {"umol/(100g*min)", UNIT_UMOL, UNIT_UNITLESS, UNIT_100G, UNIT_MIN},
119 {"mmol/(mL*min)", UNIT_MMOL, UNIT_UNITLESS, UNIT_ML, UNIT_MIN},
120 {"mmol/(dL*min)", UNIT_MMOL, UNIT_UNITLESS, UNIT_DL, UNIT_MIN},
121 {"mmol/(g*min)", UNIT_MMOL, UNIT_UNITLESS, UNIT_G, UNIT_MIN},
122 {"mmol/(100g*min)", UNIT_MMOL, UNIT_UNITLESS, UNIT_100G, UNIT_MIN},
123 {"mg/(100g*min)", UNIT_MG, UNIT_UNITLESS, UNIT_100G, UNIT_MIN},
124 {"mg/(dL*min)", UNIT_MG, UNIT_UNITLESS, UNIT_DL, UNIT_MIN},
133};
135/*****************************************************************************/
136
137/*****************************************************************************/
145 int unit_code
146) {
147 int n=0;
148
149 while(strlen(tpc_unit[n].name)>0) n++;
150 if(unit_code<1 || unit_code>n-1)
151 return tpc_unit[UNIT_UNKNOWN].name;
152 else
153 return(tpc_unit[unit_code].name);
154}
155/*****************************************************************************/
156
157/*****************************************************************************/
164 const char *s
165) {
166 if(s==NULL || strnlen(s, 1)<1) return UNIT_UNKNOWN;
167 /* Try if string can be found directly in the table */
168 int i, n=0;
169 while(strlen(tpc_unit[n].name)>0) n++;
170 for(i=0; i<n; i++) {
171 if(strcasecmp(tpc_unit[i].name, s)==0) return i;
172 }
173 /* Unit string is not following TPC standard, lets try something else */
174 if( strcasecmp(s, "ms")==0) return UNIT_MSEC;
175 else if(strcasecmp(s, "s")==0) return UNIT_SEC;
176 else if(strcasecmp(s, "second")==0) return UNIT_SEC;
177 else if(strcasecmp(s, "seconds")==0) return UNIT_SEC;
178 else if(strcasecmp(s, "mins")==0) return UNIT_MIN;
179 else if(strcasecmp(s, "minute")==0) return UNIT_MIN;
180 else if(strcasecmp(s, "minutes")==0) return UNIT_MIN;
181 else if(strcasecmp(s, "hours")==0) return UNIT_HOUR;
182 else if(strcasecmp(s, "days")==0) return UNIT_DAY;
183 else if(strcasecmp(s, "months")==0) return UNIT_MONTH;
184 else if(strcasecmp(s, "years")==0) return UNIT_YEAR;
185 else if(strcasecmp(s, "yrs")==0) return UNIT_YEAR;
186 else if(strcasecmp(s, "microm")==0) return UNIT_UM;
187 else if(strcasecmp(s, "millim")==0) return UNIT_MM;
188 else if(strcasecmp(s, "microl")==0) return UNIT_UL;
189 else if(strcasecmp(s, "mm^3")==0) return UNIT_UL;
190 else if(strcasecmp(s, "cc")==0) return UNIT_ML;
191 else if(strcasecmp(s, "liter")==0) return UNIT_L;
192 else if(strcasecmp(s, "microgram")==0) return UNIT_UG;
193 else if(strcasecmp(s, "milligram")==0) return UNIT_MG;
194 else if(strcasecmp(s, "gram")==0) return UNIT_G;
195 else if(strcasecmp(s, "100 g")==0) return UNIT_100G;
196 else if(strcasecmp(s, "kilogram")==0) return UNIT_KG;
197 else if(strcasecmp(s, "micromol")==0) return UNIT_UMOL;
198 else if(strcasecmp(s, "micromoles")==0) return UNIT_UMOL;
199 else if(strcasecmp(s, "millimol")==0) return UNIT_MMOL;
200 else if(strcasecmp(s, "millimoles")==0) return UNIT_MMOL;
201 else if(strcasecmp(s, "mole")==0) return UNIT_MOL;
202 else if(strcasecmp(s, "moles")==0) return UNIT_MOL;
203 else if(strcasecmp(s, "cnts")==0) return UNIT_COUNTS;
204 else if(strcasecmp(s, "kcnts")==0) return UNIT_KCOUNTS;
205 else if(strcasecmp(s, "becquerels")==0) return UNIT_BQ;
206 else if(strcasecmp(s, "kbecquerels")==0) return UNIT_KBQ;
207 else if(strcasecmp(s, "cnts/s")==0) return UNIT_CPS;
208 else if(strcasecmp(s, "counts/s")==0) return UNIT_CPS;
209 else if(strcasecmp(s, "counts/sec")==0) return UNIT_CPS;
210 else if(strcasecmp(s, "ECAT counts/sec")==0) return UNIT_CPS;
211 else if(strcasecmp(s, "kcounts/s")==0) return UNIT_KCPS;
212 else if(strcasecmp(s, "kcounts/sec")==0) return UNIT_KCPS;
213 else if(strcasecmp(s, "counts/min")==0) return UNIT_CPM;
214 else if(strcasecmp(s, "kcounts/min")==0) return UNIT_KCPM;
215 else if(strcasecmp(s, "Bq/cc")==0) return UNIT_BQ_PER_ML;
216 else if(strcasecmp(s, "Bqcc")==0) return UNIT_BQ_PER_ML;
217 else if(strcasecmp(s, "BqmL")==0) return UNIT_BQ_PER_ML;
218 else if(strcasecmp(s, "kBq/cc")==0) return UNIT_KBQ_PER_ML;
219 else if(strcasecmp(s, "kBqcc")==0) return UNIT_KBQ_PER_ML;
220 else if(strcasecmp(s, "kBqmL")==0) return UNIT_KBQ_PER_ML;
221 else if(strcasecmp(s, "MBq/cc")==0) return UNIT_MBQ_PER_ML;
222 else if(strcasecmp(s, "MBqcc")==0) return UNIT_MBQ_PER_ML;
223 else if(strcasecmp(s, "MBqmL")==0) return UNIT_MBQ_PER_ML;
224 else if(strcasecmp(s, "nCi/cc")==0) return UNIT_NCI_PER_ML;
225 else if(strcasecmp(s, "nCicc")==0) return UNIT_NCI_PER_ML;
226 else if(strcasecmp(s, "nCimL")==0) return UNIT_NCI_PER_ML;
227 else if(strcasecmp(s, "uCi/cc")==0) return UNIT_UCI_PER_ML;
228 else if(strcasecmp(s, "uCicc")==0) return UNIT_UCI_PER_ML;
229 else if(strcasecmp(s, "uCimL")==0) return UNIT_UCI_PER_ML;
230 else if(strcasecmp(s, "integral")==0) return UNIT_SEC_KBQ_PER_ML;
231 else if(strcasecmp(s, "percent")==0) return UNIT_PERCENTAGE;
232 else if(strcasecmp(s, "perc")==0) return UNIT_PERCENTAGE;
233 else if(strcasecmp(s, "cc/cc")==0) return UNIT_ML_PER_ML;
234 else if(strcasecmp(s, "mL/cc")==0) return UNIT_ML_PER_ML;
235 else if(strcasecmp(s, "cc/mL")==0) return UNIT_ML_PER_ML;
236 else if(strcasecmp(s, "g/cc")==0) return UNIT_G_PER_ML;
237 else if(strcasecmp(s, "SUV")==0) return UNIT_G_PER_ML;
238 else if(strcasecmp(s, "SUVbw")==0) return UNIT_G_PER_ML;
239 else if(strcasecmp(s, "SUV_bw")==0) return UNIT_G_PER_ML;
240 else if(strcasecmp(s, "cc/g")==0) return UNIT_ML_PER_G;
241 else if(strcasecmp(s, "1/s")==0) return UNIT_PER_SEC;
242 else if(strcasecmp(s, "s-1")==0) return UNIT_PER_SEC;
243 else if(strcasecmp(s, "min-1")==0) return UNIT_PER_MIN;
244 else if(strcasecmp(s, "h-1")==0) return UNIT_PER_HOUR;
245 else if(strcmp(s, "pM")==0) return UNIT_PMOL_PER_L;
246 else if(strcmp(s, "nM")==0) return UNIT_NMOL_PER_L;
247 else if(strcmp(s, "uM")==0) return UNIT_UMOL_PER_L;
248 else if(strcmp(s, "mM")==0) return UNIT_MMOL_PER_L;
249 else if(strcasecmp(s, "mL/(sec*mL)")==0) return UNIT_ML_PER_ML_SEC;
250 else if(strcasecmp(s, "mL/sec/mL")==0) return UNIT_ML_PER_ML_SEC;
251 else if(strcasecmp(s, "mL/mL/sec")==0) return UNIT_ML_PER_ML_SEC;
252 else if(strcasecmp(s, "cc/sec/cc")==0) return UNIT_ML_PER_ML_SEC;
253 else if(strcasecmp(s, "cc/cc/sec")==0) return UNIT_ML_PER_ML_SEC;
254 else if(strcasecmp(s, "mL/(sec*cc)")==0) return UNIT_ML_PER_ML_SEC;
255 else if(strcasecmp(s, "mL/(cc*sec)")==0) return UNIT_ML_PER_ML_SEC;
256 else if(strcasecmp(s, "cc/(cc*sec)")==0) return UNIT_ML_PER_ML_SEC;
257 else if(strcasecmp(s, "mL/(min*mL)")==0) return UNIT_ML_PER_ML_MIN;
258 else if(strcasecmp(s, "mL/min/mL")==0) return UNIT_ML_PER_ML_MIN;
259 else if(strcasecmp(s, "mL/mL/min")==0) return UNIT_ML_PER_ML_MIN;
260 else if(strcasecmp(s, "cc/min/cc")==0) return UNIT_ML_PER_ML_MIN;
261 else if(strcasecmp(s, "cc/cc/min")==0) return UNIT_ML_PER_ML_MIN;
262 else if(strcasecmp(s, "mL/(min*g)")==0) return UNIT_ML_PER_G_MIN;
263 else if(strcasecmp(s, "mL/(min*cc)")==0) return UNIT_ML_PER_ML_MIN;
264 else if(strcasecmp(s, "mL/(cc*min)")==0) return UNIT_ML_PER_ML_MIN;
265 else if(strcasecmp(s, "cc/(cc*min)")==0) return UNIT_ML_PER_ML_MIN;
266 else if(strcasecmp(s, "mL/(min*dL)")==0) return UNIT_ML_PER_DL_MIN;
267 else if(strcasecmp(s, "mL/min/dL")==0) return UNIT_ML_PER_DL_MIN;
268 else if(strcasecmp(s, "mL/dL/min")==0) return UNIT_ML_PER_DL_MIN;
269 else if(strcasecmp(s, "umol/(min*mL)")==0) return UNIT_UMOL_PER_ML_MIN;
270 else if(strcasecmp(s, "umol/(min*dL)")==0) return UNIT_UMOL_PER_DL_MIN;
271 else if(strcasecmp(s, "umol/dL/min)")==0) return UNIT_UMOL_PER_DL_MIN;
272 else if(strcasecmp(s, "umol/(min*g)")==0) return UNIT_UMOL_PER_G_MIN;
273 else if(strcasecmp(s, "umol/(min*100g)")==0) return UNIT_UMOL_PER_100G_MIN;
274 else if(strcasecmp(s, "mmol/(min*mL)")==0) return UNIT_MMOL_PER_ML_MIN;
275 else if(strcasecmp(s, "mmol/(min*dL)")==0) return UNIT_MMOL_PER_DL_MIN;
276 else if(strcasecmp(s, "mmol/dL/min)")==0) return UNIT_MMOL_PER_DL_MIN;
277 else if(strcasecmp(s, "mmol/(min*g)")==0) return UNIT_MMOL_PER_G_MIN;
278 else if(strcasecmp(s, "mmol/(min*100g)")==0) return UNIT_MMOL_PER_100G_MIN;
279 else if(strcasecmp(s, "% ID")==0) return UNIT_PID;
280 else if(strcasecmp(s, "%i.d.")==0) return UNIT_PID;
281 else if(strcasecmp(s, "PID")==0) return UNIT_PID;
282 else if(strcasecmp(s, "% ID/mL")==0) return UNIT_PID_PER_ML;
283 else if(strcasecmp(s, "%i.d./mL")==0) return UNIT_PID_PER_ML;
284 else if(strcasecmp(s, "PID/mL")==0) return UNIT_PID_PER_ML;
285 else if(strcasecmp(s, "%ID/cc")==0) return UNIT_PID_PER_ML;
286 else if(strcasecmp(s, "% ID/cc")==0) return UNIT_PID_PER_ML;
287 else if(strcasecmp(s, "PID/cc")==0) return UNIT_PID_PER_ML;
288 else if(strcasecmp(s, "% ID/L")==0) return UNIT_PID_PER_L;
289 else if(strcasecmp(s, "%i.d./L")==0) return UNIT_PID_PER_L;
290 else if(strcasecmp(s, "PID/L")==0) return UNIT_PID_PER_L;
291 else if(strcasecmp(s, "% ID/g")==0) return UNIT_PID_PER_G;
292 else if(strcasecmp(s, "%i.d./g")==0) return UNIT_PID_PER_G;
293 else if(strcasecmp(s, "PID/g")==0) return UNIT_PID_PER_G;
294 else if(strcasecmp(s, "% ID/kg")==0) return UNIT_PID_PER_KG;
295 else if(strcasecmp(s, "%i.d./kg")==0) return UNIT_PID_PER_KG;
296 else if(strcasecmp(s, "PID/kg")==0) return UNIT_PID_PER_KG;
297 else if(strcasecmp(s, "Hounsfield Unit")==0) return UNIT_HU;
298 else if(strcasecmp(s, "HU")==0) return UNIT_HU;
299 else if(strcasecmp(s, "1/1")==0) return UNIT_UNITLESS;
300
301 return UNIT_UNKNOWN;
302}
303/*****************************************************************************/
304
305/*****************************************************************************/
313 const char *s
314) {
315 if(s==NULL || strnlen(s, 3)<3) return UNIT_UNKNOWN;
316 char *cptr;
317 for(int i=0; i<2; i++) {
318 if(i==0) /* On the first run, look in the extension */
319 {cptr=strrchr((char*)s, '.'); if(cptr==NULL) {cptr=(char*)s; i++;}}
320 else /* Then, look into whole filename */
321 cptr=(char*)s;
322 if(strcasestr(cptr, "KBQ")) return UNIT_KBQ_PER_ML;
323 if(strcasestr(cptr, "MBQ")) return UNIT_MBQ_PER_ML;
324 if(strcasestr(cptr, "BQ")) return UNIT_BQ_PER_ML;
325 if(strcasestr(cptr, "NCI")) return UNIT_NCI_PER_ML;
326 if(strcasestr(cptr, "KCPS")) return UNIT_KCPS;
327 if(strcasestr(cptr, "CPS")) return UNIT_CPS;
328 if(strcasestr(cptr, "SUV")) return UNIT_G_PER_ML;
329 }
330 return UNIT_UNKNOWN;
331}
332/*****************************************************************************/
333
334/*****************************************************************************/
341 int u
342) {
343 switch(u) {
344 case UNIT_UM:
345 case UNIT_MM:
346 case UNIT_CM:
347 case UNIT_M:
348 return 1;
349 }
350 return 0;
351}
352/*****************************************************************************/
353
354/*****************************************************************************/
361 int u
362) {
363 switch(u) {
364 case UNIT_MSEC:
365 case UNIT_SEC:
366 case UNIT_MIN:
367 case UNIT_HOUR:
368 case UNIT_DAY:
369 case UNIT_MONTH:
370 case UNIT_YEAR:
371 return 1;
372 }
373 return 0;
374}
375/*****************************************************************************/
376
377/*****************************************************************************/
384 int u
385) {
386 switch(u) {
387 case UNIT_UL:
388 case UNIT_ML:
389 case UNIT_DL:
390 case UNIT_L:
391 return 1;
392 }
393 return 0;
394}
395/*****************************************************************************/
396
397/*****************************************************************************/
404 int u
405) {
406 switch(u) {
407 case UNIT_UG:
408 case UNIT_MG:
409 case UNIT_G:
410 case UNIT_100G:
411 case UNIT_KG:
412 return 1;
413 }
414 return 0;
415}
416/*****************************************************************************/
417
418/*****************************************************************************/
425 int u
426) {
427 switch(u) {
428 case UNIT_PMOL:
429 case UNIT_NMOL:
430 case UNIT_UMOL:
431 case UNIT_MMOL:
432 case UNIT_MOL:
433 return 1;
434 }
435 return 0;
436}
437/*****************************************************************************/
438
439/*****************************************************************************/
446 int u
447) {
448 switch(u) {
449 case UNIT_BQ:
450 case UNIT_KBQ:
451 case UNIT_MBQ:
452 case UNIT_GBQ:
453 case UNIT_NCI:
454 case UNIT_UCI:
455 case UNIT_MCI:
456 case UNIT_CI:
457 return 1;
458 }
459 return 0;
460}
461/*****************************************************************************/
462
463/*****************************************************************************/
470 int u
471) {
472 if(u<1 || u>=UNIT_LAST) return 0;
473 if(tpc_unit[u].u2==UNIT_UNITLESS && tpc_unit[u].v1==UNIT_UNITLESS &&
474 tpc_unit[u].v2==UNIT_UNITLESS) return 0;
475 return 1;
476}
477/*****************************************************************************/
478
479/*****************************************************************************/
489 const int u1,
491 const int u2
492) {
493 //printf("unitConversionFactor(%s, %s)\n", unitName(u1), unitName(u2));
494 double cf=nan("");
495 if(u1==UNIT_UNKNOWN || u2==UNIT_UNKNOWN) return cf;
496 if(u1==u2) return 1.0;
497
498 /* If both are time units, then this is easy */
499 if(unitIsTime(u1) && unitIsTime(u2)) {
500 if(u1==UNIT_MSEC) cf=1.0E-3;
501 else if(u1==UNIT_SEC) cf=1.0;
502 else if(u1==UNIT_MIN) cf=60.0;
503 else if(u1==UNIT_HOUR) cf=3600.0;
504 else if(u1==UNIT_DAY) cf=24.0*36000.0;
505 else if(u1==UNIT_MONTH) cf=30.0*24.0*36000.0;
506 else if(u1==UNIT_YEAR) cf=365.0*30.0*24.0*36000.0;
507 if(u2==UNIT_MSEC) cf/=1.0E-3;
508 else if(u2==UNIT_SEC) cf/=1.0;
509 else if(u2==UNIT_MIN) cf/=60.0;
510 else if(u2==UNIT_HOUR) cf/=3600.0;
511 else if(u2==UNIT_DAY) cf/=24.0*36000.0;
512 else if(u2==UNIT_MONTH) cf/=30.0*24.0*36000.0;
513 else if(u2==UNIT_YEAR) cf/=365.0*30.0*24.0*36000.0;
514 else cf=nan("");
515 return cf;
516 }
517
518 /* If both are distances */
519 if(unitIsDistance(u1) && unitIsDistance(u2)) {
520 if(u1==UNIT_UM) cf=1.0E-6;
521 else if(u1==UNIT_MM) cf=1.0E-3;
522 else if(u1==UNIT_CM) cf=1.0E-2;
523 else if(u1==UNIT_M) cf=1.0;
524 if(u2==UNIT_UM) cf/=1.0E-6;
525 else if(u2==UNIT_MM) cf/=1.0E-3;
526 else if(u2==UNIT_CM) cf/=1.0E-2;
527 else if(u2==UNIT_M) cf/=1.0;
528 else cf=nan("");
529 return cf;
530 }
531
532 /* If both are volumes */
533 if(unitIsVolume(u1) && unitIsVolume(u2)) {
534 if(u1==UNIT_UL) cf=1.0E-6;
535 else if(u1==UNIT_ML) cf=1.0E-3;
536 else if(u1==UNIT_DL) cf=1.0E-1;
537 else if(u1==UNIT_L) cf=1.0;
538 if(u2==UNIT_UL) cf/=1.0E-6;
539 else if(u2==UNIT_ML) cf/=1.0E-3;
540 else if(u2==UNIT_DL) cf/=1.0E-1;
541 else if(u2==UNIT_L) cf/=1.0;
542 else cf=nan("");
543 return cf;
544 }
545
546 /* If both are masses */
547 if(unitIsMass(u1) && unitIsMass(u2)) {
548 if(u1==UNIT_UG) cf=1.0E-6;
549 else if(u1==UNIT_MG) cf=1.0E-3;
550 else if(u1==UNIT_G) cf=1.0;
551 else if(u1==UNIT_100G) cf=1.0E+2;
552 else if(u1==UNIT_KG) cf=1.0E+3;
553 if(u2==UNIT_UG) cf/=1.0E-6;
554 else if(u2==UNIT_MG) cf/=1.0E-3;
555 else if(u2==UNIT_G) cf/=1.0;
556 else if(u2==UNIT_100G) cf/=1.0E+2;
557 else if(u2==UNIT_KG) cf/=1.0E+3;
558 else cf=nan("");
559 return cf;
560 }
561
562 /* If both are moles */
563 if(unitIsMole(u1) && unitIsMole(u2)) {
564 if(u1==UNIT_PMOL) cf=1.0E-12;
565 else if(u1==UNIT_NMOL) cf=1.0E-9;
566 else if(u1==UNIT_UMOL) cf=1.0E-6;
567 else if(u1==UNIT_MMOL) cf=1.0E-3;
568 else if(u1==UNIT_MOL) cf=1.0;
569 if(u2==UNIT_PMOL) cf/=1.0E-12;
570 else if(u2==UNIT_NMOL) cf/=1.0E-9;
571 else if(u2==UNIT_UMOL) cf/=1.0E-6;
572 else if(u2==UNIT_MMOL) cf/=1.0E-3;
573 else if(u2==UNIT_MOL) cf/=1.0;
574 else cf=nan("");
575 return cf;
576 }
577
578 /* If both are radioactivities */
580 if(u1==UNIT_BQ) cf=1.0;
581 else if(u1==UNIT_KBQ) cf=1.0E+3;
582 else if(u1==UNIT_MBQ) cf=1.0E+6;
583 else if(u1==UNIT_GBQ) cf=1.0E+9;
584 else if(u1==UNIT_NCI) cf=37.0;
585 else if(u1==UNIT_UCI) cf=3.7E+4;
586 else if(u1==UNIT_MCI) cf=3.7E+7;
587 else if(u1==UNIT_CI) cf=3.7E+10;
588 if(u2==UNIT_BQ) cf/=1.0;
589 else if(u2==UNIT_KBQ) cf/=1.0E+3;
590 else if(u2==UNIT_MBQ) cf/=1.0E+6;
591 else if(u2==UNIT_GBQ) cf/=1.0E+9;
592 else if(u2==UNIT_NCI) cf/=37.0;
593 else if(u2==UNIT_UCI) cf/=3.7E+4;
594 else if(u2==UNIT_MCI) cf/=3.7E+7;
595 else if(u2==UNIT_CI) cf/=3.7E+10;
596 else cf=nan("");
597 return cf;
598 }
599
600 /* Fraction vs percentage */
601 if(u1==UNIT_PERCENTAGE) {
602 if(u2==UNIT_PERCENTAGE) cf=1.0;
603 else if(u2==UNIT_UNITLESS) cf=0.01;
604 return cf;
605 }
606 if(u2==UNIT_PERCENTAGE) {
607 if(u1==UNIT_PERCENTAGE) cf=1.0;
608 else if(u1==UNIT_UNITLESS) cf=100.0;
609 return cf;
610 }
611
612 /* Counts */
613 if(u1==UNIT_COUNTS) {
614 if(u2==UNIT_COUNTS) cf=1.0;
615 else if(u2==UNIT_KCOUNTS) cf=0.001;
616 return cf;
617 }
618 if(u1==UNIT_KCOUNTS) {
619 if(u2==UNIT_KCOUNTS) cf=1.0;
620 else if(u2==UNIT_COUNTS) cf=1000.0;
621 return cf;
622 }
623
624
625 /* And last, the combination units, recursively */
626 if(!unitIsCombinatorial(u1) || !unitIsCombinatorial(u2)) return cf;
627
628 if(tpc_unit[u1].u1==UNIT_UNITLESS && tpc_unit[u2].u1==UNIT_UNITLESS)
629 cf=1.0;
630 else
631 cf=unitConversionFactor(tpc_unit[u1].u1, tpc_unit[u2].u1);
632 if(!isnan(cf)) {
633 if(tpc_unit[u1].u2!=UNIT_UNITLESS && tpc_unit[u2].u2!=UNIT_UNITLESS)
634 cf*=unitConversionFactor(tpc_unit[u1].u2, tpc_unit[u2].u2);
635 if(!isnan(cf)) {
636 if(tpc_unit[u1].v1!=UNIT_UNITLESS && tpc_unit[u2].v1!=UNIT_UNITLESS)
637 cf/=unitConversionFactor(tpc_unit[u1].v1, tpc_unit[u2].v1);
638 if(!isnan(cf)) {
639 if(tpc_unit[u1].v2!=UNIT_UNITLESS && tpc_unit[u2].v2!=UNIT_UNITLESS)
640 cf/=unitConversionFactor(tpc_unit[u1].v2, tpc_unit[u2].v2);
641 }
642 }
643 }
644
645 return cf;
646}
647/*****************************************************************************/
648
649/*****************************************************************************/
656 int u
657) {
658 if(u==UNIT_UNKNOWN) return(UNIT_UNKNOWN);
659 else if(u==UNIT_UNITLESS) return(UNIT_UNITLESS);
660 else if(u==UNIT_SEC) return(UNIT_PER_SEC);
661 else if(u==UNIT_PER_SEC) return(UNIT_SEC);
662 else if(u==UNIT_MIN) return(UNIT_PER_MIN);
663 else if(u==UNIT_PER_MIN) return(UNIT_MIN);
664 else if(u==UNIT_HOUR) return(UNIT_PER_HOUR);
665 else if(u==UNIT_PER_HOUR) return(UNIT_HOUR);
666 else if(u==UNIT_ML_PER_ML) return(UNIT_ML_PER_ML);
667 else if(u==UNIT_G_PER_ML) return(UNIT_ML_PER_G);
668 else if(u==UNIT_ML_PER_G) return(UNIT_G_PER_ML);
669 else return(UNIT_UNKNOWN);
670}
671/*****************************************************************************/
672
673/*****************************************************************************/
680 int u
681) {
682 if(!unitIsCombinatorial(u)) return 0;
683 if(unitIsVolume(tpc_unit[u].v1)) return 1;
684 if(unitIsVolume(tpc_unit[u].v2)) return 1;
685 return 0;
686}
687/*****************************************************************************/
688
689/*****************************************************************************/
696 int u
697) {
698 if(!unitIsCombinatorial(u)) return 0;
699 if(unitIsMass(tpc_unit[u].v1)) return 1;
700 if(unitIsMass(tpc_unit[u].v2)) return 1;
701 return 0;
702}
703/*****************************************************************************/
704
705/*****************************************************************************/
712 int u
713) {
714 if(unitIsRadioactivity(u)) return(1);
715 if(!unitIsCombinatorial(u)) return(0);
716 if(unitIsRadioactivity(tpc_unit[u].u1) || unitIsRadioactivity(tpc_unit[u].u2)) return(1);
717 return(0);
718}
719/*****************************************************************************/
720
721/*****************************************************************************/
728 int u
729) {
730 if(!unitIsCombinatorial(u)) return(0);
731 if(!unitDividendHasRadioactivity(u)) return(0);
732 if(!unitDividerHasMass(u) && !unitDividerHasVolume(u)) return(0);
733 if(!unitIsRadioactivity(tpc_unit[u].u1)) return(0);
734 if(!unitIsMass(tpc_unit[u].v1) && !unitIsVolume(tpc_unit[u].v1)) return(0);
735 if(tpc_unit[u].u2!=UNIT_UNITLESS || tpc_unit[u].v2!=UNIT_UNITLESS) return(0);
736 return(1);
737}
738/*****************************************************************************/
739
740/*****************************************************************************/
747 const int u1,
749 const int u2,
751 const int v1,
753 const int v2
754) {
755 /* Try if unit table has this combination */
756 int i, n=0;
757 while(strlen(tpc_unit[n].name)>0) n++;
758 for(i=0; i<n; i++) {
759 if(!((u1==tpc_unit[i].u1 && u2==tpc_unit[i].u2) || (u1==tpc_unit[i].u2 && u2==tpc_unit[i].u1)))
760 continue;
761 if(!((v1==tpc_unit[i].v1 && v2==tpc_unit[i].v2) || (v1==tpc_unit[i].v2 && v2==tpc_unit[i].v1)))
762 continue;
763 return i;
764 }
765 return(UNIT_UNKNOWN);
766}
767/*****************************************************************************/
768
769/*****************************************************************************/
777 int u
778) {
779 if(unitDividerHasVolume(u)) {
780 int uo=UNIT_UNKNOWN, uu=UNIT_UNKNOWN, uoo=UNIT_UNKNOWN;
781 if(unitIsVolume(tpc_unit[u].v1)) {uo=tpc_unit[u].v1; uoo=tpc_unit[u].v2;}
782 else if(unitIsVolume(tpc_unit[u].v2)) {uo=tpc_unit[u].v2; uoo=tpc_unit[u].v1;}
783 if(uo==UNIT_ML) uu=UNIT_G;
784 else if(uo==UNIT_DL) uu=UNIT_100G;
785 else if(uo==UNIT_L) uu=UNIT_KG;
786 else if(uo==UNIT_UL) uu=UNIT_MG;
787 if(uu==UNIT_UNKNOWN) return(UNIT_UNKNOWN);
788 return(unitCombination(tpc_unit[u].u1, tpc_unit[u].u2, uoo, uu));
789 } else if(unitDividerHasMass(u)) {
790 int uo=UNIT_UNKNOWN, uu=UNIT_UNKNOWN, uoo=UNIT_UNKNOWN;
791 if(unitIsMass(tpc_unit[u].v1)) {uo=tpc_unit[u].v1; uoo=tpc_unit[u].v2;}
792 else if(unitIsMass(tpc_unit[u].v2)) {uo=tpc_unit[u].v2; uoo=tpc_unit[u].v1;}
793 if(uo==UNIT_G) uu=UNIT_ML;
794 else if(uo==UNIT_100G) uu=UNIT_DL;
795 else if(uo==UNIT_KG) uu=UNIT_L;
796 else if(uo==UNIT_MG) uu=UNIT_UL;
797 if(uu==UNIT_UNKNOWN) return(UNIT_UNKNOWN);
798 return(unitCombination(tpc_unit[u].u1, tpc_unit[u].u2, uoo, uu));
799 }
800 return(UNIT_UNKNOWN);
801}
802/*****************************************************************************/
803
804/*****************************************************************************/
811 int ua,
813 int ub
814) {
815 /* Verify validity of input units */
816 if(ua<1 || ub<1) return(UNIT_UNKNOWN);
817 int n=0; while(strlen(tpc_unit[n].name)>0) n++;
818 if(ua>n-1 || ub>n-1) return(UNIT_UNKNOWN);
819
820 /* Collect actual components of units */
821 int u[4], v[4], nu=0, nv=0;
822 for(int i=0; i<4; i++) u[i]=v[i]=UNIT_UNITLESS;
823 if(tpc_unit[ua].u1!=UNIT_UNITLESS) u[nu++]=tpc_unit[ua].u1;
824 if(tpc_unit[ua].u2!=UNIT_UNITLESS) u[nu++]=tpc_unit[ua].u2;
825 if(tpc_unit[ua].v1!=UNIT_UNITLESS) v[nv++]=tpc_unit[ua].v1;
826 if(tpc_unit[ua].v2!=UNIT_UNITLESS) v[nv++]=tpc_unit[ua].v2;
827 if(tpc_unit[ub].u1!=UNIT_UNITLESS) u[nu++]=tpc_unit[ub].u1;
828 if(tpc_unit[ub].u2!=UNIT_UNITLESS) u[nu++]=tpc_unit[ub].u2;
829 if(tpc_unit[ub].v1!=UNIT_UNITLESS) v[nv++]=tpc_unit[ub].v1;
830 if(tpc_unit[ub].v2!=UNIT_UNITLESS) v[nv++]=tpc_unit[ub].v2;
831#if(0)
832 printf("units: (");
833 for(int i=0; i<nu; i++) printf(" %s", unitName(u[i]));
834 printf(" ) / (");
835 for(int j=0; j<nv; j++) printf(" %s", unitName(v[j]));
836 printf(" )\n");
837#endif
838
839 /* Cancel out units if possible */
840 int cn=0;
841 for(int i=0; i<nu; i++) for(int j=0; j<nv; j++) if(u[i]==v[j]) {u[i]=v[i]=UNIT_UNITLESS; cn++;}
842 if(cn>0) {
843#if(0)
844 printf("units after cancelling: (");
845 for(int i=0; i<nu; i++) printf(" %s", unitName(u[i]));
846 printf(" ) / (");
847 for(int j=0; j<nv; j++) printf(" %s", unitName(v[j]));
848 printf(" )\n");
849#endif
850 for(int i=0; i<nu-1; i++) if(u[i]==UNIT_UNITLESS)
851 for(int j=i+1; j<nu; i++) if(u[j]!=UNIT_UNITLESS) {
852 int s=u[i]; u[i]=u[j]; u[j]=s;
853 }
854 for(int i=0; i<nv-1; i++) if(v[i]==UNIT_UNITLESS)
855 for(int j=i+1; j<nv; i++) if(v[j]!=UNIT_UNITLESS) {
856 int s=v[i]; v[i]=v[j]; v[j]=s;
857 }
858 nu-=cn; nv-=cn;
859#if(0)
860 printf("units after removing gaps: (");
861 for(int i=0; i<nu; i++) printf(" %s", unitName(u[i]));
862 printf(" ) / (");
863 for(int j=0; j<nv; j++) printf(" %s", unitName(v[j]));
864 printf(" )\n");
865#endif
866 }
867
868 /* Is the new combination a valid unit? */
869 if(nu>2 || nv>2) return(UNIT_UNKNOWN);
870 return(unitCombination(u[0], u[1], v[0], v[1]));
871}
872/*****************************************************************************/
873
874/*****************************************************************************/
size_t strnlen(const char *s, size_t n)
Definition stringext.c:566
char * strcasestr(const char *haystack, const char *needle)
Definition stringext.c:155
Header file for library libtpcextensions.
@ UNIT_UMOL_PER_DL_MIN
umol/(dL*min)
@ UNIT_L
liter
@ UNIT_MMOL_PER_DL_MIN
mmol/(dL*min)
@ UNIT_YEAR
years
@ UNIT_MMOL_PER_G_MIN
mmol/(g*min)
@ UNIT_MOL
mole
@ UNIT_MBQ_PER_ML
MBq/mL.
@ UNIT_MIN
minutes
@ UNIT_KG
kilogram
@ UNIT_ML_PER_ML
mL/mL
@ UNIT_MMOL_PER_100G_MIN
mmol/(100g*min)
@ UNIT_ML_PER_ML_MIN
mL/(mL*min)
@ UNIT_MSEC
milliseconds
@ UNIT_UMOL_PER_ML_MIN
umol/(mL*min)
@ UNIT_CPS
counts/s
@ UNIT_PID_PER_L
Percent of injected dose / L.
@ UNIT_UMOL
micromole
@ UNIT_MBQ
megaBecquerel
@ UNIT_UNKNOWN
Unknown unit.
@ UNIT_CPM
counts/min
@ UNIT_KCOUNTS
kilocounts
@ UNIT_UMOL_PER_L
umol/L
@ UNIT_ML
milliliter
@ UNIT_PER_SEC
1/s
@ UNIT_KCPM
kilocounts/min
@ UNIT_KCPS
kilocounts/s
@ UNIT_G
gram
@ UNIT_PID_PER_G
Percent of injected dose / g.
@ UNIT_NMOL
nanomole
@ UNIT_KBQ
kiloBecquerel
@ UNIT_LAST
end of list
@ UNIT_ML_PER_G
mL/g
@ UNIT_KBQ_PER_ML
kBq/mL
@ UNIT_MONTH
months
@ UNIT_ML_PER_G_MIN
mL/(g*min)
@ UNIT_ML_PER_DL_MIN
mL/(dL*min)
@ UNIT_UNITLESS
Unitless.
@ UNIT_PMOL_PER_L
pmol/L
@ UNIT_G_PER_ML
g/mL
@ UNIT_PID_PER_ML
Percent of injected dose / mL.
@ UNIT_MMOL_PER_ML_MIN
mmol/(mL*min)
@ UNIT_CM
centimeter
@ UNIT_UCI_PER_ML
uCi/mL
@ UNIT_COUNTS
counts
@ UNIT_DL
desiliter
@ UNIT_MCI
milliCurie
@ UNIT_NMOL_PER_L
nmol/L
@ UNIT_PER_HOUR
1/h
@ UNIT_SEC
seconds
@ UNIT_NCI
nanoCurie
@ UNIT_DAY
days
@ UNIT_PID
Percent of injected dose.
@ UNIT_100G
100 grams
@ UNIT_PID_PER_KG
Percent of injected dose / kg.
@ UNIT_ML_PER_ML_SEC
mL/(mL*sec)
@ UNIT_UG
microgram
@ UNIT_MM
millimeter
@ UNIT_BQ
Becquerel.
@ UNIT_UMOL_PER_G_MIN
umol/(g*min)
@ UNIT_SEC_KBQ_PER_ML
s*kBq/mL
@ UNIT_PMOL
picomole
@ UNIT_HU
Hounsfield Unit.
@ UNIT_UL
microliter
@ UNIT_HOUR
hours
@ UNIT_UMOL_PER_100G_MIN
umol/(100g*min)
@ UNIT_UM
micrometer
@ UNIT_UCI
microCurie
@ UNIT_MMOL_PER_L
mmol/L
@ UNIT_PER_MIN
1/min
@ UNIT_GBQ
gigaBecquerel
@ UNIT_PERCENTAGE
Percentage (%)
@ UNIT_CI
Curie.
@ UNIT_MG
milligram
@ UNIT_BQ_PER_ML
Bq/mL.
@ UNIT_M
meter
@ UNIT_MMOL
millimole
@ UNIT_NCI_PER_ML
nCi/mL
#define MAX_UNITS_LEN
Define max units string length.
int unitIsRAConc(int u)
Definition units.c:726
int unitDividendHasRadioactivity(int u)
Definition units.c:710
int unitIsMass(int u)
Definition units.c:402
int unitInverse(int u)
Definition units.c:654
int unitIdentify(const char *s)
Definition units.c:162
int unitIdentifyFilename(const char *s)
Definition units.c:311
int unitIsRadioactivity(int u)
Definition units.c:444
double unitConversionFactor(const int u1, const int u2)
Definition units.c:487
char * unitName(int unit_code)
Definition units.c:143
int unitCombination(const int u1, const int u2, const int v1, const int v2)
Definition units.c:745
int unitIsCombinatorial(int u)
Definition units.c:468
int unitIsDistance(int u)
Definition units.c:339
int unitDividerHasVolume(int u)
Definition units.c:678
int unitIsMole(int u)
Definition units.c:423
int unitDividerMassVolumeConversion(int u)
Definition units.c:775
int unitMultiply(int ua, int ub)
Definition units.c:809
int unitIsVolume(int u)
Definition units.c:382
int unitIsTime(int u)
Definition units.c:359
int unitDividerHasMass(int u)
Definition units.c:694