1
2 /* General Numerical routines support functions, */
3 /* and common Argyll support functions. */
4 /* (Perhaps these should be moved out of numlib at some stange ?) */
5
6 /*
7 * Copyright 1997 - 2010 Graeme W. Gill
8 * All rights reserved.
9 *
10 * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
11 * see the License2.txt file for licencing details.
12 */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <math.h>
17 #include <string.h>
18 #include <limits.h>
19 #include <time.h>
20 #include <ctype.h>
21 #if defined (NT)
22 #define WIN32_LEAN_AND_MEAN
23 #include <windows.h>
24 #endif
25 #ifdef UNIX
26 #include <unistd.h>
27 #include <sys/param.h>
28 #include <sys/utsname.h>
29 #include <pthread.h>
30 #endif
31 #ifndef SALONEINSTLIB
32 #include "aconfig.h"
33 #else
34 #include "sa_config.h"
35 #endif
36
37 #define NUMSUP_C
38 #include "numsup.h"
39
40 /*
41 * TODO: Should probably break all the non-numlib stuff out into
42 * a separate library, so that it can be ommitted.
43 * Or enhance it so that numerical callers of error()
44 * can get a callback on out of memory etc. ???
45 *
46 */
47
48 /* Globals */
49
50 char *exe_path = "\000"; /* Directory executable resides in ('/' dir separator) */
51 //char *error_program = "Unknown"; /* Name to report as responsible for an error */
52
53 static int g_log_init = 0; /* Initialised ? */
54 static int g_deb_init = 0; /* Debug output Initialised ? */
55 extern a1log default_log;
56 extern a1log *g_log;
57
58 /* Should Vector/Matrix Support functions return NULL on error, */
59 /* or call error() ? */
60 int ret_null_on_malloc_fail = 0; /* Call error() */
61
62 /******************************************************************/
63 /* Executable path routine. Sets default error_program too. */
64 /******************************************************************/
65
66 /* Pass in argv[0] from main() */
67 /* Sets the error_program name too */
set_exe_path(char * argv0)68 void set_exe_path(char *argv0) {
69 int i;
70
71 g_log->tag = argv0;
72 i = strlen(argv0);
73 if ((exe_path = malloc(i + 5)) == NULL) {
74 a1loge(g_log, 1, "set_exe_path: malloc %d bytes failed\n",i+5);
75 return;
76 }
77 strcpy(exe_path, argv0);
78
79 #ifdef NT /* CMD.EXE doesn't give us the full path in argv[0] :-( */
80 /* so we need to fix this */
81 {
82 HMODULE mh;
83 char *tpath = NULL;
84 int pl;
85
86 /* Add an .exe extension if it is missing */
87 if (i < 4 || _stricmp(exe_path +i -4, ".exe") != 0)
88 strcat(exe_path, ".exe");
89
90 if ((mh = GetModuleHandle(exe_path)) == NULL) {
91 a1loge(g_log, 1, "set_exe_path: GetModuleHandle '%s' failed with%d\n",
92 exe_path,GetLastError());
93 exe_path[0] = '\000';
94 return;
95 }
96
97 /* Retry until we don't truncate the returned path */
98 for (pl = 100; ; pl *= 2) {
99 if (tpath != NULL)
100 free(tpath);
101 if ((tpath = malloc(pl)) == NULL) {
102 a1loge(g_log, 1, "set_exe_path: malloc %d bytes failed\n",pl);
103 exe_path[0] = '\000';
104 return;
105 }
106 if ((i = GetModuleFileName(mh, tpath, pl)) == 0) {
107 a1loge(g_log, 1, "set_exe_path: GetModuleFileName '%s' failed with%d\n",
108 tpath,GetLastError());
109 exe_path[0] = '\000';
110 return;
111 }
112 if (i < pl) /* There was enough space */
113 break;
114 }
115 free(exe_path);
116 exe_path = tpath;
117
118 /* Convert from MSWindows to UNIX file separator convention */
119 for (i = 0; ;i++) {
120 if (exe_path[i] == '\000')
121 break;
122 if (exe_path[i] == '\\')
123 exe_path[i] = '/';
124 }
125 }
126 #else /* Neither does UNIX */
127
128 if (*exe_path != '/') { /* Not already absolute */
129 char *p, *cp;
130 if (strchr(exe_path, '/') != 0) { /* relative path */
131 cp = ".:"; /* Fake a relative PATH */
132 } else {
133 cp = getenv("PATH");
134 }
135 if (cp != NULL) {
136 int found = 0;
137 while((p = strchr(cp,':')) != NULL
138 || *cp != '\000') {
139 char b1[PATH_MAX], b2[PATH_MAX];
140 int ll;
141 if (p == NULL)
142 ll = strlen(cp);
143 else
144 ll = p - cp;
145 if ((ll + 1 + strlen(exe_path) + 1) > PATH_MAX) {
146 a1loge(g_log, 1, "set_exe_path: Search path exceeds PATH_MAX\n");
147 exe_path[0] = '\000';
148 return;
149 }
150 strncpy(b1, cp, ll); /* Element of path to search */
151 b1[ll] = '\000';
152 strcat(b1, "/");
153 strcat(b1, exe_path); /* Construct path */
154 if (realpath(b1, b2)) {
155 if (access(b2, 0) == 0) { /* See if exe exits */
156 found = 1;
157 free(exe_path);
158 if ((exe_path = malloc(strlen(b2)+1)) == NULL) {
159 a1loge(g_log, 1, "set_exe_path: malloc %d bytes failed\n",strlen(b2)+1);
160 exe_path[0] = '\000';
161 return;
162 }
163 strcpy(exe_path, b2);
164 break;
165 }
166 }
167 if (p == NULL)
168 break;
169 cp = p + 1;
170 }
171 if (found == 0)
172 exe_path[0] = '\000';
173 }
174 }
175 #endif
176 /* strip the executable path to the base */
177 for (i = strlen(exe_path)-1; i >= 0; i--) {
178 if (exe_path[i] == '/') {
179 char *tpath;
180 if ((tpath = malloc(strlen(exe_path + i))) == NULL) {
181 a1loge(g_log, 1, "set_exe_path: malloc %d bytes failed\n",strlen(exe_path + i));
182 exe_path[0] = '\000';
183 return;
184 }
185 strcpy(tpath, exe_path + i + 1);
186 g_log->tag = tpath; /* Set g_log->tag to base name */
187 exe_path[i+1] = '\000'; /* (The malloc never gets free'd) */
188 break;
189 }
190 }
191 /* strip off any .exe from the g_log->tag to be more readable */
192 i = strlen(g_log->tag);
193 if (i >= 4
194 && g_log->tag[i-4] == '.'
195 && (g_log->tag[i-3] == 'e' || g_log->tag[i-3] == 'E')
196 && (g_log->tag[i-2] == 'x' || g_log->tag[i-2] == 'X')
197 && (g_log->tag[i-1] == 'e' || g_log->tag[i-1] == 'E'))
198 g_log->tag[i-4] = '\000';
199
200 // a1logd(g_log, 1, "exe_path = '%s'\n",exe_path);
201 // a1logd(g_log, 1, "g_log->tag = '%s'\n",g_log->tag);
202 }
203
204 /******************************************************************/
205 /* Check "ARGYLL_NOT_INTERACTIVE" environment variable. */
206 /******************************************************************/
207
208 /* Check if the "ARGYLL_NOT_INTERACTIVE" environment variable is */
209 /* set, and set cr_char to '\n' if it is. */
210
211 int not_interactive = 0;
212 char cr_char = '\r';
213
check_if_not_interactive()214 void check_if_not_interactive() {
215 char *ev;
216
217 if ((ev = getenv("ARGYLL_NOT_INTERACTIVE")) != NULL) {
218 not_interactive = 1;
219 cr_char = '\n';
220 } else {
221 not_interactive = 0;
222 cr_char = '\r';
223 }
224 }
225
226 /******************************************************************/
227 /* Default verbose/debug/error loger */
228 /* It's values can be overridden to redirect these messages. */
229 /******************************************************************/
230
231 static void va_loge(a1log *p, char *fmt, ...);
232
233 #ifdef NT
234
235 /* Get a string describing the MWin operating system */
236
237 typedef struct {
238 DWORD dwOSVersionInfoSize;
239 DWORD dwMajorVersion;
240 DWORD dwMinorVersion;
241 DWORD dwBuildNumber;
242 DWORD dwPlatformId;
243 WCHAR szCSDVersion[128];
244 WORD wServicePackMajor;
245 WORD wServicePackMinor;
246 WORD wSuiteMask;
247 BYTE wProductType;
248 BYTE wReserved;
249 } osversioninfoexw;
250
251 #ifndef VER_NT_DOMAIN_CONTROLLER
252 # define VER_NT_DOMAIN_CONTROLLER 0x0000002
253 # define VER_NT_SERVER 0x0000003
254 # define VER_NT_WORKSTATION 0x0000001
255 #endif
256
get_sys_info()257 static char *get_sys_info() {
258 static char sysinfo[100] = { "Unknown" };
259 LONG (WINAPI *pfnRtlGetVersion)(osversioninfoexw*);
260
261 *(FARPROC *)&pfnRtlGetVersion
262 = GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
263 if (pfnRtlGetVersion != NULL) {
264 osversioninfoexw ver = { 0 };
265 ver.dwOSVersionInfoSize = sizeof(ver);
266
267 if (pfnRtlGetVersion(&ver) == 0) {
268 if (ver.dwMajorVersion > 6 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion > 3)) {
269 if (ver.wProductType == VER_NT_WORKSTATION)
270 sprintf(sysinfo,"Windows V%d.%d SP %d",
271 ver.dwMajorVersion,ver.dwMinorVersion,
272 ver.wServicePackMajor);
273 else
274 sprintf(sysinfo,"Windows Server 2016 V%d.%d SP %d",
275 ver.dwMajorVersion,ver.dwMinorVersion,
276 ver.wServicePackMajor);
277
278 } else if (ver.dwMajorVersion == 6 && ver.dwMinorVersion == 3) {
279 if (ver.wProductType == VER_NT_WORKSTATION)
280 sprintf(sysinfo,"Windows V8.1 SP %d",
281 ver.wServicePackMajor);
282 else
283 sprintf(sysinfo,"Windows Server 2012 R2 SP %d",
284 ver.wServicePackMajor);
285
286 } else if (ver.dwMajorVersion == 6 && ver.dwMinorVersion == 2) {
287 if (ver.wProductType == VER_NT_WORKSTATION)
288 sprintf(sysinfo,"Windows V8 SP %d",
289 ver.wServicePackMajor);
290 else
291 sprintf(sysinfo,"Windows Server SP %d",
292 ver.wServicePackMajor);
293
294 } else if (ver.dwMajorVersion == 6 && ver.dwMinorVersion == 1) {
295 if (ver.wProductType == VER_NT_WORKSTATION)
296 sprintf(sysinfo,"Windows V7 SP %d",
297 ver.wServicePackMajor);
298 else
299 sprintf(sysinfo,"Windows Server 2008 R2 SP %d",
300 ver.wServicePackMajor);
301
302 } else if (ver.dwMajorVersion == 6 && ver.dwMinorVersion == 0) {
303 if (ver.wProductType == VER_NT_WORKSTATION)
304 sprintf(sysinfo,"Windows Vista SP %d",
305 ver.wServicePackMajor);
306 else
307 sprintf(sysinfo,"Windows Server 2008 SP %d",
308 ver.wServicePackMajor);
309
310 } else if (ver.dwMajorVersion == 5 && ver.dwMinorVersion == 2) {
311 // Actually could be Server 2003, Home Server, Server 2003 R2
312 sprintf(sysinfo,"Windows XP Pro64 SP %d",
313 ver.wServicePackMajor);
314
315 } else if (ver.dwMajorVersion == 5 && ver.dwMinorVersion == 1) {
316 sprintf(sysinfo,"Windows XP SP %d",
317 ver.wServicePackMajor);
318
319 } else if (ver.dwMajorVersion == 5 && ver.dwMinorVersion == 0) {
320 sprintf(sysinfo,"Windows XP SP %d",
321 ver.wServicePackMajor);
322
323 } else {
324 sprintf(sysinfo,"Windows Maj %d Min %d SP %d",
325 ver.dwMajorVersion,ver.dwMinorVersion,
326 ver.wServicePackMajor);
327 }
328 }
329 }
330 return sysinfo;
331 }
332
333
334 # define A1LOG_LOCK(log, deb) \
335 if (g_log_init == 0) { \
336 InitializeCriticalSection(&log->lock); \
337 EnterCriticalSection(&log->lock); \
338 g_log_init = 1; \
339 } else { \
340 EnterCriticalSection(&log->lock); \
341 } \
342 if (deb && !g_deb_init) { \
343 va_loge(log, "Argyll 'V%s' Build '%s' System '%s'\n",ARGYLL_VERSION_STR,ARGYLL_BUILD_STR, get_sys_info()); \
344 g_deb_init = 1; \
345 }
346 # define A1LOG_UNLOCK(log) LeaveCriticalSection(&log->lock)
347 #endif
348 #ifdef UNIX
349
get_sys_info()350 static char *get_sys_info() {
351 static char sysinfo[200] = { "Unknown" };
352 struct utsname ver;
353
354 if (uname(&ver) == 0)
355 sprintf(sysinfo,"%s %s %s %s",ver.sysname, ver.version, ver.release, ver.machine);
356 return sysinfo;
357 }
358
359 # define A1LOG_LOCK(log, deb) \
360 if (g_log_init == 0) { \
361 pthread_mutex_init(&log->lock, NULL); \
362 pthread_mutex_lock(&log->lock); \
363 g_log_init = 1; \
364 } else { \
365 pthread_mutex_lock(&log->lock); \
366 } \
367 if (deb && !g_deb_init) { \
368 va_loge(log, "Argyll 'V%s' Build '%s' System '%s'\n",ARGYLL_VERSION_STR,ARGYLL_BUILD_STR, get_sys_info()); \
369 g_deb_init = 1; \
370 }
371 # define A1LOG_UNLOCK(log) pthread_mutex_unlock(&log->lock)
372 #endif
373
374
375
376 /* Default verbose logging function - print to stdtout */
a1_default_v_log(void * cntx,a1log * p,char * fmt,va_list args)377 static void a1_default_v_log(void *cntx, a1log *p, char *fmt, va_list args) {
378 vfprintf(stdout, fmt, args);
379 fflush(stdout);
380 }
381
382 /* Default debug & error logging function - print to stderr */
a1_default_de_log(void * cntx,a1log * p,char * fmt,va_list args)383 static void a1_default_de_log(void *cntx, a1log *p, char *fmt, va_list args) {
384 vfprintf(stderr, fmt, args);
385 fflush(stderr);
386 }
387
388 #define a1_default_d_log a1_default_de_log
389 #define a1_default_e_log a1_default_de_log
390
391
392 /* Call log->loge() with variags */
va_loge(a1log * p,char * fmt,...)393 static void va_loge(a1log *p, char *fmt, ...) {
394 va_list args;
395 va_start(args, fmt);
396 p->loge(p->cntx, p, fmt, args);
397 va_end(args);
398 }
399
400 /* Global log */
401 a1log default_log = {
402 1, /* Refcount of 1 because this is not allocated or free'd */
403 "argyll", /* Default tag */
404 0, /* Vebose off */
405 0, /* Debug off */
406 NULL, /* Context */
407 &a1_default_v_log, /* Default verbose to stdout */
408 &a1_default_d_log, /* Default debug to stderr */
409 &a1_default_e_log, /* Default error to stderr */
410 0, /* error code 0 */
411 { '\000' } /* No error message */
412 };
413 a1log *g_log = &default_log;
414
415 /* If log NULL, allocate a new log and return it, */
416 /* otherwise increment reference count and return existing log, */
417 /* exit() if malloc fails. */
new_a1log(a1log * log,int verb,int debug,void * cntx,void (* logv)(void * cntx,a1log * p,char * fmt,va_list args),void (* logd)(void * cntx,a1log * p,char * fmt,va_list args),void (* loge)(void * cntx,a1log * p,char * fmt,va_list args))418 a1log *new_a1log(
419 a1log *log, /* Existing log to reference, NULL if none */
420 int verb, /* Verbose level to set */
421 int debug, /* Debug level to set */
422 void *cntx, /* Function context value */
423 /* Vebose log function to call - stdout if NULL */
424 void (*logv)(void *cntx, a1log *p, char *fmt, va_list args),
425 /* Debug log function to call - stderr if NULL */
426 void (*logd)(void *cntx, a1log *p, char *fmt, va_list args),
427 /* Warning/error Log function to call - stderr if NULL */
428 void (*loge)(void *cntx, a1log *p, char *fmt, va_list args)
429 ) {
430 if (log != NULL) {
431 log->refc++;
432 return log;
433 }
434 if ((log = (a1log *)calloc(sizeof(a1log), 1)) == NULL) {
435 a1loge(g_log, 1, "new_a1log: malloc of a1log failed, calling exit(1)\n");
436 exit(1);
437 }
438 log->refc = 1;
439 log->verb = verb;
440 log->debug = debug;
441
442 log->cntx = cntx;
443 if (logv != NULL)
444 log->logv = logv;
445 else
446 log->logv = a1_default_v_log;
447
448 if (logd != NULL)
449 log->logd = logd;
450 else
451 log->logd = a1_default_d_log;
452
453 if (loge != NULL)
454 log->loge = loge;
455 else
456 log->loge = a1_default_e_log;
457
458 log->errc = 0;
459 log->errm[0] = '\000';
460
461 return log;
462 }
463
464 /* Same as above but set default functions */
new_a1log_d(a1log * log)465 a1log *new_a1log_d(a1log *log) {
466 return new_a1log(log, 0, 0, NULL, NULL, NULL, NULL);
467 }
468
469 /* Decrement reference count and free log. */
470 /* Returns NULL */
del_a1log(a1log * log)471 a1log *del_a1log(a1log *log) {
472 if (log != NULL) {
473 if (--log->refc <= 0) {
474 #ifdef NT
475 DeleteCriticalSection(&log->lock);
476 #endif
477 #ifdef UNIX
478 pthread_mutex_destroy(&log->lock);
479 #endif
480 free(log);
481 }
482 }
483 return NULL;
484 }
485
486 /* Set the tag. Note that the tage string is NOT copied, just referenced */
a1log_tag(a1log * log,char * tag)487 void a1log_tag(a1log *log, char *tag) {
488 log->tag = tag;
489 }
490
491 /* Log a verbose message if level >= verb */
a1logv(a1log * log,int level,char * fmt,...)492 void a1logv(a1log *log, int level, char *fmt, ...) {
493 if (log != NULL) {
494 if (log->verb >= level) {
495 va_list args;
496
497 A1LOG_LOCK(log, 0);
498 va_start(args, fmt);
499 log->logv(log->cntx, log, fmt, args);
500 va_end(args);
501 A1LOG_UNLOCK(log);
502 }
503 }
504 }
505
506 /* Log a debug message if level >= debug */
a1logd(a1log * log,int level,char * fmt,...)507 void a1logd(a1log *log, int level, char *fmt, ...) {
508 if (log != NULL) {
509 if (log->debug >= level) {
510 va_list args;
511
512 A1LOG_LOCK(log, 1);
513 va_start(args, fmt);
514 log->loge(log->cntx, log, fmt, args);
515 va_end(args);
516 A1LOG_UNLOCK(log);
517 }
518 }
519 }
520
521 /* log a warning message to the verbose, debug and error output, */
a1logw(a1log * log,char * fmt,...)522 void a1logw(a1log *log, char *fmt, ...) {
523 if (log != NULL) {
524 va_list args;
525
526 /* log to all the outputs, but only log once */
527 A1LOG_LOCK(log, 0);
528 va_start(args, fmt);
529 log->loge(log->cntx, log, fmt, args);
530 va_end(args);
531 A1LOG_UNLOCK(log);
532 if (log->logd != log->loge) {
533 A1LOG_LOCK(log, 1);
534 va_start(args, fmt);
535 log->logd(log->cntx, log, fmt, args);
536 va_end(args);
537 A1LOG_UNLOCK(log);
538 }
539 if (log->logv != log->loge && log->logv != log->logd) {
540 A1LOG_LOCK(log, 0);
541 va_start(args, fmt);
542 log->logv(log->cntx, log, fmt, args);
543 va_end(args);
544 A1LOG_UNLOCK(log);
545 }
546 }
547 }
548
549 /* log an error message to the verbose, debug and error output, */
550 /* and latch the error if it is the first. */
551 /* ecode = system, icoms or instrument error */
a1loge(a1log * log,int ecode,char * fmt,...)552 void a1loge(a1log *log, int ecode, char *fmt, ...) {
553 if (log != NULL) {
554 va_list args;
555
556 if (log->errc == 0) {
557 A1LOG_LOCK(log, 0);
558 log->errc = ecode;
559 va_start(args, fmt);
560 vsnprintf(log->errm, A1_LOG_BUFSIZE, fmt, args);
561 va_end(args);
562 A1LOG_UNLOCK(log);
563 }
564 va_start(args, fmt);
565 /* log to all the outputs, but only log once */
566 A1LOG_LOCK(log, 0);
567 va_start(args, fmt);
568 log->loge(log->cntx, log, fmt, args);
569 va_end(args);
570 A1LOG_UNLOCK(log);
571 if (log->logd != log->loge) {
572 A1LOG_LOCK(log, 1);
573 va_start(args, fmt);
574 log->logd(log->cntx, log, fmt, args);
575 va_end(args);
576 A1LOG_UNLOCK(log);
577 }
578 if (log->logv != log->loge && log->logv != log->logd) {
579 A1LOG_LOCK(log, 0);
580 va_start(args, fmt);
581 log->logv(log->cntx, log, fmt, args);
582 va_end(args);
583 A1LOG_UNLOCK(log);
584 }
585 }
586 }
587
588 /* Unlatch an error message. */
589 /* This just resets errc and errm */
a1logue(a1log * log)590 void a1logue(a1log *log) {
591 if (log != NULL) {
592 log->errc = 0;
593 log->errm[0] = '\000';
594 }
595 }
596
597 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
598
599 /* Print bytes as hex to debug log */
600 /* base is the base of the displayed offset */
adump_bytes(a1log * log,char * pfx,unsigned char * buf,int base,int len)601 void adump_bytes(a1log *log, char *pfx, unsigned char *buf, int base, int len) {
602 int i, j, ii;
603 char oline[200] = { '\000' }, *bp = oline;
604 for (i = j = 0; i < len; i++) {
605 if ((i % 16) == 0)
606 bp += sprintf(bp,"%s%04x:",pfx,base+i);
607 bp += sprintf(bp," %02x",buf[i]);
608 if ((i+1) >= len || ((i+1) % 16) == 0) {
609 for (ii = i; ((ii+1) % 16) != 0; ii++)
610 bp += sprintf(bp," ");
611 bp += sprintf(bp," ");
612 for (; j <= i; j++) {
613 if (!(buf[j] & 0x80) && isprint(buf[j]))
614 bp += sprintf(bp,"%c",buf[j]);
615 else
616 bp += sprintf(bp,".");
617 }
618 bp += sprintf(bp,"\n");
619 a1logd(log,0,"%s",oline);
620 bp = oline;
621 }
622 }
623 }
624
625 /******************************************************************/
626 /* Default verbose/warning/error output routines */
627 /* These fall through to, and can be re-director using the */
628 /* above log class. */
629 /******************************************************************/
630
631 /* Some utilities to allow us to format output to log functions */
632 /* (Caller aquires lock) */
g_logv(char * fmt,...)633 static void g_logv(char *fmt, ...) {
634 va_list args;
635 va_start(args, fmt);
636 g_log->logv(g_log->cntx, g_log, fmt, args);
637 va_end(args);
638 }
639
g_loge(char * fmt,...)640 static void g_loge(char *fmt, ...) {
641 va_list args;
642 va_start(args, fmt);
643 g_log->loge(g_log->cntx, g_log, fmt, args);
644 va_end(args);
645 }
646
647 void
verbose(int level,char * fmt,...)648 verbose(int level, char *fmt, ...) {
649 if (g_log->verb >= level) {
650 va_list args;
651
652 A1LOG_LOCK(g_log, 0);
653 g_logv("%s: ",g_log->tag);
654 va_start(args, fmt);
655 g_log->logv(g_log->cntx, g_log, fmt, args);
656 va_end(args);
657 g_logv("\n");
658 A1LOG_UNLOCK(g_log);
659 }
660 }
661
662 void
warning(char * fmt,...)663 warning(char *fmt, ...) {
664 va_list args;
665
666 A1LOG_LOCK(g_log, 0);
667 g_loge("%s: Warning - ",g_log->tag);
668 va_start(args, fmt);
669 g_log->loge(g_log->cntx, g_log, fmt, args);
670 va_end(args);
671 g_loge("\n");
672 A1LOG_UNLOCK(g_log);
673 }
674
675 ATTRIBUTE_NORETURN void
error(char * fmt,...)676 error(char *fmt, ...) {
677 va_list args;
678
679 A1LOG_LOCK(g_log, 0);
680 g_loge("%s: Error - ",g_log->tag);
681 va_start(args, fmt);
682 g_log->loge(g_log->cntx, g_log, fmt, args);
683 va_end(args);
684 g_loge("\n");
685 A1LOG_UNLOCK(g_log);
686
687 exit(1);
688 }
689
690
691 /******************************************************************/
692 /* Suplimental allcation functions */
693 /******************************************************************/
694
695 #ifndef SIZE_MAX
696 # define SIZE_MAX ((size_t)(-1))
697 #endif
698
699 /* a * b */
ssat_mul(size_t a,size_t b)700 static size_t ssat_mul(size_t a, size_t b) {
701 size_t c;
702
703 if (a == 0 || b == 0)
704 return 0;
705
706 if (a > (SIZE_MAX/b))
707 return SIZE_MAX;
708 else
709 return a * b;
710 }
711
712 /* reallocate and clear new allocation */
recalloc(void * ptr,size_t cnum,size_t csize,size_t nnum,size_t nsize)713 void *recalloc( /* Return new address */
714 void *ptr, /* Current address */
715 size_t cnum, /* Current number and unit size */
716 size_t csize,
717 size_t nnum, /* New number and unit size */
718 size_t nsize
719 ) {
720 int ind = 0;
721 size_t ctot, ntot;
722
723 if (ptr == NULL)
724 return calloc(nnum, nsize);
725
726 if ((ntot = ssat_mul(nnum, nsize)) == SIZE_MAX)
727 return NULL; /* Overflow */
728
729 if ((ctot = ssat_mul(cnum, csize)) == SIZE_MAX)
730 return NULL; /* Overflow */
731
732 ptr = realloc(ptr, ntot);
733
734 if (ptr != NULL && ntot > ctot)
735 memset((char *)ptr + ctot, 0, ntot - ctot); /* Clear the new region */
736
737 return ptr;
738 }
739
740 /******************************************************************/
741 /* OS X App Nap fixes */
742 /******************************************************************/
743
744 #if defined(__APPLE__)
745
746 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
747 # include <objc/runtime.h>
748 # include <objc/message.h>
749 #else
750 # include <objc/objc-runtime.h>
751 #endif
752 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
753 # include <objc/objc-auto.h>
754 #endif
755
756 /*
757 OS X 10.9+ App Nap problems bug:
758
759 <http://stackoverflow.com/questions/22784886/what-can-make-nanosleep-drift-with-exactly-10-sec-on-mac-os-x-10-9>
760
761 NSProcessInfo variables:
762
763 <https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSProcessInfo_Class/#//apple_ref/c/tdef/NSActivityOptions>
764
765 typedef enum : uint64_t { NSActivityIdleDisplaySleepDisabled = (1ULL << 40),
766 NSActivityIdleSystemSleepDisabled = (1ULL << 20),
767 NSActivitySuddenTerminationDisabled = (1ULL << 14),
768 NSActivityAutomaticTerminationDisabled = (1ULL << 15),
769 NSActivityUserInitiated = (0x00FFFFFFULL | NSActivityIdleSystemSleepDisabled ),
770 NSActivityUserInitiatedAllowingIdleSystemSleep =
771 (NSActivityUserInitiated & ~NSActivityIdleSystemSleepDisabled ),
772 NSActivityBackground = 0x000000FFULL,
773 NSActivityLatencyCritical = 0xFF00000000ULL,
774 } NSActivityOptions;
775
776 See <http://stackoverflow.com/questions/19847293/disable-app-nap-in-macos-10-9-mavericks-application>:
777
778 @property (strong) id activity;
779
780 if ([[NSProcessInfo processInfo] respondsToSelector:@selector(beginActivityWithOptions:reason:)]) {
781 self.activity = [[NSProcessInfo processInfo] beginActivityWithOptions:0x00FFFFFF reason:@"receiving OSC messages"];
782 }
783
784 <http://stackoverflow.com/questions/19671197/disabling-app-nap-with-beginactivitywithoptions>
785
786 NSProcessInfo = interface(NSObject)['{B96935F6-3809-4A49-AD4F-CBBAB0F2C961}']
787 function beginActivityWithOptions(options: NSActivityOptions; reason: NSString): NSObject; cdecl;
788
789 <http://stackoverflow.com/questions/22164571/weird-behaviour-of-dispatch-after>
790
791 */
792
793 static int osx_userinitiated_cnt = 0;
794 static id osx_userinitiated_activity = nil;
795
796 /* Tell App Nap that this is user initiated */
osx_userinitiated_start()797 void osx_userinitiated_start() {
798 Class pic; /* Process info class */
799 SEL pis; /* Process info selector */
800 SEL bawo; /* Begin Activity With Options selector */
801 id pi; /* Process info */
802 id str;
803
804 if (osx_userinitiated_cnt++ != 0)
805 return;
806
807 a1logd(g_log, 7, "OS X - User Initiated Activity start\n");
808
809 /* We have to be conservative to avoid triggering an exception when run on older OS X, */
810 /* since beginActivityWithOptions is only available in >= 10.9 */
811 if ((pic = (Class)objc_getClass("NSProcessInfo")) == nil) {
812 return;
813 }
814
815 if (class_getClassMethod(pic, (pis = sel_getUid("processInfo"))) == NULL) {
816 return;
817 }
818
819 if (class_getInstanceMethod(pic, (bawo = sel_getUid("beginActivityWithOptions:reason:"))) == NULL) {
820 a1logd(g_log, 7, "OS X - beginActivityWithOptions not supported\n");
821 return;
822 }
823
824 /* Get the process instance */
825 if ((pi = objc_msgSend((id)pic, pis)) == nil) {
826 return;
827 }
828
829 /* Create a reason string */
830 str = objc_msgSend(objc_getClass("NSString"), sel_getUid("alloc"));
831 str = objc_msgSend(str, sel_getUid("initWithUTF8String:"), "ArgyllCMS");
832
833 /* Start activity that tells App Nap to mind its own business. */
834 /* NSActivityUserInitiatedAllowingIdleSystemSleep */
835 osx_userinitiated_activity = objc_msgSend(pi, bawo, 0x00FFFFFFULL, str);
836 }
837
838 /* Done with user initiated */
osx_userinitiated_end()839 void osx_userinitiated_end() {
840 if (osx_userinitiated_cnt > 0) {
841 osx_userinitiated_cnt--;
842 if (osx_userinitiated_cnt == 0 && osx_userinitiated_activity != nil) {
843 a1logd(g_log, 7, "OS X - User Initiated Activity end");
844 objc_msgSend(
845 objc_msgSend(objc_getClass("NSProcessInfo"), sel_getUid("processInfo")),
846 sel_getUid("endActivity:"), osx_userinitiated_activity);
847 osx_userinitiated_activity = nil;
848 }
849 }
850 }
851
852 static int osx_latencycritical_cnt = 0;
853 static id osx_latencycritical_activity = nil;
854
855 /* Tell App Nap that this is latency critical */
osx_latencycritical_start()856 void osx_latencycritical_start() {
857 Class pic; /* Process info class */
858 SEL pis; /* Process info selector */
859 SEL bawo; /* Begin Activity With Options selector */
860 id pi; /* Process info */
861 id str;
862
863 if (osx_latencycritical_cnt++ != 0)
864 return;
865
866 a1logd(g_log, 7, "OS X - Latency Critical Activity start\n");
867
868 /* We have to be conservative to avoid triggering an exception when run on older OS X */
869 if ((pic = (Class)objc_getClass("NSProcessInfo")) == nil) {
870 return;
871 }
872
873 if (class_getClassMethod(pic, (pis = sel_getUid("processInfo"))) == NULL) {
874 return;
875 }
876
877 if (class_getInstanceMethod(pic, (bawo = sel_getUid("beginActivityWithOptions:reason:"))) == NULL) {
878 a1logd(g_log, 7, "OS X - beginActivityWithOptions not supported\n");
879 return;
880 }
881
882 /* Get the process instance */
883 if ((pi = objc_msgSend((id)pic, pis)) == nil) {
884 return;
885 }
886
887 /* Create a reason string */
888 str = objc_msgSend(objc_getClass("NSString"), sel_getUid("alloc"));
889 str = objc_msgSend(str, sel_getUid("initWithUTF8String:"), "Measuring Color");
890
891 /* Start activity that tells App Nap to mind its own business. */
892 /* NSActivityUserInitiatedAllowingIdleSystemSleep | NSActivityLatencyCritical */
893 osx_latencycritical_activity = objc_msgSend(pi, bawo, 0x00FFFFFFULL | 0xFF00000000ULL, str);
894 }
895
896 /* Done with latency critical */
osx_latencycritical_end()897 void osx_latencycritical_end() {
898 if (osx_latencycritical_cnt > 0) {
899 osx_latencycritical_cnt--;
900 if (osx_latencycritical_cnt == 0 && osx_latencycritical_activity != nil) {
901 a1logd(g_log, 7, "OS X - Latency Critical Activity end");
902 objc_msgSend(
903 objc_msgSend(objc_getClass("NSProcessInfo"), sel_getUid("processInfo")),
904 sel_getUid("endActivity:"), osx_latencycritical_activity);
905 osx_latencycritical_activity = nil;
906 }
907 }
908 }
909
910 #endif /* __APPLE__ */
911
912 /******************************************************************/
913 /* Numerical Recipes Vector/Matrix Support functions */
914 /******************************************************************/
915 /* Note the z suffix versions return zero'd vectors/matricies */
916
917 /* Double Vector malloc/free */
dvector(int nl,int nh)918 double *dvector(
919 int nl, /* Lowest index */
920 int nh /* Highest index */
921 ) {
922 double *v;
923
924 if ((v = (double *) malloc((nh-nl+1) * sizeof(double))) == NULL) {
925 if (ret_null_on_malloc_fail)
926 return NULL;
927 else
928 error("Malloc failure in dvector()");
929 }
930 return v-nl;
931 }
932
dvectorz(int nl,int nh)933 double *dvectorz(
934 int nl, /* Lowest index */
935 int nh /* Highest index */
936 ) {
937 double *v;
938
939 if ((v = (double *) calloc(nh-nl+1, sizeof(double))) == NULL) {
940 if (ret_null_on_malloc_fail)
941 return NULL;
942 else
943 error("Malloc failure in dvector()");
944 }
945 return v-nl;
946 }
947
free_dvector(double * v,int nl,int nh)948 void free_dvector(
949 double *v,
950 int nl, /* Lowest index */
951 int nh /* Highest index */
952 ) {
953 if (v == NULL)
954 return;
955
956 free((char *) (v+nl));
957 }
958
959 /* --------------------- */
960 /* 2D Double vector malloc/free */
dmatrix(int nrl,int nrh,int ncl,int nch)961 double **dmatrix(
962 int nrl, /* Row low index */
963 int nrh, /* Row high index */
964 int ncl, /* Col low index */
965 int nch /* Col high index */
966 ) {
967 int i;
968 int rows, cols;
969 double **m;
970
971 if (nrh < nrl) /* Prevent failure for 0 dimension */
972 nrh = nrl;
973 if (nch < ncl)
974 nch = ncl;
975
976 rows = nrh - nrl + 1;
977 cols = nch - ncl + 1;
978
979 if ((m = (double **) malloc((rows + 1) * sizeof(double *))) == NULL) {
980 if (ret_null_on_malloc_fail)
981 return NULL;
982 else
983 error("Malloc failure in dmatrix(), pointers");
984 }
985 m -= nrl; /* Offset to nrl */
986 m += 1; /* Make nrl-1 pointer to main allocation, in case rows get swaped */
987
988 if ((m[nrl-1] = (double *) malloc(rows * cols * sizeof(double))) == NULL) {
989 if (ret_null_on_malloc_fail)
990 return NULL;
991 else
992 error("Malloc failure in dmatrix(), array");
993 }
994
995 m[nrl] = m[nrl-1] - ncl; /* Set first row address, offset to ncl */
996 for(i = nrl+1; i <= nrh; i++) /* Set subsequent row addresses */
997 m[i] = m[i-1] + cols;
998
999 return m;
1000 }
1001
dmatrixz(int nrl,int nrh,int ncl,int nch)1002 double **dmatrixz(
1003 int nrl, /* Row low index */
1004 int nrh, /* Row high index */
1005 int ncl, /* Col low index */
1006 int nch /* Col high index */
1007 ) {
1008 int i;
1009 int rows, cols;
1010 double **m;
1011
1012 if (nrh < nrl) /* Prevent failure for 0 dimension */
1013 nrh = nrl;
1014 if (nch < ncl)
1015 nch = ncl;
1016
1017 rows = nrh - nrl + 1;
1018 cols = nch - ncl + 1;
1019
1020 if ((m = (double **) malloc((rows + 1) * sizeof(double *))) == NULL) {
1021 if (ret_null_on_malloc_fail)
1022 return NULL;
1023 else
1024 error("Malloc failure in dmatrix(), pointers");
1025 }
1026 m -= nrl; /* Offset to nrl */
1027 m += 1; /* Make nrl-1 pointer to main allocation, in case rows get swaped */
1028
1029 if ((m[nrl-1] = (double *) calloc(rows * cols, sizeof(double))) == NULL) {
1030 if (ret_null_on_malloc_fail)
1031 return NULL;
1032 else
1033 error("Malloc failure in dmatrix(), array");
1034 }
1035
1036 m[nrl] = m[nrl-1] - ncl; /* Set first row address, offset to ncl */
1037 for(i = nrl+1; i <= nrh; i++) /* Set subsequent row addresses */
1038 m[i] = m[i-1] + cols;
1039
1040 return m;
1041 }
1042
free_dmatrix(double ** m,int nrl,int nrh,int ncl,int nch)1043 void free_dmatrix(
1044 double **m,
1045 int nrl,
1046 int nrh,
1047 int ncl,
1048 int nch
1049 ) {
1050 if (m == NULL)
1051 return;
1052
1053 if (nrh < nrl) /* Prevent failure for 0 dimension */
1054 nrh = nrl;
1055 if (nch < ncl)
1056 nch = ncl;
1057
1058 free((char *)(m[nrl-1]));
1059 free((char *)(m+nrl-1));
1060 }
1061
1062 /* --------------------- */
1063 /* 2D diagonal half matrix vector malloc/free */
1064 /* A half matrix must have equal rows and columns, */
1065 /* and the column address must always be >= than the row. */
dhmatrix(int nrl,int nrh,int ncl,int nch)1066 double **dhmatrix(
1067 int nrl, /* Row low index */
1068 int nrh, /* Row high index */
1069 int ncl, /* Col low index */
1070 int nch /* Col high index */
1071 ) {
1072 int i, j;
1073 int rows, cols;
1074 double **m;
1075
1076 if (nrh < nrl) /* Prevent failure for 0 dimension */
1077 nrh = nrl;
1078 if (nch < ncl)
1079 nch = ncl;
1080
1081 rows = nrh - nrl + 1;
1082 cols = nch - ncl + 1;
1083
1084 if (rows != cols) {
1085 if (ret_null_on_malloc_fail)
1086 return NULL;
1087 else
1088 error("dhmatrix() given unequal rows and columns");
1089 }
1090
1091 if ((m = (double **) malloc((rows + 1) * sizeof(double *))) == NULL) {
1092 if (ret_null_on_malloc_fail)
1093 return NULL;
1094 else
1095 error("Malloc failure in dhmatrix(), pointers");
1096 }
1097 m -= nrl; /* Offset to nrl */
1098 m += 1; /* Make nrl-1 pointer to main allocation, in case rows get swaped */
1099
1100 if ((m[nrl-1] = (double *) malloc((rows * rows + rows)/2 * sizeof(double))) == NULL) {
1101 if (ret_null_on_malloc_fail)
1102 return NULL;
1103 else
1104 error("Malloc failure in dhmatrix(), array");
1105 }
1106
1107 m[nrl] = m[nrl-1] - ncl; /* Set first row address, offset to ncl */
1108 for(i = nrl+1, j = 1; i <= nrh; i++, j++) /* Set subsequent row addresses */
1109 m[i] = m[i-1] + j; /* Start with 1 entry and increment */
1110
1111 return m;
1112 }
1113
dhmatrixz(int nrl,int nrh,int ncl,int nch)1114 double **dhmatrixz(
1115 int nrl, /* Row low index */
1116 int nrh, /* Row high index */
1117 int ncl, /* Col low index */
1118 int nch /* Col high index */
1119 ) {
1120 int i, j;
1121 int rows, cols;
1122 double **m;
1123
1124 if (nrh < nrl) /* Prevent failure for 0 dimension */
1125 nrh = nrl;
1126 if (nch < ncl)
1127 nch = ncl;
1128
1129 rows = nrh - nrl + 1;
1130 cols = nch - ncl + 1;
1131
1132 if (rows != cols) {
1133 if (ret_null_on_malloc_fail)
1134 return NULL;
1135 else
1136 error("dhmatrix() given unequal rows and columns");
1137 }
1138
1139 if ((m = (double **) malloc((rows + 1) * sizeof(double *))) == NULL) {
1140 if (ret_null_on_malloc_fail)
1141 return NULL;
1142 else
1143 error("Malloc failure in dhmatrix(), pointers");
1144 }
1145 m -= nrl; /* Offset to nrl */
1146 m += 1; /* Make nrl-1 pointer to main allocation, in case rows get swaped */
1147
1148 if ((m[nrl-1] = (double *) calloc((rows * rows + rows)/2, sizeof(double))) == NULL) {
1149 if (ret_null_on_malloc_fail)
1150 return NULL;
1151 else
1152 error("Malloc failure in dhmatrix(), array");
1153 }
1154
1155 m[nrl] = m[nrl-1] - ncl; /* Set first row address, offset to ncl */
1156 for(i = nrl+1, j = 1; i <= nrh; i++, j++) /* Set subsequent row addresses */
1157 m[i] = m[i-1] + j; /* Start with 1 entry and increment */
1158
1159 return m;
1160 }
1161
free_dhmatrix(double ** m,int nrl,int nrh,int ncl,int nch)1162 void free_dhmatrix(
1163 double **m,
1164 int nrl,
1165 int nrh,
1166 int ncl,
1167 int nch
1168 ) {
1169 if (m == NULL)
1170 return;
1171
1172 if (nrh < nrl) /* Prevent failure for 0 dimension */
1173 nrh = nrl;
1174 if (nch < ncl)
1175 nch = ncl;
1176
1177 free((char *)(m[nrl-1]));
1178 free((char *)(m+nrl-1));
1179 }
1180
1181 /* --------------------- */
1182 /* 2D vector copy */
copy_dmatrix(double ** dst,double ** src,int nrl,int nrh,int ncl,int nch)1183 void copy_dmatrix(
1184 double **dst,
1185 double **src,
1186 int nrl, /* Row low index */
1187 int nrh, /* Row high index */
1188 int ncl, /* Col low index */
1189 int nch /* Col high index */
1190 ) {
1191 int i, j;
1192 for (j = nrl; j <= nrh; j++)
1193 for (i = ncl; i <= nch; i++)
1194 dst[j][i] = src[j][i];
1195 }
1196
1197 /* Copy a matrix to a 3x3 standard C array */
copy_dmatrix_to3x3(double dst[3][3],double ** src,int nrl,int nrh,int ncl,int nch)1198 void copy_dmatrix_to3x3(
1199 double dst[3][3],
1200 double **src,
1201 int nrl, /* Row low index */
1202 int nrh, /* Row high index */
1203 int ncl, /* Col low index */
1204 int nch /* Col high index */
1205 ) {
1206 int i, j;
1207 if ((nrh - nrl) > 2)
1208 nrh = nrl + 2;
1209 if ((nch - ncl) > 2)
1210 nch = ncl + 2;
1211 for (j = nrl; j <= nrh; j++)
1212 for (i = ncl; i <= nch; i++)
1213 dst[j][i] = src[j][i];
1214 }
1215
1216 /* -------------------------------------------------------------- */
1217 /* Convert standard C type 2D array into an indirect referenced array */
convert_dmatrix(double * a,int nrl,int nrh,int ncl,int nch)1218 double **convert_dmatrix(
1219 double *a, /* base address of normal C array, ie &a[0][0] */
1220 int nrl, /* Row low index */
1221 int nrh, /* Row high index */
1222 int ncl, /* Col low index */
1223 int nch /* Col high index */
1224 ) {
1225 int i, j, nrow = nrh-nrl+1, ncol = nch-ncl+1;
1226 double **m;
1227
1228 /* Allocate pointers to rows */
1229 if ((m = (double **) malloc(nrow * sizeof(double*))) == NULL) {
1230 if (ret_null_on_malloc_fail)
1231 return NULL;
1232 else
1233 error("Malloc failure in convert_dmatrix()");
1234 }
1235
1236 m -= nrl;
1237
1238 m[nrl] = a - ncl;
1239 for(i=1, j = nrl+1; i < nrow; i++, j++)
1240 m[j] = m[j-1] + ncol;
1241 /* return pointer to array of pointers */
1242 return m;
1243 }
1244
1245 /* Free the indirect array reference (but not array) */
free_convert_dmatrix(double ** m,int nrl,int nrh,int ncl,int nch)1246 void free_convert_dmatrix(
1247 double **m,
1248 int nrl,
1249 int nrh,
1250 int ncl,
1251 int nch
1252 ) {
1253 if (m == NULL)
1254 return;
1255
1256 free((char*) (m+nrl));
1257 }
1258
1259 /* -------------------------- */
1260 /* Float vector malloc/free */
fvector(int nl,int nh)1261 float *fvector(
1262 int nl, /* Lowest index */
1263 int nh /* Highest index */
1264 ) {
1265 float *v;
1266
1267 if ((v = (float *) malloc((nh-nl+1) * sizeof(float))) == NULL) {
1268 if (ret_null_on_malloc_fail)
1269 return NULL;
1270 else
1271 error("Malloc failure in fvector()");
1272 }
1273 return v-nl;
1274 }
1275
fvectorz(int nl,int nh)1276 float *fvectorz(
1277 int nl, /* Lowest index */
1278 int nh /* Highest index */
1279 ) {
1280 float *v;
1281
1282 if ((v = (float *) calloc(nh-nl+1, sizeof(float))) == NULL) {
1283 if (ret_null_on_malloc_fail)
1284 return NULL;
1285 else
1286 error("Malloc failure in fvector()");
1287 }
1288 return v-nl;
1289 }
1290
free_fvector(float * v,int nl,int nh)1291 void free_fvector(
1292 float *v,
1293 int nl, /* Lowest index */
1294 int nh /* Highest index */
1295 ) {
1296 if (v == NULL)
1297 return;
1298
1299 free((char *) (v+nl));
1300 }
1301
1302 /* --------------------- */
1303 /* 2D Float matrix malloc/free */
fmatrix(int nrl,int nrh,int ncl,int nch)1304 float **fmatrix(
1305 int nrl, /* Row low index */
1306 int nrh, /* Row high index */
1307 int ncl, /* Col low index */
1308 int nch /* Col high index */
1309 ) {
1310 int i;
1311 int rows, cols;
1312 float **m;
1313
1314 if (nrh < nrl) /* Prevent failure for 0 dimension */
1315 nrh = nrl;
1316 if (nch < ncl)
1317 nch = ncl;
1318
1319 rows = nrh - nrl + 1;
1320 cols = nch - ncl + 1;
1321
1322 if ((m = (float **) malloc((rows + 1) * sizeof(float *))) == NULL) {
1323 if (ret_null_on_malloc_fail)
1324 return NULL;
1325 else
1326 error("Malloc failure in dmatrix(), pointers");
1327 }
1328 m -= nrl; /* Offset to nrl */
1329 m += 1; /* Make nrl-1 pointer to main allocation, in case rows get swaped */
1330
1331 if ((m[nrl-1] = (float *) malloc(rows * cols * sizeof(float))) == NULL) {
1332 if (ret_null_on_malloc_fail)
1333 return NULL;
1334 else
1335 error("Malloc failure in dmatrix(), array");
1336 }
1337
1338 m[nrl] = m[nrl-1] - ncl; /* Set first row address, offset to ncl */
1339 for(i = nrl+1; i <= nrh; i++) /* Set subsequent row addresses */
1340 m[i] = m[i-1] + cols;
1341
1342 return m;
1343 }
1344
fmatrixz(int nrl,int nrh,int ncl,int nch)1345 float **fmatrixz(
1346 int nrl, /* Row low index */
1347 int nrh, /* Row high index */
1348 int ncl, /* Col low index */
1349 int nch /* Col high index */
1350 ) {
1351 int i;
1352 int rows, cols;
1353 float **m;
1354
1355 if (nrh < nrl) /* Prevent failure for 0 dimension */
1356 nrh = nrl;
1357 if (nch < ncl)
1358 nch = ncl;
1359
1360 rows = nrh - nrl + 1;
1361 cols = nch - ncl + 1;
1362
1363 if ((m = (float **) malloc((rows + 1) * sizeof(float *))) == NULL) {
1364 if (ret_null_on_malloc_fail)
1365 return NULL;
1366 else
1367 error("Malloc failure in dmatrix(), pointers");
1368 }
1369 m -= nrl; /* Offset to nrl */
1370 m += 1; /* Make nrl-1 pointer to main allocation, in case rows get swaped */
1371
1372 if ((m[nrl-1] = (float *) calloc(rows * cols, sizeof(float))) == NULL) {
1373 if (ret_null_on_malloc_fail)
1374 return NULL;
1375 else
1376 error("Malloc failure in dmatrix(), array");
1377 }
1378
1379 m[nrl] = m[nrl-1] - ncl; /* Set first row address, offset to ncl */
1380 for(i = nrl+1; i <= nrh; i++) /* Set subsequent row addresses */
1381 m[i] = m[i-1] + cols;
1382
1383 return m;
1384 }
1385
free_fmatrix(float ** m,int nrl,int nrh,int ncl,int nch)1386 void free_fmatrix(
1387 float **m,
1388 int nrl,
1389 int nrh,
1390 int ncl,
1391 int nch
1392 ) {
1393 if (m == NULL)
1394 return;
1395
1396 if (nrh < nrl) /* Prevent failure for 0 dimension */
1397 nrh = nrl;
1398 if (nch < ncl)
1399 nch = ncl;
1400
1401 free((char *)(m[nrl-1]));
1402 free((char *)(m+nrl-1));
1403 }
1404
1405 /* ------------------ */
1406 /* Integer vector malloc/free */
ivector(int nl,int nh)1407 int *ivector(
1408 int nl, /* Lowest index */
1409 int nh /* Highest index */
1410 ) {
1411 int *v;
1412
1413 if ((v = (int *) malloc((nh-nl+1) * sizeof(int))) == NULL) {
1414 if (ret_null_on_malloc_fail)
1415 return NULL;
1416 else
1417 error("Malloc failure in ivector()");
1418 }
1419 return v-nl;
1420 }
1421
ivectorz(int nl,int nh)1422 int *ivectorz(
1423 int nl, /* Lowest index */
1424 int nh /* Highest index */
1425 ) {
1426 int *v;
1427
1428 if ((v = (int *) calloc(nh-nl+1, sizeof(int))) == NULL) {
1429 if (ret_null_on_malloc_fail)
1430 return NULL;
1431 else
1432 error("Malloc failure in ivector()");
1433 }
1434 return v-nl;
1435 }
1436
free_ivector(int * v,int nl,int nh)1437 void free_ivector(
1438 int *v,
1439 int nl, /* Lowest index */
1440 int nh /* Highest index */
1441 ) {
1442 if (v == NULL)
1443 return;
1444
1445 free((char *) (v+nl));
1446 }
1447
1448
1449 /* ------------------------------ */
1450 /* 2D integer matrix malloc/free */
1451
imatrix(int nrl,int nrh,int ncl,int nch)1452 int **imatrix(
1453 int nrl, /* Row low index */
1454 int nrh, /* Row high index */
1455 int ncl, /* Col low index */
1456 int nch /* Col high index */
1457 ) {
1458 int i;
1459 int rows, cols;
1460 int **m;
1461
1462 if (nrh < nrl) /* Prevent failure for 0 dimension */
1463 nrh = nrl;
1464 if (nch < ncl)
1465 nch = ncl;
1466
1467 rows = nrh - nrl + 1;
1468 cols = nch - ncl + 1;
1469
1470 if ((m = (int **) malloc((rows + 1) * sizeof(int *))) == NULL) {
1471 if (ret_null_on_malloc_fail)
1472 return NULL;
1473 else
1474 error("Malloc failure in imatrix(), pointers");
1475 }
1476 m -= nrl; /* Offset to nrl */
1477 m += 1; /* Make nrl-1 pointer to main allocation, in case rows get swaped */
1478
1479 if ((m[nrl-1] = (int *) malloc(rows * cols * sizeof(int))) == NULL) {
1480 if (ret_null_on_malloc_fail)
1481 return NULL;
1482 else
1483 error("Malloc failure in imatrix(), array");
1484 }
1485
1486 m[nrl] = m[nrl-1] - ncl; /* Set first row address, offset to ncl */
1487 for(i = nrl+1; i <= nrh; i++) /* Set subsequent row addresses */
1488 m[i] = m[i-1] + cols;
1489
1490 return m;
1491 }
1492
imatrixz(int nrl,int nrh,int ncl,int nch)1493 int **imatrixz(
1494 int nrl, /* Row low index */
1495 int nrh, /* Row high index */
1496 int ncl, /* Col low index */
1497 int nch /* Col high index */
1498 ) {
1499 int i;
1500 int rows, cols;
1501 int **m;
1502
1503 if (nrh < nrl) /* Prevent failure for 0 dimension */
1504 nrh = nrl;
1505 if (nch < ncl)
1506 nch = ncl;
1507
1508 rows = nrh - nrl + 1;
1509 cols = nch - ncl + 1;
1510
1511 if ((m = (int **) malloc((rows + 1) * sizeof(int *))) == NULL) {
1512 if (ret_null_on_malloc_fail)
1513 return NULL;
1514 else
1515 error("Malloc failure in imatrix(), pointers");
1516 }
1517 m -= nrl; /* Offset to nrl */
1518 m += 1; /* Make nrl-1 pointer to main allocation, in case rows get swaped */
1519
1520 if ((m[nrl-1] = (int *) calloc(rows * cols, sizeof(int))) == NULL) {
1521 if (ret_null_on_malloc_fail)
1522 return NULL;
1523 else
1524 error("Malloc failure in imatrix(), array");
1525 }
1526
1527 m[nrl] = m[nrl-1] - ncl; /* Set first row address, offset to ncl */
1528 for(i = nrl+1; i <= nrh; i++) /* Set subsequent row addresses */
1529 m[i] = m[i-1] + cols;
1530
1531 return m;
1532 }
1533
free_imatrix(int ** m,int nrl,int nrh,int ncl,int nch)1534 void free_imatrix(
1535 int **m,
1536 int nrl,
1537 int nrh,
1538 int ncl,
1539 int nch
1540 ) {
1541 if (m == NULL)
1542 return;
1543
1544 if (nrh < nrl) /* Prevent failure for 0 dimension */
1545 nrh = nrl;
1546 if (nch < ncl)
1547 nch = ncl;
1548
1549 free((char *)(m[nrl-1]));
1550 free((char *)(m+nrl-1));
1551 }
1552
1553 /* ------------------ */
1554 /* Short vector malloc/free */
svector(int nl,int nh)1555 short *svector(
1556 int nl, /* Lowest index */
1557 int nh /* Highest index */
1558 ) {
1559 short *v;
1560
1561 if ((v = (short *) malloc((nh-nl+1) * sizeof(short))) == NULL) {
1562 if (ret_null_on_malloc_fail)
1563 return NULL;
1564 else
1565 error("Malloc failure in svector()");
1566 }
1567 return v-nl;
1568 }
1569
svectorz(int nl,int nh)1570 short *svectorz(
1571 int nl, /* Lowest index */
1572 int nh /* Highest index */
1573 ) {
1574 short *v;
1575
1576 if ((v = (short *) calloc(nh-nl+1, sizeof(short))) == NULL) {
1577 if (ret_null_on_malloc_fail)
1578 return NULL;
1579 else
1580 error("Malloc failure in svector()");
1581 }
1582 return v-nl;
1583 }
1584
free_svector(short * v,int nl,int nh)1585 void free_svector(
1586 short *v,
1587 int nl, /* Lowest index */
1588 int nh /* Highest index */
1589 ) {
1590 if (v == NULL)
1591 return;
1592
1593 free((char *) (v+nl));
1594 }
1595
1596
1597 /* ------------------------------ */
1598 /* 2D short vector malloc/free */
1599
smatrix(int nrl,int nrh,int ncl,int nch)1600 short **smatrix(
1601 int nrl, /* Row low index */
1602 int nrh, /* Row high index */
1603 int ncl, /* Col low index */
1604 int nch /* Col high index */
1605 ) {
1606 int i;
1607 int rows, cols;
1608 short **m;
1609
1610 if (nrh < nrl) /* Prevent failure for 0 dimension */
1611 nrh = nrl;
1612 if (nch < ncl)
1613 nch = ncl;
1614
1615 rows = nrh - nrl + 1;
1616 cols = nch - ncl + 1;
1617
1618 if ((m = (short **) malloc((rows + 1) * sizeof(short *))) == NULL) {
1619 if (ret_null_on_malloc_fail)
1620 return NULL;
1621 else
1622 error("Malloc failure in smatrix(), pointers");
1623 }
1624 m -= nrl; /* Offset to nrl */
1625 m += 1; /* Make nrl-1 pointer to main allocation, in case rows get swaped */
1626
1627 if ((m[nrl-1] = (short *) malloc(rows * cols * sizeof(short))) == NULL) {
1628 if (ret_null_on_malloc_fail)
1629 return NULL;
1630 else
1631 error("Malloc failure in smatrix(), array");
1632 }
1633
1634 m[nrl] = m[nrl-1] - ncl; /* Set first row address, offset to ncl */
1635 for(i = nrl+1; i <= nrh; i++) /* Set subsequent row addresses */
1636 m[i] = m[i-1] + cols;
1637
1638 return m;
1639 }
1640
smatrixz(int nrl,int nrh,int ncl,int nch)1641 short **smatrixz(
1642 int nrl, /* Row low index */
1643 int nrh, /* Row high index */
1644 int ncl, /* Col low index */
1645 int nch /* Col high index */
1646 ) {
1647 int i;
1648 int rows, cols;
1649 short **m;
1650
1651 if (nrh < nrl) /* Prevent failure for 0 dimension */
1652 nrh = nrl;
1653 if (nch < ncl)
1654 nch = ncl;
1655
1656 rows = nrh - nrl + 1;
1657 cols = nch - ncl + 1;
1658
1659 if ((m = (short **) malloc((rows + 1) * sizeof(short *))) == NULL) {
1660 if (ret_null_on_malloc_fail)
1661 return NULL;
1662 else
1663 error("Malloc failure in smatrix(), pointers");
1664 }
1665 m -= nrl; /* Offset to nrl */
1666 m += 1; /* Make nrl-1 pointer to main allocation, in case rows get swaped */
1667
1668 if ((m[nrl-1] = (short *) calloc(rows * cols, sizeof(short))) == NULL) {
1669 if (ret_null_on_malloc_fail)
1670 return NULL;
1671 else
1672 error("Malloc failure in smatrix(), array");
1673 }
1674
1675 m[nrl] = m[nrl-1] - ncl; /* Set first row address, offset to ncl */
1676 for(i = nrl+1; i <= nrh; i++) /* Set subsequent row addresses */
1677 m[i] = m[i-1] + cols;
1678
1679 return m;
1680 }
1681
free_smatrix(short ** m,int nrl,int nrh,int ncl,int nch)1682 void free_smatrix(
1683 short **m,
1684 int nrl,
1685 int nrh,
1686 int ncl,
1687 int nch
1688 ) {
1689 if (m == NULL)
1690 return;
1691
1692 if (nrh < nrl) /* Prevent failure for 0 dimension */
1693 nrh = nrl;
1694 if (nch < ncl)
1695 nch = ncl;
1696
1697 free((char *)(m[nrl-1]));
1698 free((char *)(m+nrl-1));
1699 }
1700
1701 /***************************/
1702 /* Basic matrix operations */
1703 /***************************/
1704
1705 /* Transpose a 0 base matrix */
matrix_trans(double ** d,double ** s,int nr,int nc)1706 void matrix_trans(double **d, double **s, int nr, int nc) {
1707 int i, j;
1708
1709 for (i = 0; i < nr; i++) {
1710 for (j = 0; j < nc; j++) {
1711 d[j][i] = s[i][j];
1712 }
1713 }
1714 }
1715
1716 /* Multiply two 0 based matricies */
1717 /* Return nz on matching error */
matrix_mult(double ** d,int nr,int nc,double ** s1,int nr1,int nc1,double ** s2,int nr2,int nc2)1718 int matrix_mult(
1719 double **d, int nr, int nc,
1720 double **s1, int nr1, int nc1,
1721 double **s2, int nr2, int nc2
1722 ) {
1723 int i, j, k;
1724
1725 /* s1 and s2 must mesh */
1726 if (nc1 != nr2)
1727 return 1;
1728
1729 /* Output rows = s1 rows */
1730 if (nr != nr1)
1731 return 2;
1732
1733 /* Output colums = s2 columns */
1734 if (nc != nc2)
1735 return 2;
1736
1737 for (i = 0; i < nr1; i++) {
1738 for (j = 0; j < nc2; j++) {
1739 d[i][j] = 0.0;
1740 for (k = 0; k < nc1; k++) {
1741 d[i][j] += s1[i][k] * s2[k][j];
1742 }
1743 }
1744 }
1745
1746 return 0;
1747 }
1748
1749 /* Diagnostic - print to g_log debug */
matrix_print(char * c,double ** a,int nr,int nc)1750 void matrix_print(char *c, double **a, int nr, int nc) {
1751 int i, j;
1752 a1logd(g_log, 0, "%s, %d x %d\n",c,nr,nc);
1753
1754 for (j = 0; j < nr; j++) {
1755 a1logd(g_log, 0, " ");
1756 for (i = 0; i < nc; i++) {
1757 a1logd(g_log, 0, " %.2f",a[j][i]);
1758 }
1759 a1logd(g_log, 0, "\n");
1760 }
1761 }
1762
1763
1764 /*******************************************/
1765 /* Platform independent IEE754 conversions */
1766 /*******************************************/
1767
1768 /* Convert a native double to an IEEE754 encoded single precision value, */
1769 /* in a platform independent fashion. (ie. This works even */
1770 /* on the rare platforms that don't use IEEE 754 floating */
1771 /* point for their C implementation) */
doubletoIEEE754(double d)1772 ORD32 doubletoIEEE754(double d) {
1773 ORD32 sn = 0, ep = 0, ma;
1774 ORD32 id;
1775
1776 /* Convert double to IEEE754 single precision. */
1777 /* This would be easy if we're running on an IEEE754 architecture, */
1778 /* but isn't generally portable, so we use ugly code: */
1779
1780 if (d < 0.0) {
1781 sn = 1;
1782 d = -d;
1783 }
1784 if (d != 0.0) {
1785 int ee;
1786 ee = (int)floor(log(d)/log(2.0));
1787 if (ee < -126) /* Allow for denormalized */
1788 ee = -126;
1789 d *= pow(0.5, (double)(ee - 23));
1790 ee += 127;
1791 if (ee < 1) /* Too small */
1792 ee = 0; /* Zero or denormalised */
1793 else if (ee > 254) { /* Too large */
1794 ee = 255; /* Infinity */
1795 d = 0.0;
1796 }
1797 ep = ee;
1798 } else {
1799 ep = 0; /* Zero */
1800 }
1801 ma = ((ORD32)d) & ((1 << 23)-1);
1802 id = (sn << 31) | (ep << 23) | ma;
1803
1804 return id;
1805 }
1806
1807 /* Convert a an IEEE754 encoded single precision value to a native double, */
1808 /* in a platform independent fashion. (ie. This works even */
1809 /* on the rare platforms that don't use IEEE 754 floating */
1810 /* point for their C implementation) */
IEEE754todouble(ORD32 ip)1811 double IEEE754todouble(ORD32 ip) {
1812 double op;
1813 ORD32 sn = 0, ep = 0, ma;
1814
1815 sn = (ip >> 31) & 0x1;
1816 ep = (ip >> 23) & 0xff;
1817 ma = ip & 0x7fffff;
1818
1819 if (ep == 0) { /* Zero or denormalised */
1820 op = (double)ma/(double)(1 << 23);
1821 op *= pow(2.0, (-126.0));
1822 } else {
1823 op = (double)(ma | (1 << 23))/(double)(1 << 23);
1824 op *= pow(2.0, (((int)ep)-127.0));
1825 }
1826 if (sn)
1827 op = -op;
1828 return op;
1829 }
1830
1831 /* Convert a native double to an IEEE754 encoded double precision value, */
1832 /* in a platform independent fashion. (ie. This works even */
1833 /* on the rare platforms that don't use IEEE 754 floating */
1834 /* point for their C implementation) */
doubletoIEEE754_64(double d)1835 ORD64 doubletoIEEE754_64(double d) {
1836 ORD32 sn = 0, ep = 0;
1837 ORD64 ma, id;
1838
1839 /* Convert double to IEEE754 double precision. */
1840 /* This would be easy if we know we're running on an IEEE754 architecture, */
1841 /* but isn't generally portable, so we use ugly code: */
1842
1843 if (d < 0.0) {
1844 sn = 1;
1845 d = -d;
1846 }
1847 if (d != 0.0) {
1848 int ee;
1849 ee = (int)floor(log(d)/log(2.0));
1850 if (ee < -1022) /* Allow for denormalized */
1851 ee = -1022;
1852 d *= pow(0.5, (double)(ee - 52));
1853 ee += 1023; /* Exponent bias */
1854 if (ee < 1) /* Too small */
1855 ee = 0; /* Zero or denormalised */
1856 else if (ee > 2046) { /* Too large */
1857 ee = 2047; /* Infinity */
1858 d = 0.0;
1859 }
1860 ep = ee;
1861 } else {
1862 ep = 0; /* Zero */
1863 }
1864 ma = ((ORD64)d) & (((ORD64)1 << 52)-1);
1865 id = ((ORD64)sn << 63) | ((ORD64)ep << 52) | ma;
1866
1867 return id;
1868 }
1869
1870 /* Convert a an IEEE754 encode double precision value to a native double, */
1871 /* in a platform independent fashion. (ie. This works even */
1872 /* on the rare platforms that don't use IEEE 754 floating */
1873 /* point for their C implementation) */
IEEE754_64todouble(ORD64 ip)1874 double IEEE754_64todouble(ORD64 ip) {
1875 double op;
1876 ORD32 sn = 0, ep = 0;
1877 INR64 ma;
1878
1879 sn = (ip >> 63) & 0x1;
1880 ep = (ip >> 52) & 0x7ff;
1881 ma = ip & (((INR64)1 << 52)-1);
1882
1883 if (ep == 0) { /* Zero or denormalised */
1884 op = (double)ma/(double)((INR64)1 << 52);
1885 op *= pow(2.0, -1022.0);
1886 } else {
1887 op = (double)(ma | ((INR64)1 << 52))/(double)((INR64)1 << 52);
1888 op *= pow(2.0, (((int)ep)-1023.0));
1889 }
1890 if (sn)
1891 op = -op;
1892 return op;
1893 }
1894
1895 /* Return a string representation of a 32 bit ctime. */
1896 /* A static buffer is used. There is no \n at the end */
ctime_32(const INR32 * timer)1897 char *ctime_32(const INR32 *timer) {
1898 char *rv;
1899 #if defined(_MSC_VER) && __MSVCRT_VERSION__ >= 0x0601
1900 rv = _ctime32((const __time32_t *)timer);
1901 #else
1902 time_t timerv = (time_t) *timer; /* May case to 64 bit */
1903 rv = ctime(&timerv);
1904 #endif
1905
1906 if (rv != NULL)
1907 rv[strlen(rv)-1] = '\000';
1908
1909 return rv;
1910 }
1911
1912 /* Return a string representation of a 64 bit ctime. */
1913 /* A static buffer is used. There is no \n at the end */
ctime_64(const INR64 * timer)1914 char *ctime_64(const INR64 *timer) {
1915 char *rv;
1916 #if defined(_MSC_VER) && __MSVCRT_VERSION__ >= 0x0601
1917 rv = _ctime64((const __time64_t *)timer);
1918 #else
1919 time_t timerv;
1920
1921 if (sizeof(time_t) == 4 && *timer > 0x7fffffff)
1922 return NULL;
1923 timerv = (time_t) *timer; /* May truncate to 32 bits */
1924 rv = ctime(&timerv);
1925 #endif
1926
1927 if (rv != NULL)
1928 rv[strlen(rv)-1] = '\000';
1929
1930 return rv;
1931 }
1932
1933 /*******************************************/
1934 /* Native to/from byte buffer functions */
1935 /*******************************************/
1936
1937 /* No overflow detection is done - */
1938 /* numbers are clipped or truncated. */
1939
1940 /* be = Big Endian */
1941 /* le = Little Endian */
1942
1943 /* - - - - - - - - */
1944 /* Unsigned 8 bit */
1945
read_ORD8(ORD8 * p)1946 unsigned int read_ORD8(ORD8 *p) {
1947 unsigned int rv;
1948 rv = ((unsigned int)p[0]);
1949 return rv;
1950 }
1951
write_ORD8(ORD8 * p,unsigned int d)1952 void write_ORD8(ORD8 *p, unsigned int d) {
1953 if (d > 0xff)
1954 d = 0xff;
1955 p[0] = (ORD8)(d);
1956 }
1957
1958 /* - - - - - - - - */
1959 /* Signed 8 bit */
1960
read_INR8(ORD8 * p)1961 int read_INR8(ORD8 *p) {
1962 int rv;
1963 rv = (int)(INR8)p[0];
1964 return rv;
1965 }
1966
write_INR8(ORD8 * p,int d)1967 void write_INR8(ORD8 *p, int d) {
1968 if (d > 0x7f)
1969 d = 0x7f;
1970 else if (d < -0x80)
1971 d = -0x80;
1972 p[0] = (ORD8)(d);
1973 }
1974
1975 /* - - - - - - - - */
1976 /* Unsigned 16 bit */
1977
read_ORD16_be(ORD8 * p)1978 unsigned int read_ORD16_be(ORD8 *p) {
1979 unsigned int rv;
1980 rv = (((unsigned int)p[0]) << 8)
1981 + (((unsigned int)p[1]));
1982 return rv;
1983 }
1984
read_ORD16_le(ORD8 * p)1985 unsigned int read_ORD16_le(ORD8 *p) {
1986 unsigned int rv;
1987 rv = (((unsigned int)p[0]))
1988 + (((unsigned int)p[1]) << 8);
1989 return rv;
1990 }
1991
write_ORD16_be(ORD8 * p,unsigned int d)1992 void write_ORD16_be(ORD8 *p, unsigned int d) {
1993 if (d > 0xffff)
1994 d = 0xffff;
1995 p[0] = (ORD8)(d >> 8);
1996 p[1] = (ORD8)(d);
1997 }
1998
write_ORD16_le(ORD8 * p,unsigned int d)1999 void write_ORD16_le(ORD8 *p, unsigned int d) {
2000 if (d > 0xffff)
2001 d = 0xffff;
2002 p[0] = (ORD8)(d);
2003 p[1] = (ORD8)(d >> 8);
2004 }
2005
2006 /* - - - - - - - - */
2007 /* Signed 16 bit */
2008
read_INR16_be(ORD8 * p)2009 int read_INR16_be(ORD8 *p) {
2010 int rv;
2011 rv = (((int)(INR8)p[0]) << 8)
2012 + (((int)p[1]));
2013 return rv;
2014 }
2015
read_INR16_le(ORD8 * p)2016 int read_INR16_le(ORD8 *p) {
2017 int rv;
2018 rv = (((int)p[0]))
2019 + (((int)(INR8)p[1]) << 8);
2020 return rv;
2021 }
2022
write_INR16_be(ORD8 * p,int d)2023 void write_INR16_be(ORD8 *p, int d) {
2024 if (d > 0x7fff)
2025 d = 0x7fff;
2026 else if (d < -0x8000)
2027 d = -0x8000;
2028 p[0] = (ORD8)(d >> 8);
2029 p[1] = (ORD8)(d);
2030 }
2031
write_INR16_le(ORD8 * p,int d)2032 void write_INR16_le(ORD8 *p, int d) {
2033 if (d > 0x7fff)
2034 d = 0x7fff;
2035 else if (d < -0x8000)
2036 d = -0x8000;
2037 p[0] = (ORD8)(d);
2038 p[1] = (ORD8)(d >> 8);
2039 }
2040
2041 /* - - - - - - - - */
2042 /* Unsigned 32 bit */
2043
read_ORD32_be(ORD8 * p)2044 unsigned int read_ORD32_be(ORD8 *p) {
2045 unsigned int rv;
2046 rv = (((unsigned int)p[0]) << 24)
2047 + (((unsigned int)p[1]) << 16)
2048 + (((unsigned int)p[2]) << 8)
2049 + (((unsigned int)p[3]));
2050 return rv;
2051 }
2052
read_ORD32_le(ORD8 * p)2053 unsigned int read_ORD32_le(ORD8 *p) {
2054 unsigned int rv;
2055 rv = (((unsigned int)p[0]))
2056 + (((unsigned int)p[1]) << 8)
2057 + (((unsigned int)p[2]) << 16)
2058 + (((unsigned int)p[3]) << 24);
2059 return rv;
2060 }
2061
write_ORD32_be(ORD8 * p,unsigned int d)2062 void write_ORD32_be(ORD8 *p, unsigned int d) {
2063 p[0] = (ORD8)(d >> 24);
2064 p[1] = (ORD8)(d >> 16);
2065 p[2] = (ORD8)(d >> 8);
2066 p[3] = (ORD8)(d);
2067 }
2068
write_ORD32_le(ORD8 * p,unsigned int d)2069 void write_ORD32_le(ORD8 *p, unsigned int d) {
2070 p[0] = (ORD8)(d);
2071 p[1] = (ORD8)(d >> 8);
2072 p[2] = (ORD8)(d >> 16);
2073 p[3] = (ORD8)(d >> 24);
2074 }
2075
2076 /* - - - - - - - - */
2077 /* Signed 32 bit */
2078
read_INR32_be(ORD8 * p)2079 int read_INR32_be(ORD8 *p) {
2080 int rv;
2081 rv = (((int)(INR8)p[0]) << 24)
2082 + (((int)p[1]) << 16)
2083 + (((int)p[2]) << 8)
2084 + (((int)p[3]));
2085 return rv;
2086 }
2087
read_INR32_le(ORD8 * p)2088 int read_INR32_le(ORD8 *p) {
2089 int rv;
2090 rv = (((int)p[0]))
2091 + (((int)p[1]) << 8)
2092 + (((int)p[2]) << 16)
2093 + (((int)(INR8)p[3]) << 24);
2094 return rv;
2095 }
2096
write_INR32_be(ORD8 * p,int d)2097 void write_INR32_be(ORD8 *p, int d) {
2098 p[0] = (ORD8)(d >> 24);
2099 p[1] = (ORD8)(d >> 16);
2100 p[2] = (ORD8)(d >> 8);
2101 p[3] = (ORD8)(d);
2102 }
2103
write_INR32_le(ORD8 * p,int d)2104 void write_INR32_le(ORD8 *p, int d) {
2105 p[0] = (ORD8)(d);
2106 p[1] = (ORD8)(d >> 8);
2107 p[2] = (ORD8)(d >> 16);
2108 p[3] = (ORD8)(d >> 24);
2109 }
2110
2111 /* - - - - - - - - */
2112 /* Unsigned 64 bit */
2113
read_ORD64_be(ORD8 * p)2114 ORD64 read_ORD64_be(ORD8 *p) {
2115 ORD64 rv;
2116 rv = (((ORD64)p[0]) << 56)
2117 + (((ORD64)p[1]) << 48)
2118 + (((ORD64)p[2]) << 40)
2119 + (((ORD64)p[3]) << 32)
2120 + (((ORD64)p[4]) << 24)
2121 + (((ORD64)p[5]) << 16)
2122 + (((ORD64)p[6]) << 8)
2123 + (((ORD64)p[7]));
2124 return rv;
2125 }
2126
read_ORD64_le(ORD8 * p)2127 ORD64 read_ORD64_le(ORD8 *p) {
2128 ORD64 rv;
2129 rv = (((ORD64)p[0]))
2130 + (((ORD64)p[1]) << 8)
2131 + (((ORD64)p[2]) << 16)
2132 + (((ORD64)p[3]) << 24)
2133 + (((ORD64)p[4]) << 32)
2134 + (((ORD64)p[5]) << 40)
2135 + (((ORD64)p[6]) << 48)
2136 + (((ORD64)p[7]) << 56);
2137 return rv;
2138 }
2139
write_ORD64_be(ORD8 * p,ORD64 d)2140 void write_ORD64_be(ORD8 *p, ORD64 d) {
2141 p[0] = (ORD8)(d >> 56);
2142 p[1] = (ORD8)(d >> 48);
2143 p[2] = (ORD8)(d >> 40);
2144 p[3] = (ORD8)(d >> 32);
2145 p[4] = (ORD8)(d >> 24);
2146 p[5] = (ORD8)(d >> 16);
2147 p[6] = (ORD8)(d >> 8);
2148 p[7] = (ORD8)(d);
2149 }
2150
write_ORD64_le(ORD8 * p,ORD64 d)2151 void write_ORD64_le(ORD8 *p, ORD64 d) {
2152 p[0] = (ORD8)(d);
2153 p[1] = (ORD8)(d >> 8);
2154 p[2] = (ORD8)(d >> 16);
2155 p[3] = (ORD8)(d >> 24);
2156 p[4] = (ORD8)(d >> 32);
2157 p[5] = (ORD8)(d >> 40);
2158 p[6] = (ORD8)(d >> 48);
2159 p[7] = (ORD8)(d >> 56);
2160 }
2161
2162 /* - - - - - - - - */
2163 /* Signed 64 bit */
2164
read_INR64_be(ORD8 * p)2165 INR64 read_INR64_be(ORD8 *p) {
2166 INR64 rv;
2167 rv = (((INR64)(INR8)p[0]) << 56)
2168 + (((INR64)p[1]) << 48)
2169 + (((INR64)p[2]) << 40)
2170 + (((INR64)p[3]) << 32)
2171 + (((INR64)p[4]) << 24)
2172 + (((INR64)p[5]) << 16)
2173 + (((INR64)p[6]) << 8)
2174 + (((INR64)p[7]));
2175 return rv;
2176 }
2177
read_INR64_le(ORD8 * p)2178 INR64 read_INR64_le(ORD8 *p) {
2179 INR64 rv;
2180 rv = (((INR64)p[0]))
2181 + (((INR64)p[1]) << 8)
2182 + (((INR64)p[2]) << 16)
2183 + (((INR64)p[3]) << 24)
2184 + (((INR64)p[4]) << 32)
2185 + (((INR64)p[5]) << 40)
2186 + (((INR64)p[6]) << 48)
2187 + (((INR64)(INR8)p[7]) << 56);
2188 return rv;
2189 }
2190
write_INR64_be(ORD8 * p,INR64 d)2191 void write_INR64_be(ORD8 *p, INR64 d) {
2192 p[0] = (ORD8)(d >> 56);
2193 p[1] = (ORD8)(d >> 48);
2194 p[2] = (ORD8)(d >> 40);
2195 p[3] = (ORD8)(d >> 32);
2196 p[4] = (ORD8)(d >> 24);
2197 p[5] = (ORD8)(d >> 16);
2198 p[6] = (ORD8)(d >> 8);
2199 p[7] = (ORD8)(d);
2200 }
2201
write_INR64_le(ORD8 * p,INR64 d)2202 void write_INR64_le(ORD8 *p, INR64 d) {
2203 p[0] = (ORD8)(d);
2204 p[1] = (ORD8)(d >> 8);
2205 p[2] = (ORD8)(d >> 16);
2206 p[3] = (ORD8)(d >> 24);
2207 p[4] = (ORD8)(d >> 32);
2208 p[5] = (ORD8)(d >> 40);
2209 p[6] = (ORD8)(d >> 48);
2210 p[7] = (ORD8)(d >> 56);
2211 }
2212
2213 /*******************************/
2214 /* System independent timing */
2215
2216 #ifdef NT
2217
2218 /* Sleep for the given number of msec */
msec_sleep(unsigned int msec)2219 void msec_sleep(unsigned int msec) {
2220 Sleep(msec);
2221 }
2222
2223 /* Return the current time in msec since */
2224 /* the first invokation of msec_time() */
2225 /* (Is this based on timeGetTime() ? ) */
msec_time()2226 unsigned int msec_time() {
2227 unsigned int rv;
2228 static unsigned int startup = 0;
2229
2230 rv = GetTickCount();
2231 if (startup == 0)
2232 startup = rv;
2233
2234 return rv - startup;
2235 }
2236
2237 /* Return the current time in usec */
2238 /* since the first invokation of usec_time() */
2239 /* Return -1.0 if not available */
usec_time()2240 double usec_time() {
2241 double rv;
2242 LARGE_INTEGER val;
2243 static double scale = 0.0;
2244 static LARGE_INTEGER startup;
2245
2246 if (scale == 0.0) {
2247 if (QueryPerformanceFrequency(&val) == 0)
2248 return -1.0;
2249 scale = 1000000.0/val.QuadPart;
2250 QueryPerformanceCounter(&val);
2251 startup.QuadPart = val.QuadPart;
2252
2253 } else {
2254 QueryPerformanceCounter(&val);
2255 }
2256 val.QuadPart -= startup.QuadPart;
2257
2258 rv = val.QuadPart * scale;
2259
2260 return rv;
2261 }
2262
2263 #endif /* NT */
2264
2265 #if defined(UNIX)
2266
2267 /* Sleep for the given number of msec */
2268 /* (Note that OS X 10.9+ App Nap can wreck this, unless */
2269 /* it is turned off.) */
msec_sleep(unsigned int msec)2270 void msec_sleep(unsigned int msec) {
2271 #ifdef NEVER
2272 if (msec > 1000) {
2273 unsigned int secs;
2274 secs = msec / 1000;
2275 msec = msec % 1000;
2276 sleep(secs);
2277 }
2278 usleep(msec * 1000);
2279 #else
2280 struct timespec ts;
2281
2282 ts.tv_sec = msec / 1000;
2283 ts.tv_nsec = (msec % 1000) * 1000000;
2284 nanosleep(&ts, NULL);
2285 #endif
2286 }
2287
2288
2289 #if defined(__APPLE__) && !defined(CLOCK_MONOTONIC)
2290
2291 #include <mach/mach_time.h>
2292
msec_time()2293 unsigned int msec_time() {
2294 mach_timebase_info_data_t timebase;
2295 static uint64_t startup = 0;
2296 uint64_t time;
2297 double msec;
2298
2299 time = mach_absolute_time();
2300 if (startup == 0)
2301 startup = time;
2302
2303 mach_timebase_info(&timebase);
2304 time -= startup;
2305 msec = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e6);
2306
2307 return (unsigned int)floor(msec + 0.5);
2308 }
2309
2310 /* Return the current time in usec */
2311 /* since the first invokation of usec_time() */
usec_time()2312 double usec_time() {
2313 mach_timebase_info_data_t timebase;
2314 static uint64_t startup = 0;
2315 uint64_t time;
2316 double usec;
2317
2318 time = mach_absolute_time();
2319 if (startup == 0)
2320 startup = time;
2321
2322 mach_timebase_info(&timebase);
2323 time -= startup;
2324 usec = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e3);
2325
2326 return usec;
2327 }
2328
2329 #else
2330
2331 /* Return the current time in msec */
2332 /* since the first invokation of msec_time() */
msec_time()2333 unsigned int msec_time() {
2334 unsigned int rv;
2335 static struct timespec startup = { 0, 0 };
2336 struct timespec cv;
2337
2338 clock_gettime(CLOCK_MONOTONIC, &cv);
2339
2340 /* Set time to 0 on first invocation */
2341 if (startup.tv_sec == 0 && startup.tv_nsec == 0)
2342 startup = cv;
2343
2344 /* Subtract, taking care of carry */
2345 cv.tv_sec -= startup.tv_sec;
2346 if (startup.tv_nsec > cv.tv_nsec) {
2347 cv.tv_sec--;
2348 cv.tv_nsec += 1000000000;
2349 }
2350 cv.tv_nsec -= startup.tv_nsec;
2351
2352 /* Convert nsec to msec */
2353 rv = cv.tv_sec * 1000 + cv.tv_nsec / 1000000;
2354
2355 return rv;
2356 }
2357
2358 /* Return the current time in usec */
2359 /* since the first invokation of usec_time() */
usec_time()2360 double usec_time() {
2361 double rv;
2362 static struct timespec startup = { 0, 0 };
2363 struct timespec cv;
2364
2365 clock_gettime(CLOCK_MONOTONIC, &cv);
2366
2367 /* Set time to 0 on first invocation */
2368 if (startup.tv_sec == 0 && startup.tv_nsec == 0)
2369 startup = cv;
2370
2371 /* Subtract, taking care of carry */
2372 cv.tv_sec -= startup.tv_sec;
2373 if (startup.tv_nsec > cv.tv_nsec) {
2374 cv.tv_sec--;
2375 cv.tv_nsec += 1000000000;
2376 }
2377 cv.tv_nsec -= startup.tv_nsec;
2378
2379 /* Convert to usec */
2380 rv = cv.tv_sec * 1000000.0 + cv.tv_nsec/1000;
2381
2382 return rv;
2383 }
2384
2385 #endif
2386
2387 #endif /* UNIX */
2388
2389 /*******************************/
2390 /* Debug convenience functions */
2391 /*******************************/
2392
2393 #define DEB_MAX_CHAN 15
2394
2395 /* Print an int vector to a string. */
2396 /* Returned static buffer is re-used every 5 calls. */
debPiv(int di,int * p)2397 char *debPiv(int di, int *p) {
2398 static char buf[5][DEB_MAX_CHAN * 16];
2399 static int ix = 0;
2400 int e;
2401 char *bp;
2402
2403 if (++ix >= 5)
2404 ix = 0;
2405 bp = buf[ix];
2406
2407 if (di > DEB_MAX_CHAN)
2408 di = DEB_MAX_CHAN; /* Make sure that buf isn't overrun */
2409
2410 for (e = 0; e < di; e++) {
2411 if (e > 0)
2412 *bp++ = ' ';
2413 sprintf(bp, "%d", p[e]); bp += strlen(bp);
2414 }
2415 return buf[ix];
2416 }
2417
2418 /* Print a double color vector to a string. */
2419 /* Returned static buffer is re-used every 5 calls. */
debPdv(int di,double * p)2420 char *debPdv(int di, double *p) {
2421 static char buf[5][DEB_MAX_CHAN * 16];
2422 static int ix = 0;
2423 int e;
2424 char *bp;
2425
2426 if (++ix >= 5)
2427 ix = 0;
2428 bp = buf[ix];
2429
2430 if (di > DEB_MAX_CHAN)
2431 di = DEB_MAX_CHAN; /* Make sure that buf isn't overrun */
2432
2433 for (e = 0; e < di; e++) {
2434 if (e > 0)
2435 *bp++ = ' ';
2436 sprintf(bp, "%.8f", p[e]); bp += strlen(bp);
2437 }
2438 return buf[ix];
2439 }
2440
2441 /* Print a float color vector to a string. */
2442 /* Returned static buffer is re-used every 5 calls. */
debPfv(int di,float * p)2443 char *debPfv(int di, float *p) {
2444 static char buf[5][DEB_MAX_CHAN * 16];
2445 static int ix = 0;
2446 int e;
2447 char *bp;
2448
2449 if (++ix >= 5)
2450 ix = 0;
2451 bp = buf[ix];
2452
2453 if (di > DEB_MAX_CHAN)
2454 di = DEB_MAX_CHAN; /* Make sure that buf isn't overrun */
2455
2456 for (e = 0; e < di; e++) {
2457 if (e > 0)
2458 *bp++ = ' ';
2459 sprintf(bp, "%.8f", p[e]); bp += strlen(bp);
2460 }
2461 return buf[ix];
2462 }
2463
2464 #undef DEB_MAX_CHAN
2465