/src/hierarchical/C/util.h

http://github.com/beechung/Latent-Factor-Models · C Header · 252 lines · 202 code · 35 blank · 15 comment · 71 complexity · 987628e33f50a6c9298ba731fd74a68b MD5 · raw file

  1. #ifndef UTIL_H
  2. #define UTIL_H
  3. #include <stdarg.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string>
  7. #include <string.h>
  8. #include <algorithm>
  9. #include <vector>
  10. #include <ctime>
  11. #include <ctype.h>
  12. #include <float.h>
  13. #include <errno.h>
  14. #include <limits.h>
  15. #include <sys/stat.h>
  16. #include <sys/types.h>
  17. #define CHK_C_INDEX(index, num) if(index < 0 || index >= num) error("index out of bound: index=%d, bound=%d (file: %s, line: %d)", index, num, __FILE__, __LINE__)
  18. #define CHK_C_INDEX_2D(row_i, col_j, nrow, ncol) if(row_i < 0 || row_i >= nrow || col_j < 0 || col_j >= ncol) error("index out of bound: i=%d, j=%d nrow=%d ncol=%d (file: %s, line: %d)", row_i, col_j, nrow, ncol, __FILE__, __LINE__)
  19. #define STOP_HERE(msg) error("Error at %s on line %d: %s\n", __FILE__, __LINE__, msg)
  20. #define STOP2(msg,x) error2(__FILE__, __LINE__, msg, x)
  21. #define STOP3(msg,x1,x2) error2(__FILE__, __LINE__, msg, x1, x2)
  22. #define STOP4(msg,x1,x2,x3) error2(__FILE__, __LINE__, msg, x1, x2, x3)
  23. #define CHK_SAME_NUMBER_(x, y, rel_tol, abs_tol) if((x != 0 || y != 0) && (fabs(x-y) / fmax(fabs(x), fabs(y)) > rel_tol) && fabs(x-y) > abs_tol) error("Error: The two number should be the same: %16g vs %16g (file: %s, line: %d)\n", x, y, __FILE__, __LINE__)
  24. #define CHK_SAME_NUMBER(x, y) CHK_SAME_NUMBER_(x, y, 1e-8, 1e-12)
  25. #define WARN_SAME_NUMBER(x, y, prec) if((x != 0 || y != 0) && (fabs(x-y) / fmax(fabs(x), fabs(y)) > prec)) printf("WARN: The two number should be the same: %16g vs %16g (file: %s, line: %d)\n", x, y, __FILE__, __LINE__)
  26. #define C_MAT(i,j,nrow) (((j)*(nrow))+(i))
  27. #define C_3DA(i,j,k,nrow,ncol) ((((k)*(ncol))+(j))*(nrow) + (i))
  28. #define C_4DA(i,j,k,m,dim1,dim2,dim3) (((((m)*(dim3)+(k))*(dim2))+(j))*(dim1) + (i))
  29. #define Malloc(type,n) (type *)malloc((n)*sizeof(type))
  30. #define SQR(x) ((x)*(x))
  31. #define MAX(x,y) ((x) > (y) ? (x) : (y))
  32. #define MIN(x,y) ((x) < (y) ? (x) : (y))
  33. #define LOGIT(x) (log((x)/(1-(x))))
  34. #define INV_LOGIT(x) (1/(1+exp(-(x))))
  35. // Index conversion from Matrix (m x n) to Vector ((m*n) x 1)
  36. #define INDEX_M2V(i,j,nrow) (((j)*(nrow))+(i))
  37. #define FORCE_RANGE(value, min, max) (value > max ? max : (value < min ? min : value))
  38. void error(const char *fmt, ...);
  39. // Consider index value i
  40. // i = indexArray[ revIndex[i][0:(num[i]-1)] ]
  41. // E.g., consider user i
  42. // y[ revIndex[i][0:(num[i]-1)] ]
  43. // are the observations of user i
  44. class CReverseIndex {
  45. private:
  46. int* index_space;
  47. public:
  48. int** revIndex;
  49. int* num;
  50. int size;
  51. CReverseIndex(const int* indexArray, const int arrayLength, const int nIndexValues);
  52. ~CReverseIndex();
  53. };
  54. class MyTimer {
  55. private:
  56. time_t t_begin;
  57. clock_t c_begin;
  58. public:
  59. MyTimer(void){ reset(); }
  60. void reset(void){ t_begin = time(NULL); c_begin = clock(); }
  61. int wallTime(void){ return (int)(time(NULL) - t_begin); }
  62. double cpuTime(void){ return ((double)(clock() - c_begin)) / CLOCKS_PER_SEC; }
  63. };
  64. std::string indent(const char* input, int n);
  65. void info(FILE* fp, const int verboseLevel, const char* fmt, ...);
  66. void error2(const char *filename, int lineno, const char *fmt, ...);
  67. void tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters = " ");
  68. void print_matrix(double **matrix, const int nrow, const int ncol, FILE* fp=stdout, const char* sep="\t", const char* format="%.16g");
  69. void print_row_vector(double *vector, const int num, FILE* fp=stdout, const char* sep="\t", const char* format="%.16g");
  70. void print_col_vector(double *vector, const int num, FILE* fp=stdout, const char* sep="\t", const char* format="%.16g");
  71. void print_matrix(int **matrix, const int nrow, const int ncol, FILE* fp=stdout, const char* sep="\t", const char* format="%d");
  72. void print_row_vector(int *vector, const int num, FILE* fp=stdout, const char* sep="\t", const char* format="%d");
  73. void print_col_vector(int *vector, const int num, FILE* fp=stdout, const char* sep="\t", const char* format="%d");
  74. inline void swap(int& a, int& b){
  75. int c = b; b = a; a = c;
  76. }
  77. inline void swap(double& a, double& b){
  78. double c = b; b = a; a = c;
  79. }
  80. inline void save_matrix(double **matrix, const int nrow, const int ncol, const char* file, const char* sep="\t", const char* format="%.16g"){
  81. FILE *fp = fopen(file, "w");
  82. if(fp == NULL) error("ERROR: Cannot open file %s\n", file);
  83. print_matrix(matrix, nrow, ncol, fp, sep, format);
  84. fclose(fp);
  85. }
  86. inline void save_col_vector(double *vector, const int num, const char* file, const char* sep="\t", const char* format="%.16g"){
  87. FILE *fp = fopen(file, "w");
  88. if(fp == NULL) error("ERROR: Cannot open file %s\n", file);
  89. print_col_vector(vector, num, fp, sep, format);
  90. fclose(fp);
  91. }
  92. inline int parse_double(const char *str, double* ans){
  93. char *endptr;
  94. errno = 0;
  95. (*ans) = strtod(str,&endptr);
  96. if(errno != 0) return errno;
  97. if(endptr == str || (*endptr != '\0' && !isspace(*endptr))) return -1;
  98. return 0;
  99. }
  100. inline int parse_int(const char *str, int* ans, int base=10){
  101. char *endptr;
  102. errno = 0;
  103. (*ans) = (int)strtol(str,&endptr, base);
  104. if(errno != 0) return errno;
  105. if(endptr == str || (*endptr != '\0' && !isspace(*endptr))) return -1;
  106. return 0;
  107. }
  108. inline bool file_exist(const char *file){
  109. struct stat statbuf;
  110. if(stat(file, &statbuf) == 0) return true;
  111. return false;
  112. }
  113. inline void check_file_overwrite(const char *file, bool allow_overwrite){
  114. struct stat statbuf;
  115. if(stat(file, &statbuf) == 0){
  116. if(allow_overwrite) fprintf(stderr, "\nWARNING: File/directory %s exists and will be overwritten!!\n\n", file);
  117. else error("\nERROR: %s aready exists and you chose not to overwrite it!!\n\n", file);
  118. }
  119. }
  120. inline void normalizeToSumUpToOne(double *vector, const int length){
  121. double sum = 0;
  122. for(int k=0; k<length; k++) sum += vector[k];
  123. for(int k=0; k<length; k++) vector[k] /= sum;
  124. }
  125. inline int which_max(double *array, int num){
  126. if(array == NULL || num == 0) error("ERROR: The input array is empty (source: %s@%d)\n", __FILE__, __LINE__);
  127. int best=0; double max = array[0];
  128. for(int i=1; i<num ;i++) if(array[i] > max){
  129. max = array[i];
  130. best = i;
  131. }
  132. return best;
  133. }
  134. inline int which_min(double *array, int num){
  135. if(array == NULL || num == 0) error("ERROR: The input array is empty (source: %s@%d)\n", __FILE__, __LINE__);
  136. int best=0; double min = array[0];
  137. for(int i=1; i<num ;i++) if(array[i] < min){
  138. min = array[i];
  139. best = i;
  140. }
  141. return best;
  142. }
  143. double* get_doubleArray(const char* list, int* num, const char* sep=",");
  144. /** Convert dimenional index to linear index.
  145. * dim[i]: the value of the i-th dimension
  146. * dimSize[i]: the number of values in the i-th dimension
  147. */
  148. int toLinearIndex(const int *dim, const int *dimSize, int ndim);
  149. /** Convert linear index to dimensional index
  150. */
  151. void fillInDimIndex(int index, int *dim, const int *dimSize, int ndim);
  152. /**
  153. * A wrapper for R array
  154. */
  155. template <typename ValueType>
  156. class R_MultiDimArray {
  157. private:
  158. ValueType *data; // data[0, ..., length-1]
  159. int *dimSize; // dimSize[i] is the size of the ith dimension
  160. int nDim;
  161. public:
  162. int length; // length = dimSize[0] x ... x dimSize[nDim-1]
  163. R_MultiDimArray(ValueType *array, const int *dimSize, int nDim){
  164. if(nDim <= 0) STOP2("nDim = %d", nDim);
  165. data=array; this->nDim = nDim;
  166. this->dimSize = new int[nDim]; for(int i=0; i<nDim; i++) this->dimSize[i] = dimSize[i];
  167. length = 1; for(int i=0; i<nDim; i++) length *= dimSize[i];
  168. }
  169. ~R_MultiDimArray(void){ delete[] dimSize; }
  170. inline unsigned int index(const int *entry) const {
  171. int index = 0;
  172. for(int i=nDim-1; i>=0; i--){
  173. if(entry[i] < 0 || entry[i] >= dimSize[i]) STOP4("Index out of bound: i=%d, entry[i]=%d, dimSize[i]=%d", i, entry[i], dimSize[i]);
  174. index = (index*dimSize[i])+entry[i];
  175. }
  176. return index;
  177. }
  178. inline ValueType get(const int *entry) const {
  179. return data[index(entry)];
  180. }
  181. inline void set(const int *entry, ValueType value){
  182. data[index(entry)] = value;
  183. }
  184. inline ValueType getBy1DIndex(int i) const {
  185. return data[i];
  186. }
  187. inline void setBy1DIndex(int i, ValueType value){
  188. data[i] = value;
  189. }
  190. };
  191. template <typename ValueType>
  192. class R_2DArray {
  193. private:
  194. ValueType *data;
  195. int nrow, ncol;
  196. public:
  197. R_2DArray(ValueType *array, int nrow, int ncol){
  198. data = array; this->nrow = nrow; this->ncol = ncol;
  199. }
  200. inline ValueType get(int i, int j) const {
  201. if(i < 0 || i >= nrow || j < 0 || j >= ncol) STOP3("Index out of bound: i=%d, j=%d", i, j);
  202. return data[C_MAT(i,j,nrow)];
  203. }
  204. inline void set(int i, int j, ValueType value){
  205. if(i < 0 || i >= nrow || j < 0 || j >= ncol) STOP3("Index out of bound: i=%d, j=%d", i, j);
  206. data[C_MAT(i,j,nrow)] = value;
  207. }
  208. inline int nRow() const { return nrow; }
  209. inline int nCol() const { return ncol; }
  210. inline void getRow(int i, ValueType row[]) const {
  211. for(int j=0; j<ncol; j++) row[j] = data[C_MAT(i,j,nrow)];
  212. }
  213. inline void getCol(int j, ValueType col[]) const {
  214. for(int i=0; i<nrow; i++) col[i] = data[C_MAT(i,j,nrow)];
  215. }
  216. };
  217. #endif