PageRenderTime 66ms CodeModel.GetById 11ms app.highlight 50ms RepoModel.GetById 2ms app.codeStats 0ms

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