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

utilities.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2011 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.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.126 $      $Date: 2011/11/20 00:45:58 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * General utility routines and definitions.
00020  *
00021  ***************************************************************************/
00022 
00023 #include <string.h>
00024 #include <ctype.h>
00025 #include <math.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 
00029 #if defined(_MSC_VER)
00030 #include <windows.h>
00031 #include <conio.h>
00032 #else
00033 #include <unistd.h>
00034 #include <sys/time.h>
00035 #include <errno.h>
00036 
00037 #if defined(ARCH_AIX4)
00038 #include <strings.h>
00039 #endif
00040 
00041 #if defined(__irix)
00042 #include <bstring.h>
00043 #endif
00044 
00045 #if defined(__hpux)
00046 #include <time.h>
00047 #endif // HPUX
00048 #endif // _MSC_VER
00049 
00050 #if defined(AIXUSEPERFSTAT)
00051 #include <libperfstat.h>
00052 #endif
00053 
00054 #if defined(__APPLE__)
00055 #include <sys/sysctl.h>
00056 #endif
00057 
00058 #include "utilities.h"
00059 
00060 // given an argc, argv pair, take all the arguments from the Nth one on
00061 // and combine them into a single string with spaces separating words.  This
00062 // allocates space for the string, which must be freed by the user.
00063 char *combine_arguments(int argc, const char **argv, int n) {
00064   char *newstr = NULL;
00065 
00066   if(argc > 0 && n < argc && n >= 0) {
00067     int i, sl = 0;
00068     // find out the length of the words we must combine
00069     for(i=n; i < argc; i++)
00070       sl += strlen(argv[i]);
00071 
00072     // combine the words together
00073     if(sl) {
00074       newstr = new char[sl + 8 + argc - n];     // extra buffer added
00075       *newstr = '\0';
00076       for(i=n; i < argc; i++) {
00077         if(i != n)
00078           strcat(newstr," ");
00079         strcat(newstr, argv[i]);
00080       }
00081     }
00082   }
00083 
00084   // return the string, or NULL if a problem occurred
00085   return newstr;
00086 }
00087 
00088 
00089 // duplicate a string using c++ new call
00090 char *stringdup(const char *s) {
00091   char *rs;
00092 
00093   if(!s)
00094     return NULL;
00095 
00096   rs = new char[strlen(s) + 1];
00097   strcpy(rs,s);
00098 
00099   return rs;
00100 }
00101 
00102 
00103 // convert a string to upper case
00104 char *stringtoupper(char *s) {
00105   if (s != NULL) {
00106     int i;
00107     int sz = strlen(s);
00108     for(i=0; i<sz; i++)
00109       s[i] = toupper(s[i]);
00110   }
00111 
00112   return s;
00113 }
00114 
00115 void stripslashes(char *str) {
00116   while (strlen(str) > 0 && str[strlen(str) - 1] == '/') {
00117     str[strlen(str) - 1] = '\0';
00118   }
00119 }
00120 
00121 // do upper-case comparison
00122 int strupcmp(const char *a, const char *b) {
00123   char *ua, *ub;
00124   int retval;
00125 
00126   ua = stringtoupper(stringdup(a));
00127   ub = stringtoupper(stringdup(b));
00128 
00129   retval = strcmp(ua,ub);
00130 
00131   delete [] ub;
00132   delete [] ua;
00133 
00134   return retval;
00135 }
00136 
00137 
00138 // do upper-case comparison, up to n characters
00139 int strupncmp(const char *a, const char *b, int n) {
00140 #if defined(ARCH_AIX3) || defined(ARCH_AIX4) || defined(_MSC_VER)
00141    while (n-- > 0) {
00142       if (toupper(*a) != toupper(*b)) {
00143          return toupper(*b) - toupper(*a);
00144       }
00145       if (*a == 0) return 0;
00146       a++; b++;
00147    }
00148    return 0;
00149 #else
00150    return strncasecmp(a, b, n);
00151 #endif
00152 }
00153 
00154 
00155 // break a file name up into path + name, returning both in the specified
00156 //      character pointers.  This creates storage for the new strings
00157 //      by allocating space for them.
00158 void breakup_filename(const char *full, char **path, char **name) {
00159   const char *namestrt;
00160   int pathlen;
00161 
00162   if(full == NULL) {
00163     *path = *name = NULL;
00164     return;
00165   } else if (strlen(full) == 0) {
00166     *path = new char[1];
00167     *name = new char[1];
00168     (*path)[0] = (*name)[0] = '\0';
00169     return;
00170   }
00171 
00172   // find start of final file name
00173   if((namestrt = strrchr(full,'/')) != NULL && strlen(namestrt) > 0) {
00174     namestrt++;
00175   } else {
00176     namestrt = full;
00177   }
00178 
00179   // make a copy of the name
00180   *name = stringdup(namestrt);
00181 
00182   // make a copy of the path
00183   pathlen = strlen(full) - strlen(*name);
00184   *path = new char[pathlen + 1];
00185   strncpy(*path,full,pathlen);
00186   (*path)[pathlen] = '\0';
00187 } 
00188 
00189 // break a configuration line up into tokens.
00190 char *str_tokenize(const char *newcmd, int *argc, char *argv[]) {
00191   char *cmd; 
00192   const char *cmdstart;
00193   cmdstart = newcmd;
00194 
00195   // guarantee that the command string we return begins on the first
00196   // character returned by strtok(), otherwise the subsequent delete[]
00197   // calls will reference invalid memory blocks
00198   while (cmdstart != NULL &&
00199          (*cmdstart == ' '  ||
00200           *cmdstart == ','  ||
00201           *cmdstart == ';'  ||
00202           *cmdstart == '\t' ||
00203           *cmdstart == '\n')) {
00204     cmdstart++; // advance pointer to first command character
00205   } 
00206 
00207   cmd = stringdup(cmdstart);
00208   *argc = 0;
00209 
00210   // initialize tokenizing calls
00211   argv[*argc] = strtok(cmd, " ,;\t\n");
00212 
00213   // loop through words until end-of-string, or comment character, found
00214   while(argv[*argc] != NULL) {
00215     // see if the token starts with '#'
00216     if(argv[*argc][0] == '#') {
00217       break;                    // don't process any further tokens
00218     } else {
00219       (*argc)++;                // another token in list
00220     }
00221     
00222     // scan for next token
00223     argv[*argc] = strtok(NULL," ,;\t\n");
00224   }
00225 
00226   return (*argc > 0 ? argv[0] : (char *) NULL);
00227 }
00228 
00229 
00230 // get the time of day from the system clock, and store it (in seconds)
00231 double time_of_day(void) {
00232 #if defined(_MSC_VER)
00233   double t;
00234  
00235   t = GetTickCount(); 
00236   t = t / 1000.0;
00237 
00238   return t;
00239 #else
00240   struct timeval tm;
00241   struct timezone tz;
00242 
00243   gettimeofday(&tm, &tz);
00244   return((double)(tm.tv_sec) + (double)(tm.tv_usec)/1000000.0);
00245 #endif
00246 }
00247 
00248 
00249 int vmd_check_stdin(void) {
00250 #if defined(_MSC_VER)
00251   if (_kbhit() != 0)
00252     return TRUE;
00253   else
00254     return FALSE;
00255 #else
00256   fd_set readvec;
00257   struct timeval timeout;
00258   int ret, stdin_fd;
00259 
00260   timeout.tv_sec = 0;
00261   timeout.tv_usec = 0;
00262   stdin_fd = 0;
00263   FD_ZERO(&readvec);
00264   FD_SET(stdin_fd, &readvec);
00265 
00266 #if !defined(ARCH_AIX3)
00267   ret = select(16, &readvec, NULL, NULL, &timeout);
00268 #else
00269   ret = select(16, (int *)(&readvec), NULL, NULL, &timeout);
00270 #endif
00271  
00272   if (ret == -1) {  // got an error
00273     if (errno != EINTR)  // XXX: this is probably too lowlevel to be converted to Inform.h
00274       printf("select() error while attempting to read text input.\n");
00275     return FALSE;
00276   } else if (ret == 0) {
00277     return FALSE;  // select timed out
00278   }
00279   return TRUE;
00280 #endif
00281 }
00282 
00283 
00284 // return the username of the currently logged-on user
00285 char *vmd_username(void) {
00286 #if defined(_MSC_VER)
00287   char username[1024];
00288   unsigned long size = 1023;
00289 
00290   if (GetUserName((char *) &username, &size)) {
00291     return stringdup(username);
00292   }
00293   else { 
00294     return stringdup("Windows User");
00295   }
00296 #else
00297 #if defined(ARCH_FREEBSD) || defined(ARCH_FREEBSDAMD64) || defined(__APPLE__) || defined(__linux)
00298   return stringdup(getlogin());
00299 #else
00300   return stringdup(cuserid(NULL));
00301 #endif 
00302 #endif
00303 }
00304 
00305 int vmd_getuid(void) {
00306 #if defined(_MSC_VER)
00307   return 0;
00308 #else
00309   return getuid(); 
00310 #endif
00311 }
00312 
00313 // take three 3-vectors and compute x2 cross x3; with the results
00314 // in x1.  x1 must point to different memory than x2 or x3
00315 // This returns a pointer to x1
00316 float * cross_prod(float *x1, const float *x2, const float *x3)
00317 {
00318   x1[0] =  x2[1]*x3[2] - x3[1]*x2[2];
00319   x1[1] = -x2[0]*x3[2] + x3[0]*x2[2];
00320   x1[2] =  x2[0]*x3[1] - x3[0]*x2[1];
00321   return x1;
00322 }
00323 
00324 // normalize a vector, and return a pointer to it
00325 // Warning:  it changes the value of the vector!!
00326 float * vec_normalize(float *vect) {
00327   float len = vect[0]*vect[0] + vect[1]*vect[1] + vect[2]*vect[2];
00328 
00329   // prevent division by zero
00330   if (len > 0) {
00331     float rescale = 1.0f / sqrtf(len);
00332     vect[0] *= rescale;
00333     vect[1] *= rescale;
00334     vect[2] *= rescale;
00335   }
00336 
00337   return vect;
00338 }
00339 
00340 
00341 // find and return the norm of a 3-vector
00342 float norm(const float *vect) {
00343   return sqrtf(vect[0]*vect[0] + vect[1]*vect[1] + vect[2]*vect[2]);
00344 }
00345 
00346 
00347 // determine if a triangle is degenerate or not
00348 int tri_degenerate(const float * v0, const float * v1, const float * v2) {
00349   float s1[3], s2[3], s1_length, s2_length;
00350 
00351   /*
00352    various rendering packages have amusingly different ideas about what
00353    constitutes a degenerate triangle.  -1 and 1 work well.  numbers
00354    below 0.999 and -0.999 show up in OpenGL
00355    numbers as low as 0.98 have worked in POVRay with certain models while
00356    numbers as high as 0.999999 have produced massive holes in other
00357    models
00358          -matt 11/13/96
00359   */
00360 
00361   /**************************************************************/
00362   /*    turn the triangle into 2 normalized vectors.            */
00363   /*    If the dot product is 1 or -1 then                      */
00364   /*   the triangle is degenerate                               */
00365   /**************************************************************/
00366   s1[0] = v0[0] - v1[0];
00367   s1[1] = v0[1] - v1[1];
00368   s1[2] = v0[2] - v1[2];
00369 
00370   s2[0] = v0[0] - v2[0];
00371   s2[1] = v0[1] - v2[1];
00372   s2[2] = v0[2] - v2[2];
00373 
00374   s1_length = sqrtf(s1[0]*s1[0] + s1[1]*s1[1] + s1[2]*s1[2]);
00375   s2_length = sqrtf(s2[0]*s2[0] + s2[1]*s2[1] + s2[2]*s2[2]);
00376 
00377   /**************************************************************/
00378   /*                   invert to avoid divides:                 */
00379   /*                         1.0/v1_length * 1.0/v2_length      */
00380   /**************************************************************/
00381 
00382   s2_length = 1.0f / (s1_length*s2_length);
00383   s1_length = s2_length * (s1[0]*s2[0] + s1[1]*s2[1] + s1[2]*s2[2]);
00384 
00385   // and add it to the list if it's not degenerate
00386   if ((s1_length >= 1.0 ) || (s1_length <= -1.0)) 
00387     return 1;
00388   else
00389     return 0;
00390 }
00391 
00392 
00393 // compute the angle (in degrees 0 to 180 ) between two vectors a & b
00394 float angle(const float *a, const float *b) {
00395   float ab[3];
00396   cross_prod(ab, a, b);
00397   float psin = sqrtf(dot_prod(ab, ab));
00398   float pcos = dot_prod(a, b);
00399   return 57.2958f * (float) atan2(psin, pcos);
00400 }
00401 
00402 
00403 // Compute the dihedral angle for the given atoms, returning a value between
00404 // -180 and 180.
00405 // faster, cleaner implementation based on atan2
00406 float dihedral(const float *a1,const float *a2,const float *a3,const float *a4)
00407 {
00408   float r1[3], r2[3], r3[3], n1[3], n2[3];
00409   vec_sub(r1, a2, a1);
00410   vec_sub(r2, a3, a2);
00411   vec_sub(r3, a4, a3);
00412   
00413   cross_prod(n1, r1, r2);
00414   cross_prod(n2, r2, r3);
00415   
00416   float psin = dot_prod(n1, r3) * sqrtf(dot_prod(r2, r2));
00417   float pcos = dot_prod(n1, n2);
00418 
00419   // atan2f would be faster, but we'll have to workaround the lack
00420   // of existence on some platforms.
00421   return 57.2958f * (float) atan2(psin, pcos);
00422 }
00423  
00424 // compute the distance between points a & b
00425 float distance(const float *a, const float *b) {
00426   return sqrtf(distance2(a,b));
00427 }
00428 
00429 char *vmd_tempfile(const char *s) {
00430   char *envtxt, *TempDir;
00431 
00432   if((envtxt = getenv("VMDTMPDIR")) != NULL) {
00433     TempDir = stringdup(envtxt);
00434   } else {
00435 #if defined(_MSC_VER)
00436     if ((envtxt = getenv("TMP")) != NULL) {
00437       TempDir = stringdup(envtxt);
00438     }
00439     else if ((envtxt = getenv("TEMP")) != NULL) {
00440       TempDir = stringdup(envtxt);
00441     }
00442     else {
00443       TempDir = stringdup("c:\\\\");
00444     }
00445 #else
00446     TempDir = stringdup("/tmp");
00447 #endif
00448   }
00449   stripslashes(TempDir); // strip out ending '/' chars.
00450 
00451   char *tmpfilebuf = new char[1024];
00452  
00453   // copy in temp string
00454   strcpy(tmpfilebuf, TempDir);
00455  
00456 #if defined(_MSC_VER)
00457   strcat(tmpfilebuf, "\\");
00458   strncat(tmpfilebuf, s, 1022 - strlen(TempDir));
00459 #else
00460   strcat(tmpfilebuf, "/");
00461   strncat(tmpfilebuf, s, 1022 - strlen(TempDir));
00462 #endif
00463  
00464   tmpfilebuf[1023] = '\0';
00465  
00466   delete [] TempDir;
00467 
00468   // return converted string
00469   return tmpfilebuf;
00470 }
00471 
00472 
00473 int vmd_delete_file(const char * path) {
00474 #if defined(_MSC_VER)
00475   if (DeleteFile(path) == 0) 
00476     return -1;
00477   else 
00478     return 0;  
00479 #else
00480   return unlink(path);
00481 #endif
00482 }
00483 
00484 void vmd_sleep(int secs) {
00485 #if defined(_MSC_VER)
00486   Sleep(secs * 1000);
00487 #else 
00488   sleep(secs);
00489 #endif
00490 }
00491 
00492 void vmd_msleep(int msecs) {
00493 #if defined(_MSC_VER)
00494   Sleep(msecs);
00495 #else 
00496   struct timeval timeout;
00497   timeout.tv_sec = 0;
00498   timeout.tv_usec = 1000 * msecs;
00499   select(0, NULL, NULL, NULL, &timeout);
00500 #endif // _MSC_VER
00501 }
00502 
00503 int vmd_system(const char* cmd) {
00504    return system(cmd);
00505 }
00506 
00507 
00511 long vmd_random(void) {
00512 #ifdef _MSC_VER
00513   return rand();
00514 #else
00515   return random();
00516 #endif
00517 }
00518 
00519 void vmd_srandom(unsigned int seed) {
00520 #ifdef _MSC_VER
00521   srand(seed);
00522 #else
00523   srandom(seed);
00524 #endif
00525 }
00526 
00529 float vmd_random_gaussian() {
00530   static bool cache = false;
00531   static float cached_value;
00532   const float RAND_FACTOR = 2.f/VMD_RAND_MAX;
00533   float r, s, w;
00534   
00535   if (cache) {
00536     cache = false;
00537     return cached_value;
00538   }
00539   do {
00540     r = RAND_FACTOR*vmd_random()-1.f; 
00541     s = RAND_FACTOR*vmd_random()-1.f;
00542     w = r*r+s*s;
00543   } while (w >= 1.f);
00544   w = sqrtf(-2.f*logf(w)/w);
00545   cached_value = s * w;
00546   cache = true;
00547   return (r*w);
00548 }
00549 
00550 
00553 long vmd_get_total_physmem_mb(void) {
00554 #if defined(_MSC_VER)
00555   MEMORYSTATUS memstat;
00556   GlobalMemoryStatus(&memstat);
00557   if (memstat.dwLength != sizeof(memstat))
00558     return -1; /* memstat result is wrong size! */
00559   return memstat.dwTotalPhys/(1024 * 1024);
00560 #elif defined(__linux)
00561   FILE *fp;
00562   char meminfobuf[1024], *pos;
00563   size_t len;
00564 
00565   fp = fopen("/proc/meminfo", "r");
00566   if (fp != NULL) {
00567     len = fread(meminfobuf,1,1024, fp);
00568     meminfobuf[1023] = 0;
00569     fclose(fp);
00570     if (len > 0) {
00571       pos=strstr(meminfobuf,"MemTotal:");
00572       if (pos == NULL) 
00573         return -1;
00574       pos += 9; /* skip tag */;
00575       return strtol(pos, (char **)NULL, 10)/1024L;
00576     }
00577   } 
00578   return -1;
00579 #elif defined(AIXUSEPERFSTAT) && defined(_AIX)
00580   perfstat_memory_total_t minfo;
00581   perfstat_memory_total(NULL, &minfo, sizeof(perfstat_memory_total_t), 1);
00582   return minfo.real_total*(4096/1024)/1024;
00583 #elif defined(_AIX)
00584   return (sysconf(_SC_AIX_REALMEM) / 1024);
00585 #elif defined(_SC_PAGESIZE) && defined(_SC_PHYS_PAGES)
00586   /* SysV Unix */
00587   long pgsz = sysconf(_SC_PAGESIZE);
00588   long physpgs = sysconf(_SC_PHYS_PAGES);
00589   return ((pgsz / 1024) * physpgs) / 1024;
00590 #elif defined(__APPLE__)
00591   /* MacOS X uses BSD sysctl */
00592   /* use hw.memsize, as it's a 64-bit value */
00593   int rc;
00594   uint64_t membytes;
00595   size_t len = sizeof(membytes);
00596   if (sysctlbyname("hw.memsize", &membytes, &len, NULL, 0)) 
00597     return -1;
00598   return (membytes / (1024*1024));
00599 #else
00600   return -1; /* unrecognized system, no method to get this info */
00601 #endif
00602 }
00603 
00604 
00605 
00608 long vmd_get_avail_physmem_mb(void) {
00609 #if defined(_MSC_VER)
00610   MEMORYSTATUS memstat;
00611   GlobalMemoryStatus(&memstat);
00612   if (memstat.dwLength != sizeof(memstat))
00613     return -1; /* memstat result is wrong size! */ 
00614   return memstat.dwAvailPhys / (1024 * 1024);
00615 #elif defined(__linux)
00616   FILE *fp;
00617   char meminfobuf[1024], *pos;
00618   size_t len;
00619   long val;
00620 
00621   fp = fopen("/proc/meminfo", "r");
00622   if (fp != NULL) {
00623     len = fread(meminfobuf,1,1024, fp);
00624     meminfobuf[1023] = 0;
00625     fclose(fp);
00626     if (len > 0) {
00627       val = 0L;
00628       pos=strstr(meminfobuf,"MemFree:");
00629       if (pos != NULL) {
00630         pos += 8; /* skip tag */;
00631         val += strtol(pos, (char **)NULL, 10);
00632       }
00633       pos=strstr(meminfobuf,"Buffers:");
00634       if (pos != NULL) {
00635         pos += 8; /* skip tag */;
00636         val += strtol(pos, (char **)NULL, 10);
00637       }
00638       pos=strstr(meminfobuf,"Cached:");
00639       if (pos != NULL) {
00640         pos += 8; /* skip tag */;
00641         val += strtol(pos, (char **)NULL, 10);
00642       }
00643       return val/1024L;
00644     } else {
00645       return -1;
00646     }
00647   } else {
00648     return -1;
00649   }
00650 #elif defined(AIXUSEPERFSTAT) && defined(_AIX)
00651   perfstat_memory_total_t minfo;
00652   perfstat_memory_total(NULL, &minfo, sizeof(perfstat_memory_total_t), 1);
00653   return minfo.real_free*(4096/1024)/1024;
00654 #elif defined(_SC_PAGESIZE) && defined(_SC_AVPHYS_PAGES)
00655   /* SysV Unix */
00656   long pgsz = sysconf(_SC_PAGESIZE);
00657   long avphyspgs = sysconf(_SC_AVPHYS_PAGES);
00658   return ((pgsz / 1024) * avphyspgs) / 1024;
00659 #elif defined(__APPLE__)
00660 #if 0
00661   /* BSD sysctl */
00662   /* hw.usermem isn't really the amount of free memory, it's */
00663   /* really more a measure of the non-kernel memory          */
00664   int rc;
00665   int membytes;
00666   size_t len = sizeof(membytes);
00667   if (sysctlbyname("hw.usermem", &membytes, &len, NULL, 0)) 
00668     return -1;
00669   return (membytes / (1024*1024));
00670 #else
00671   return -1;
00672 #endif
00673 #else
00674   return -1; /* unrecognized system, no method to get this info */
00675 #endif
00676 }
00677 
00678 
00680 long vmd_get_avail_physmem_percent(void) {
00681   double total, avail;
00682   total = (double) vmd_get_total_physmem_mb();
00683   avail = (double) vmd_get_avail_physmem_mb();
00684   if (total > 0.0 && avail >= 0.0)
00685     return (long) (avail / (total / 100.0));
00686 
00687   return -1; /* return an error */
00688 }
00689 
00690 

Generated on Thu May 24 01:51:35 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002