GURLS++  2.0.00
C++ Implementation of GURLS Matlab Toolbox
gmath.h
Go to the documentation of this file.
00001 /*
00002  * The GURLS Package in C++
00003  *
00004  * Copyright (C) 2011-1013, IIT@MIT Lab
00005  * All rights reserved.
00006  *
00007  * author:  M. Santoro
00008  * email:   msantoro@mit.edu
00009  * website: http://cbcl.mit.edu/IIT@MIT/IIT@MIT.html
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions
00013  * are met:
00014  *
00015  *     * Redistributions of source code must retain the above
00016  *       copyright notice, this list of conditions and the following
00017  *       disclaimer.
00018  *     * Redistributions in binary form must reproduce the above
00019  *       copyright notice, this list of conditions and the following
00020  *       disclaimer in the documentation and/or other materials
00021  *       provided with the distribution.
00022  *     * Neither the name(s) of the copyright holders nor the names
00023  *       of its contributors or of the Massacusetts Institute of
00024  *       Technology or of the Italian Institute of Technology may be
00025  *       used to endorse or promote products derived from this software
00026  *       without specific prior written permission.
00027  *
00028  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00029  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00030  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00031  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00032  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00033  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00034  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00035  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00036  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00037  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00038  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00039  * POSSIBILITY OF SUCH DAMAGE.
00040  */
00041 
00042 
00050 #ifndef _GURLS_GMATH_H_
00051 #define _GURLS_GMATH_H_
00052 
00053 #include <cstring>
00054 #include <cmath>
00055 #include <cfloat>
00056 #include <cassert>
00057 #include <sstream>
00058 #include <algorithm>
00059 #include <limits>
00060 
00061 #include "gurls++/exports.h"
00062 #include "gurls++/exceptions.h"
00063 
00064 #ifdef _WIN32
00065 #pragma warning(disable : 4290)
00066 #endif
00067 
00068 #include "gurls++/blas_lapack.h"
00069 
00070 namespace gurls {
00071 
00072 template <typename T>
00073 class gMat2D;
00074 
00075 template <typename T>
00076 class gVec;
00077 
00087 template <typename T>
00088 void dot(const gMat2D<T>& A, const gMat2D<T>& B, gMat2D<T>& C);
00089 
00099 template <typename T>
00100 void dot(const gMat2D<T>& A, const gVec<T>& x, gVec<T>& y);
00101 
00107 template <typename T>
00108 T dot(const gVec<T>& x, const gVec<T>& y);
00109 
00114 template <typename T>
00115 gMat2D<T> repmat(const gVec<T>& x, unsigned long n, bool transpose = false)
00116 {
00117     gMat2D<T> A;
00118 
00119     const T* dataX = x.getData();
00120     const unsigned long len = x.getSize();
00121 
00122     if(transpose)
00123     {
00124         A.resize(n, len);
00125 
00126         for(int i = 0; i < n; ++i)
00127             copy(A.getData() + i, dataX, len, n, 1);
00128     }
00129     else
00130     {
00131         A.resize(len, n);
00132 
00133         for(int i = 0; i < n; ++i)
00134             copy(A.getData() + (i*len), dataX, len);
00135     }
00136 
00137     return A;
00138 }
00139 
00144 enum InversionAlgorithm {LU,GaussJ};
00145 
00149 template <typename T>
00150 void lu(gMat2D<T>& A);
00151 
00152 
00161 template <typename T>
00162 void lu(gMat2D<T>& A, gVec<int>& pv);
00163 
00171 template <typename T>
00172 void svd(const gMat2D<T>& A, gMat2D<T>& U, gVec<T>& W, gMat2D<T>& Vt);
00173 
00178 template <typename T>
00179 void eig(const gMat2D<T>& A, gMat2D<T>& V, gVec<T>& Wr, gVec<T>& Wi);
00180 
00185 template <typename T>
00186 void eig(const gMat2D<T>& A, gMat2D<T>& V, gVec<T>& W);
00187 
00188 
00192 template <typename T>
00193 void eig(const gMat2D<T>& A, gVec<T>& Wr, gVec<T>& Wi);
00194 
00198 template <typename T>
00199 void eig(const gMat2D<T>& A, gVec<T>& W);
00200 
00201 
00205 template <typename T>
00206 void inv(const gMat2D<T>& A, gMat2D<T>& Ainv, InversionAlgorithm alg = LU);
00207 
00211 template <typename T>
00212 void pinv(const gMat2D<T>& A, gMat2D<T>& Ainv, T RCOND = 0);
00213 
00218 template <typename T>
00219 void  cholesky(const gMat2D<T>& A, gMat2D<T>& L, bool upper = true);
00220 
00229 template<typename T>
00230 void set(T* buffer, const T value, const int size, const int incr);
00231 
00239 template<typename T>
00240 void set(T* buffer, const T value, const int size)
00241 {
00242     for(T *it = buffer, *end = buffer+size; it != end; ++it)
00243         *it = value;
00244 }
00245 
00249 template<>
00250 void GURLS_EXPORT set(float* buffer, const float value, const int size);
00251 
00255 template<>
00256 void GURLS_EXPORT set(double* buffer, const double value, const int size);
00257 
00265 template<typename T>
00266 void copy(T* dst, const T* src, const int size)
00267 {
00268     memcpy(dst, src, size*sizeof(T));
00269 }
00270 
00274 template<>
00275 GURLS_EXPORT void copy(float* dst, const float* src, const int size);
00276 
00280 template<>
00281 GURLS_EXPORT void copy(double* dst, const double* src, const int size);
00282 
00292 template<typename T>
00293 void copy(T* dst, const T* src, const int size, const int dstIncr, const int srcIncr)
00294 {
00295     if(dstIncr == 1 && srcIncr == 1)
00296         copy(dst, src, size);
00297 
00298     else
00299     {
00300         const T* s_it = src;
00301 
00302         for(T *d_it = dst, *end = dst+(size*dstIncr); d_it != end; d_it += dstIncr, src+=srcIncr)
00303             *d_it = *s_it;
00304     }
00305 }
00306 
00310 template<>
00311 GURLS_EXPORT void copy(float* dst, const float* src, const int size, const int dstIncr, const int srcIncr);
00312 
00316 template<>
00317 GURLS_EXPORT void copy(double* dst, const double* src, const int size, const int dstIncr, const int srcIncr);
00318 
00330 template<typename T>
00331 void copy_submatrix(T* dst, const T* src, const int src_Rows, const int sizeRows, const int sizeCols, unsigned long *indices_rows, unsigned long *indices_cols)
00332 {
00333   int t=0;
00334   for (int j = 0; j < sizeCols; ++j)
00335     for (int i = 0; i < sizeRows; ++i)
00336     {
00337         dst[t] = src[ indices_rows[i] + indices_cols[j]*src_Rows ];
00338         ++t;
00339     }
00340 }
00341 
00352 template<typename T>
00353 void subMatrixFromRows(const T* matrix, const int mRows, const int mCols, const unsigned long* rowsIndices, const int nIndices, T* submat)
00354 {
00355     if(mRows < nIndices)
00356         throw gException(Exception_Inconsistent_Size);
00357 
00358     for(const unsigned long *it = rowsIndices, *end = rowsIndices+nIndices; it != end; ++it)
00359         copy(submat + (it-rowsIndices), matrix+(*it), mCols, nIndices, mRows);
00360 }
00361 
00362 
00373 template<typename T>
00374 void subMatrixFromColumns(const T* matrix, const int mRows, const int mCols, const unsigned long* colsIndices, const int nIndices, T* submat)
00375 {
00376     if(mCols < nIndices)
00377         throw gException(Exception_Inconsistent_Size);
00378 
00379     for(const unsigned long *it = colsIndices, *end = colsIndices+nIndices; it != end; ++it)
00380         copy(submat+(mRows*(it-colsIndices)), matrix+(mRows*(*it)), mRows);
00381 }
00382 
00390 template <typename T>
00391 void clearLowerTriangular(T* matrix, int rows, int cols)
00392 {
00393     T* it = matrix;
00394     const T zero = static_cast<T>(0.0);
00395 
00396     for (int i = 1; i <= cols; ++i)
00397     {
00398         const int len = rows-i;
00399 
00400         if(len > 0)
00401         {
00402             it+=i;
00403 
00404             set(it, zero, len);
00405 
00406             it+=len;
00407         }
00408     }
00409 }
00410 
00422 template <typename T>
00423 T* pinv(const T* A, const int rows, const int cols, int& res_rows, int& res_cols, T* RCOND = NULL)
00424 {
00425     int M = rows;
00426     int N = cols;
00427 
00428     T* a = new T[rows*cols];
00429     copy(a, A, rows*cols);
00430 
00431     int LDA = M;
00432     int LDB = std::max(M, N);
00433     int NRHS = LDB;
00434 
00435     const int b_size = LDB*NRHS;
00436     T *b = new T[LDB*NRHS];
00437 
00438     set(b, (T)0.0, b_size);
00439     set(b, (T)1.0, std::min(LDB, NRHS), NRHS+1);
00440 
00441     T* S = new T[std::min(M,N)];
00442     T rcond = (RCOND == NULL)? (std::max(rows, cols)*std::numeric_limits<T>::epsilon()): *RCOND;
00443 
00444     int RANK = -1; // std::min(M,N);
00445     int LWORK = -1; //2 * (3*LDB + std::max( 2*std::min(M,N), LDB));
00446     T* WORK = new T[1];
00447 
00448     int INFO;
00449 
00450     /* Query and allocate the optimal workspace */
00451     gelss( &M, &N, &NRHS, a, &LDA, b, &LDB, S, &rcond, &RANK, WORK, &LWORK, &INFO);
00452     LWORK = static_cast<int>(WORK[0]);
00453     delete [] WORK;
00454     WORK = new T[LWORK];
00455 
00456     gelss( &M, &N, &NRHS, a, &LDA, b, &LDB, S, &rcond, &RANK, WORK, &LWORK, &INFO);
00457 
00458     delete [] S;
00459     delete [] WORK;
00460     delete [] a;
00461 
00462     if(INFO != 0)
00463     {
00464         delete [] b;
00465 
00466         std::stringstream str;
00467         str << "Pinv failed, error code " << INFO << ";" << std::endl;
00468         throw gException(str.str());
00469     }
00470 
00471     res_rows = LDB;
00472     res_cols = NRHS;
00473 
00474     return b;
00475 }
00476 
00486 template <typename T>
00487 void transpose(const T* matrix, const int rows, const int cols, T* transposed)
00488 {
00489     T* d1 = transposed;
00490     const T* d0 = matrix;
00491     const int N = rows;
00492 
00493     for (int r = 0; r < rows; ++r)
00494         for (int c = 0; c < cols; ++c)
00495             *d1++=*(d0+c*N+r);
00496 }
00497 
00515 template <typename T>
00516 void dot(const T* A, const T* B, T* C,
00517          int A_rows, int A_cols,
00518          int B_rows, int B_cols,
00519          int C_rows, int C_cols,
00520          const CBLAS_TRANSPOSE TransA,
00521          const CBLAS_TRANSPOSE TransB,
00522          const CBLAS_ORDER Order)
00523 {
00524 
00525     bool transposeA = (TransA == CblasTrans || TransA == CblasConjTrans);
00526     bool transposeB = (TransB == CblasTrans || TransB == CblasConjTrans);
00527 
00528     if(transposeA)
00529         std::swap(A_rows, A_cols);
00530 
00531     if(transposeB)
00532         std::swap(B_rows, B_cols);
00533 
00534     if ((C_rows != A_rows) || (C_cols != B_cols))
00535         throw gException(gurls::Exception_Inconsistent_Size);
00536 
00537     if (A_cols != B_rows)
00538         throw gException(gurls::Exception_Inconsistent_Size);
00539 
00540     const T alpha = 1.0;
00541     const T beta = 0.0;
00542 
00543     int lda, ldb, ldc;
00544 
00545     int k = A_cols;
00546 
00547     // mxk kxn mxn
00548 
00549     switch(Order)
00550     {
00551     case CblasColMajor:
00552 
00553         lda = transposeA? k: A_rows;
00554         ldb = transposeB? B_cols: k;
00555         ldc = C_rows;
00556 
00557         gemm(TransA, TransB, A_rows, B_cols, k, alpha, A, lda, B, ldb, beta, C, ldc);
00558         break;
00559 
00560     case CblasRowMajor:
00561 
00562         lda = transposeA? A_rows: k;
00563         ldb = transposeB? k: B_cols;
00564         ldc = C_cols;
00565 
00566         gemm(TransB, TransA, B_cols, A_rows, k, alpha, B, ldb, A, lda, beta, C, ldc);
00567         break;
00568 
00569     default:
00570         lda = ldb = ldc = 0;
00571         assert(0);
00572     }
00573 }
00574 
00585 template<typename T>
00586 void cholesky(const T* matrix, const int rows, const int cols, T* result, bool upper = true)
00587 {
00588     copy(result, matrix, rows*cols);
00589 
00590     int LDA = rows;
00591     int nc = cols;
00592     char UPLO = upper? 'U':'L';
00593     int info;
00594 
00595     potrf_(&UPLO, &nc, result, &LDA, &info);
00596 
00597     if(info != 0)
00598     {
00599         std::stringstream str;
00600         str << "Cholesky factorization failed, error code " << info << ";" << std::endl;
00601         throw gException(str.str());
00602     }
00603 
00604     clearLowerTriangular(result, rows, cols);
00605 }
00606 
00613 template <typename T>
00614 void setReciprocal(T* matrix, const int len)
00615 {
00616     const T one = static_cast<T>(1.0);
00617 
00618     for(T *it = matrix, *end = matrix+len; it != end; ++it)
00619         *it = one / *it;
00620 }
00621 
00629 template <typename T>
00630 void diag(T* vector, const int len, T* result)
00631 {
00632     const T zero = static_cast<T>(0.0);
00633 
00634     set(result, zero, len*len);
00635     copy(result, vector, len, len+1, 1);
00636 }
00637 
00641 template <typename T>
00642 T mul(T a, T b)
00643 {
00644     return a*b;
00645 }
00646 
00650 template <typename T>
00651 T div(T a, T b)
00652 {
00653     return a/b;
00654 }
00655 
00659 template<typename T>
00660 bool eq(T val1, T val2)
00661 {
00662     return val1 == val2;
00663 }
00664 
00668 template<>
00669 GURLS_EXPORT bool eq(float val1, float val2);
00670 
00674 template<>
00675 GURLS_EXPORT bool eq(double val1, double val2);
00676 
00680 template<typename T>
00681 bool gt(T a, T b)
00682 {
00683     return a > b;
00684 }
00685 
00689 template<>
00690 GURLS_EXPORT bool gt(float a, float b);
00691 
00695 template<>
00696 GURLS_EXPORT bool gt(double a, double b);
00697 
00701 template<typename T>
00702 bool gte(T a, T b)
00703 {
00704     return gt(a,b) || eq(a,b);
00705 }
00706 
00710 template<typename T>
00711 bool le(T a, T b)
00712 {
00713     return !gt(a,b);
00714 }
00715 
00719 template<typename T>
00720 bool lt(T a, T b)
00721 {
00722     return a < b;
00723 }
00724 
00728 template<>
00729 GURLS_EXPORT bool lt(float a, float b);
00730 
00734 template<>
00735 GURLS_EXPORT bool lt(double a, double b);
00736 
00746 template <typename T>
00747 void binOperation(const T* A, const T* B, T* result, const int len, T(*op)(T,T))
00748 {
00749     const T *a_it = A, *a_end = A+len;
00750     const T *b_it = B;
00751     T *r_it = result;
00752 
00753     while(a_it != a_end)
00754     {
00755         *r_it = (*op)((*a_it),(*b_it));
00756 
00757         ++a_it;
00758         ++b_it;
00759         ++r_it;
00760     }
00761 }
00762 
00771 template <typename T>
00772 void mult(const T* A, const T* B, T* result, const int len)
00773 {
00774     binOperation<T>(A, B, result, len, &mul);
00775 }
00776 
00785 template <typename T>
00786 void rdivide(const T* A, const T* B, T* result, const int len)
00787 {
00788     binOperation<T>(A, B, result, len, &div);
00789 }
00790 
00800 template <typename T>
00801 void sum(const T* A, T* result, const int A_rows, const int A_cols, const int res_length) throw (gException)
00802 {
00803     if(A_cols != res_length)
00804         throw gException(Exception_Inconsistent_Size);
00805 
00806     const T *a_it = A, *a_end;
00807 
00808     const T zero = static_cast<T>(0.0);
00809 
00810     for(T *r_it = result, *r_end = result+A_cols; r_it != r_end; ++r_it)
00811     {
00812         *r_it = zero;
00813         a_end = a_it+A_rows;
00814 
00815         while(a_it != a_end)
00816         {
00817             *r_it += *a_it;
00818 
00819             ++a_it;
00820         }
00821     }
00822 }
00823 
00832 template <typename T>
00833 void sum_col(const T* A, T* result, const int A_rows, const int A_cols) throw (gException)
00834 {
00835     const T *a_it = A, *a_end;
00836 
00837     const T zero = static_cast<T>(0.0);
00838 
00839     for(T *r_it = result, *r_end = result+A_rows; r_it != r_end; ++r_it)
00840     {
00841         *r_it = zero;
00842 
00843         for(a_it = A+(r_it-result), a_end = a_it+(A_cols*A_rows); a_it != a_end; a_it += A_rows)
00844             *r_it += *a_it;
00845     }
00846 }
00847 
00857 template <typename T>
00858 void mean(const T* A, T* result, const int A_rows, const int A_cols, const int res_length) throw (gException)
00859 {
00860     sum(A, result, A_rows, A_cols, res_length);
00861     scal(res_length, (T)(1.0/A_rows), result, 1);
00862 }
00863 
00873 template <typename T>
00874 void argmin(const T* A, unsigned long* result, const int A_rows, const int A_cols, const int res_length) throw (gException)
00875 {
00876     if(A_cols != res_length)
00877         throw gException(Exception_Inconsistent_Size);
00878 
00879     const T *a_it = A;
00880 
00881     for(unsigned long *r_it = result, *r_end = result+A_cols; r_it != r_end; ++r_it, a_it += A_rows)
00882         *r_it = (std::min_element(a_it, a_it+A_rows) - a_it);
00883 }
00884 
00894 template <typename T>
00895 void copyLocations(const unsigned long* locs, const T* src, const int locs_len, const int src_len, T* result)
00896 {
00897     T* ptr_v = result;
00898 
00899     int val;
00900     for(const unsigned long* l_it = locs, *l_end=locs+locs_len; l_it != l_end; ++l_it, ++ptr_v)
00901     {
00902         val = *l_it;
00903         if((val < 0) || (val > src_len))
00904             throw gException(gurls::Exception_Index_Out_of_Bound);
00905 
00906         *ptr_v = src[val];
00907     }
00908 }
00909 
00917 template <typename T>
00918 T sumv(const T* V, const int len) throw (gException)
00919 {
00920     T y = 1;
00921     return dot(len, V, 1, &y, 0);
00922 }
00923 
00939 template<typename T>
00940 void rls_eigen(const T* Q, const T* L, const T* Qty, T* C, const T lambda, const int n,
00941              const int Q_rows, const int Q_cols,
00942              const int L_length,
00943              const int Qty_rows, const int Qty_cols)//  throw (gException)
00944 {
00945     T* work = new T [(Q_rows+1)*L_length];
00946 
00947     rls_eigen(Q, L, Qty, C, lambda, n, Q_rows, Q_cols, L_length, Qty_rows, Qty_cols, work);
00948 
00949     delete [] work;
00950 }
00951 
00968 template<typename T>
00969 void rls_eigen(const T* Q, const T* L, const T* Qty, T* C, const T lambda, const int n,
00970              const int Q_rows, const int Q_cols,
00971              const int L_length,
00972              const int Qty_rows, const int Qty_cols, T* work)//  throw (gException)
00973 {
00974     //function C = rls_eigen(Q,L,QtY,lambda,n)
00975 
00976     //sQ = size(Q,1); -> Q_rows
00977 
00978     //L = L + n*lambda;
00979     T* L1 = work; // size L_length
00980 
00981     set(L1, n*lambda , L_length);
00982 
00983     axpy(L_length, (T)1.0, L, 1, L1, 1);
00984 
00985     //L = L.^(-1);
00986     setReciprocal(L1, L_length);
00987 
00988     // L = diag(L)
00989     T* QL = work+L_length; // size Q_rows*L_length
00990 
00991     copy(QL, Q, Q_rows*Q_cols);
00992     for(int i=0; i< Q_cols; ++i)
00993         scal(Q_rows, L1[i], QL+(Q_rows*i), 1);
00994 
00995     //C = (Q*L)*QtY;
00996     dot(QL, Qty, C, Q_rows, L_length, Qty_rows, Qty_cols, Q_rows, Qty_cols, CblasNoTrans, CblasNoTrans, CblasColMajor);
00997 }
00998 
01009 template<typename T>
01010 T* sign(const T* vector, const int size)
01011 {
01012     const T* v_it = vector;
01013     const T* v_end = vector+size;
01014 
01015     T* ret = new T[size];
01016     T* r_it = ret;
01017 
01018     const T zero = (T)0.0;
01019 
01020     while(v_it != v_end)
01021     {
01022         *r_it = static_cast<T>((eq(*v_it, zero)? 0.0 : ((*v_it > 0.0)? 1.0 : -1.0)));
01023 
01024         ++v_it;
01025         ++r_it;
01026     }
01027 
01028     return ret;
01029 }
01030 
01043 template<typename T>
01044 T* compare(const T* vector1, const T* vector2, const int size, bool(*pred)(T,T))
01045 {
01046     const T* v1_end = vector1+size;
01047 
01048     T* ret = new T[size];
01049     T* r_it = ret;
01050 
01051     const T zero = static_cast<T>(0.0);
01052     const T one = static_cast<T>(1.0);
01053 
01054     for(const T *v1_it = vector1, *v2_it = vector2; v1_it != v1_end; ++v1_it, ++v2_it, ++r_it)
01055         *r_it = (*pred)(*v1_it, *v2_it)? one: zero;
01056 
01057     return ret;
01058 }
01059 
01060 
01073 template<typename T>
01074 T* compare(const T* vector, const T thr, const int size, bool(*pred)(T,T))
01075 {
01076     const T* v1_end = vector+size;
01077 
01078     T* ret = new T[size];
01079     T* r_it = ret;
01080 
01081     const T zero = static_cast<T>(0.0);
01082     const T one = static_cast<T>(1.0);
01083 
01084     for(const T *v1_it = vector; v1_it != v1_end; ++v1_it, ++r_it)
01085         *r_it = (*pred)(*v1_it, thr)? one: zero;
01086 
01087     return ret;
01088 }
01089 
01090 
01101 template<typename T>
01102 void sort(const T* M, const unsigned long rows, const unsigned long cols, bool(*pred)(T,T), T* values, unsigned long* indices)
01103 {
01104     typedef std::multimap<T, unsigned long, bool(*)(T,T) > MapType;
01105 
01106     for(unsigned long i=0; i< rows; ++i)
01107     {
01108         MapType data(pred);
01109 
01110         for (unsigned long j = 0; j < cols; ++j)
01111         {
01112             const unsigned long index = i+(rows*j);
01113             data.insert( std::pair<T,unsigned long>(M[index], j));
01114         }
01115 
01116         typename MapType::iterator it = data.begin();
01117 
01118         for (unsigned long j = 0; j < cols; ++j, ++it)
01119         {
01120             const unsigned long index = i+(rows*j);
01121 
01122             if(values != NULL)
01123                 values[index] = it->first;
01124 
01125             if(indices != NULL)
01126                 indices[index] = it->second;
01127         }
01128     }
01129 }
01130 
01142 template<typename T>
01143 void indicesOfMax(const T* A, const int A_rows, const int A_cols, unsigned long* ind, T* work, const int dimension) throw (gException)
01144 {
01145     const T *m_it;
01146     int m_rows;
01147     int m_cols;
01148 
01149     switch(dimension)
01150     {
01151     case 1:
01152         m_it = A;
01153         m_rows = A_rows;
01154         m_cols = A_cols;
01155         break;
01156     case 2:
01157         transpose(A, A_rows, A_cols, work);
01158         m_it = work;
01159         m_rows = A_cols;
01160         m_cols = A_rows;
01161         break;
01162     default:
01163         throw gException(gurls::Exception_Illegal_Argument_Value);
01164     }
01165 
01166     for(unsigned long *r_it = ind, *r_end = ind+m_cols; r_it != r_end; ++r_it, m_it += m_rows)
01167         *r_it = (std::max_element(m_it, m_it+m_rows) - m_it);
01168 
01169 }
01170 
01182 template<typename T>
01183 void maxValues(const T* A, const int A_rows, const int A_cols, T* maxv, T* work, const int dimension) throw (gException)
01184 {
01185     const T *m_it;
01186     int m_rows;
01187     int m_cols;
01188 
01189     switch(dimension)
01190     {
01191     case 1:
01192         m_it = A;
01193         m_rows = A_rows;
01194         m_cols = A_cols;
01195         break;
01196     case 2:
01197         transpose(A, A_rows, A_cols, work);
01198         m_it = work;
01199         m_rows = A_cols;
01200         m_cols = A_rows;
01201         break;
01202     default:
01203         throw gException(gurls::Exception_Illegal_Argument_Value);
01204     }
01205 
01206     for(T *r_it = maxv, *r_end = maxv+m_cols; r_it != r_end; ++r_it, m_it += m_rows)
01207         *r_it = *std::max_element(m_it, m_it+m_rows);
01208 
01209 }
01210 
01225 template<typename T>
01226 T* lambdaguesses(const T* eigvals, const int len, const int r, const int n, const int nlambda, const T minl)
01227 {
01228     T* guesses = new T[nlambda];
01229 
01230     T* tmp = new T[len];
01231     copy(tmp, eigvals, len);
01232 
01233     std::sort(tmp, tmp+len);
01234 
01235     /*const*/ T lmin = tmp[len-r];
01236     const T lmax = tmp[len-1];
01237 
01238     delete[] tmp;
01239 
01240     T thr1 = std::min(lmin, minl*lmax);
01241     T thr2 = 200*static_cast<T>(sqrt(std::numeric_limits<T>::epsilon()));
01242 
01243     lmin = std::max(thr1, thr2);
01244 
01245     const T base = (lmax/lmin);
01246     const T den = nlambda-static_cast<T>(1.0);
01247     const T nT = (T)n;
01248 
01249     for(int i=0; i< nlambda; ++i)
01250         guesses[i] = (lmin * pow( base, ((T)i)/den ) )/nT;
01251 
01252     return guesses;
01253 }
01254 
01255 //template<typename T>
01256 //T* mldivide(const T* A, const T* B,
01257 //            const int a_rows, const int a_cols,
01258 //            const int b_rows, const int b_cols,
01259 //            int& res_rows, int& res_cols)
01260 //{
01261 //    // A\B = pinv(A)*B
01262 
01263 //    int aInv_rows, aInv_cols;
01264 //    T* A_inv = pinv(A, a_rows, a_cols, aInv_rows, aInv_cols);
01265 
01266 //    T* ret = new T[aInv_rows*b_cols];
01267 //    dot(A_inv, B, ret, aInv_rows, aInv_cols, b_rows, b_cols, aInv_rows, b_cols, CblasNoTrans, CblasNoTrans, CblasColMajor);
01268 
01269 //    delete[] A_inv;
01270 
01271 //    res_rows = aInv_rows;
01272 //    res_cols = b_cols;
01273 
01274 //    return ret;
01275 
01276 //}
01277 
01289 template<typename T>
01290 void mldivide_squared(const T* A, T* B,
01291             const int a_rows, const int a_cols,
01292             const int b_rows, const int b_cols,
01293             const CBLAS_TRANSPOSE transA)
01294 {
01295     if (a_cols != a_rows)
01296         throw gException("The input matrix A must be squared");
01297 
01298     const int lda = a_rows;
01299     const int ldb = b_rows;
01300 
01301     trsm(CblasLeft, CblasUpper, transA, CblasNonUnit, b_rows, b_cols, (T)1.0, A, lda, B, ldb);
01302 }
01303 
01304 
01323 template <typename T>
01324 void svd(const T* A, T*& U, T*& S, T*& Vt,
01325          const int A_rows, const int A_cols,
01326          int& U_rows, int& U_cols,
01327          int& S_len,
01328          int& Vt_rows, int& Vt_cols, bool econ = false) throw(gException)
01329 {
01330     // A = U*S*Vt
01331 
01332     char jobu, jobvt;
01333 
01334     int m = A_rows;
01335     int n = A_cols;
01336     int k = std::min<int>(m, n);
01337     int ldvt;
01338 
01339     S = new T[k];
01340     S_len = k;
01341 
01342     U_rows = m;
01343     Vt_cols = n;
01344 
01345     if(econ)
01346     {
01347 //        jobu = jobvt = 'S';
01348         if(m>n)
01349         {
01350             jobu = 'S';
01351             jobvt = 'A';
01352         }
01353         else if(m<n)
01354         {
01355             jobu = 'A';
01356             jobvt = 'S';
01357         }
01358         else
01359             jobu = jobvt = 'S';
01360 
01361         U = new T[m*k];
01362         Vt = new T[k*n];
01363 
01364         U_cols = k;
01365         Vt_rows = k;
01366 
01367         ldvt = k;
01368     }
01369     else
01370     {
01371         jobu = jobvt = 'A';
01372 
01373         U = new T[m*m];
01374         Vt = new T[n*n];
01375 
01376         U_cols = m;
01377         Vt_rows = n;
01378 
01379         ldvt = n;
01380     }
01381 
01382     //MAX(1,3*MIN(M,N)+MAX(M,N),5*MIN(M,N))
01383 
01384     int lda = A_rows;
01385     int ldu = m;
01386     int info, lwork = std::max<int>(3*k+std::max<int>(m,n), 5*k);
01387     T* work = new T[lwork];
01388     T* cpy = new T[m*n];
01389     copy(cpy, A, A_rows*A_cols);
01390 
01391     gesvd_(&jobu, &jobvt, &m, &n, cpy, &lda, S, U, &ldu, Vt, &ldvt, work, &lwork, &info);
01392 
01393     delete[] work;
01394     delete[] cpy;
01395 
01396     if(info != 0)
01397     {
01398         std::stringstream str;
01399         str << "SVD failed, error code " << info << std::endl;
01400         throw gException(str.str());
01401     }
01402 }
01403 
01407 template<typename T>
01408 void randperm(const unsigned long n, T* seq, bool generate = true, unsigned long start = 1)
01409 {
01410     if(generate)
01411     {
01412         unsigned long val = start;
01413         for(T *it = seq, *end= seq+n; it != end; ++it)
01414             *it = val++;
01415     }
01416 
01417     for(unsigned long i=0; i<n; ++i)
01418         std::swap(seq[rand()%n], seq[rand()%n]);
01419 }
01420 
01430 template<typename T>
01431 void getRow(const T* M, const int rows, const int cols, const int row_index , T* row)
01432 {
01433     copy(row, M+row_index, cols, 1, rows);
01434 }
01435 
01443 template<typename T>
01444 void eig_sm(T* A, T* L, int A_rows_cols) throw (gException)
01445 {
01446     char jobz = 'V';
01447     char uplo = 'L';
01448     int n = A_rows_cols, lda = n;
01449     int info, lwork = 4*n;
01450     T* work = new T[lwork];
01451 
01452     syev(&jobz, &uplo, &n, A, &lda, L, work, &lwork, &info );
01453 
01454     delete[] work;
01455 
01456     if(info != 0)
01457     {
01458         std::stringstream str;
01459         str << "Eigenvalues/eigenVectors computation failed, error code " << info << ";" << std::endl;
01460         throw gException(str.str());
01461     }
01462 }
01463 
01470 template<typename T>
01471 void exp(T* v, const int length)
01472 {
01473     for(T *it = v, *end = v+length; it != end; ++it)
01474         *it = (T) std::exp(*it);
01475 }
01476 
01486 template<typename T>
01487 T eucl_dist(const T* A, const T* B, const int len, T* work)
01488 {
01489     copy(work, A, len);
01490     axpy(len, (T)-1.0, B, 1, work, 1);
01491     return nrm2(len, work, 1);
01492 }
01493 
01501 template<typename T>
01502 void pdist(const T* A, const int N/*A_rows*/, const int P/*A_cols*/, T* D)
01503 {
01504     T* work = new T[P];
01505     T* rowN = new T[P];
01506     T* rowNPlusOne = new T[P];
01507     T* D_it = D;
01508 
01509     for(int i=0; i<N-1; ++i)
01510     {
01511         getRow(A, N, P, i, rowN);
01512 
01513         for(int j=i+1; j<N; ++j)
01514         {
01515             getRow(A, N, P, j, rowNPlusOne);
01516 
01517             *D_it = eucl_dist(rowN,rowNPlusOne,P, work);
01518             ++D_it;
01519         }
01520     }
01521 
01522     delete [] work;
01523     delete [] rowN;
01524     delete [] rowNPlusOne;
01525 }
01526 
01527 
01537 template<typename T>
01538 void squareform(const T* A, const int N/*A_rows*/, const int P/*A_cols*/, T* D, const int d_cols)
01539 {
01540     if(d_cols!=1)
01541     {
01542         T* work = new T[P];
01543         T* rowN = new T[P];
01544         T* rowNPlusOne = new T[P];
01545 
01546         set(D, (T)0.0, N, N+1); // zeroes the diagonal
01547 
01548         for(int i=0; i<N; ++i)
01549         {
01550             copy(D+(i*N), D+i, i, 1, N); // copy from the other side
01551 
01552             if(i+1 < N)
01553             {
01554                 getRow(A, N, P, i, rowN);
01555 
01556                 for(int j=i+1; j<N; ++j)
01557                 {
01558                     getRow(A, N, P, j, rowNPlusOne);
01559                     D[j + i*N] = eucl_dist(rowN, rowNPlusOne, P, work);
01560                 }
01561             }
01562         }
01563 
01564         delete [] work;
01565         delete [] rowN;
01566         delete [] rowNPlusOne;
01567 
01568     }
01569     else
01570     {
01571         pdist(A, N, P, D);
01572     }
01573 }
01574 
01584 template<typename T>
01585 void indicesOfEqualsTo(const T* V, const int len, const T value, unsigned long* ind, int& ind_length)
01586 {
01587     unsigned long* r_it = ind;
01588     for(const T *it = V, *end = V+len; it != end; ++it)
01589     {
01590         if(eq(*it, value))
01591         {
01592             *r_it = it-V;
01593             ++r_it;
01594         }
01595     }
01596 
01597     ind_length = r_it - ind;
01598 }
01599 
01603 template<typename T>
01604 int round(const T value)
01605 {
01606     if(eq(value, (T)0.0))
01607         return 0;
01608 
01609     return gt(value,(T)0.0)? ((int)(value+0.5)): ((int)(value-0.5));
01610 }
01611 
01623 template<typename T>
01624 void qr_econ(const T* A, int m, int n, T* Q, T* R, int* E)
01625 {
01626     // Q: mxmin(m,n)
01627     // R: min(m,n)xn
01628     // E: n
01629 
01630     T* Q_tmp = new T[m*n];
01631     copy(Q_tmp, A, m*n);
01632 
01633     int k = std::min(m, n);
01634 
01635     int lda = std::max(1,m);
01636     int* jpvt = E;
01637     set(jpvt, 0, n);
01638 
01639     T* tau = new T[k];
01640 
01641     T* work;
01642     int lwork = -1;
01643     int info;
01644 
01645     // query
01646     T qwork;
01647     geqp3( &m, &n, Q_tmp, &lda, jpvt, tau, &qwork, &lwork, &info);
01648 
01649     // exec
01650     lwork = static_cast<int>(qwork);
01651     work = new T[lwork];
01652     geqp3( &m, &n, Q_tmp, &lda, jpvt, tau, work, &lwork, &info);
01653 
01654     if(info != 0)
01655     {
01656         delete[] tau;
01657         delete[] work;
01658         delete[] Q_tmp;
01659 
01660         std::stringstream str;
01661         str << "QR factorization failed, error code " << info << std::endl;
01662         throw gException(str.str());
01663     }
01664 
01665     if(R != NULL)
01666     {
01667         for(int i=0; i<n; ++i)
01668         {
01669             copy(R + k*i, Q_tmp + m*i, i+1);
01670 
01671             set(R + (k*i) + i+1, (T)0.0, k - (i+1));
01672         }
01673     }
01674 
01675     // query
01676     lwork = -1;
01677     orgqr(&m, &k, &k, Q_tmp, &lda, tau, &qwork, &lwork, &info);
01678 
01679     if(info != 0)
01680     {
01681         delete[] tau;
01682         delete[] work;
01683         delete[] Q_tmp;
01684 
01685         std::stringstream str;
01686         str << "QR factorization failed, error code " << info << std::endl;
01687         throw gException(str.str());
01688     }
01689 
01690     //exec
01691     lwork = static_cast<int>(qwork);
01692     delete[] work;
01693     work = new T[lwork];
01694     orgqr(&m, &k, &k, Q_tmp, &lda, tau, work, &lwork, &info);
01695 
01696     copy(Q, Q_tmp, m*k);
01697 
01698     delete[] tau;
01699     delete[] work;
01700     delete[] Q_tmp;
01701 
01702 }
01703 
01707 template<typename T>
01708 void linspace(T a, T b, unsigned long n, T* res)
01709 {
01710     unsigned long i = 0;
01711 
01712     if(n > 0)
01713     {
01714         const T coeff = (b - a)/(static_cast<T>(n)-1);
01715         for(i = 0; i < n-1; ++i)
01716             res[i] = a + (i*coeff);
01717     }
01718 
01719     res[i] = b;
01720 }
01721 
01722 
01732 template<typename T>
01733 void stdDev(const T* X, const int rows, const int cols, T* res, T* work)
01734 {
01735     T* meanX = work;
01736     mean(X, meanX, rows, cols, cols);
01737 
01738     T* stdX = res;
01739     T* column = work+cols;
01740 
01741     for(int i=0; i< cols; ++i)
01742     {
01743         copy(column, X+(rows*i), rows);
01744 
01745         axpy(rows, (T)-1.0, meanX+i, 0, column, 1);
01746 
01747         stdX[i] = sqrt( pow(nrm2(rows, column, 1), 2) / (rows-1));
01748     }
01749 }
01750 
01757 template<typename T>
01758 T median(T* v, const int length)
01759 {
01760     std::sort(v, v+length);
01761 
01762     if(length%2)
01763         return v[length/2];
01764     else
01765         return static_cast<T>( (v[length/2] + v[(length/2)-1]) /2.0 );
01766 }
01767 
01777 template<typename T>
01778 void median(const T* M, const int rows, const int cols, const int dimension, T* res, T* work)
01779 {
01780     switch(dimension)
01781     {
01782     case 1:
01783         for(int i=0; i<cols; ++i)
01784         {
01785             copy(work, M+(i*rows), rows);
01786             res[i] = median(work, rows);
01787         }
01788         break;
01789     case 2:
01790         for(int i=0; i<rows; ++i)
01791         {
01792             copy(work, M+i, cols, 1, rows);
01793             res[i] = median(work, cols);
01794         }
01795         break;
01796     default:
01797         throw gException(Exception_Illegal_Argument_Value);
01798     }
01799 }
01800 
01801 }
01802 
01803 #endif // _GURLS_GMATH_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends