/*
--------------------------------- random_r.c and utilities Park & Miller's minimimal standard random number generator argc/argv conversion Used by rbox. Do not use 'qh' */ #include "libqhull_r.h" #include "random_r.h" #include#include #include #ifdef _MSC_VER /* Microsoft Visual C++ -- warning level 4 */ #pragma warning( disable : 4706) /* assignment within conditional function */ #pragma warning( disable : 4996) /* function was declared deprecated(strcpy, localtime, etc.) */ #endif /*--------------------------------- qh_argv_to_command( argc, argv, command, max_size ) build command from argc/argv max_size is at least returns: a space-delimited string of options (just as typed) returns false if max_size is too short notes: silently removes makes option string easy to input and output matches qh_argv_to_command_size argc may be 0 */ int qh_argv_to_command(int argc, char *argv[], char* command, int max_size) { int i, remaining; char *s; *command= '\0'; /* max_size > 0 */ if (argc) { if ((s= strrchr( argv[0], '\\')) /* get filename w/o .exe extension */ || (s= strrchr( argv[0], '/'))) s++; else s= argv[0]; if ((int)strlen(s) < max_size) /* WARN64 */ strcpy(command, s); else goto error_argv; if ((s= strstr(command, ".EXE")) || (s= strstr(command, ".exe"))) *s= '\0'; } for (i=1; i < argc; i++) { s= argv[i]; remaining= max_size - (int)strlen(command) - (int)strlen(s) - 2; /* WARN64 */ if (!*s || strchr(s, ' ')) { char *t= command + strlen(command); remaining -= 2; if (remaining < 0) { goto error_argv; } *t++= ' '; *t++= '"'; while (*s) { if (*s == '"') { if (--remaining < 0) goto error_argv; *t++= '\\'; } *t++= *s++; } *t++= '"'; *t= '\0'; }else if (remaining < 0) { goto error_argv; }else { strcat(command, " "); strcat(command, s); } } return 1; error_argv: return 0; } /* argv_to_command */ /*--------------------------------- qh_argv_to_command_size( argc, argv ) return size to allocate for qh_argv_to_command() notes: only called from rbox with qh_errexit not enabled caller should report error if returned size is less than 1 argc may be 0 actual size is usually shorter */ int qh_argv_to_command_size(int argc, char *argv[]) { int count= 1; /* null-terminator if argc==0 */ int i; char *s; for (i=0; i 0 && strchr(argv[i], ' ')) { count += 2; /* quote delimiters */ for (s=argv[i]; *s; s++) { if (*s == '"') { count++; } } } } return count; } /* argv_to_command_size */ /*--------------------------------- qh_rand() qh_srand(qh, seed ) generate pseudo-random number between 1 and 2^31 -2 notes: For qhull and rbox, called from qh_RANDOMint(),etc. [user_r.h] From Park & Miller's minimal standard random number generator Communications of the ACM, 31:1192-1201, 1988. Does not use 0 or 2^31 -1 this is silently enforced by qh_srand() Can make 'Rn' much faster by moving qh_rand to qh_distplane */ /* Global variables and constants */ #define qh_rand_a 16807 #define qh_rand_m 2147483647 #define qh_rand_q 127773 /* m div a */ #define qh_rand_r 2836 /* m mod a */ int qh_rand(qhT *qh) { int lo, hi, test; int seed= qh->last_random; hi= seed / qh_rand_q; /* seed div q */ lo= seed % qh_rand_q; /* seed mod q */ test= qh_rand_a * lo - qh_rand_r * hi; if (test > 0) seed= test; else seed= test + qh_rand_m; qh->last_random= seed; /* seed= seed < qh_RANDOMmax/2 ? 0 : qh_RANDOMmax; for testing */ /* seed= qh_RANDOMmax; for testing */ return seed; } /* rand */ void qh_srand(qhT *qh, int seed) { if (seed < 1) qh->last_random= 1; else if (seed >= qh_rand_m) qh->last_random= qh_rand_m - 1; else qh->last_random= seed; } /* qh_srand */ /*--------------------------------- qh_randomfactor(qh, scale, offset ) return a random factor r * scale + offset notes: qh.RANDOMa/b are defined in global_r.c qh_RANDOMint requires 'qh' */ realT qh_randomfactor(qhT *qh, realT scale, realT offset) { realT randr; randr= qh_RANDOMint; return randr * scale + offset; } /* randomfactor */ /*--------------------------------- qh_randommatrix(qh, buffer, dim, rows ) generate a random dim X dim matrix in range [-1,1] assumes buffer is [dim+1, dim] returns: sets buffer to random numbers sets rows to rows of buffer sets row[dim] as scratch row notes: qh_RANDOMint requires 'qh' */ void qh_randommatrix(qhT *qh, realT *buffer, int dim, realT **rows) { int i, k; realT **rowi, *coord, realr; coord= buffer; rowi= rows; for (i=0; i < dim; i++) { *(rowi++)= coord; for (k=0; k < dim; k++) { realr= qh_RANDOMint; *(coord++)= 2.0 * realr/(qh_RANDOMmax+1) - 1.0; } } *rowi= coord; } /* randommatrix */ /*--------------------------------- qh_strtol( s, endp) qh_strtod( s, endp) internal versions of strtol() and strtod() does not skip trailing spaces notes: some implementations of strtol()/strtod() skip trailing spaces */ double qh_strtod(const char *s, char **endp) { double result; result= strtod(s, endp); if (s < (*endp) && (*endp)[-1] == ' ') (*endp)--; return result; } /* strtod */ int qh_strtol(const char *s, char **endp) { int result; result= (int) strtol(s, endp, 10); /* WARN64 */ if (s< (*endp) && (*endp)[-1] == ' ') (*endp)--; return result; } /* strtol */