// ascee_math.h // // Author: J.A. de Jong - ASCEE // // Description: // ////////////////////////////////////////////////////////////////////// #pragma once #ifndef ASCEE_MATH_H #define ASCEE_MATH_H #include #include "types.h" #include "tracer.h" #include "ascee_assert.h" #include "ascee_alloc.h" #if ASCEE_USE_BLAS == 1 #include #endif #ifdef ASCEE_DOUBLE_PRECISION #define c_real creal #define c_imag cimag #define d_abs fabs #define c_abs cabs #define c_conj conj #define d_atan2 atan2 #define d_acos acos #define d_sqrt sqrt #define c_exp cexp #define d_sin sin #define d_cos cos #define d_pow pow #else // ASCEE_DOUBLE_PRECISION not defined #define c_conj conjf #define c_real crealf #define c_imag cimagf #define d_abs fabsf #define c_abs cabsf #define d_atan2 atan2f #define d_acos acosf #define d_sqrt sqrtf #define c_exp cexpf #define d_sin sinf #define d_cos cosf #define d_pow powf #endif // ASCEE_DOUBLE_PRECISION #ifdef M_PI static const d number_pi = M_PI; #else static const d number_pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679; #endif /// Code generation for vector of floats and vector of complex floats. #define vxinit(type) \ typedef struct { \ us size; \ type* data; \ } v##type; vxinit(d); vxinit(c); /// Code generation for matrix of floats and matrix of complex floats. #define xmatinit(type) \ typedef struct { \ us n_rows; \ us n_cols; \ type* data; \ } type##mat; xmatinit(d); xmatinit(c); #define setvecval(vec,index,val) \ dbgassert((((us) index) <= (vec)->size),OUTOFBOUNDSVEC); \ (vec)->data[index] = val; #define setmatval(mat,row,col,val) \ dbgassert((((us) row) <= mat->n_rows),OUTOFBOUNDSMATR); \ dbgassert((((us) col) <= mat->n_cols),,OUTOFBOUNDSMATC); \ (mat)->data[(col)*(mat)->n_rows+(row)] = val; /** * Return a value from a vector * * @param mat The vector * @param row The row */ static inline d* getvdval(const vd* vec,us row){ dbgassert(row < vec->size,OUTOFBOUNDSVEC); return &vec->data[row]; } /** * Return a value from a complex vector * * @param mat The vector * @param row The row */ static inline c* getvcval(const vc* vec,us row){ dbgassert(row < vec->size,OUTOFBOUNDSVEC); return &vec->data[row]; } /** * Return a value from a matrix of floating points * * @param mat The matrix * @param row The row * @param col The column */ static inline d* getdmatval(const dmat* mat,us row,us col){ assert((row) < mat->n_rows); assert((col) < mat->n_cols); return &mat->data[(col)*mat->n_rows+(row)]; } /** * Return a value from a matrix of complex floating points * * @param mat The matrix * @param row The row * @param col The column */ static inline c* getcmatval(const cmat* mat,const us row,const us col){ dbgassert(row < mat->n_rows,OUTOFBOUNDSMATR); dbgassert(col < mat->n_cols,OUTOFBOUNDSMATC); return &mat->data[col*mat->n_rows+row]; } /** * Sets all values in a vector to the value * * @param b the vector to set * @param value */ static inline void vd_set(vd* vec, d value){ us i; for(i=0;isize;i++){ vec->data[i] = value; } } /** * Sets all values in a vector to the value * * @param vec the vector to set * @param value */ static inline void vc_set(vc* vec,const c value){ us i; for(i=0;isize;i++){ vec->data[i] = value; } } /** * Sets all values in a matrix to the value * * @param mat The matrix to set * @param value */ static inline void dmat_set(dmat* mat,const d value){ us i,size = mat->n_cols*mat->n_rows; for(i=0;idata[i] = value; } } /** * Sets all values in a matrix to the value * * @param mat The matrix to set * @param value */ static inline void cmat_set(cmat* mat,const c value){ us i,size = mat->n_cols*mat->n_rows; for(i=0;idata[i] = value; } } /** * Return a column pointer of the matrix * * @param mtrx The matrix. * @param column The column number. * * @return Pointer to the column. */ static inline d* d_column(dmat* mtrx,us column){ return &mtrx->data[mtrx->n_rows*column]; } /** * Return a column pointer of the matrix * * @param mtrx The matrix. * @param column The column number. * * @return Pointer to the column. */ static inline c* c_column(cmat* mtrx,us column){ return &mtrx->data[mtrx->n_rows*column]; } /** * Return the maximum of two doubles * * @param a value 1 * @param b value 2 * * @returns the maximum of value 1 and 2 */ static inline d max(const d a,const d b) { return a>b?a:b; } /** * Return the dot product of two arrays, one of them complex-valued, * the other real-valued * * @param a the complex-valued array * @param b the real-valued array * @param size the size of the arrays. *Should be equal-sized!* * * @return the dot product */ static inline c cd_dot(const c a[],const d b[],us size){ c result = 0; us i; for(i=0;isize == b->size,SIZEINEQUAL); return d_dot(a->data,b->data,a->size); } /** * Copy array of floats. * * @param to : Array to write to * @param from : Array to read from * @param size : Size of arrays */ static inline void d_copy(d to[],const d from[],const us size){ #if ASCEE_USE_BLAS == 1 cblas_dcopy(size,from,1,to,1); #else us i; for(i=0;isize==from->size,SIZEINEQUAL); d_copy(to->data,from->data,to->size); } /** * Copy array of floats to array of complex floats. Imaginary part set * to zero. * * @param to : Array to write to * @param from : Array to read from * @param size : Size of arrays */ static inline void cd_copy(c to[],const d from[],const us size) { us i; for(i=0;i max) max=a[i]; } return max; } /** * Compute the minimum of an array * * @param a array * @param size size of the array * @return minimum */ static inline d d_min(const d a[],us size){ us i; d min = a[0]; for(i=1;i min) min=a[i]; } return min; } /** * Compute the \f$ L_2 \f$ norm of an array of doubles * * @param a Array * @param size Size of array */ static inline d d_norm(const d a[],us size){ #if ASCEE_USE_BLAS == 1 return cblas_dnrm2(size,a,1); #else d norm = 0; us i; for(i=0;idata); \ } matvec_free(vd); matvec_free(vc); matvec_free(dmat); matvec_free(cmat); /** * Now the following functions exist: vd_free, vc_free, dmat_free and * cmat_free. */ /** * Allocate data for a matrix of floating points * * @param n_rows Number of rows * @param n_cols Number of columns * @param p Memory pool * * @return dmat with allocated data */ static inline dmat dmat_alloc(us n_rows, us n_cols) { dmat result = { n_rows, n_cols, NULL}; result.data = (d*) a_malloc(n_rows*n_cols*sizeof(d)); #ifdef ASCEE_DEBUG dmat_set(&result,NAN); #endif // ASCEE_DEBUG assert(result.data); return result; } /** * Allocate data for a matrix of complex floating points * * @param n_rows Number of rows * @param n_cols Number of columns * @param p Memory pool * * @return cmat with allocated data */ static inline cmat cmat_alloc(us n_rows, us n_cols) { cmat result = { n_rows, n_cols, NULL}; result.data = (c*) a_malloc(n_rows*n_cols*sizeof(c)); #ifdef ASCEE_DEBUG cmat_set(&result,NAN+I*NAN); #endif // ASCEE_DEBUG assert(result.data); return result; } /** * Resize an existing dmat or a cmat */ #define type_mat_resize(type) \ static inline void type##mat_resize(type##mat * mat,\ us nrows,us ncols) { \ mat->n_rows = nrows; \ mat->n_cols = ncols; \ mat->data = realloc(mat->data,(nrows*ncols)*sizeof( type )); \ } type_mat_resize(d); type_mat_resize(c); /** * Copy some rows from one matrix to another * * @param to Matrix to copy to * @param from Matrix to copy from * @param startrow_from Starting row where to get the values * @param startrow_to Starting row where to insert the values * @param nrows Number of rows to copy */ static inline void copy_dmat_rows(dmat* to,const dmat* from, us startrow_from, us startrow_to, us nrows) { us col,ncols = to->n_cols; dbgassert(startrow_from+nrows <= from->n_rows,OUTOFBOUNDSMATR); dbgassert(startrow_to+nrows <= to->n_rows,OUTOFBOUNDSMATR); for(col=0;col