![]() |
GURLS++
2.0.00
C++ Implementation of GURLS Matlab Toolbox
|
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_