Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

utilities.h

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: utilities.h,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.121 $      $Date: 2022/03/25 05:16:49 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * General utility routines and definitions.
00020  *
00021  ***************************************************************************/
00022 #ifndef UTILITIES_H
00023 #define UTILITIES_H
00024 
00025 // forward declarations for WKFThreads typedefs
00026 struct wkf_cpu_caps_struct;
00027 typedef wkf_cpu_caps_struct wkf_cpu_caps_t;
00028 
00029 #include <stdlib.h> // need RAND_MAX
00030 #include <stddef.h> // ptrdiff_t 
00031 
00032 // macro workaround for MacOS X failing to expose C99 math routines in
00033 // their standard math headers.  This is probably unnecessary with 
00034 // later revs of MacOS X, but is necessary for MacOS X 10.10 and earlier.
00035 #ifdef __APPLE__
00036 #define sincos(x, s, c) __sincos(x, s, c)
00037 #define sincosf(x, s, c) __sincosf(x, s, c)
00038 #endif
00039 
00040 #if defined(_MSC_VER)
00041 #define sincos(x, s, c)  (*s) = sin(x); (*c) = cos(x);
00042 #define sincosf(x, s, c)  (*s) = sinf(x); (*c) = cosf(x);
00043 #endif
00044 
00045 #ifndef FALSE
00046 #define FALSE 0
00047 #define TRUE  1
00048 #endif
00049 
00050 #ifndef NULL
00051 #define NULL 0
00052 #endif
00053 
00054 #ifndef ABS
00055 #define ABS(A) ((A)>0?(A):-(A))
00056 #endif
00057 
00058 // various PI macros not available on all machines
00059 #define VMD_PI      3.14159265358979323846
00060 #define VMD_TWOPI   (2.0 * VMD_PI)
00061 #define VMD_1_PI    0.31830988618379067154
00062 
00063 // single-precision versions
00064 #define VMD_PIF     3.14159265358979323846f
00065 #define VMD_TWOPIF  (2.0f * VMD_PIF)
00066 #define VMD_1_PIF   0.31830988618379067154f
00067 
00068 // Convert Angstroms to Bohr
00069 #define VMD_ANGS_TO_BOHR 1.88972612478289694072
00070 
00071 // Degree-to-Radians and Radians-to-Degrees Conversion macros
00072 #define DEGTORAD(a)     (a*VMD_PI/180.0)
00073 #define RADTODEG(a)     (a*180.0/VMD_PI)
00074 
00078 extern char *combine_arguments(int, const char **, int);
00079 
00080 
00082 extern char *stringdup(const char *);
00083 
00084 
00086 extern char *stringtoupper(char *);
00087 
00089 void stripslashes(char *str);
00090 
00092 extern int strupcmp(const char *, const char *);
00094 extern int strupncmp(const char *, const char *, int);
00095 
00096 
00100 extern void breakup_filename(const char *, char **, char **);
00101 
00103 extern char *str_tokenize(const char *, int *, char **);
00104 
00107 extern double time_of_day(void);
00108 
00110 extern int vmd_check_stdin(void);
00111 
00113 extern char * vmd_username(void);
00115 extern int vmd_getuid(void);
00116 
00117 
00118 // Find the first selected atom, return 0 on success, return -1 if no selection
00119 extern int find_first_selection_aligned(int n, const int *on, int *firstsel);
00120 
00121 // Find the last selected atom, return 0 on success, return -1 if no selection
00122 extern int find_last_selection_aligned(int n, const int *on, int *lastsel);
00123 
00124 // Find the first selected atom, the last selected atom,
00125 // and the total number of selected atoms.
00126 // return 0 on success, return -1 if no selection
00127 extern int analyze_selection_aligned(int n, const int *on,
00128                                      int *firstsel, int *lastsel, int *selected);
00129 
00130 extern int analyze_selection_aligned_dispatch(wkf_cpu_caps_t *cpucaps,
00131                                               int n, const int *on,
00132                                               int *firstsel, int *lastsel, 
00133                                               int *selected);
00134 
00136 extern void minmaxmean_1fv_aligned(const float *f, ptrdiff_t n, 
00137                                    float *fmin, float *fmax, float *fmean);
00138 
00140 extern void minmax_1fv_aligned(const float *f, ptrdiff_t n, float *min, float *max);
00141 
00142 // Compute min/max values for a 16-byte-aligned array of floats
00143 // input value n3 is the number of 3-element vectors to process
00144 extern void minmax_3fv_aligned(const float *f, const ptrdiff_t n3, float *fmin, float *fmax);
00145 
00146 // Compute min/max values for a 16-byte-aligned array of floats
00147 // input value on is the array of atom selection flags, and firstsel
00148 // and lastsel indicate the first and last 3-element vectors to process
00149 // return 0 on success, -1 on no selected atoms or other problems
00150 extern int minmax_selected_3fv_aligned(const float *f, const int *on, 
00151                                        const ptrdiff_t n3, 
00152                                        const ptrdiff_t firstsel, 
00153                                        const ptrdiff_t lastsel, 
00154                                        float *fmin, float *fmax);
00155 
00157 inline int clamp_int(int val, int min, int max) {
00158   return (val > min) ? ((val <= max) ? val : max) : min;
00159 }
00160 
00163 extern float * cross_prod(float *x1, const float *x2, const float *x3);
00164 
00166 inline float dot_prod(const float *v1, const float *v2) {
00167   return v1[0]* v2[0] + v1[1]* v2[1] + v1[2] * v2[2];
00168 }
00169 
00170 inline double dot_prod(const double *v1, const double *v2) {
00171   return v1[0]* v2[0] + v1[1]* v2[1] + v1[2] * v2[2];
00172 }
00173 
00175 inline void vec_copy(float *v1, const float *v2) {
00176   v1[0] = v2[0];
00177   v1[1] = v2[1];
00178   v1[2] = v2[2];
00179 }
00180 
00182 inline void vec_copy(double *v1, const double *v2) {
00183   v1[0] = v2[0];
00184   v1[1] = v2[1];
00185   v1[2] = v2[2];
00186 }
00187 
00190 extern float * vec_normalize(float *);
00191 
00194 inline void vec_sub(float *a, const float *b, const float *c) {
00195   a[0]=b[0]-c[0];
00196   a[1]=b[1]-c[1];
00197   a[2]=b[2]-c[2];
00198 }
00199 
00202 inline void vec_sub(double *a, const double *b, const double *c) {
00203   a[0]=b[0]-c[0];
00204   a[1]=b[1]-c[1];
00205   a[2]=b[2]-c[2];
00206 }
00207 
00209 inline void vec_add(float *a, const float *b, const float *c) {
00210   a[0]=b[0]+c[0];
00211   a[1]=b[1]+c[1];
00212   a[2]=b[2]+c[2];
00213 }
00214 
00216 inline void vec_incr(float *a, const float *b) {
00217   a[0] += b[0];
00218   a[1] += b[1];
00219   a[2] += b[2];
00220 }
00221 
00223 inline void vec_scale(float *a, float b, const float *c) {
00224   a[0] = b*c[0];
00225   a[1] = b*c[1];
00226   a[2] = b*c[2];
00227 }
00228 
00230 inline void vec_scale(float *a, float b, const double *c) {
00231   a[0] = b * (float) c[0];
00232   a[1] = b * (float) c[1];
00233   a[2] = b * (float) c[2];
00234 }
00235 
00237 inline void vec_negate(float *a, const float *b) {
00238   a[0] = -b[0];
00239   a[1] = -b[1];
00240   a[2] = -b[2];
00241 }
00242 
00244 inline void vec_scaled_add(float *a, float b, const float *c) {
00245   a[0] += b*c[0];
00246   a[1] += b*c[1];
00247   a[2] += b*c[2];
00248 }
00249 
00251 inline void vec_scaled_add(double *a, float b, const double *c) {
00252   a[0] += b*c[0];
00253   a[1] += b*c[1];
00254   a[2] += b*c[2];
00255 }
00256 
00258 inline void vec_triad(float *a, const float *b, float c, const float *d) {
00259   a[0] = b[0] + c*d[0];
00260   a[1] = b[1] + c*d[1];
00261   a[2] = b[2] + c*d[2];
00262 }
00263 
00265 inline void vec_lerp(float *a, const float *b, const float *c, float frac) {
00266   float diff[3], tmp[3];
00267   vec_sub(diff, c, b);
00268   vec_scale(tmp, frac, diff);
00269   vec_add(a, b, tmp);
00270 }
00271 
00272 // multiply the matrix mat with the vector vec (length 3)
00273 inline void vectrans(float *npoint, float *mat, double *vec){
00274   npoint[0]=float(vec[0]*mat[0]+vec[1]*mat[4]+vec[2]*mat[8]);
00275   npoint[1]=float(vec[0]*mat[1]+vec[1]*mat[5]+vec[2]*mat[9]);
00276   npoint[2]=float(vec[0]*mat[2]+vec[1]*mat[6]+vec[2]*mat[10]);
00277 }
00278 
00279 inline void vec_zero(float *a) {
00280   a[0] = 0.0f;
00281   a[1] = 0.0f;
00282   a[2] = 0.0f;
00283 }
00284 
00285 inline void vec_zero(double *a) {
00286   a[0] = 0.0f;
00287   a[1] = 0.0f;
00288   a[2] = 0.0f;
00289 }
00290 
00291 inline void clamp_color(float *rgb) {
00292   // clamp color values to legal range
00293   if (rgb[0] < 0.0f)
00294     rgb[0] = 0.0f;
00295   if (rgb[0] > 1.0f)
00296     rgb[0] = 1.0f;
00297 
00298   if (rgb[1] < 0.0f)
00299     rgb[1] = 0.0f;
00300   if (rgb[1] > 1.0f)
00301     rgb[1] = 1.0f;
00302 
00303   if (rgb[2] < 0.0f)
00304     rgb[2] = 0.0f;
00305   if (rgb[2] > 1.0f)
00306     rgb[2] = 1.0f;
00307 }
00308 
00309 
00311 inline void midpoint(float *a, const float *b, const float *c) {
00312   a[0] = 0.5f * (b[0]+c[0]);
00313   a[1] = 0.5f * (b[1]+c[1]);
00314   a[2] = 0.5f * (b[2]+c[2]);
00315 }
00316 
00317 
00318 // These define a cubic spline with various bases
00319 // see Foley and Van Dam, et. al., Computer Graphics, p505 or so
00320 //
00321 // this one was too sharply curved for my tastes
00322 //
00323 // float CatmullRom_basis[4][4]={{-1.0/2.0,  3.0/2.0, -3.0/2.0,  1.0/2.0},
00324 //                               { 2.0/2.0, -5.0/2.0,  4.0/2.0, -1.0/2.0},
00325 //                               {-1.0/2.0,  0.0/2.0,  1.0/2.0,  0.0/2.0},
00326 //                               { 0.0/2.0,  2.0/2.0,  0.0/2.0,  0.0/2.0}};
00327 //
00328 // this define makes the next basis identical to CatmullRom
00329 // #define SLOPE 2.0f
00330 //
00331 // This deemphasizes the slope and makes things look nicer (IMHO)
00332 // #define SLOPE 1.25f
00333 //
00334 // float modified_CR_basis[4][4] = {
00335 //    {-1.0f/SLOPE,  -1.0f/SLOPE + 2.0f,  1.0f/SLOPE - 2.0f,  1.0f/SLOPE},
00336 //    { 2.0f/SLOPE,   1.0f/SLOPE - 3.0f,   -2.0f/SLOPE+3.0f, -1.0f/SLOPE},
00337 //    {-1.0f/SLOPE,                0.0f,         1.0f/SLOPE,        0.0f},
00338 //    {       0.0f,                1.0f,               0.0f,        0.0f}
00339 // };
00340 //
00341 // This doesn't describe the system very nicely as the lines don't
00342 // go through the control points (which are the C-alphas)
00343 // float Bspline_basis[4][4]={{-1.0/6.0,  3.0/6.0, -3.0/6.0,  1.0/6.0},
00344 //                            { 3.0/6.0, -6.0/6.0,  3.0/6.0,  0.0/6.0},
00345 //                            {-3.0/6.0,  0.0/6.0,  3.0/6.0,  0.0/6.0},
00346 //                            { 1.0/6.0,  4.0/6.0,  1.0/6.0,  0.0/6.0}};
00347 
00349 inline void create_Bspline_basis(float array[4][4]) {
00350   array[0][0] = -1.0f/6.0f;
00351   array[0][1] =  3.0f/6.0f;
00352   array[0][2] = -3.0f/6.0f;
00353   array[0][3] =  1.0f/6.0f;
00354   array[1][0] =  3.0f/6.0f;
00355   array[1][1] = -6.0f/6.0f;
00356   array[1][2] =  3.0f/6.0f;
00357   array[1][3] =  0.0f/6.0f;
00358   array[2][0] = -3.0f/6.0f;
00359   array[2][1] =  0.0f/6.0f;
00360   array[2][2] =  3.0f/6.0f;
00361   array[2][3] =  0.0f/6.0f;
00362   array[3][0] =  1.0f/6.0f;
00363   array[3][1] =  4.0f/6.0f;
00364   array[3][2] =  1.0f/6.0f;
00365   array[3][3] =  0.0f/6.0f;
00366 }
00367 
00369 inline void create_modified_CR_spline_basis(float array[4][4], float slope) {
00370   array[0][0] = -1.0f / slope;
00371   array[0][1] = -1.0f / slope + 2.0f;
00372   array[0][2] =  1.0f / slope - 2.0f;
00373   array[0][3] =  1.0f / slope;
00374   array[1][0] =  2.0f / slope;
00375   array[1][1] =  1.0f / slope - 3.0f;
00376   array[1][2] = -2.0f / slope + 3.0f;
00377   array[1][3] = -1.0f / slope;
00378   array[2][0] = -1.0f / slope;
00379   array[2][1] =  0.0f;
00380   array[2][2] =  1.0f / slope;
00381   array[2][3] =  0.0f;
00382   array[3][0] =  0.0f;
00383   array[3][1] =  1.0f;
00384   array[3][2] =  0.0f;
00385   array[3][3] =  0.0f;
00386 }
00387 
00394 inline void make_spline_Q_matrix(float q[4][3], float basis[4][4], const float *pts) {
00395   int i, j;
00396   for (i = 0; i<4; i++) {
00397     float a, b, c;
00398     a = b = c = 0.0;
00399 
00400     for (j = 0; j<4; j++) {
00401       a += basis[i][j] * pts[j*3L    ];
00402       b += basis[i][j] * pts[j*3L + 1];
00403       c += basis[i][j] * pts[j*3L + 2];
00404     }
00405 
00406     q[i][0] = a; 
00407     q[i][1] = b; 
00408     q[i][2] = c; 
00409   }
00410 }
00411 
00418 inline void make_spline_Q_matrix_noncontig(float q[4][3], float basis[4][4], 
00419                                         const float *pts1, const float *pts2,
00420                                         const float *pts3, const float *pts4) {
00421   int i;
00422 
00423   for (i = 0; i<4; i++) {
00424     float a, b, c;
00425     a = b = c = 0.0;
00426 
00427     a += basis[i][0] * pts1[0];
00428     b += basis[i][0] * pts1[1];
00429     c += basis[i][0] * pts1[2];
00430 
00431     a += basis[i][1] * pts2[0];
00432     b += basis[i][1] * pts2[1];
00433     c += basis[i][1] * pts2[2];
00434 
00435     a += basis[i][2] * pts3[0];
00436     b += basis[i][2] * pts3[1];
00437     c += basis[i][2] * pts3[2];
00438 
00439     a += basis[i][3] * pts4[0];
00440     b += basis[i][3] * pts4[1];
00441     c += basis[i][3] * pts4[2];
00442 
00443     q[i][0] = a; 
00444     q[i][1] = b; 
00445     q[i][2] = c; 
00446   }
00447 }
00448 
00449 
00461 inline void make_spline_interpolation(float out[3], float w, float q[4][3]) {
00462   out[0] = w * (w * (w * q[0][0] + q[1][0]) + q[2][0]) + q[3][0];
00463   out[1] = w * (w * (w * q[0][1] + q[1][1]) + q[2][1]) + q[3][1];
00464   out[2] = w * (w * (w * q[0][2] + q[1][2]) + q[2][2]) + q[3][2];
00465 }
00466 
00468 extern int tri_degenerate(const float *, const float *, const float *);
00469 
00471 extern float angle(const float *, const float *);
00472 
00475 extern float dihedral(const float *, const float *, const float *, 
00476                       const float *);
00477 
00479 extern float distance(const float *, const float *);
00480 
00482 inline float distance2(const float *a, const float *b) {
00483   float delta = a[0] - b[0];
00484   float r2 = delta*delta;
00485   delta = a[1] - b[1];
00486   r2 += delta*delta;
00487   delta = a[2] - b[2];
00488   return r2 + delta*delta;
00489 }
00490 
00492 extern float norm(const float *);
00493 
00497 char *vmd_tempfile(const char *);
00498 
00500 int vmd_delete_file(const char *);
00501 
00503 void vmd_sleep(int);   // sleeps for N seconds
00504 void vmd_msleep(int);  // sleeps for N milliseconds
00505 
00508 extern int vmd_system(const char* cmd);
00509 
00510 
00512 extern void vmd_srandom(unsigned int);
00513 extern long vmd_random();
00514 extern float vmd_random_gaussian();
00515 
00516 // select the right VMD_RAND_MAX value depending on implementation and platform
00517 #if defined(__linux) || defined(_MSC_VER)
00518 // Linux uses RAND_MAX for both rand() and random()
00519 // Windows is currently implemented with rand()
00520 #define VMD_RAND_MAX RAND_MAX
00521 #else
00522 // All other platforms I've seen use 2^31-1 for their max random() return val
00523 #if defined(LONG_MAX)
00524 #define VMD_RAND_MAX LONG_MAX
00525 #else
00526 // just in case no LONG_MAX, 
00527 // or in cases where they choose to update it for 64-bits or something
00528 #define VMD_RAND_MAX 2147483647L
00529 #endif
00530 #endif
00531 
00533 long vmd_get_total_physmem_mb(void);
00534 
00536 long vmd_get_avail_physmem_mb(void);
00537 
00539 long vmd_get_avail_physmem_percent(void);
00540 
00541 #endif
00542 
00543 // Poisson disk sampling
00544 int k_candidates(int,int,int,int,float,float*,float*); // generates K candidates, returns farthest away from all previous samples
00545 float arcdistance(float,float,float,float); //arcdistance between 2 pts on unit sphere
00546 void print_xyz(float*,int); //print poisson set to .xyz file for validation
00547 float correction(int); //returns minimum distance given N samples
00548 int poisson_sample_on_sphere(float*,int,int,int); //Poisson disk sampling procedure
00549 // -- 
00550 
00551 
00552 // Hardware-specific SIMD query routines available only via
00553 // runtime CPU dispatch checks
00554 #if defined(VMDCPUDISPATCH) && (defined(__ARM_ARCH_ISA_A64) || defined(__ARM_NEON))
00555 int arm_sve_vecsize_32bits();
00556 int arm_sve_vecsize_64bits();
00557 #endif
00558 

Generated on Wed Apr 24 02:43:31 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002