From 2e0231b0b480fd399008697288fd6746efc17c08 Mon Sep 17 00:00:00 2001 From: Alberto Ruiz Date: Thu, 14 Jun 2007 16:46:24 +0000 Subject: refactored vector operations --- lib/GSL/Vector.hs | 163 ++++++++++++ lib/GSL/gsl-aux.c | 721 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/GSL/gsl-aux.h | 66 +++++ 3 files changed, 950 insertions(+) create mode 100644 lib/GSL/Vector.hs create mode 100644 lib/GSL/gsl-aux.c create mode 100644 lib/GSL/gsl-aux.h (limited to 'lib') diff --git a/lib/GSL/Vector.hs b/lib/GSL/Vector.hs new file mode 100644 index 0000000..e538b7e --- /dev/null +++ b/lib/GSL/Vector.hs @@ -0,0 +1,163 @@ +{-# OPTIONS_GHC -fglasgow-exts #-} +----------------------------------------------------------------------------- +-- | +-- Module : GSL.Vector +-- Copyright : (c) Alberto Ruiz 2007 +-- License : GPL-style +-- +-- Maintainer : Alberto Ruiz +-- Stability : provisional +-- Portability : portable (uses FFI) +-- +-- Vector operations +-- +----------------------------------------------------------------------------- + +module GSL.Vector ( + FunCodeS(..), toScalarR, + FunCodeV(..), vectorMapR, vectorMapC, + FunCodeSV(..), vectorMapValR, vectorMapValC, + FunCodeVV(..), vectorZipR, vectorZipC, + scale, addConstant +) where + +import Data.Packed.Internal +import Complex +import Foreign + +data FunCodeV = Sin + | Cos + | Tan + | Abs + | ASin + | ACos + | ATan + | Sinh + | Cosh + | Tanh + | ASinh + | ACosh + | ATanh + | Exp + | Log + | Sign + | Sqrt + deriving Enum + +data FunCodeSV = Scale + | Recip + | AddConstant + | Negate + | PowSV + | PowVS + deriving Enum + +data FunCodeVV = Add + | Sub + | Mul + | Div + | Pow + | ATan2 + deriving Enum + +data FunCodeS = Norm2 + | AbsSum + | MaxIdx + | Max + | MinIdx + | Min + deriving Enum + + +scale :: (Num a, Field a) => a -> Vector a -> Vector a +scale x v | isReal baseOf v = scast $ vectorMapValR Scale (scast x) (scast v) + | isComp baseOf v = scast $ vectorMapValC Scale (scast x) (scast v) + | otherwise = fromList $ map (*x) $ toList v + +addConstant :: (Num a, Field a) => a -> Vector a -> Vector a +addConstant x v | isReal baseOf v = scast $ vectorMapValR AddConstant (scast x) (scast v) + | isComp baseOf v = scast $ vectorMapValC AddConstant (scast x) (scast v) + | otherwise = fromList $ map (*x) $ toList v + +------------------------------------------------------------------ + +toScalarAux fun code v = unsafePerformIO $ do + r <- createVector 1 + fun (fromEnum code) // vec v // vec r // check "toScalarAux" [v] + return (r `at` 0) + +vectorMapAux fun code v = unsafePerformIO $ do + r <- createVector (dim v) + fun (fromEnum code) // vec v // vec r // check "vectorMapAux" [v] + return r + +vectorMapValAux fun code val v = unsafePerformIO $ do + r <- createVector (dim v) + pval <- newArray [val] + fun (fromEnum code) pval // vec v // vec r // check "vectorMapValAux" [v] + free pval + return r + +vectorZipAux fun code u v = unsafePerformIO $ do + r <- createVector (dim u) + fun (fromEnum code) // vec u // vec v // vec r // check "vectorZipAux" [u,v] + return r + +--------------------------------------------------------------------- + +-- | obtains different functions of a vector: norm1, norm2, max, min, posmax, posmin, etc. +toScalarR :: FunCodeS -> Vector Double -> Double +toScalarR oper = toScalarAux c_toScalarR (fromEnum oper) + +foreign import ccall safe "gsl-aux.h toScalarR" + c_toScalarR :: Int -> Double :> Double :> IO Int + +------------------------------------------------------------------ + +-- | map of real vectors with given function +vectorMapR :: FunCodeV -> Vector Double -> Vector Double +vectorMapR = vectorMapAux c_vectorMapR + +foreign import ccall safe "gsl-aux.h mapR" + c_vectorMapR :: Int -> Double :> Double :> IO Int + +-- | map of complex vectors with given function +vectorMapC :: FunCodeV -> Vector (Complex Double) -> Vector (Complex Double) +vectorMapC oper = vectorMapAux c_vectorMapC (fromEnum oper) + +foreign import ccall safe "gsl-aux.h mapC" + c_vectorMapC :: Int -> Complex Double :> Complex Double :> IO Int + +------------------------------------------------------------------- + +-- | map of real vectors with given function +vectorMapValR :: FunCodeSV -> Double -> Vector Double -> Vector Double +vectorMapValR oper = vectorMapValAux c_vectorMapValR (fromEnum oper) + +foreign import ccall safe "gsl-aux.h mapValR" + c_vectorMapValR :: Int -> Ptr Double -> Double :> Double :> IO Int + +-- | map of complex vectors with given function +vectorMapValC :: FunCodeSV -> Complex Double -> Vector (Complex Double) -> Vector (Complex Double) +vectorMapValC = vectorMapValAux c_vectorMapValC + +foreign import ccall safe "gsl-aux.h mapValC" + c_vectorMapValC :: Int -> Ptr (Complex Double) -> Complex Double :> Complex Double :> IO Int + +------------------------------------------------------------------- + +-- | elementwise operation on real vectors +vectorZipR :: FunCodeVV -> Vector Double -> Vector Double -> Vector Double +vectorZipR = vectorZipAux c_vectorZipR + +foreign import ccall safe "gsl-aux.h zipR" + c_vectorZipR :: Int -> Double :> Double :> Double :> IO Int + +-- | elementwise operation on complex vectors +vectorZipC :: FunCodeVV -> Vector (Complex Double) -> Vector (Complex Double) -> Vector (Complex Double) +vectorZipC = vectorZipAux c_vectorZipC + +foreign import ccall safe "gsl-aux.h zipC" + c_vectorZipC :: Int -> Complex Double :> Complex Double :> Complex Double :> IO Int + + diff --git a/lib/GSL/gsl-aux.c b/lib/GSL/gsl-aux.c new file mode 100644 index 0000000..fc95e6f --- /dev/null +++ b/lib/GSL/gsl-aux.c @@ -0,0 +1,721 @@ +#include "gsl-aux.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MACRO(B) do {B} while (0) +#define ERROR(CODE) MACRO(return CODE;) +#define REQUIRES(COND, CODE) MACRO(if(!(COND)) {ERROR(CODE);}) +#define OK return 0; + +#define MIN(A,B) ((A)<(B)?(A):(B)) +#define MAX(A,B) ((A)>(B)?(A):(B)) + +#ifdef DBG +#define DEBUGMSG(M) printf("*** calling aux C function: %s\n",M); +#else +#define DEBUGMSG(M) +#endif + +#define CHECK(RES,CODE) MACRO(if(RES) return CODE;) + +#ifdef DBG +#define DEBUGMAT(MSG,X) printf(MSG" = \n"); gsl_matrix_fprintf(stdout,X,"%f"); printf("\n"); +#else +#define DEBUGMAT(MSG,X) +#endif + +#ifdef DBG +#define DEBUGVEC(MSG,X) printf(MSG" = \n"); gsl_vector_fprintf(stdout,X,"%f"); printf("\n"); +#else +#define DEBUGVEC(MSG,X) +#endif + +#define DVVIEW(A) gsl_vector_view A = gsl_vector_view_array(A##p,A##n) +#define DMVIEW(A) gsl_matrix_view A = gsl_matrix_view_array(A##p,A##r,A##c) +#define CVVIEW(A) gsl_vector_complex_view A = gsl_vector_complex_view_array((double*)A##p,A##n) +#define CMVIEW(A) gsl_matrix_complex_view A = gsl_matrix_complex_view_array((double*)A##p,A##r,A##c) +#define KDVVIEW(A) gsl_vector_const_view A = gsl_vector_const_view_array(A##p,A##n) +#define KDMVIEW(A) gsl_matrix_const_view A = gsl_matrix_const_view_array(A##p,A##r,A##c) +#define KCVVIEW(A) gsl_vector_complex_const_view A = gsl_vector_complex_const_view_array((double*)A##p,A##n) +#define KCMVIEW(A) gsl_matrix_complex_const_view A = gsl_matrix_complex_const_view_array((double*)A##p,A##r,A##c) + +#define V(a) (&a.vector) +#define M(a) (&a.matrix) + +#define GCVEC(A) int A##n, gsl_complex*A##p +#define KGCVEC(A) int A##n, const gsl_complex*A##p + +#define BAD_SIZE 1000 +#define BAD_CODE 1001 +#define MEM 1002 +#define BAD_FILE 1003 + + +int toScalarR(int code, KRVEC(x), RVEC(r)) { + REQUIRES(rn==1,BAD_SIZE); + DEBUGMSG("toScalarR"); + KDVVIEW(x); + double res; + switch(code) { + case 0: { res = gsl_blas_dnrm2(V(x)); break; } + case 1: { res = gsl_blas_dasum(V(x)); break; } + case 2: { res = gsl_vector_max_index(V(x)); break; } + case 3: { res = gsl_vector_max(V(x)); break; } + case 4: { res = gsl_vector_min_index(V(x)); break; } + case 5: { res = gsl_vector_min(V(x)); break; } + default: ERROR(BAD_CODE); + } + rp[0] = res; + OK +} + + +inline double sign(double x) { + if(x>0) { + return +1.0; + } else if (x<0) { + return -1.0; + } else { + return 0.0; + } +} + + +#define OP(C,F) case C: { for(k=0;k1,BAD_SIZE); + gsl_poly_complex_workspace * w = gsl_poly_complex_workspace_alloc (an); + int res = gsl_poly_complex_solve ((double*)ap, an, w, (double*)zp); + CHECK(res,res); + gsl_poly_complex_workspace_free (w); + OK; +} + +int matrix_fscanf(char*filename, RMAT(a)) { + DEBUGMSG("gsl_matrix_fscanf"); + //printf(filename); printf("\n"); + DMVIEW(a); + FILE * f = fopen(filename,"r"); + CHECK(!f,BAD_FILE); + int res = gsl_matrix_fscanf(f, M(a)); + CHECK(res,res); + fclose (f); + OK +} + +//--------------------------------------------------------------- + +typedef double Trawfun(int, double*); + +double only_f_aux_min(const gsl_vector*x, void *pars) { + Trawfun * f = (Trawfun*) pars; + double* p = (double*)calloc(x->size,sizeof(double)); + int k; + for(k=0;ksize;k++) { + p[k] = gsl_vector_get(x,k); + } + double res = f(x->size,p); + free(p); + return res; +} + +// this version returns info about intermediate steps +int minimize(double f(int, double*), double tolsize, int maxit, + KRVEC(xi), KRVEC(sz), RMAT(sol)) { + REQUIRES(xin==szn && solr == maxit && solc == 3+xin,BAD_SIZE); + DEBUGMSG("minimizeList (nmsimplex)"); + gsl_multimin_function my_func; + // extract function from pars + my_func.f = only_f_aux_min; + my_func.n = xin; + my_func.params = f; + size_t iter = 0; + int status; + double size; + const gsl_multimin_fminimizer_type *T; + gsl_multimin_fminimizer *s = NULL; + // Initial vertex size vector + KDVVIEW(sz); + // Starting point + KDVVIEW(xi); + // Minimizer nmsimplex, without derivatives + T = gsl_multimin_fminimizer_nmsimplex; + s = gsl_multimin_fminimizer_alloc (T, my_func.n); + gsl_multimin_fminimizer_set (s, &my_func, V(xi), V(sz)); + do { + status = gsl_multimin_fminimizer_iterate (s); + size = gsl_multimin_fminimizer_size (s); + + solp[iter*solc+0] = iter; + solp[iter*solc+1] = s->fval; + solp[iter*solc+2] = size; + + int k; + for(k=0;kx,k); + } + status = gsl_multimin_test_size (size, tolsize); + iter++; + } while (status == GSL_CONTINUE && iter < maxit); + int i,j; + for (i=iter; isize,sizeof(double)); + int k; + for(k=0;ksize;k++) { + p[k] = gsl_vector_get(x,k); + } + double res = fdf->f(x->size,p); + free(p); + return res; +} + + +void df_aux_min(const gsl_vector * x, void * pars, gsl_vector * g) { + Tfdf * fdf = ((Tfdf*) pars); + double* p = (double*)calloc(x->size,sizeof(double)); + double* q = (double*)calloc(x->size,sizeof(double)); + int k; + for(k=0;ksize;k++) { + p[k] = gsl_vector_get(x,k); + } + + fdf->df(x->size,p,q); + + for(k=0;ksize;k++) { + gsl_vector_set(g,k,q[k]); + } + free(p); + free(q); +} + +void fdf_aux_min(const gsl_vector * x, void * pars, double * f, gsl_vector * g) { + *f = f_aux_min(x,pars); + df_aux_min(x,pars,g); +} + +// conjugate gradient +int minimizeWithDeriv(double f(int, double*), void df(int, double*, double*), + double initstep, double minimpar, double tolgrad, int maxit, + KRVEC(xi), RMAT(sol)) { + REQUIRES(solr == maxit && solc == 2+xin,BAD_SIZE); + DEBUGMSG("minimizeWithDeriv (conjugate_fr)"); + gsl_multimin_function_fdf my_func; + // extract function from pars + my_func.f = f_aux_min; + my_func.df = df_aux_min; + my_func.fdf = fdf_aux_min; + my_func.n = xin; + Tfdf stfdf; + stfdf.f = f; + stfdf.df = df; + my_func.params = &stfdf; + size_t iter = 0; + int status; + const gsl_multimin_fdfminimizer_type *T; + gsl_multimin_fdfminimizer *s = NULL; + // Starting point + KDVVIEW(xi); + // conjugate gradient fr + T = gsl_multimin_fdfminimizer_conjugate_fr; + s = gsl_multimin_fdfminimizer_alloc (T, my_func.n); + gsl_multimin_fdfminimizer_set (s, &my_func, V(xi), initstep, minimpar); + do { + status = gsl_multimin_fdfminimizer_iterate (s); + solp[iter*solc+0] = iter; + solp[iter*solc+1] = s->f; + int k; + for(k=0;kx,k); + } + status = gsl_multimin_test_gradient (s->gradient, tolgrad); + iter++; + } while (status == GSL_CONTINUE && iter < maxit); + int i,j; + for (i=iter; i + +#define RVEC(A) int A##n, double*A##p +#define RMAT(A) int A##r, int A##c, double* A##p +#define KRVEC(A) int A##n, const double*A##p +#define KRMAT(A) int A##r, int A##c, const double* A##p + +#define CVEC(A) int A##n, gsl_complex*A##p +#define CMAT(A) int A##r, int A##c, gsl_complex* A##p +#define KCVEC(A) int A##n, const gsl_complex*A##p +#define KCMAT(A) int A##r, int A##c, const gsl_complex* A##p + +int toScalarR(int code, KRVEC(x), RVEC(r)); +/* norm2, absdif, maximum, posmax, etc. */ + +int mapR(int code, KRVEC(x), RVEC(r)); +int mapC(int code, KCVEC(x), CVEC(r)); +/* sin cos tan etc. */ + +int mapValR(int code, double*, KRVEC(x), RVEC(r)); +int mapValC(int code, gsl_complex*, KCVEC(x), CVEC(r)); + +int zipR(int code, KRVEC(a), KRVEC(b), RVEC(r)); +int zipC(int code, KCVEC(a), KCVEC(b), CVEC(r)); + + +int luSolveR(KRMAT(a),KRMAT(b),RMAT(r)); +int luSolveC(KCMAT(a),KCMAT(b),CMAT(r)); +int luRaux(KRMAT(a),RVEC(b)); +int luCaux(KCMAT(a),CVEC(b)); + +int svd(KRMAT(x),RMAT(u), RVEC(s),RMAT(v)); + +int eigensystemR(KRMAT(x),RVEC(l),RMAT(v)); +int eigensystemC(KCMAT(x),RVEC(l),CMAT(v)); + +int QR(KRMAT(x),RMAT(q),RMAT(r)); + +int chol(KRMAT(x),RMAT(l)); + +int fft(int code, KCVEC(a), CVEC(b)); + +int integrate_qng(double f(double, void*), double a, double b, double prec, + double *result, double*error); + +int integrate_qags(double f(double,void*), double a, double b, double prec, int w, + double *result, double* error); + +int polySolve(KRVEC(a), CVEC(z)); + +int matrix_fscanf(char*filename, RMAT(a)); + +int minimize(double f(int, double*), double tolsize, int maxit, + KRVEC(xi), KRVEC(sz), RMAT(sol)); + +int minimizeWithDeriv(double f(int, double*), void df(int, double*, double*), + double initstep, double minimpar, double tolgrad, int maxit, + KRVEC(xi), RMAT(sol)); + +int deriv(int code, double f(double, void*), double x, double h, double * result, double * abserr); + +double gsl_sf_erf(double); +double gsl_sf_erf_Z(double); + +int gsl_sf_bessel_J0_e(double, double*); // hmmm... +int gsl_sf_exp_e10_e(double, double*); // HMMMMM... -- cgit v1.2.3