diff options
Diffstat (limited to 'ml/dlib/dlib/matrix')
50 files changed, 0 insertions, 30343 deletions
diff --git a/ml/dlib/dlib/matrix/cblas_constants.h b/ml/dlib/dlib/matrix/cblas_constants.h deleted file mode 100644 index 6ff89f141..000000000 --- a/ml/dlib/dlib/matrix/cblas_constants.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_CBLAS_CONSTAnTS_Hh_ -#define DLIB_CBLAS_CONSTAnTS_Hh_ - -#ifndef CBLAS_H -namespace dlib -{ - namespace blas_bindings - { - enum CBLAS_ORDER {CblasRowMajor=101, CblasColMajor=102}; - enum CBLAS_TRANSPOSE {CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113}; - enum CBLAS_UPLO {CblasUpper=121, CblasLower=122}; - enum CBLAS_DIAG {CblasNonUnit=131, CblasUnit=132}; - enum CBLAS_SIDE {CblasLeft=141, CblasRight=142}; - - } -} -#endif // if not CBLAS_H - -#endif // DLIB_CBLAS_CONSTAnTS_Hh_ - diff --git a/ml/dlib/dlib/matrix/lapack/fortran_id.h b/ml/dlib/dlib/matrix/lapack/fortran_id.h deleted file mode 100644 index 8027ea34f..000000000 --- a/ml/dlib/dlib/matrix/lapack/fortran_id.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_BOOST_NUMERIC_BINDINGS_TRAITS_FORTRAN_H -#define DLIB_BOOST_NUMERIC_BINDINGS_TRAITS_FORTRAN_H - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// FORTRAN BINDING STUFF FROM BOOST -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// Copyright (C) 2002, 2003 Si-Lab b.v.b.a., Toon Knapen and Kresimir Fresl - - -// First we need to know what the conventions for linking -// C with Fortran is on this platform/toolset -#if defined(LAPACK_FORCE_UNDERSCORE) -#define DLIB_BIND_FORTRAN_LOWERCASE_UNDERSCORE -#elif defined(LAPACK_FORCE_NOUNDERSCORE) -#define DLIB_BIND_FORTRAN_LOWERCASE -#elif defined(__GNUC__) || defined(__ICC) || defined(__sgi) || defined(__COMO__) || defined(__KCC) -#define DLIB_BIND_FORTRAN_LOWERCASE_UNDERSCORE -#elif defined(__IBMCPP__) || defined(_MSC_VER) || defined(__BORLANDC__) -#define DLIB_BIND_FORTRAN_LOWERCASE -#else -#error do not know how to link with fortran for the given platform -#endif - -// Next we define macros to convert our symbols to -// the current convention -#if defined(DLIB_BIND_FORTRAN_LOWERCASE_UNDERSCORE) -#define DLIB_FORTRAN_ID( id ) id##_ -#elif defined(DLIB_BIND_FORTRAN_LOWERCASE) -#define DLIB_FORTRAN_ID( id ) id -#else -#error do not know how to bind to fortran calling convention -#endif - - - -namespace dlib -{ - namespace lapack - { - // stuff from f2c used to define what exactly is an integer in fortran -#if (defined(__alpha__) || defined(__sparc64__) || defined(__x86_64__) || defined(__ia64__)) && !defined(MATLAB_MEX_FILE) - typedef int integer; - typedef unsigned int uinteger; -#else - typedef long int integer; - typedef unsigned long int uinteger; -#endif - - } -} - -#endif // DLIB_BOOST_NUMERIC_BINDINGS_TRAITS_FORTRAN_H - diff --git a/ml/dlib/dlib/matrix/lapack/gees.h b/ml/dlib/dlib/matrix/lapack/gees.h deleted file mode 100644 index a8ee63ff1..000000000 --- a/ml/dlib/dlib/matrix/lapack/gees.h +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_LAPACk_ES_Hh_ -#define DLIB_LAPACk_ES_Hh_ - -#include "fortran_id.h" -#include "../matrix.h" - -namespace dlib -{ - namespace lapack - { - namespace binding - { -#if defined(__alpha__) || defined(__sparc64__) || defined(__x86_64__) || defined(__ia64__) - typedef int logical; -#else - typedef long int logical; -#endif - typedef logical (*L_fp)(...); - - extern "C" - { - void DLIB_FORTRAN_ID(dgees) (char *jobvs, char *sort, L_fp select, integer *n, - double *a, integer *lda, integer *sdim, double *wr, - double *wi, double *vs, integer *ldvs, double *work, - integer *lwork, logical *bwork, integer *info); - - void DLIB_FORTRAN_ID(sgees) (char *jobvs, char *sort, L_fp select, integer *n, - float *a, integer *lda, integer *sdim, float *wr, - float *wi, float *vs, integer *ldvs, float *work, - integer *lwork, logical *bwork, integer *info); - - } - - inline int gees (char jobvs, integer n, - double *a, integer lda, double *wr, - double *wi, double *vs, integer ldvs, double *work, - integer lwork) - { - // No sorting allowed - integer info = 0; - char sort = 'N'; - L_fp fnil = 0; - logical bwork = 0; - integer sdim = 0; - DLIB_FORTRAN_ID(dgees)(&jobvs, &sort, fnil, &n, - a, &lda, &sdim, wr, - wi, vs, &ldvs, work, - &lwork, &bwork, &info); - return info; - } - - - inline int gees (char jobvs, integer n, - float *a, integer lda, float *wr, - float *wi, float *vs, integer ldvs, float *work, - integer lwork) - { - // No sorting allowed - integer info = 0; - char sort = 'N'; - L_fp fnil = 0; - logical bwork = 0; - integer sdim = 0; - DLIB_FORTRAN_ID(sgees)(&jobvs, &sort, fnil, &n, - a, &lda, &sdim, wr, - wi, vs, &ldvs, work, - &lwork, &bwork, &info); - return info; - } - - - } - - // ------------------------------------------------------------------------------------ - -/* -- LAPACK driver routine (version 3.1) -- */ -/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ -/* November 2006 */ - -/* .. Scalar Arguments .. */ -/* .. */ -/* .. Array Arguments .. */ -/* .. */ -/* .. Function Arguments .. */ -/* .. */ - -/* Purpose */ -/* ======= */ - -/* DGEES computes for an N-by-N real nonsymmetric matrix A, the */ -/* eigenvalues, the real Schur form T, and, optionally, the matrix of */ -/* Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). */ - -/* Optionally, it also orders the eigenvalues on the diagonal of the */ -/* real Schur form so that selected eigenvalues are at the top left. */ -/* The leading columns of Z then form an orthonormal basis for the */ -/* invariant subspace corresponding to the selected eigenvalues. */ - -/* A matrix is in real Schur form if it is upper quasi-triangular with */ -/* 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the */ -/* form */ -/* [ a b ] */ -/* [ c a ] */ - -/* where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). */ - -/* Arguments */ -/* ========= */ - -/* JOBVS (input) CHARACTER*1 */ -/* = 'N': Schur vectors are not computed; */ -/* = 'V': Schur vectors are computed. */ - -/* SORT (input) CHARACTER*1 */ -/* Specifies whether or not to order the eigenvalues on the */ -/* diagonal of the Schur form. */ -/* = 'N': Eigenvalues are not ordered; */ -/* = 'S': Eigenvalues are ordered (see SELECT). */ - -/* SELECT (external procedure) LOGICAL FUNCTION of two DOUBLE PRECISION arguments */ -/* SELECT must be declared EXTERNAL in the calling subroutine. */ -/* If SORT = 'S', SELECT is used to select eigenvalues to sort */ -/* to the top left of the Schur form. */ -/* If SORT = 'N', SELECT is not referenced. */ -/* An eigenvalue WR(j)+sqrt(-1)*WI(j) is selected if */ -/* SELECT(WR(j),WI(j)) is true; i.e., if either one of a complex */ -/* conjugate pair of eigenvalues is selected, then both complex */ -/* eigenvalues are selected. */ -/* Note that a selected complex eigenvalue may no longer */ -/* satisfy SELECT(WR(j),WI(j)) = .TRUE. after ordering, since */ -/* ordering may change the value of complex eigenvalues */ -/* (especially if the eigenvalue is ill-conditioned); in this */ -/* case INFO is set to N+2 (see INFO below). */ - -/* N (input) INTEGER */ -/* The order of the matrix A. N >= 0. */ - -/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ -/* On entry, the N-by-N matrix A. */ -/* On exit, A has been overwritten by its real Schur form T. */ - -/* LDA (input) INTEGER */ -/* The leading dimension of the array A. LDA >= max(1,N). */ - -/* SDIM (output) INTEGER */ -/* If SORT = 'N', SDIM = 0. */ -/* If SORT = 'S', SDIM = number of eigenvalues (after sorting) */ -/* for which SELECT is true. (Complex conjugate */ -/* pairs for which SELECT is true for either */ -/* eigenvalue count as 2.) */ - -/* WR (output) DOUBLE PRECISION array, dimension (N) */ -/* WI (output) DOUBLE PRECISION array, dimension (N) */ -/* WR and WI contain the real and imaginary parts, */ -/* respectively, of the computed eigenvalues in the same order */ -/* that they appear on the diagonal of the output Schur form T. */ -/* Complex conjugate pairs of eigenvalues will appear */ -/* consecutively with the eigenvalue having the positive */ -/* imaginary part first. */ - -/* VS (output) DOUBLE PRECISION array, dimension (LDVS,N) */ -/* If JOBVS = 'V', VS contains the orthogonal matrix Z of Schur */ -/* vectors. */ -/* If JOBVS = 'N', VS is not referenced. */ - -/* LDVS (input) INTEGER */ -/* The leading dimension of the array VS. LDVS >= 1; if */ -/* JOBVS = 'V', LDVS >= N. */ - -/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ -/* On exit, if INFO = 0, WORK(1) contains the optimal LWORK. */ - -/* LWORK (input) INTEGER */ -/* The dimension of the array WORK. LWORK >= max(1,3*N). */ -/* For good performance, LWORK must generally be larger. */ - -/* If LWORK = -1, then a workspace query is assumed; the routine */ -/* only calculates the optimal size of the WORK array, returns */ -/* this value as the first entry of the WORK array, and no error */ -/* message related to LWORK is issued by XERBLA. */ - -/* BWORK (workspace) LOGICAL array, dimension (N) */ -/* Not referenced if SORT = 'N'. */ - -/* INFO (output) INTEGER */ -/* = 0: successful exit */ -/* < 0: if INFO = -i, the i-th argument had an illegal value. */ -/* > 0: if INFO = i, and i is */ -/* <= N: the QR algorithm failed to compute all the */ -/* eigenvalues; elements 1:ILO-1 and i+1:N of WR and WI */ -/* contain those eigenvalues which have converged; if */ -/* JOBVS = 'V', VS contains the matrix which reduces A */ -/* to its partially converged Schur form. */ -/* = N+1: the eigenvalues could not be reordered because some */ -/* eigenvalues were too close to separate (the problem */ -/* is very ill-conditioned); */ -/* = N+2: after reordering, roundoff changed values of some */ -/* complex eigenvalues so that leading eigenvalues in */ -/* the Schur form no longer satisfy SELECT=.TRUE. This */ -/* could also be caused by underflow due to scaling. */ - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, long NR3, long NR4, - long NC1, long NC2, long NC3, long NC4, - typename MM, - typename layout - > - int gees ( - const char jobz, - matrix<T,NR1,NC1,MM,column_major_layout>& a, - matrix<T,NR2,NC2,MM,layout>& wr, - matrix<T,NR3,NC3,MM,layout>& wi, - matrix<T,NR4,NC4,MM,column_major_layout>& vs - ) - { - matrix<T,0,1,MM,column_major_layout> work; - - const long n = a.nr(); - - wr.set_size(n,1); - wi.set_size(n,1); - - if (jobz == 'V') - vs.set_size(n,n); - else - vs.set_size(NR4?NR4:1, NC4?NC4:1); - - // figure out how big the workspace needs to be. - T work_size = 1; - int info = binding::gees(jobz, n, - &a(0,0), a.nr(), &wr(0,0), - &wi(0,0), &vs(0,0), vs.nr(), &work_size, - -1); - - if (info != 0) - return info; - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - - // compute the actual decomposition - info = binding::gees(jobz, n, - &a(0,0), a.nr(), &wr(0,0), - &wi(0,0), &vs(0,0), vs.nr(), &work(0,0), - work.size()); - - return info; - } - - // ------------------------------------------------------------------------------------ - - } - -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_LAPACk_ES_Hh_ - diff --git a/ml/dlib/dlib/matrix/lapack/geev.h b/ml/dlib/dlib/matrix/lapack/geev.h deleted file mode 100644 index d8fdc4af5..000000000 --- a/ml/dlib/dlib/matrix/lapack/geev.h +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_LAPACk_GEEV_Hh_ -#define DLIB_LAPACk_GEEV_Hh_ - -#include "fortran_id.h" -#include "../matrix.h" - -namespace dlib -{ - namespace lapack - { - namespace binding - { - extern "C" - { - void DLIB_FORTRAN_ID(dgeev) (char *jobvl, char *jobvr, integer *n, double * a, - integer *lda, double *wr, double *wi, double *vl, - integer *ldvl, double *vr, integer *ldvr, double *work, - integer *lwork, integer *info); - - void DLIB_FORTRAN_ID(sgeev) (char *jobvl, char *jobvr, integer *n, float * a, - integer *lda, float *wr, float *wi, float *vl, - integer *ldvl, float *vr, integer *ldvr, float *work, - integer *lwork, integer *info); - - } - - inline int geev (char jobvl, char jobvr, integer n, double *a, - integer lda, double *wr, double *wi, double *vl, - integer ldvl, double *vr, integer ldvr, double *work, - integer lwork) - { - integer info = 0; - DLIB_FORTRAN_ID(dgeev)(&jobvl, &jobvr, &n, a, - &lda, wr, wi, vl, - &ldvl, vr, &ldvr, work, - &lwork, &info); - return info; - } - - inline int geev (char jobvl, char jobvr, integer n, float *a, - integer lda, float *wr, float *wi, float *vl, - integer ldvl, float *vr, integer ldvr, float *work, - integer lwork) - { - integer info = 0; - DLIB_FORTRAN_ID(sgeev)(&jobvl, &jobvr, &n, a, - &lda, wr, wi, vl, - &ldvl, vr, &ldvr, work, - &lwork, &info); - return info; - } - - - } - - // ------------------------------------------------------------------------------------ - -/* -- LAPACK driver routine (version 3.1) -- */ -/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ -/* November 2006 */ - -/* .. Scalar Arguments .. */ -/* .. */ -/* .. Array Arguments .. */ -/* .. */ - -/* Purpose */ -/* ======= */ - -/* DGEEV computes for an N-by-N real nonsymmetric matrix A, the */ -/* eigenvalues and, optionally, the left and/or right eigenvectors. */ - -/* The right eigenvector v(j) of A satisfies */ -/* A * v(j) = lambda(j) * v(j) */ -/* where lambda(j) is its eigenvalue. */ -/* The left eigenvector u(j) of A satisfies */ -/* u(j)**H * A = lambda(j) * u(j)**H */ -/* where u(j)**H denotes the conjugate transpose of u(j). */ - -/* The computed eigenvectors are normalized to have Euclidean norm */ -/* equal to 1 and largest component real. */ - -/* Arguments */ -/* ========= */ - -/* JOBVL (input) CHARACTER*1 */ -/* = 'N': left eigenvectors of A are not computed; */ -/* = 'V': left eigenvectors of A are computed. */ - -/* JOBVR (input) CHARACTER*1 */ -/* = 'N': right eigenvectors of A are not computed; */ -/* = 'V': right eigenvectors of A are computed. */ - -/* N (input) INTEGER */ -/* The order of the matrix A. N >= 0. */ - -/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ -/* On entry, the N-by-N matrix A. */ -/* On exit, A has been overwritten. */ - -/* LDA (input) INTEGER */ -/* The leading dimension of the array A. LDA >= max(1,N). */ - -/* WR (output) DOUBLE PRECISION array, dimension (N) */ -/* WI (output) DOUBLE PRECISION array, dimension (N) */ -/* WR and WI contain the real and imaginary parts, */ -/* respectively, of the computed eigenvalues. Complex */ -/* conjugate pairs of eigenvalues appear consecutively */ -/* with the eigenvalue having the positive imaginary part */ -/* first. */ - -/* VL (output) DOUBLE PRECISION array, dimension (LDVL,N) */ -/* If JOBVL = 'V', the left eigenvectors u(j) are stored one */ -/* after another in the columns of VL, in the same order */ -/* as their eigenvalues. */ -/* If JOBVL = 'N', VL is not referenced. */ -/* If the j-th eigenvalue is real, then u(j) = VL(:,j), */ -/* the j-th column of VL. */ -/* If the j-th and (j+1)-st eigenvalues form a complex */ -/* conjugate pair, then u(j) = VL(:,j) + i*VL(:,j+1) and */ -/* u(j+1) = VL(:,j) - i*VL(:,j+1). */ - -/* LDVL (input) INTEGER */ -/* The leading dimension of the array VL. LDVL >= 1; if */ -/* JOBVL = 'V', LDVL >= N. */ - -/* VR (output) DOUBLE PRECISION array, dimension (LDVR,N) */ -/* If JOBVR = 'V', the right eigenvectors v(j) are stored one */ -/* after another in the columns of VR, in the same order */ -/* as their eigenvalues. */ -/* If JOBVR = 'N', VR is not referenced. */ -/* If the j-th eigenvalue is real, then v(j) = VR(:,j), */ -/* the j-th column of VR. */ -/* If the j-th and (j+1)-st eigenvalues form a complex */ -/* conjugate pair, then v(j) = VR(:,j) + i*VR(:,j+1) and */ -/* v(j+1) = VR(:,j) - i*VR(:,j+1). */ - -/* LDVR (input) INTEGER */ -/* The leading dimension of the array VR. LDVR >= 1; if */ -/* JOBVR = 'V', LDVR >= N. */ - -/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ -/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ - -/* LWORK (input) INTEGER */ -/* The dimension of the array WORK. LWORK >= max(1,3*N), and */ -/* if JOBVL = 'V' or JOBVR = 'V', LWORK >= 4*N. For good */ -/* performance, LWORK must generally be larger. */ - -/* If LWORK = -1, then a workspace query is assumed; the routine */ -/* only calculates the optimal size of the WORK array, returns */ -/* this value as the first entry of the WORK array, and no error */ -/* message related to LWORK is issued by XERBLA. */ - -/* INFO (output) INTEGER */ -/* = 0: successful exit */ -/* < 0: if INFO = -i, the i-th argument had an illegal value. */ -/* > 0: if INFO = i, the QR algorithm failed to compute all the */ -/* eigenvalues, and no eigenvectors have been computed; */ -/* elements i+1:N of WR and WI contain eigenvalues which */ -/* have converged. */ - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, long NR3, long NR4, long NR5, - long NC1, long NC2, long NC3, long NC4, long NC5, - typename MM, - typename layout - > - int geev ( - const char jobvl, - const char jobvr, - matrix<T,NR1,NC1,MM,column_major_layout>& a, - matrix<T,NR2,NC2,MM,layout>& wr, - matrix<T,NR3,NC3,MM,layout>& wi, - matrix<T,NR4,NC4,MM,column_major_layout>& vl, - matrix<T,NR5,NC5,MM,column_major_layout>& vr - ) - { - matrix<T,0,1,MM,column_major_layout> work; - - const long n = a.nr(); - - wr.set_size(n,1); - wi.set_size(n,1); - - if (jobvl == 'V') - vl.set_size(n,n); - else - vl.set_size(NR4?NR4:1, NC4?NC4:1); - - if (jobvr == 'V') - vr.set_size(n,n); - else - vr.set_size(NR5?NR5:1, NC5?NC5:1); - - - // figure out how big the workspace needs to be. - T work_size = 1; - int info = binding::geev(jobvl, jobvr, n, &a(0,0), - a.nr(), &wr(0,0), &wi(0,0), &vl(0,0), - vl.nr(), &vr(0,0), vr.nr(), &work_size, - -1); - - if (info != 0) - return info; - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - - // compute the actual decomposition - info = binding::geev(jobvl, jobvr, n, &a(0,0), - a.nr(), &wr(0,0), &wi(0,0), &vl(0,0), - vl.nr(), &vr(0,0), vr.nr(), &work(0,0), - work.size()); - - return info; - } - - // ------------------------------------------------------------------------------------ - - } - -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_LAPACk_GEEV_Hh_ - - diff --git a/ml/dlib/dlib/matrix/lapack/geqrf.h b/ml/dlib/dlib/matrix/lapack/geqrf.h deleted file mode 100644 index c1f8fc050..000000000 --- a/ml/dlib/dlib/matrix/lapack/geqrf.h +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_LAPACk_GEQRF_Hh_ -#define DLIB_LAPACk_GEQRF_Hh_ - -#include "fortran_id.h" -#include "../matrix.h" - -namespace dlib -{ - namespace lapack - { - namespace binding - { - extern "C" - { - void DLIB_FORTRAN_ID(dgeqrf) (integer *m, integer *n, double *a, integer * - lda, double *tau, double *work, integer *lwork, - integer *info); - - void DLIB_FORTRAN_ID(sgeqrf) (integer *m, integer *n, float *a, integer * - lda, float *tau, float *work, integer *lwork, - integer *info); - } - - inline int geqrf (integer m, integer n, double *a, integer lda, - double *tau, double *work, integer lwork) - { - integer info = 0; - DLIB_FORTRAN_ID(dgeqrf)(&m, &n, a, &lda, - tau, work, &lwork, &info); - return info; - } - - inline int geqrf (integer m, integer n, float *a, integer lda, - float *tau, float *work, integer lwork) - { - integer info = 0; - DLIB_FORTRAN_ID(sgeqrf)(&m, &n, a, &lda, - tau, work, &lwork, &info); - return info; - } - - - } - - // ------------------------------------------------------------------------------------ - -/* -- LAPACK routine (version 3.1) -- */ -/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ -/* November 2006 */ - -/* .. Scalar Arguments .. */ -/* .. */ -/* .. Array Arguments .. */ -/* .. */ - -/* Purpose */ -/* ======= */ - -/* DGEQRF computes a QR factorization of a real M-by-N matrix A: */ -/* A = Q * R. */ - -/* Arguments */ -/* ========= */ - -/* M (input) INTEGER */ -/* The number of rows of the matrix A. M >= 0. */ - -/* N (input) INTEGER */ -/* The number of columns of the matrix A. N >= 0. */ - -/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ -/* On entry, the M-by-N matrix A. */ -/* On exit, the elements on and above the diagonal of the array */ -/* contain the min(M,N)-by-N upper trapezoidal matrix R (R is */ -/* upper triangular if m >= n); the elements below the diagonal, */ -/* with the array TAU, represent the orthogonal matrix Q as a */ -/* product of min(m,n) elementary reflectors (see Further */ -/* Details). */ - -/* LDA (input) INTEGER */ -/* The leading dimension of the array A. LDA >= max(1,M). */ - -/* TAU (output) DOUBLE PRECISION array, dimension (min(M,N)) */ -/* The scalar factors of the elementary reflectors (see Further */ -/* Details). */ - -/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ -/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ - -/* LWORK (input) INTEGER */ -/* The dimension of the array WORK. LWORK >= max(1,N). */ -/* For optimum performance LWORK >= N*NB, where NB is */ -/* the optimal blocksize. */ - -/* If LWORK = -1, then a workspace query is assumed; the routine */ -/* only calculates the optimal size of the WORK array, returns */ -/* this value as the first entry of the WORK array, and no error */ -/* message related to LWORK is issued by XERBLA. */ - -/* INFO (output) INTEGER */ -/* = 0: successful exit */ -/* < 0: if INFO = -i, the i-th argument had an illegal value */ - -/* Further Details */ -/* =============== */ - -/* The matrix Q is represented as a product of elementary reflectors */ - -/* Q = H(1) H(2) . . . H(k), where k = min(m,n). */ - -/* Each H(i) has the form */ - -/* H(i) = I - tau * v * v' */ - -/* where tau is a real scalar, and v is a real vector with */ -/* v(1:i-1) = 0 and v(i) = 1; v(i+1:m) is stored on exit in A(i+1:m,i), */ -/* and tau in TAU(i). */ - - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, - long NC1, long NC2, - typename MM - > - int geqrf ( - matrix<T,NR1,NC1,MM,column_major_layout>& a, - matrix<T,NR2,NC2,MM,column_major_layout>& tau - ) - { - matrix<T,0,1,MM,column_major_layout> work; - - tau.set_size(std::min(a.nr(), a.nc()), 1); - - // figure out how big the workspace needs to be. - T work_size = 1; - int info = binding::geqrf(a.nr(), a.nc(), &a(0,0), a.nr(), - &tau(0,0), &work_size, -1); - - if (info != 0) - return info; - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - - // compute the actual decomposition - info = binding::geqrf(a.nr(), a.nc(), &a(0,0), a.nr(), - &tau(0,0), &work(0,0), work.size()); - - return info; - } - - // ------------------------------------------------------------------------------------ - - } - -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_LAPACk_GEQRF_Hh_ - - - diff --git a/ml/dlib/dlib/matrix/lapack/gesdd.h b/ml/dlib/dlib/matrix/lapack/gesdd.h deleted file mode 100644 index e6b4d26e1..000000000 --- a/ml/dlib/dlib/matrix/lapack/gesdd.h +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_LAPACk_SDD_Hh_ -#define DLIB_LAPACk_SDD_Hh_ - -#include "fortran_id.h" -#include "../matrix.h" - -namespace dlib -{ - namespace lapack - { - namespace binding - { - extern "C" - { - void DLIB_FORTRAN_ID(dgesdd) (char const* jobz, - const integer* m, const integer* n, double* a, const integer* lda, - double* s, double* u, const integer* ldu, - double* vt, const integer* ldvt, - double* work, const integer* lwork, integer* iwork, integer* info); - - void DLIB_FORTRAN_ID(sgesdd) (char const* jobz, - const integer* m, const integer* n, float* a, const integer* lda, - float* s, float* u, const integer* ldu, - float* vt, const integer* ldvt, - float* work, const integer* lwork, integer* iwork, integer* info); - - } - - inline integer gesdd (const char jobz, - const integer m, const integer n, double* a, const integer lda, - double* s, double* u, const integer ldu, - double* vt, const integer ldvt, - double* work, const integer lwork, integer* iwork) - { - integer info = 0; - DLIB_FORTRAN_ID(dgesdd)(&jobz, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, iwork, &info); - return info; - } - - inline integer gesdd (const char jobz, - const integer m, const integer n, float* a, const integer lda, - float* s, float* u, const integer ldu, - float* vt, const integer ldvt, - float* work, const integer lwork, integer* iwork) - { - integer info = 0; - DLIB_FORTRAN_ID(sgesdd)(&jobz, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, iwork, &info); - return info; - } - } - - // ------------------------------------------------------------------------------------ - -/* -- LAPACK driver routine (version 3.1) -- */ -/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ -/* November 2006 */ - -/* .. Scalar Arguments .. */ -/* .. */ -/* .. Array Arguments .. */ -/* .. */ - -/* Purpose */ -/* ======= */ - -/* DGESDD computes the singular value decomposition (SVD) of a real */ -/* M-by-N matrix A, optionally computing the left and right singular */ -/* vectors. If singular vectors are desired, it uses a */ -/* divide-and-conquer algorithm. */ - -/* The SVD is written */ - -/* A = U * SIGMA * transpose(V) */ - -/* where SIGMA is an M-by-N matrix which is zero except for its */ -/* min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and */ -/* V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA */ -/* are the singular values of A; they are real and non-negative, and */ -/* are returned in descending order. The first min(m,n) columns of */ -/* U and V are the left and right singular vectors of A. */ - -/* Note that the routine returns VT = V**T, not V. */ - -/* The divide and conquer algorithm makes very mild assumptions about */ -/* floating point arithmetic. It will work on machines with a guard */ -/* digit in add/subtract, or on those binary machines without guard */ -/* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or */ -/* Cray-2. It could conceivably fail on hexadecimal or decimal machines */ -/* without guard digits, but we know of none. */ - -/* Arguments */ -/* ========= */ - -/* JOBZ (input) CHARACTER*1 */ -/* Specifies options for computing all or part of the matrix U: */ -/* = 'A': all M columns of U and all N rows of V**T are */ -/* returned in the arrays U and VT; */ -/* = 'S': the first min(M,N) columns of U and the first */ -/* min(M,N) rows of V**T are returned in the arrays U */ -/* and VT; */ -/* = 'O': If M >= N, the first N columns of U are overwritten */ -/* on the array A and all rows of V**T are returned in */ -/* the array VT; */ -/* otherwise, all columns of U are returned in the */ -/* array U and the first M rows of V**T are overwritten */ -/* in the array A; */ -/* = 'N': no columns of U or rows of V**T are computed. */ - -/* M (input) INTEGER */ -/* The number of rows of the input matrix A. M >= 0. */ - -/* N (input) INTEGER */ -/* The number of columns of the input matrix A. N >= 0. */ - -/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ -/* On entry, the M-by-N matrix A. */ -/* On exit, */ -/* if JOBZ = 'O', A is overwritten with the first N columns */ -/* of U (the left singular vectors, stored */ -/* columnwise) if M >= N; */ -/* A is overwritten with the first M rows */ -/* of V**T (the right singular vectors, stored */ -/* rowwise) otherwise. */ -/* if JOBZ .ne. 'O', the contents of A are destroyed. */ - -/* LDA (input) INTEGER */ -/* The leading dimension of the array A. LDA >= max(1,M). */ - -/* S (output) DOUBLE PRECISION array, dimension (min(M,N)) */ -/* The singular values of A, sorted so that S(i) >= S(i+1). */ - -/* U (output) DOUBLE PRECISION array, dimension (LDU,UCOL) */ -/* UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N; */ -/* UCOL = min(M,N) if JOBZ = 'S'. */ -/* If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M */ -/* orthogonal matrix U; */ -/* if JOBZ = 'S', U contains the first min(M,N) columns of U */ -/* (the left singular vectors, stored columnwise); */ -/* if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced. */ - -/* LDU (input) INTEGER */ -/* The leading dimension of the array U. LDU >= 1; if */ -/* JOBZ = 'S' or 'A' or JOBZ = 'O' and M < N, LDU >= M. */ - -/* VT (output) DOUBLE PRECISION array, dimension (LDVT,N) */ -/* If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the */ -/* N-by-N orthogonal matrix V**T; */ -/* if JOBZ = 'S', VT contains the first min(M,N) rows of */ -/* V**T (the right singular vectors, stored rowwise); */ -/* if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced. */ - -/* LDVT (input) INTEGER */ -/* The leading dimension of the array VT. LDVT >= 1; if */ -/* JOBZ = 'A' or JOBZ = 'O' and M >= N, LDVT >= N; */ -/* if JOBZ = 'S', LDVT >= min(M,N). */ - -/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ -/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK; */ - -/* LWORK (input) INTEGER */ -/* The dimension of the array WORK. LWORK >= 1. */ -/* If JOBZ = 'N', */ -/* LWORK >= 3*min(M,N) + max(max(M,N),7*min(M,N)). */ -/* If JOBZ = 'O', */ -/* LWORK >= 3*min(M,N)*min(M,N) + */ -/* max(max(M,N),5*min(M,N)*min(M,N)+4*min(M,N)). */ -/* If JOBZ = 'S' or 'A' */ -/* LWORK >= 3*min(M,N)*min(M,N) + */ -/* max(max(M,N),4*min(M,N)*min(M,N)+4*min(M,N)). */ -/* For good performance, LWORK should generally be larger. */ -/* If LWORK = -1 but other input arguments are legal, WORK(1) */ -/* returns the optimal LWORK. */ - -/* IWORK (workspace) INTEGER array, dimension (8*min(M,N)) */ - -/* INFO (output) INTEGER */ -/* = 0: successful exit. */ -/* < 0: if INFO = -i, the i-th argument had an illegal value. */ -/* > 0: DBDSDC did not converge, updating process failed. */ - -/* Further Details */ -/* =============== */ - -/* Based on contributions by */ -/* Ming Gu and Huan Ren, Computer Science Division, University of */ -/* California at Berkeley, USA */ - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, long NR3, long NR4, - long NC1, long NC2, long NC3, long NC4, - typename MM - > - int gesdd ( - const char jobz, - matrix<T,NR1,NC1,MM,column_major_layout>& a, - matrix<T,NR2,NC2,MM,column_major_layout>& s, - matrix<T,NR3,NC3,MM,column_major_layout>& u, - matrix<T,NR4,NC4,MM,column_major_layout>& vt - ) - { - matrix<T,0,1,MM,column_major_layout> work; - matrix<integer,0,1,MM,column_major_layout> iwork; - - const long m = a.nr(); - const long n = a.nc(); - s.set_size(std::min(m,n), 1); - - // make sure the iwork memory block is big enough - if (iwork.size() < 8*std::min(m,n)) - iwork.set_size(8*std::min(m,n), 1); - - if (jobz == 'A') - { - u.set_size(m,m); - vt.set_size(n,n); - } - else if (jobz == 'S') - { - u.set_size(m, std::min(m,n)); - vt.set_size(std::min(m,n), n); - } - else if (jobz == 'O') - { - DLIB_CASSERT(false, "jobz == 'O' not supported"); - } - else - { - u.set_size(NR3?NR3:1, NC3?NC3:1); - vt.set_size(NR4?NR4:1, NC4?NC4:1); - } - - // figure out how big the workspace needs to be. - T work_size = 1; - int info = binding::gesdd(jobz, a.nr(), a.nc(), &a(0,0), a.nr(), - &s(0,0), &u(0,0), u.nr(), &vt(0,0), vt.nr(), - &work_size, -1, &iwork(0,0)); - - if (info != 0) - return info; - - // There is a bug in an older version of LAPACK in Debian etch - // that causes the gesdd to return the wrong value for work_size - // when jobz == 'N'. So verify the value of work_size. - if (jobz == 'N') - { - using std::min; - using std::max; - const T min_work_size = 3*min(m,n) + max(max(m,n),7*min(m,n)); - if (work_size < min_work_size) - work_size = min_work_size; - } - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - - // compute the actual SVD - info = binding::gesdd(jobz, a.nr(), a.nc(), &a(0,0), a.nr(), - &s(0,0), &u(0,0), u.nr(), &vt(0,0), vt.nr(), - &work(0,0), work.size(), &iwork(0,0)); - - return info; - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, long NR3, long NR4, - long NC1, long NC2, long NC3, long NC4, - typename MM - > - int gesdd ( - const char jobz, - matrix<T,NR1,NC1,MM,row_major_layout>& a, - matrix<T,NR2,NC2,MM,row_major_layout>& s, - matrix<T,NR3,NC3,MM,row_major_layout>& u_, - matrix<T,NR4,NC4,MM,row_major_layout>& vt_ - ) - { - matrix<T,0,1,MM,row_major_layout> work; - matrix<integer,0,1,MM,row_major_layout> iwork; - - // Row major order matrices are transposed from LAPACK's point of view. - matrix<T,NR4,NC4,MM,row_major_layout>& u = vt_; - matrix<T,NR3,NC3,MM,row_major_layout>& vt = u_; - - - const long m = a.nc(); - const long n = a.nr(); - s.set_size(std::min(m,n), 1); - - // make sure the iwork memory block is big enough - if (iwork.size() < 8*std::min(m,n)) - iwork.set_size(8*std::min(m,n), 1); - - if (jobz == 'A') - { - u.set_size(m,m); - vt.set_size(n,n); - } - else if (jobz == 'S') - { - u.set_size(std::min(m,n), m); - vt.set_size(n, std::min(m,n)); - } - else if (jobz == 'O') - { - DLIB_CASSERT(false, "jobz == 'O' not supported"); - } - else - { - u.set_size(NR4?NR4:1, NC4?NC4:1); - vt.set_size(NR3?NR3:1, NC3?NC3:1); - } - - // figure out how big the workspace needs to be. - T work_size = 1; - int info = binding::gesdd(jobz, m, n, &a(0,0), a.nc(), - &s(0,0), &u(0,0), u.nc(), &vt(0,0), vt.nc(), - &work_size, -1, &iwork(0,0)); - - if (info != 0) - return info; - - // There is a bug in an older version of LAPACK in Debian etch - // that causes the gesdd to return the wrong value for work_size - // when jobz == 'N'. So verify the value of work_size. - if (jobz == 'N') - { - using std::min; - using std::max; - const T min_work_size = 3*min(m,n) + max(max(m,n),7*min(m,n)); - if (work_size < min_work_size) - work_size = min_work_size; - } - - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - - // compute the actual SVD - info = binding::gesdd(jobz, m, n, &a(0,0), a.nc(), - &s(0,0), &u(0,0), u.nc(), &vt(0,0), vt.nc(), - &work(0,0), work.size(), &iwork(0,0)); - - return info; - } - - // ------------------------------------------------------------------------------------ - - } - -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_LAPACk_SDD_Hh_ - - diff --git a/ml/dlib/dlib/matrix/lapack/gesvd.h b/ml/dlib/dlib/matrix/lapack/gesvd.h deleted file mode 100644 index e00654db6..000000000 --- a/ml/dlib/dlib/matrix/lapack/gesvd.h +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_LAPACk_SVD_Hh_ -#define DLIB_LAPACk_SVD_Hh_ - -#include "fortran_id.h" -#include "../matrix.h" - -namespace dlib -{ - namespace lapack - { - namespace binding - { - extern "C" - { - void DLIB_FORTRAN_ID(dgesvd) (const char* jobu, const char* jobvt, - const integer* m, const integer* n, double* a, const integer* lda, - double* s, double* u, const integer* ldu, - double* vt, const integer* ldvt, - double* work, const integer* lwork, integer* info); - - void DLIB_FORTRAN_ID(sgesvd) (const char* jobu, const char* jobvt, - const integer* m, const integer* n, float* a, const integer* lda, - float* s, float* u, const integer* ldu, - float* vt, const integer* ldvt, - float* work, const integer* lwork, integer* info); - - } - - inline integer gesvd (const char jobu, const char jobvt, - const integer m, const integer n, double* a, const integer lda, - double* s, double* u, const integer ldu, - double* vt, const integer ldvt, - double* work, const integer lwork) - { - integer info = 0; - DLIB_FORTRAN_ID(dgesvd)(&jobu, &jobvt, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, &info); - return info; - } - - inline integer gesvd (const char jobu, const char jobvt, - const integer m, const integer n, float* a, const integer lda, - float* s, float* u, const integer ldu, - float* vt, const integer ldvt, - float* work, const integer lwork) - { - integer info = 0; - DLIB_FORTRAN_ID(sgesvd)(&jobu, &jobvt, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, &info); - return info; - } - - } - - // ------------------------------------------------------------------------------------ - -/* -- LAPACK driver routine (version 3.1) -- */ -/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ -/* November 2006 */ - -/* .. Scalar Arguments .. */ -/* .. */ -/* .. Array Arguments .. */ -/* .. */ - -/* Purpose */ -/* ======= */ - -/* DGESVD computes the singular value decomposition (SVD) of a real */ -/* M-by-N matrix A, optionally computing the left and/or right singular */ -/* vectors. The SVD is written */ - -/* A = U * SIGMA * transpose(V) */ - -/* where SIGMA is an M-by-N matrix which is zero except for its */ -/* min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and */ -/* V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA */ -/* are the singular values of A; they are real and non-negative, and */ -/* are returned in descending order. The first min(m,n) columns of */ -/* U and V are the left and right singular vectors of A. */ - -/* Note that the routine returns V**T, not V. */ - -/* Arguments */ -/* ========= */ - -/* JOBU (input) CHARACTER*1 */ -/* Specifies options for computing all or part of the matrix U: */ -/* = 'A': all M columns of U are returned in array U: */ -/* = 'S': the first min(m,n) columns of U (the left singular */ -/* vectors) are returned in the array U; */ -/* = 'O': the first min(m,n) columns of U (the left singular */ -/* vectors) are overwritten on the array A; */ -/* = 'N': no columns of U (no left singular vectors) are */ -/* computed. */ - -/* JOBVT (input) CHARACTER*1 */ -/* Specifies options for computing all or part of the matrix */ -/* V**T: */ -/* = 'A': all N rows of V**T are returned in the array VT; */ -/* = 'S': the first min(m,n) rows of V**T (the right singular */ -/* vectors) are returned in the array VT; */ -/* = 'O': the first min(m,n) rows of V**T (the right singular */ -/* vectors) are overwritten on the array A; */ -/* = 'N': no rows of V**T (no right singular vectors) are */ -/* computed. */ - -/* JOBVT and JOBU cannot both be 'O'. */ - -/* M (input) INTEGER */ -/* The number of rows of the input matrix A. M >= 0. */ - -/* N (input) INTEGER */ -/* The number of columns of the input matrix A. N >= 0. */ - -/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ -/* On entry, the M-by-N matrix A. */ -/* On exit, */ -/* if JOBU = 'O', A is overwritten with the first min(m,n) */ -/* columns of U (the left singular vectors, */ -/* stored columnwise); */ -/* if JOBVT = 'O', A is overwritten with the first min(m,n) */ -/* rows of V**T (the right singular vectors, */ -/* stored rowwise); */ -/* if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A */ -/* are destroyed. */ - -/* LDA (input) INTEGER */ -/* The leading dimension of the array A. LDA >= max(1,M). */ - -/* S (output) DOUBLE PRECISION array, dimension (min(M,N)) */ -/* The singular values of A, sorted so that S(i) >= S(i+1). */ - -/* U (output) DOUBLE PRECISION array, dimension (LDU,UCOL) */ -/* (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'. */ -/* If JOBU = 'A', U contains the M-by-M orthogonal matrix U; */ -/* if JOBU = 'S', U contains the first min(m,n) columns of U */ -/* (the left singular vectors, stored columnwise); */ -/* if JOBU = 'N' or 'O', U is not referenced. */ - -/* LDU (input) INTEGER */ -/* The leading dimension of the array U. LDU >= 1; if */ -/* JOBU = 'S' or 'A', LDU >= M. */ - -/* VT (output) DOUBLE PRECISION array, dimension (LDVT,N) */ -/* If JOBVT = 'A', VT contains the N-by-N orthogonal matrix */ -/* V**T; */ -/* if JOBVT = 'S', VT contains the first min(m,n) rows of */ -/* V**T (the right singular vectors, stored rowwise); */ -/* if JOBVT = 'N' or 'O', VT is not referenced. */ - -/* LDVT (input) INTEGER */ -/* The leading dimension of the array VT. LDVT >= 1; if */ -/* JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N). */ - -/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ -/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK; */ -/* if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged */ -/* superdiagonal elements of an upper bidiagonal matrix B */ -/* whose diagonal is in S (not necessarily sorted). B */ -/* satisfies A = U * B * VT, so it has the same singular values */ -/* as A, and singular vectors related by U and VT. */ - -/* LWORK (input) INTEGER */ -/* The dimension of the array WORK. */ -/* LWORK >= MAX(1,3*MIN(M,N)+MAX(M,N),5*MIN(M,N)). */ -/* For good performance, LWORK should generally be larger. */ - -/* If LWORK = -1, then a workspace query is assumed; the routine */ -/* only calculates the optimal size of the WORK array, returns */ -/* this value as the first entry of the WORK array, and no error */ -/* message related to LWORK is issued by XERBLA. */ - -/* INFO (output) INTEGER */ -/* = 0: successful exit. */ -/* < 0: if INFO = -i, the i-th argument had an illegal value. */ -/* > 0: if DBDSQR did not converge, INFO specifies how many */ -/* superdiagonals of an intermediate bidiagonal form B */ -/* did not converge to zero. See the description of WORK */ -/* above for details. */ - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, long NR3, long NR4, - long NC1, long NC2, long NC3, long NC4, - typename MM - > - int gesvd ( - const char jobu, - const char jobvt, - matrix<T,NR1,NC1,MM,column_major_layout>& a, - matrix<T,NR2,NC2,MM,column_major_layout>& s, - matrix<T,NR3,NC3,MM,column_major_layout>& u, - matrix<T,NR4,NC4,MM,column_major_layout>& vt - ) - { - matrix<T,0,1,MM,column_major_layout> work; - - const long m = a.nr(); - const long n = a.nc(); - s.set_size(std::min(m,n), 1); - - if (jobu == 'A') - u.set_size(m,m); - else if (jobu == 'S') - u.set_size(m, std::min(m,n)); - else - u.set_size(NR3?NR3:1, NC3?NC3:1); - - if (jobvt == 'A') - vt.set_size(n,n); - else if (jobvt == 'S') - vt.set_size(std::min(m,n), n); - else - vt.set_size(NR4?NR4:1, NC4?NC4:1); - - - if (jobu == 'O' || jobvt == 'O') - { - DLIB_CASSERT(false, "job == 'O' not supported"); - } - - - // figure out how big the workspace needs to be. - T work_size = 1; - int info = binding::gesvd(jobu, jobvt, a.nr(), a.nc(), &a(0,0), a.nr(), - &s(0,0), &u(0,0), u.nr(), &vt(0,0), vt.nr(), - &work_size, -1); - - if (info != 0) - return info; - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - - // compute the actual SVD - info = binding::gesvd(jobu, jobvt, a.nr(), a.nc(), &a(0,0), a.nr(), - &s(0,0), &u(0,0), u.nr(), &vt(0,0), vt.nr(), - &work(0,0), work.size()); - - return info; - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, long NR3, long NR4, - long NC1, long NC2, long NC3, long NC4, - typename MM - > - int gesvd ( - char jobu, - char jobvt, - matrix<T,NR1,NC1,MM,row_major_layout>& a, - matrix<T,NR2,NC2,MM,row_major_layout>& s, - matrix<T,NR3,NC3,MM,row_major_layout>& u_, - matrix<T,NR4,NC4,MM,row_major_layout>& vt_ - ) - { - matrix<T,0,1,MM,row_major_layout> work; - - // Row major order matrices are transposed from LAPACK's point of view. - matrix<T,NR4,NC4,MM,row_major_layout>& u = vt_; - matrix<T,NR3,NC3,MM,row_major_layout>& vt = u_; - std::swap(jobu, jobvt); - - const long m = a.nc(); - const long n = a.nr(); - s.set_size(std::min(m,n), 1); - - if (jobu == 'A') - u.set_size(m,m); - else if (jobu == 'S') - u.set_size(std::min(m,n), m); - else - u.set_size(NR4?NR4:1, NC4?NC4:1); - - if (jobvt == 'A') - vt.set_size(n,n); - else if (jobvt == 'S') - vt.set_size(n, std::min(m,n)); - else - vt.set_size(NR3?NR3:1, NC3?NC3:1); - - if (jobu == 'O' || jobvt == 'O') - { - DLIB_CASSERT(false, "job == 'O' not supported"); - } - - - // figure out how big the workspace needs to be. - T work_size = 1; - int info = binding::gesvd(jobu, jobvt, m, n, &a(0,0), a.nc(), - &s(0,0), &u(0,0), u.nc(), &vt(0,0), vt.nc(), - &work_size, -1); - - if (info != 0) - return info; - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - - // compute the actual SVD - info = binding::gesvd(jobu, jobvt, m, n, &a(0,0), a.nc(), - &s(0,0), &u(0,0), u.nc(), &vt(0,0), vt.nc(), - &work(0,0), work.size()); - - return info; - } - - // ------------------------------------------------------------------------------------ - - } - -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_LAPACk_SVD_Hh_ - diff --git a/ml/dlib/dlib/matrix/lapack/getrf.h b/ml/dlib/dlib/matrix/lapack/getrf.h deleted file mode 100644 index a1f0b139d..000000000 --- a/ml/dlib/dlib/matrix/lapack/getrf.h +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_LAPACk_GETRF_Hh_ -#define DLIB_LAPACk_GETRF_Hh_ - -#include "fortran_id.h" -#include "../matrix.h" - -namespace dlib -{ - namespace lapack - { - namespace binding - { - extern "C" - { - void DLIB_FORTRAN_ID(dgetrf) (integer* m, integer *n, double *a, - integer* lda, integer *ipiv, integer *info); - - void DLIB_FORTRAN_ID(sgetrf) (integer* m, integer *n, float *a, - integer* lda, integer *ipiv, integer *info); - - } - - inline int getrf (integer m, integer n, double *a, - integer lda, integer *ipiv) - { - integer info = 0; - DLIB_FORTRAN_ID(dgetrf)(&m, &n, a, &lda, ipiv, &info); - return info; - } - - inline int getrf (integer m, integer n, float *a, - integer lda, integer *ipiv) - { - integer info = 0; - DLIB_FORTRAN_ID(sgetrf)(&m, &n, a, &lda, ipiv, &info); - return info; - } - - - } - - // ------------------------------------------------------------------------------------ - - -/* -- LAPACK routine (version 3.1) -- */ -/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ -/* November 2006 */ - -/* .. Scalar Arguments .. */ -/* .. */ -/* .. Array Arguments .. */ -/* .. */ - -/* Purpose */ -/* ======= */ - -/* DGETRF computes an LU factorization of a general M-by-N matrix A */ -/* using partial pivoting with row interchanges. */ - -/* The factorization has the form */ -/* A = P * L * U */ -/* where P is a permutation matrix, L is lower triangular with unit */ -/* diagonal elements (lower trapezoidal if m > n), and U is upper */ -/* triangular (upper trapezoidal if m < n). */ - -/* This is the right-looking Level 3 BLAS version of the algorithm. */ - -/* Arguments */ -/* ========= */ - -/* M (input) INTEGER */ -/* The number of rows of the matrix A. M >= 0. */ - -/* N (input) INTEGER */ -/* The number of columns of the matrix A. N >= 0. */ - -/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ -/* On entry, the M-by-N matrix to be factored. */ -/* On exit, the factors L and U from the factorization */ -/* A = P*L*U; the unit diagonal elements of L are not stored. */ - -/* LDA (input) INTEGER */ -/* The leading dimension of the array A. LDA >= max(1,M). */ - -/* IPIV (output) INTEGER array, dimension (min(M,N)) */ -/* The pivot indices; for 1 <= i <= min(M,N), row i of the */ -/* matrix was interchanged with row IPIV(i). */ - -/* INFO (output) INTEGER */ -/* = 0: successful exit */ -/* < 0: if INFO = -i, the i-th argument had an illegal value */ -/* > 0: if INFO = i, U(i,i) is exactly zero. The factorization */ -/* has been completed, but the factor U is exactly */ -/* singular, and division by zero will occur if it is used */ -/* to solve a system of equations. */ - - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, - long NC1, long NC2, - typename MM, - typename layout - > - int getrf ( - matrix<T,NR1,NC1,MM,column_major_layout>& a, - matrix<integer,NR2,NC2,MM,layout>& ipiv - ) - { - const long m = a.nr(); - const long n = a.nc(); - - ipiv.set_size(std::min(m,n), 1); - - // compute the actual decomposition - return binding::getrf(m, n, &a(0,0), a.nr(), &ipiv(0,0)); - } - - // ------------------------------------------------------------------------------------ - - } - -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_LAPACk_GETRF_Hh_ - diff --git a/ml/dlib/dlib/matrix/lapack/ormqr.h b/ml/dlib/dlib/matrix/lapack/ormqr.h deleted file mode 100644 index ab66ff4d2..000000000 --- a/ml/dlib/dlib/matrix/lapack/ormqr.h +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_LAPACk_ORMQR_Hh_ -#define DLIB_LAPACk_ORMQR_Hh_ - -#include "fortran_id.h" -#include "../matrix.h" - -namespace dlib -{ - namespace lapack - { - namespace binding - { - extern "C" - { - void DLIB_FORTRAN_ID(dormqr) (char *side, char *trans, integer *m, integer *n, - integer *k, const double *a, integer *lda, const double *tau, - double * c_, integer *ldc, double *work, integer *lwork, - integer *info); - - void DLIB_FORTRAN_ID(sormqr) (char *side, char *trans, integer *m, integer *n, - integer *k, const float *a, integer *lda, const float *tau, - float * c_, integer *ldc, float *work, integer *lwork, - integer *info); - - } - - inline int ormqr (char side, char trans, integer m, integer n, - integer k, const double *a, integer lda, const double *tau, - double *c_, integer ldc, double *work, integer lwork) - { - integer info = 0; - DLIB_FORTRAN_ID(dormqr)(&side, &trans, &m, &n, - &k, a, &lda, tau, - c_, &ldc, work, &lwork, &info); - return info; - } - - inline int ormqr (char side, char trans, integer m, integer n, - integer k, const float *a, integer lda, const float *tau, - float *c_, integer ldc, float *work, integer lwork) - { - integer info = 0; - DLIB_FORTRAN_ID(sormqr)(&side, &trans, &m, &n, - &k, a, &lda, tau, - c_, &ldc, work, &lwork, &info); - return info; - } - - - - } - - // ------------------------------------------------------------------------------------ - -/* -- LAPACK routine (version 3.1) -- */ -/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ -/* November 2006 */ - -/* .. Scalar Arguments .. */ -/* .. */ -/* .. Array Arguments .. */ -/* .. */ - -/* Purpose */ -/* ======= */ - -/* DORMQR overwrites the general real M-by-N matrix C with */ - -/* SIDE = 'L' SIDE = 'R' */ -/* TRANS = 'N': Q * C C * Q */ -/* TRANS = 'T': Q**T * C C * Q**T */ - -/* where Q is a real orthogonal matrix defined as the product of k */ -/* elementary reflectors */ - -/* Q = H(1) H(2) . . . H(k) */ - -/* as returned by DGEQRF. Q is of order M if SIDE = 'L' and of order N */ -/* if SIDE = 'R'. */ - -/* Arguments */ -/* ========= */ - -/* SIDE (input) CHARACTER*1 */ -/* = 'L': apply Q or Q**T from the Left; */ -/* = 'R': apply Q or Q**T from the Right. */ - -/* TRANS (input) CHARACTER*1 */ -/* = 'N': No transpose, apply Q; */ -/* = 'T': Transpose, apply Q**T. */ - -/* M (input) INTEGER */ -/* The number of rows of the matrix C. M >= 0. */ - -/* N (input) INTEGER */ -/* The number of columns of the matrix C. N >= 0. */ - -/* K (input) INTEGER */ -/* The number of elementary reflectors whose product defines */ -/* the matrix Q. */ -/* If SIDE = 'L', M >= K >= 0; */ -/* if SIDE = 'R', N >= K >= 0. */ - -/* A (input) DOUBLE PRECISION array, dimension (LDA,K) */ -/* The i-th column must contain the vector which defines the */ -/* elementary reflector H(i), for i = 1,2,...,k, as returned by */ -/* DGEQRF in the first k columns of its array argument A. */ -/* A is modified by the routine but restored on exit. */ - -/* LDA (input) INTEGER */ -/* The leading dimension of the array A. */ -/* If SIDE = 'L', LDA >= max(1,M); */ -/* if SIDE = 'R', LDA >= max(1,N). */ - -/* TAU (input) DOUBLE PRECISION array, dimension (K) */ -/* TAU(i) must contain the scalar factor of the elementary */ -/* reflector H(i), as returned by DGEQRF. */ - -/* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) */ -/* On entry, the M-by-N matrix C. */ -/* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. */ - -/* LDC (input) INTEGER */ -/* The leading dimension of the array C. LDC >= max(1,M). */ - -/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ -/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ - -/* LWORK (input) INTEGER */ -/* The dimension of the array WORK. */ -/* If SIDE = 'L', LWORK >= max(1,N); */ -/* if SIDE = 'R', LWORK >= max(1,M). */ -/* For optimum performance LWORK >= N*NB if SIDE = 'L', and */ -/* LWORK >= M*NB if SIDE = 'R', where NB is the optimal */ -/* blocksize. */ - -/* If LWORK = -1, then a workspace query is assumed; the routine */ -/* only calculates the optimal size of the WORK array, returns */ -/* this value as the first entry of the WORK array, and no error */ -/* message related to LWORK is issued by XERBLA. */ - -/* INFO (output) INTEGER */ -/* = 0: successful exit */ -/* < 0: if INFO = -i, the i-th argument had an illegal value */ - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, long NR3, - long NC1, long NC2, long NC3, - typename MM, - typename C_LAYOUT - > - int ormqr ( - char side, - char trans, - const matrix<T,NR1,NC1,MM,column_major_layout>& a, - const matrix<T,NR2,NC2,MM,column_major_layout>& tau, - matrix<T,NR3,NC3,MM,C_LAYOUT>& c - ) - { - long m = c.nr(); - long n = c.nc(); - const long k = a.nc(); - long ldc; - if (is_same_type<C_LAYOUT,column_major_layout>::value) - { - ldc = c.nr(); - } - else - { - // Since lapack expects c to be in column major layout we have to - // do something to make this work. Since a row major layout matrix - // will look just like a transposed C we can just swap a few things around. - - ldc = c.nc(); - swap(m,n); - - if (side == 'L') - side = 'R'; - else - side = 'L'; - - if (trans == 'T') - trans = 'N'; - else - trans = 'T'; - } - - matrix<T,0,1,MM,column_major_layout> work; - - // figure out how big the workspace needs to be. - T work_size = 1; - int info = binding::ormqr(side, trans, m, n, - k, &a(0,0), a.nr(), &tau(0,0), - &c(0,0), ldc, &work_size, -1); - - if (info != 0) - return info; - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - - // compute the actual result - info = binding::ormqr(side, trans, m, n, - k, &a(0,0), a.nr(), &tau(0,0), - &c(0,0), ldc, &work(0,0), work.size()); - - return info; - } - - // ------------------------------------------------------------------------------------ - - } - -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_LAPACk_ORMQR_Hh_ - diff --git a/ml/dlib/dlib/matrix/lapack/pbtrf.h b/ml/dlib/dlib/matrix/lapack/pbtrf.h deleted file mode 100644 index 23bcc127b..000000000 --- a/ml/dlib/dlib/matrix/lapack/pbtrf.h +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_LAPACk_BDC_Hh_ -#define DLIB_LAPACk_BDC_Hh_ - -#include "fortran_id.h" -#include "../matrix.h" -namespace dlib -{ - namespace lapack - { - namespace binding - { - extern "C" - { - void DLIB_FORTRAN_ID(dpbtrf) (const char* uplo, const integer* n, const integer* kd, - double* ab, const integer* ldab, integer* info); - - void DLIB_FORTRAN_ID(spbtrf) (const char* uplo, const integer* n, const integer* kd, - float* ab, const integer* ldab, integer* info); - - } - - inline integer pbtrf (const char uplo, const integer n, const integer kd, - double* ab, const integer ldab) - { - integer info = 0; - DLIB_FORTRAN_ID(dpbtrf)(&uplo, &n, &kd, ab, &ldab, &info); - return info; - } - - inline integer pbtrf (const char uplo, const integer n, const integer kd, - float* ab, const integer ldab) - { - integer info = 0; - DLIB_FORTRAN_ID(spbtrf)(&uplo, &n, &kd, ab, &ldab, &info); - return info; - } - } - - // ------------------------------------------------------------------------------------ -/* DPBTRF(l) LAPACK routine (version 1.1) DPBTRF(l) - -NAME - DPBTRF - compute the Cholesky factorization of a real symmetric positive - definite band matrix A - -SYNOPSIS - - SUBROUTINE DPBTRF( UPLO, N, KD, AB, LDAB, INFO ) - - CHARACTER UPLO - - INTEGER INFO, KD, LDAB, N - - DOUBLE PRECISION AB( LDAB, * ) - -PURPOSE - DPBTRF computes the Cholesky factorization of a real symmetric positive - definite band matrix A. - - The factorization has the form - A = U**T * U, if UPLO = 'U', or - A = L * L**T, if UPLO = 'L', - where U is an upper triangular matrix and L is lower triangular. - -ARGUMENTS - - UPLO (input) CHARACTER*1 - = 'U': Upper triangle of A is stored; - = 'L': Lower triangle of A is stored. - - N (input) INTEGER - The order of the matrix A. N >= 0. - - KD (input) INTEGER - The number of superdiagonals of the matrix A if UPLO = 'U', or the - number of subdiagonals if UPLO = 'L'. KD >= 0. - - AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N) - On entry, the upper or lower triangle of the symmetric band matrix - A, stored in the first KD+1 rows of the array. The j-th column of - A is stored in the j-th column of the array AB as follows: if UPLO - = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j; if UPLO = - 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd). - - On exit, if INFO = 0, the triangular factor U or L from the Chole- - sky factorization A = U**T*U or A = L*L**T of the band matrix A, in - the same storage format as A. - - LDAB (input) INTEGER - The leading dimension of the array AB. LDAB >= KD+1. - - INFO (output) INTEGER - = 0: successful exit - < 0: if INFO = -i, the i-th argument had an illegal value - > 0: if INFO = i, the leading minor of order i is not positive - definite, and the factorization could not be completed. - -FURTHER DETAILS - The band storage scheme is illustrated by the following example, when N = - 6, KD = 2, and UPLO = 'U': - - On entry: On exit: - - * * a13 a24 a35 a46 * * u13 u24 u35 u46 - * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56 - a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66 - - Similarly, if UPLO = 'L' the format of A is as follows: - - On entry: On exit: - - a11 a22 a33 a44 a55 a66 l11 l22 l33 l44 l55 l66 - a21 a32 a43 a54 a65 * l21 l32 l43 l54 l65 * - a31 a42 a53 a64 * * l31 l42 l53 l64 * * - - Array elements marked * are not used by the routine. - - Contributed by - Peter Mayes and Giuseppe Radicati, IBM ECSEC, Rome, March 23, 1989 */ - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NC1, - typename MM - > - int pbtrf ( - char uplo, matrix<T,NR1,NC1,MM,column_major_layout>& ab - ) - { - const long ldab = ab.nr(); - const long n = ab.nc(); - const long kd = ldab - 1; // assume fully packed - - int info = binding::pbtrf(uplo, n, kd, &ab(0,0), ldab); - - return info; - } - - // ------------------------------------------------------------------------------------ - - - template < - typename T, - long NR1, long NC1, - typename MM - > - int pbtrf ( - char uplo, matrix<T,NR1,NC1,MM,row_major_layout>& ab - ) - { - const long ldab = ab.nr(); - const long n = ab.nc(); - const long kd = ldab - 1; // assume fully packed - - matrix<T,NC1,NR1,MM,row_major_layout> abt = trans(ab); - - int info = binding::pbtrf(uplo, n, kd, &abt(0,0), ldab); - - ab = trans(abt); - - return info; - } - - // ------------------------------------------------------------------------------------ - - } - -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_LAPACk_BDC_Hh_ - - diff --git a/ml/dlib/dlib/matrix/lapack/potrf.h b/ml/dlib/dlib/matrix/lapack/potrf.h deleted file mode 100644 index b9d6a7cc8..000000000 --- a/ml/dlib/dlib/matrix/lapack/potrf.h +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_LAPACk_POTRF_Hh_ -#define DLIB_LAPACk_POTRF_Hh_ - -#include "fortran_id.h" -#include "../matrix.h" - -namespace dlib -{ - namespace lapack - { - namespace binding - { - extern "C" - { - void DLIB_FORTRAN_ID(dpotrf) (char *uplo, integer *n, double *a, - integer* lda, integer *info); - - void DLIB_FORTRAN_ID(spotrf) (char *uplo, integer *n, float *a, - integer* lda, integer *info); - - } - - inline int potrf (char uplo, integer n, double *a, integer lda) - { - integer info = 0; - DLIB_FORTRAN_ID(dpotrf)(&uplo, &n, a, &lda, &info); - return info; - } - - inline int potrf (char uplo, integer n, float *a, integer lda) - { - integer info = 0; - DLIB_FORTRAN_ID(spotrf)(&uplo, &n, a, &lda, &info); - return info; - } - - } - - // ------------------------------------------------------------------------------------ - -/* -- LAPACK routine (version 3.1) -- */ -/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ -/* November 2006 */ - -/* .. Scalar Arguments .. */ -/* .. */ -/* .. Array Arguments .. */ -/* .. */ - -/* Purpose */ -/* ======= */ - -/* DPOTRF computes the Cholesky factorization of a real symmetric */ -/* positive definite matrix A. */ - -/* The factorization has the form */ -/* A = U**T * U, if UPLO = 'U', or */ -/* A = L * L**T, if UPLO = 'L', */ -/* where U is an upper triangular matrix and L is lower triangular. */ - -/* This is the block version of the algorithm, calling Level 3 BLAS. */ - -/* Arguments */ -/* ========= */ - -/* UPLO (input) CHARACTER*1 */ -/* = 'U': Upper triangle of A is stored; */ -/* = 'L': Lower triangle of A is stored. */ - -/* N (input) INTEGER */ -/* The order of the matrix A. N >= 0. */ - -/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ -/* On entry, the symmetric matrix A. If UPLO = 'U', the leading */ -/* N-by-N upper triangular part of A contains the upper */ -/* triangular part of the matrix A, and the strictly lower */ -/* triangular part of A is not referenced. If UPLO = 'L', the */ -/* leading N-by-N lower triangular part of A contains the lower */ -/* triangular part of the matrix A, and the strictly upper */ -/* triangular part of A is not referenced. */ - -/* On exit, if INFO = 0, the factor U or L from the Cholesky */ -/* factorization A = U**T*U or A = L*L**T. */ - -/* LDA (input) INTEGER */ -/* The leading dimension of the array A. LDA >= max(1,N). */ - -/* INFO (output) INTEGER */ -/* = 0: successful exit */ -/* < 0: if INFO = -i, the i-th argument had an illegal value */ -/* > 0: if INFO = i, the leading minor of order i is not */ -/* positive definite, and the factorization could not be */ -/* completed. */ - - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, - long NC1, - typename MM - > - int potrf ( - char uplo, - matrix<T,NR1,NC1,MM,column_major_layout>& a - ) - { - // compute the actual decomposition - int info = binding::potrf(uplo, a.nr(), &a(0,0), a.nr()); - - // If it fails part way though the factorization then make sure - // the end of the matrix gets properly initialized with zeros. - if (info > 0) - { - if (uplo == 'L') - set_colm(a, range(info-1, a.nc()-1)) = 0; - else - set_rowm(a, range(info-1, a.nr()-1)) = 0; - } - - return info; - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, - long NC1, - typename MM - > - int potrf ( - char uplo, - matrix<T,NR1,NC1,MM,row_major_layout>& a - ) - { - // since we are working on a row major order matrix we need to ask - // LAPACK for the transpose of whatever the user asked for. - - if (uplo == 'L') - uplo = 'U'; - else - uplo = 'L'; - - // compute the actual decomposition - int info = binding::potrf(uplo, a.nr(), &a(0,0), a.nr()); - - // If it fails part way though the factorization then make sure - // the end of the matrix gets properly initialized with zeros. - if (info > 0) - { - if (uplo == 'U') - set_colm(a, range(info-1, a.nc()-1)) = 0; - else - set_rowm(a, range(info-1, a.nr()-1)) = 0; - } - - return info; - } - - // ------------------------------------------------------------------------------------ - - } - -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_LAPACk_POTRF_Hh_ - - diff --git a/ml/dlib/dlib/matrix/lapack/syev.h b/ml/dlib/dlib/matrix/lapack/syev.h deleted file mode 100644 index 0c9fd251a..000000000 --- a/ml/dlib/dlib/matrix/lapack/syev.h +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_LAPACk_EV_Hh_ -#define DLIB_LAPACk_EV_Hh_ - -#include "fortran_id.h" -#include "../matrix.h" - -namespace dlib -{ - namespace lapack - { - namespace binding - { - extern "C" - { - void DLIB_FORTRAN_ID(dsyev) (char *jobz, char *uplo, integer *n, double *a, - integer *lda, double *w, double *work, integer *lwork, - integer *info); - - void DLIB_FORTRAN_ID(ssyev) (char *jobz, char *uplo, integer *n, float *a, - integer *lda, float *w, float *work, integer *lwork, - integer *info); - - } - - inline int syev (char jobz, char uplo, integer n, double *a, - integer lda, double *w, double *work, integer lwork) - { - integer info = 0; - DLIB_FORTRAN_ID(dsyev)(&jobz, &uplo, &n, a, - &lda, w, work, &lwork, &info); - return info; - } - - inline int syev (char jobz, char uplo, integer n, float *a, - integer lda, float *w, float *work, integer lwork) - { - integer info = 0; - DLIB_FORTRAN_ID(ssyev)(&jobz, &uplo, &n, a, - &lda, w, work, &lwork, &info); - return info; - } - - - } - - // ------------------------------------------------------------------------------------ - -/* -- LAPACK driver routine (version 3.1) -- */ -/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ -/* November 2006 */ - -/* .. Scalar Arguments .. */ -/* .. */ -/* .. Array Arguments .. */ -/* .. */ - -/* Purpose */ -/* ======= */ - -/* DSYEV computes all eigenvalues and, optionally, eigenvectors of a */ -/* real symmetric matrix A. */ - -/* Arguments */ -/* ========= */ - -/* JOBZ (input) CHARACTER*1 */ -/* = 'N': Compute eigenvalues only; */ -/* = 'V': Compute eigenvalues and eigenvectors. */ - -/* UPLO (input) CHARACTER*1 */ -/* = 'U': Upper triangle of A is stored; */ -/* = 'L': Lower triangle of A is stored. */ - -/* N (input) INTEGER */ -/* The order of the matrix A. N >= 0. */ - -/* A (input/output) DOUBLE PRECISION array, dimension (LDA, N) */ -/* On entry, the symmetric matrix A. If UPLO = 'U', the */ -/* leading N-by-N upper triangular part of A contains the */ -/* upper triangular part of the matrix A. If UPLO = 'L', */ -/* the leading N-by-N lower triangular part of A contains */ -/* the lower triangular part of the matrix A. */ -/* On exit, if JOBZ = 'V', then if INFO = 0, A contains the */ -/* orthonormal eigenvectors of the matrix A. */ -/* If JOBZ = 'N', then on exit the lower triangle (if UPLO='L') */ -/* or the upper triangle (if UPLO='U') of A, including the */ -/* diagonal, is destroyed. */ - -/* LDA (input) INTEGER */ -/* The leading dimension of the array A. LDA >= max(1,N). */ - -/* W (output) DOUBLE PRECISION array, dimension (N) */ -/* If INFO = 0, the eigenvalues in ascending order. */ - -/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ -/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ - -/* LWORK (input) INTEGER */ -/* The length of the array WORK. LWORK >= max(1,3*N-1). */ -/* For optimal efficiency, LWORK >= (NB+2)*N, */ -/* where NB is the blocksize for DSYTRD returned by ILAENV. */ - -/* If LWORK = -1, then a workspace query is assumed; the routine */ -/* only calculates the optimal size of the WORK array, returns */ -/* this value as the first entry of the WORK array, and no error */ -/* message related to LWORK is issued by XERBLA. */ - -/* INFO (output) INTEGER */ -/* = 0: successful exit */ -/* < 0: if INFO = -i, the i-th argument had an illegal value */ -/* > 0: if INFO = i, the algorithm failed to converge; i */ -/* off-diagonal elements of an intermediate tridiagonal */ -/* form did not converge to zero. */ - - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, - long NC1, long NC2, - typename MM - > - int syev ( - const char jobz, - const char uplo, - matrix<T,NR1,NC1,MM,column_major_layout>& a, - matrix<T,NR2,NC2,MM,column_major_layout>& w - ) - { - matrix<T,0,1,MM,column_major_layout> work; - - const long n = a.nr(); - - w.set_size(n,1); - - - // figure out how big the workspace needs to be. - T work_size = 1; - int info = binding::syev(jobz, uplo, n, &a(0,0), - a.nr(), &w(0,0), &work_size, -1); - - if (info != 0) - return info; - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - - // compute the actual decomposition - info = binding::syev(jobz, uplo, n, &a(0,0), - a.nr(), &w(0,0), &work(0,0), work.size()); - - return info; - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, - long NC1, long NC2, - typename MM - > - int syev ( - char jobz, - char uplo, - matrix<T,NR1,NC1,MM,row_major_layout>& a, - matrix<T,NR2,NC2,MM,row_major_layout>& w - ) - { - matrix<T,0,1,MM,row_major_layout> work; - - if (uplo == 'L') - uplo = 'U'; - else - uplo = 'L'; - - const long n = a.nr(); - - w.set_size(n,1); - - - // figure out how big the workspace needs to be. - T work_size = 1; - int info = binding::syev(jobz, uplo, n, &a(0,0), - a.nc(), &w(0,0), &work_size, -1); - - if (info != 0) - return info; - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - - // compute the actual decomposition - info = binding::syev(jobz, uplo, n, &a(0,0), - a.nc(), &w(0,0), &work(0,0), work.size()); - - - a = trans(a); - - return info; - } - - // ------------------------------------------------------------------------------------ - - } - -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_LAPACk_EV_Hh_ - - - - diff --git a/ml/dlib/dlib/matrix/lapack/syevr.h b/ml/dlib/dlib/matrix/lapack/syevr.h deleted file mode 100644 index 65190b3d8..000000000 --- a/ml/dlib/dlib/matrix/lapack/syevr.h +++ /dev/null @@ -1,445 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_LAPACk_EVR_Hh_ -#define DLIB_LAPACk_EVR_Hh_ - -#include "fortran_id.h" -#include "../matrix.h" - -namespace dlib -{ - namespace lapack - { - namespace binding - { - extern "C" - { - void DLIB_FORTRAN_ID(dsyevr) (char *jobz, char *range, char *uplo, integer *n, - double *a, integer *lda, double *vl, double *vu, integer * il, - integer *iu, double *abstol, integer *m, double *w, - double *z_, integer *ldz, integer *isuppz, double *work, - integer *lwork, integer *iwork, integer *liwork, integer *info); - - void DLIB_FORTRAN_ID(ssyevr) (char *jobz, char *range, char *uplo, integer *n, - float *a, integer *lda, float *vl, float *vu, integer * il, - integer *iu, float *abstol, integer *m, float *w, - float *z_, integer *ldz, integer *isuppz, float *work, - integer *lwork, integer *iwork, integer *liwork, integer *info); - } - - inline int syevr (char jobz, char range, char uplo, integer n, - double* a, integer lda, double vl, double vu, integer il, - integer iu, double abstol, integer *m, double *w, - double *z, integer ldz, integer *isuppz, double *work, - integer lwork, integer *iwork, integer liwork) - { - integer info = 0; - DLIB_FORTRAN_ID(dsyevr)(&jobz, &range, &uplo, &n, - a, &lda, &vl, &vu, &il, - &iu, &abstol, m, w, - z, &ldz, isuppz, work, - &lwork, iwork, &liwork, &info); - return info; - } - - inline int syevr (char jobz, char range, char uplo, integer n, - float* a, integer lda, float vl, float vu, integer il, - integer iu, float abstol, integer *m, float *w, - float *z, integer ldz, integer *isuppz, float *work, - integer lwork, integer *iwork, integer liwork) - { - integer info = 0; - DLIB_FORTRAN_ID(ssyevr)(&jobz, &range, &uplo, &n, - a, &lda, &vl, &vu, &il, - &iu, &abstol, m, w, - z, &ldz, isuppz, work, - &lwork, iwork, &liwork, &info); - return info; - } - - } - - // ------------------------------------------------------------------------------------ - - /* - -* -- LAPACK driver routine (version 3.1) -- -* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. -* November 2006 -* -* .. Scalar Arguments .. - CHARACTER JOBZ, RANGE, UPLO - INTEGER IL, INFO, IU, LDA, LDZ, LIWORK, LWORK, M, N - DOUBLE PRECISION ABSTOL, VL, VU -* .. -* .. Array Arguments .. - INTEGER ISUPPZ( * ), IWORK( * ) - DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ), Z( LDZ, * ) -* .. -* -* Purpose -* ======= -* -* DSYEVR computes selected eigenvalues and, optionally, eigenvectors -* of a real symmetric matrix A. Eigenvalues and eigenvectors can be -* selected by specifying either a range of values or a range of -* indices for the desired eigenvalues. -* -* DSYEVR first reduces the matrix A to tridiagonal form T with a call -* to DSYTRD. Then, whenever possible, DSYEVR calls DSTEMR to compute -* the eigenspectrum using Relatively Robust Representations. DSTEMR -* computes eigenvalues by the dqds algorithm, while orthogonal -* eigenvectors are computed from various "good" L D L^T representations -* (also known as Relatively Robust Representations). Gram-Schmidt -* orthogonalization is avoided as far as possible. More specifically, -* the various steps of the algorithm are as follows. -* -* For each unreduced block (submatrix) of T, -* (a) Compute T - sigma I = L D L^T, so that L and D -* define all the wanted eigenvalues to high relative accuracy. -* This means that small relative changes in the entries of D and L -* cause only small relative changes in the eigenvalues and -* eigenvectors. The standard (unfactored) representation of the -* tridiagonal matrix T does not have this property in general. -* (b) Compute the eigenvalues to suitable accuracy. -* If the eigenvectors are desired, the algorithm attains full -* accuracy of the computed eigenvalues only right before -* the corresponding vectors have to be computed, see steps c) and d). -* (c) For each cluster of close eigenvalues, select a new -* shift close to the cluster, find a new factorization, and refine -* the shifted eigenvalues to suitable accuracy. -* (d) For each eigenvalue with a large enough relative separation compute -* the corresponding eigenvector by forming a rank revealing twisted -* factorization. Go back to (c) for any clusters that remain. -* -* The desired accuracy of the output can be specified by the input -* parameter ABSTOL. -* -* For more details, see DSTEMR's documentation and: -* - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations -* to compute orthogonal eigenvectors of symmetric tridiagonal matrices," -* Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. -* - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and -* Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, -* 2004. Also LAPACK Working Note 154. -* - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric -* tridiagonal eigenvalue/eigenvector problem", -* Computer Science Division Technical Report No. UCB/CSD-97-971, -* UC Berkeley, May 1997. -* -* -* Note 1 : DSYEVR calls DSTEMR when the full spectrum is requested -* on machines which conform to the ieee-754 floating point standard. -* DSYEVR calls DSTEBZ and SSTEIN on non-ieee machines and -* when partial spectrum requests are made. -* -* Normal execution of DSTEMR may create NaNs and infinities and -* hence may abort due to a floating point exception in environments -* which do not handle NaNs and infinities in the ieee standard default -* manner. -* -* Arguments -* ========= -* -* JOBZ (input) CHARACTER*1 -* = 'N': Compute eigenvalues only; -* = 'V': Compute eigenvalues and eigenvectors. -* -* RANGE (input) CHARACTER*1 -* = 'A': all eigenvalues will be found. -* = 'V': all eigenvalues in the half-open interval (VL,VU] -* will be found. -* = 'I': the IL-th through IU-th eigenvalues will be found. -********** For RANGE = 'V' or 'I' and IU - IL < N - 1, DSTEBZ and -********** DSTEIN are called -* -* UPLO (input) CHARACTER*1 -* = 'U': Upper triangle of A is stored; -* = 'L': Lower triangle of A is stored. -* -* N (input) INTEGER -* The order of the matrix A. N >= 0. -* -* A (input/output) DOUBLE PRECISION array, dimension (LDA, N) -* On entry, the symmetric matrix A. If UPLO = 'U', the -* leading N-by-N upper triangular part of A contains the -* upper triangular part of the matrix A. If UPLO = 'L', -* the leading N-by-N lower triangular part of A contains -* the lower triangular part of the matrix A. -* On exit, the lower triangle (if UPLO='L') or the upper -* triangle (if UPLO='U') of A, including the diagonal, is -* destroyed. -* -* LDA (input) INTEGER -* The leading dimension of the array A. LDA >= max(1,N). -* -* VL (input) DOUBLE PRECISION -* VU (input) DOUBLE PRECISION -* If RANGE='V', the lower and upper bounds of the interval to -* be searched for eigenvalues. VL < VU. -* Not referenced if RANGE = 'A' or 'I'. -* -* IL (input) INTEGER -* IU (input) INTEGER -* If RANGE='I', the indices (in ascending order) of the -* smallest and largest eigenvalues to be returned. -* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0. -* Not referenced if RANGE = 'A' or 'V'. -* -* ABSTOL (input) DOUBLE PRECISION -* The absolute error tolerance for the eigenvalues. -* An approximate eigenvalue is accepted as converged -* when it is determined to lie in an interval [a,b] -* of width less than or equal to -* -* ABSTOL + EPS * max( |a|,|b| ) , -* -* where EPS is the machine precision. If ABSTOL is less than -* or equal to zero, then EPS*|T| will be used in its place, -* where |T| is the 1-norm of the tridiagonal matrix obtained -* by reducing A to tridiagonal form. -* -* See "Computing Small Singular Values of Bidiagonal Matrices -* with Guaranteed High Relative Accuracy," by Demmel and -* Kahan, LAPACK Working Note #3. -* -* If high relative accuracy is important, set ABSTOL to -* DLAMCH( 'Safe minimum' ). Doing so will guarantee that -* eigenvalues are computed to high relative accuracy when -* possible in future releases. The current code does not -* make any guarantees about high relative accuracy, but -* future releases will. See J. Barlow and J. Demmel, -* "Computing Accurate Eigensystems of Scaled Diagonally -* Dominant Matrices", LAPACK Working Note #7, for a discussion -* of which matrices define their eigenvalues to high relative -* accuracy. -* -* M (output) INTEGER -* The total number of eigenvalues found. 0 <= M <= N. -* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. -* -* W (output) DOUBLE PRECISION array, dimension (N) -* The first M elements contain the selected eigenvalues in -* ascending order. -* -* Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M)) -* If JOBZ = 'V', then if INFO = 0, the first M columns of Z -* contain the orthonormal eigenvectors of the matrix A -* corresponding to the selected eigenvalues, with the i-th -* column of Z holding the eigenvector associated with W(i). -* If JOBZ = 'N', then Z is not referenced. -* Note: the user must ensure that at least max(1,M) columns are -* supplied in the array Z; if RANGE = 'V', the exact value of M -* is not known in advance and an upper bound must be used. -* Supplying N columns is always safe. -* -* LDZ (input) INTEGER -* The leading dimension of the array Z. LDZ >= 1, and if -* JOBZ = 'V', LDZ >= max(1,N). -* -* ISUPPZ (output) INTEGER array, dimension ( 2*max(1,M) ) -* The support of the eigenvectors in Z, i.e., the indices -* indicating the nonzero elements in Z. The i-th eigenvector -* is nonzero only in elements ISUPPZ( 2*i-1 ) through -* ISUPPZ( 2*i ). -********** Implemented only for RANGE = 'A' or 'I' and IU - IL = N - 1 -* -* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) -* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. -* -* LWORK (input) INTEGER -* The dimension of the array WORK. LWORK >= max(1,26*N). -* For optimal efficiency, LWORK >= (NB+6)*N, -* where NB is the max of the blocksize for DSYTRD and DORMTR -* returned by ILAENV. -* -* If LWORK = -1, then a workspace query is assumed; the routine -* only calculates the optimal size of the WORK array, returns -* this value as the first entry of the WORK array, and no error -* message related to LWORK is issued by XERBLA. -* -* IWORK (workspace/output) INTEGER array, dimension (MAX(1,LIWORK)) -* On exit, if INFO = 0, IWORK(1) returns the optimal LWORK. -* -* LIWORK (input) INTEGER -* The dimension of the array IWORK. LIWORK >= max(1,10*N). -* -* If LIWORK = -1, then a workspace query is assumed; the -* routine only calculates the optimal size of the IWORK array, -* returns this value as the first entry of the IWORK array, and -* no error message related to LIWORK is issued by XERBLA. -* -* INFO (output) INTEGER -* = 0: successful exit -* < 0: if INFO = -i, the i-th argument had an illegal value -* > 0: Internal error -* -* Further Details -* =============== -* -* Based on contributions by -* Inderjit Dhillon, IBM Almaden, USA -* Osni Marques, LBNL/NERSC, USA -* Ken Stanley, Computer Science Division, University of -* California at Berkeley, USA -* Jason Riedy, Computer Science Division, University of -* California at Berkeley, USA -* -* ===================================================================== - - */ - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, long NR3, long NR4, - long NC1, long NC2, long NC3, long NC4, - typename MM - > - int syevr ( - const char jobz, - const char range, - const char uplo, - matrix<T,NR1,NC1,MM,column_major_layout>& a, - const double vl, - const double vu, - const integer il, - const integer iu, - const double abstol, - integer& num_eigenvalues_found, - matrix<T,NR2,NC2,MM,column_major_layout>& w, - matrix<T,NR3,NC3,MM,column_major_layout>& z, - matrix<integer,NR4,NC4,MM,column_major_layout>& isuppz - ) - { - matrix<T,0,1,MM,column_major_layout> work; - matrix<integer,0,1,MM,column_major_layout> iwork; - - const long n = a.nr(); - - w.set_size(n,1); - - isuppz.set_size(2*n, 1); - - if (jobz == 'V') - { - z.set_size(n,n); - } - else - { - z.set_size(NR3?NR3:1, NC3?NC3:1); - } - - // figure out how big the workspace needs to be. - T work_size = 1; - integer iwork_size = 1; - int info = binding::syevr(jobz, range, uplo, n, &a(0,0), - a.nr(), vl, vu, il, iu, abstol, &num_eigenvalues_found, - &w(0,0), &z(0,0), z.nr(), &isuppz(0,0), &work_size, -1, - &iwork_size, -1); - - if (info != 0) - return info; - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - if (iwork.size() < iwork_size) - iwork.set_size(iwork_size, 1); - - // compute the actual decomposition - info = binding::syevr(jobz, range, uplo, n, &a(0,0), - a.nr(), vl, vu, il, iu, abstol, &num_eigenvalues_found, - &w(0,0), &z(0,0), z.nr(), &isuppz(0,0), &work(0,0), work.size(), - &iwork(0,0), iwork.size()); - - - return info; - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, long NR3, long NR4, - long NC1, long NC2, long NC3, long NC4, - typename MM - > - int syevr ( - const char jobz, - const char range, - char uplo, - matrix<T,NR1,NC1,MM,row_major_layout>& a, - const double vl, - const double vu, - const integer il, - const integer iu, - const double abstol, - integer& num_eigenvalues_found, - matrix<T,NR2,NC2,MM,row_major_layout>& w, - matrix<T,NR3,NC3,MM,row_major_layout>& z, - matrix<integer,NR4,NC4,MM,row_major_layout>& isuppz - ) - { - matrix<T,0,1,MM,row_major_layout> work; - matrix<integer,0,1,MM,row_major_layout> iwork; - - if (uplo == 'L') - uplo = 'U'; - else - uplo = 'L'; - - const long n = a.nr(); - - w.set_size(n,1); - - isuppz.set_size(2*n, 1); - - if (jobz == 'V') - { - z.set_size(n,n); - } - else - { - z.set_size(NR3?NR3:1, NC3?NC3:1); - } - - // figure out how big the workspace needs to be. - T work_size = 1; - integer iwork_size = 1; - int info = binding::syevr(jobz, range, uplo, n, &a(0,0), - a.nc(), vl, vu, il, iu, abstol, &num_eigenvalues_found, - &w(0,0), &z(0,0), z.nc(), &isuppz(0,0), &work_size, -1, - &iwork_size, -1); - - if (info != 0) - return info; - - if (work.size() < work_size) - work.set_size(static_cast<long>(work_size), 1); - if (iwork.size() < iwork_size) - iwork.set_size(iwork_size, 1); - - // compute the actual decomposition - info = binding::syevr(jobz, range, uplo, n, &a(0,0), - a.nc(), vl, vu, il, iu, abstol, &num_eigenvalues_found, - &w(0,0), &z(0,0), z.nc(), &isuppz(0,0), &work(0,0), work.size(), - &iwork(0,0), iwork.size()); - - z = trans(z); - - return info; - } - - // ------------------------------------------------------------------------------------ - - } - -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_LAPACk_EVR_Hh_ - - - diff --git a/ml/dlib/dlib/matrix/matrix.h b/ml/dlib/dlib/matrix/matrix.h deleted file mode 100644 index b16635879..000000000 --- a/ml/dlib/dlib/matrix/matrix.h +++ /dev/null @@ -1,2162 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_ -#define DLIB_MATRIx_ - -#include "matrix_exp.h" -#include "matrix_abstract.h" -#include "../algs.h" -#include "../serialize.h" -#include "../enable_if.h" -#include <sstream> -#include <algorithm> -#include "../memory_manager.h" -#include "../is_kind.h" -#include "matrix_data_layout.h" -#include "matrix_assign_fwd.h" -#include "matrix_op.h" -#include <utility> -#ifdef DLIB_HAS_INITIALIZER_LISTS -#include <initializer_list> -#endif - -#ifdef MATLAB_MEX_FILE -#include <mex.h> -#endif - -#ifdef _MSC_VER -// Disable the following warnings for Visual Studio - -// This warning is: -// "warning C4355: 'this' : used in base member initializer list" -// Which we get from this code but it is not an error so I'm turning this -// warning off and then turning it back on at the end of the file. -#pragma warning(disable : 4355) - -// "warning C4723: potential divide by 0" - This warning is triggered in -// matrix(const std::initializer_list<T>& l) where the compiler can see that -// matrix<> was templated in a way making NR ending up 0, but division by 0 at runtime -// is not possible because the division operation is inside "if (NR!=0)" block. -#pragma warning(disable : 4723) - -#endif - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - // This template will perform the needed loop for element multiplication using whichever - // dimension is provided as a compile time constant (if one is at all). - template < - typename LHS, - typename RHS, - long lhs_nc = LHS::NC, - long rhs_nr = RHS::NR - > - struct matrix_multiply_helper - { - typedef typename LHS::type type; - template <typename RHS_, typename LHS_> - inline const static type eval ( - const RHS_& rhs, - const LHS_& lhs, - const long r, - const long c - ) - { - type temp = lhs(r,0)*rhs(0,c); - for (long i = 1; i < rhs.nr(); ++i) - { - temp += lhs(r,i)*rhs(i,c); - } - return temp; - } - }; - - template < - typename LHS, - typename RHS, - long lhs_nc - > - struct matrix_multiply_helper <LHS,RHS,lhs_nc,0> - { - typedef typename LHS::type type; - template <typename RHS_, typename LHS_> - inline const static type eval ( - const RHS_& rhs, - const LHS_& lhs, - const long r, - const long c - ) - { - type temp = lhs(r,0)*rhs(0,c); - for (long i = 1; i < lhs.nc(); ++i) - { - temp += lhs(r,i)*rhs(i,c); - } - return temp; - } - }; - - template <typename LHS, typename RHS> - class matrix_multiply_exp; - - template <typename LHS, typename RHS> - struct matrix_traits<matrix_multiply_exp<LHS,RHS> > - { - typedef typename LHS::type type; - typedef typename LHS::type const_ret_type; - typedef typename LHS::mem_manager_type mem_manager_type; - typedef typename LHS::layout_type layout_type; - const static long NR = LHS::NR; - const static long NC = RHS::NC; - -#ifdef DLIB_USE_BLAS - // if there are BLAS functions to be called then we want to make sure we - // always evaluate any complex expressions so that the BLAS bindings can happen. - const static bool lhs_is_costly = (LHS::cost > 2)&&(RHS::NC != 1 || LHS::cost >= 10000); - const static bool rhs_is_costly = (RHS::cost > 2)&&(LHS::NR != 1 || RHS::cost >= 10000); -#else - const static bool lhs_is_costly = (LHS::cost > 4)&&(RHS::NC != 1); - const static bool rhs_is_costly = (RHS::cost > 4)&&(LHS::NR != 1); -#endif - - // Note that if we decide that one of the matrices is too costly we will evaluate it - // into a temporary. Doing this resets its cost back to 1. - const static long lhs_cost = ((lhs_is_costly==true)? 1 : (LHS::cost)); - const static long rhs_cost = ((rhs_is_costly==true)? 1 : (RHS::cost)); - - // The cost of evaluating an element of a matrix multiply is the cost of evaluating elements from - // RHS and LHS times the number of rows/columns in the RHS/LHS matrix. If we don't know the matrix - // dimensions then just assume it is really large. - const static long cost = ((tmax<LHS::NC,RHS::NR>::value!=0)? ((lhs_cost+rhs_cost)*tmax<LHS::NC,RHS::NR>::value):(10000)); - }; - - template <typename T, bool is_ref> struct conditional_matrix_temp { typedef typename T::matrix_type type; }; - template <typename T> struct conditional_matrix_temp<T,true> { typedef T& type; }; - - template < - typename LHS, - typename RHS - > - class matrix_multiply_exp : public matrix_exp<matrix_multiply_exp<LHS,RHS> > - { - /*! - REQUIREMENTS ON LHS AND RHS - - must be matrix_exp objects. - !*/ - public: - - typedef typename matrix_traits<matrix_multiply_exp>::type type; - typedef typename matrix_traits<matrix_multiply_exp>::const_ret_type const_ret_type; - typedef typename matrix_traits<matrix_multiply_exp>::mem_manager_type mem_manager_type; - const static long NR = matrix_traits<matrix_multiply_exp>::NR; - const static long NC = matrix_traits<matrix_multiply_exp>::NC; - const static long cost = matrix_traits<matrix_multiply_exp>::cost; - typedef typename matrix_traits<matrix_multiply_exp>::layout_type layout_type; - - - const static bool lhs_is_costly = matrix_traits<matrix_multiply_exp>::lhs_is_costly; - const static bool rhs_is_costly = matrix_traits<matrix_multiply_exp>::rhs_is_costly; - const static bool either_is_costly = lhs_is_costly || rhs_is_costly; - const static bool both_are_costly = lhs_is_costly && rhs_is_costly; - - typedef typename conditional_matrix_temp<const LHS,lhs_is_costly == false>::type LHS_ref_type; - typedef typename conditional_matrix_temp<const RHS,rhs_is_costly == false>::type RHS_ref_type; - - // This constructor exists simply for the purpose of causing a compile time error if - // someone tries to create an instance of this object with the wrong kind of objects. - template <typename T1, typename T2> - matrix_multiply_exp (T1,T2); - - inline matrix_multiply_exp ( - const LHS& lhs_, - const RHS& rhs_ - ) : - lhs(lhs_), - rhs(rhs_) - { - // You are trying to multiply two incompatible matrices together. The number of columns - // in the matrix on the left must match the number of rows in the matrix on the right. - COMPILE_TIME_ASSERT(LHS::NC == RHS::NR || LHS::NC*RHS::NR == 0); - DLIB_ASSERT(lhs.nc() == rhs.nr() && lhs.size() > 0 && rhs.size() > 0, - "\tconst matrix_exp operator*(const matrix_exp& lhs, const matrix_exp& rhs)" - << "\n\tYou are trying to multiply two incompatible matrices together" - << "\n\tlhs.nr(): " << lhs.nr() - << "\n\tlhs.nc(): " << lhs.nc() - << "\n\trhs.nr(): " << rhs.nr() - << "\n\trhs.nc(): " << rhs.nc() - << "\n\t&lhs: " << &lhs - << "\n\t&rhs: " << &rhs - ); - - // You can't multiply matrices together if they don't both contain the same type of elements. - COMPILE_TIME_ASSERT((is_same_type<typename LHS::type, typename RHS::type>::value == true)); - } - - inline const type operator() ( - const long r, - const long c - ) const - { - return matrix_multiply_helper<LHS,RHS>::eval(rhs,lhs,r,c); - } - - inline const type operator() ( long i ) const - { return matrix_exp<matrix_multiply_exp>::operator()(i); } - - long nr ( - ) const { return lhs.nr(); } - - long nc ( - ) const { return rhs.nc(); } - - template <typename U> - bool aliases ( - const matrix_exp<U>& item - ) const { return lhs.aliases(item) || rhs.aliases(item); } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& item - ) const { return aliases(item); } - - LHS_ref_type lhs; - RHS_ref_type rhs; - }; - - template < typename EXP1, typename EXP2 > - inline const matrix_multiply_exp<EXP1, EXP2> operator* ( - const matrix_exp<EXP1>& m1, - const matrix_exp<EXP2>& m2 - ) - { - return matrix_multiply_exp<EXP1, EXP2>(m1.ref(), m2.ref()); - } - - template <typename M, bool use_reference = true> - class matrix_mul_scal_exp; - - // ------------------------- - - // Now we declare some overloads that cause any scalar multiplications to percolate - // up and outside of any matrix multiplies. Note that we are using the non-reference containing - // mode of the matrix_mul_scal_exp object since we are passing in locally constructed matrix_multiply_exp - // objects. So the matrix_mul_scal_exp object will contain copies of matrix_multiply_exp objects - // rather than references to them. This could result in extra matrix copies if the matrix_multiply_exp - // decided it should evaluate any of its arguments. So we also try to not apply this percolating operation - // if the matrix_multiply_exp would contain a fully evaluated copy of the original matrix_mul_scal_exp - // expression. - // - // Also, the reason we want to apply this transformation in the first place is because it (1) makes - // the expressions going into matrix multiply expressions simpler and (2) it makes it a lot more - // straightforward to bind BLAS calls to matrix expressions involving scalar multiplies. - template < typename EXP1, typename EXP2 > - inline const typename disable_if_c< matrix_multiply_exp<matrix_mul_scal_exp<EXP1>, matrix_mul_scal_exp<EXP2> >::both_are_costly , - matrix_mul_scal_exp<matrix_multiply_exp<EXP1, EXP2>,false> >::type operator* ( - const matrix_mul_scal_exp<EXP1>& m1, - const matrix_mul_scal_exp<EXP2>& m2 - ) - { - typedef matrix_multiply_exp<EXP1, EXP2> exp1; - typedef matrix_mul_scal_exp<exp1,false> exp2; - return exp2(exp1(m1.m, m2.m), m1.s*m2.s); - } - - template < typename EXP1, typename EXP2 > - inline const typename disable_if_c< matrix_multiply_exp<matrix_mul_scal_exp<EXP1>, EXP2 >::lhs_is_costly , - matrix_mul_scal_exp<matrix_multiply_exp<EXP1, EXP2>,false> >::type operator* ( - const matrix_mul_scal_exp<EXP1>& m1, - const matrix_exp<EXP2>& m2 - ) - { - typedef matrix_multiply_exp<EXP1, EXP2> exp1; - typedef matrix_mul_scal_exp<exp1,false> exp2; - return exp2(exp1(m1.m, m2.ref()), m1.s); - } - - template < typename EXP1, typename EXP2 > - inline const typename disable_if_c< matrix_multiply_exp<EXP1, matrix_mul_scal_exp<EXP2> >::rhs_is_costly , - matrix_mul_scal_exp<matrix_multiply_exp<EXP1, EXP2>,false> >::type operator* ( - const matrix_exp<EXP1>& m1, - const matrix_mul_scal_exp<EXP2>& m2 - ) - { - typedef matrix_multiply_exp<EXP1, EXP2> exp1; - typedef matrix_mul_scal_exp<exp1,false> exp2; - return exp2(exp1(m1.ref(), m2.m), m2.s); - } - -// ---------------------------------------------------------------------------------------- - - template <typename LHS, typename RHS> - class matrix_add_exp; - - template <typename LHS, typename RHS> - struct matrix_traits<matrix_add_exp<LHS,RHS> > - { - typedef typename LHS::type type; - typedef typename LHS::type const_ret_type; - typedef typename LHS::mem_manager_type mem_manager_type; - typedef typename LHS::layout_type layout_type; - const static long NR = (RHS::NR > LHS::NR) ? RHS::NR : LHS::NR; - const static long NC = (RHS::NC > LHS::NC) ? RHS::NC : LHS::NC; - const static long cost = LHS::cost+RHS::cost+1; - }; - - template < - typename LHS, - typename RHS - > - class matrix_add_exp : public matrix_exp<matrix_add_exp<LHS,RHS> > - { - /*! - REQUIREMENTS ON LHS AND RHS - - must be matrix_exp objects. - !*/ - public: - typedef typename matrix_traits<matrix_add_exp>::type type; - typedef typename matrix_traits<matrix_add_exp>::const_ret_type const_ret_type; - typedef typename matrix_traits<matrix_add_exp>::mem_manager_type mem_manager_type; - const static long NR = matrix_traits<matrix_add_exp>::NR; - const static long NC = matrix_traits<matrix_add_exp>::NC; - const static long cost = matrix_traits<matrix_add_exp>::cost; - typedef typename matrix_traits<matrix_add_exp>::layout_type layout_type; - - // This constructor exists simply for the purpose of causing a compile time error if - // someone tries to create an instance of this object with the wrong kind of objects. - template <typename T1, typename T2> - matrix_add_exp (T1,T2); - - matrix_add_exp ( - const LHS& lhs_, - const RHS& rhs_ - ) : - lhs(lhs_), - rhs(rhs_) - { - // You can only add matrices together if they both have the same number of rows and columns. - COMPILE_TIME_ASSERT(LHS::NR == RHS::NR || LHS::NR == 0 || RHS::NR == 0); - COMPILE_TIME_ASSERT(LHS::NC == RHS::NC || LHS::NC == 0 || RHS::NC == 0); - DLIB_ASSERT(lhs.nc() == rhs.nc() && - lhs.nr() == rhs.nr(), - "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" - << "\n\tYou are trying to add two incompatible matrices together" - << "\n\tlhs.nr(): " << lhs.nr() - << "\n\tlhs.nc(): " << lhs.nc() - << "\n\trhs.nr(): " << rhs.nr() - << "\n\trhs.nc(): " << rhs.nc() - << "\n\t&lhs: " << &lhs - << "\n\t&rhs: " << &rhs - ); - - // You can only add matrices together if they both contain the same types of elements. - COMPILE_TIME_ASSERT((is_same_type<typename LHS::type, typename RHS::type>::value == true)); - } - - const type operator() ( - long r, - long c - ) const { return lhs(r,c) + rhs(r,c); } - - inline const type operator() ( long i ) const - { return matrix_exp<matrix_add_exp>::operator()(i); } - - template <typename U> - bool aliases ( - const matrix_exp<U>& item - ) const { return lhs.aliases(item) || rhs.aliases(item); } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& item - ) const { return lhs.destructively_aliases(item) || rhs.destructively_aliases(item); } - - long nr ( - ) const { return lhs.nr(); } - - long nc ( - ) const { return lhs.nc(); } - - const LHS& lhs; - const RHS& rhs; - }; - - template < - typename EXP1, - typename EXP2 - > - inline const matrix_add_exp<EXP1, EXP2> operator+ ( - const matrix_exp<EXP1>& m1, - const matrix_exp<EXP2>& m2 - ) - { - return matrix_add_exp<EXP1, EXP2>(m1.ref(),m2.ref()); - } - -// ---------------------------------------------------------------------------------------- - - template <typename LHS, typename RHS> - class matrix_subtract_exp; - - template <typename LHS, typename RHS> - struct matrix_traits<matrix_subtract_exp<LHS,RHS> > - { - typedef typename LHS::type type; - typedef typename LHS::type const_ret_type; - typedef typename LHS::mem_manager_type mem_manager_type; - typedef typename LHS::layout_type layout_type; - const static long NR = (RHS::NR > LHS::NR) ? RHS::NR : LHS::NR; - const static long NC = (RHS::NC > LHS::NC) ? RHS::NC : LHS::NC; - const static long cost = LHS::cost+RHS::cost+1; - }; - - template < - typename LHS, - typename RHS - > - class matrix_subtract_exp : public matrix_exp<matrix_subtract_exp<LHS,RHS> > - { - /*! - REQUIREMENTS ON LHS AND RHS - - must be matrix_exp objects. - !*/ - public: - typedef typename matrix_traits<matrix_subtract_exp>::type type; - typedef typename matrix_traits<matrix_subtract_exp>::const_ret_type const_ret_type; - typedef typename matrix_traits<matrix_subtract_exp>::mem_manager_type mem_manager_type; - const static long NR = matrix_traits<matrix_subtract_exp>::NR; - const static long NC = matrix_traits<matrix_subtract_exp>::NC; - const static long cost = matrix_traits<matrix_subtract_exp>::cost; - typedef typename matrix_traits<matrix_subtract_exp>::layout_type layout_type; - - - // This constructor exists simply for the purpose of causing a compile time error if - // someone tries to create an instance of this object with the wrong kind of objects. - template <typename T1, typename T2> - matrix_subtract_exp (T1,T2); - - matrix_subtract_exp ( - const LHS& lhs_, - const RHS& rhs_ - ) : - lhs(lhs_), - rhs(rhs_) - { - // You can only subtract one matrix from another if they both have the same number of rows and columns. - COMPILE_TIME_ASSERT(LHS::NR == RHS::NR || LHS::NR == 0 || RHS::NR == 0); - COMPILE_TIME_ASSERT(LHS::NC == RHS::NC || LHS::NC == 0 || RHS::NC == 0); - DLIB_ASSERT(lhs.nc() == rhs.nc() && - lhs.nr() == rhs.nr(), - "\tconst matrix_exp operator-(const matrix_exp& lhs, const matrix_exp& rhs)" - << "\n\tYou are trying to subtract two incompatible matrices" - << "\n\tlhs.nr(): " << lhs.nr() - << "\n\tlhs.nc(): " << lhs.nc() - << "\n\trhs.nr(): " << rhs.nr() - << "\n\trhs.nc(): " << rhs.nc() - << "\n\t&lhs: " << &lhs - << "\n\t&rhs: " << &rhs - ); - - // You can only subtract one matrix from another if they both contain elements of the same type. - COMPILE_TIME_ASSERT((is_same_type<typename LHS::type, typename RHS::type>::value == true)); - } - - const type operator() ( - long r, - long c - ) const { return lhs(r,c) - rhs(r,c); } - - inline const type operator() ( long i ) const - { return matrix_exp<matrix_subtract_exp>::operator()(i); } - - template <typename U> - bool aliases ( - const matrix_exp<U>& item - ) const { return lhs.aliases(item) || rhs.aliases(item); } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& item - ) const { return lhs.destructively_aliases(item) || rhs.destructively_aliases(item); } - - long nr ( - ) const { return lhs.nr(); } - - long nc ( - ) const { return lhs.nc(); } - - const LHS& lhs; - const RHS& rhs; - }; - - template < - typename EXP1, - typename EXP2 - > - inline const matrix_subtract_exp<EXP1, EXP2> operator- ( - const matrix_exp<EXP1>& m1, - const matrix_exp<EXP2>& m2 - ) - { - return matrix_subtract_exp<EXP1, EXP2>(m1.ref(),m2.ref()); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - class matrix_div_scal_exp; - - template <typename M> - struct matrix_traits<matrix_div_scal_exp<M> > - { - typedef typename M::type type; - typedef typename M::type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const static long NR = M::NR; - const static long NC = M::NC; - const static long cost = M::cost+1; - }; - - template < - typename M - > - class matrix_div_scal_exp : public matrix_exp<matrix_div_scal_exp<M> > - { - /*! - REQUIREMENTS ON M - - must be a matrix_exp object. - !*/ - public: - typedef typename matrix_traits<matrix_div_scal_exp>::type type; - typedef typename matrix_traits<matrix_div_scal_exp>::const_ret_type const_ret_type; - typedef typename matrix_traits<matrix_div_scal_exp>::mem_manager_type mem_manager_type; - const static long NR = matrix_traits<matrix_div_scal_exp>::NR; - const static long NC = matrix_traits<matrix_div_scal_exp>::NC; - const static long cost = matrix_traits<matrix_div_scal_exp>::cost; - typedef typename matrix_traits<matrix_div_scal_exp>::layout_type layout_type; - - - // This constructor exists simply for the purpose of causing a compile time error if - // someone tries to create an instance of this object with the wrong kind of objects. - template <typename T1> - matrix_div_scal_exp (T1, const type&); - - matrix_div_scal_exp ( - const M& m_, - const type& s_ - ) : - m(m_), - s(s_) - {} - - const type operator() ( - long r, - long c - ) const { return m(r,c)/s; } - - inline const type operator() ( long i ) const - { return matrix_exp<matrix_div_scal_exp>::operator()(i); } - - template <typename U> - bool aliases ( - const matrix_exp<U>& item - ) const { return m.aliases(item); } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& item - ) const { return m.destructively_aliases(item); } - - long nr ( - ) const { return m.nr(); } - - long nc ( - ) const { return m.nc(); } - - const M& m; - const type s; - }; - - template < - typename EXP, - typename S - > - inline const typename enable_if_c<std::numeric_limits<typename EXP::type>::is_integer, matrix_div_scal_exp<EXP> >::type operator/ ( - const matrix_exp<EXP>& m, - const S& s - ) - { - return matrix_div_scal_exp<EXP>(m.ref(),static_cast<typename EXP::type>(s)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M, bool use_reference > - struct matrix_traits<matrix_mul_scal_exp<M,use_reference> > - { - typedef typename M::type type; - typedef typename M::type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const static long NR = M::NR; - const static long NC = M::NC; - const static long cost = M::cost+1; - }; - - template <typename T, bool is_ref> struct conditional_reference { typedef T type; }; - template <typename T> struct conditional_reference<T,true> { typedef T& type; }; - - - template < - typename M, - bool use_reference - > - class matrix_mul_scal_exp : public matrix_exp<matrix_mul_scal_exp<M,use_reference> > - { - /*! - REQUIREMENTS ON M - - must be a matrix_exp object. - - !*/ - public: - typedef typename matrix_traits<matrix_mul_scal_exp>::type type; - typedef typename matrix_traits<matrix_mul_scal_exp>::const_ret_type const_ret_type; - typedef typename matrix_traits<matrix_mul_scal_exp>::mem_manager_type mem_manager_type; - const static long NR = matrix_traits<matrix_mul_scal_exp>::NR; - const static long NC = matrix_traits<matrix_mul_scal_exp>::NC; - const static long cost = matrix_traits<matrix_mul_scal_exp>::cost; - typedef typename matrix_traits<matrix_mul_scal_exp>::layout_type layout_type; - - // You aren't allowed to multiply a matrix of matrices by a scalar. - COMPILE_TIME_ASSERT(is_matrix<type>::value == false); - - // This constructor exists simply for the purpose of causing a compile time error if - // someone tries to create an instance of this object with the wrong kind of objects. - template <typename T1> - matrix_mul_scal_exp (T1, const type&); - - matrix_mul_scal_exp ( - const M& m_, - const type& s_ - ) : - m(m_), - s(s_) - {} - - const type operator() ( - long r, - long c - ) const { return m(r,c)*s; } - - inline const type operator() ( long i ) const - { return matrix_exp<matrix_mul_scal_exp>::operator()(i); } - - template <typename U> - bool aliases ( - const matrix_exp<U>& item - ) const { return m.aliases(item); } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& item - ) const { return m.destructively_aliases(item); } - - long nr ( - ) const { return m.nr(); } - - long nc ( - ) const { return m.nc(); } - - typedef typename conditional_reference<const M,use_reference>::type M_ref_type; - - M_ref_type m; - const type s; - }; - - template < - typename EXP, - typename S - > - inline typename disable_if<is_matrix<S>, const matrix_mul_scal_exp<EXP> >::type operator* ( - const matrix_exp<EXP>& m, - const S& s - ) - { - typedef typename EXP::type type; - return matrix_mul_scal_exp<EXP>(m.ref(),static_cast<type>(s)); - } - - template < - typename EXP, - typename S, - bool B - > - inline typename disable_if<is_matrix<S>, const matrix_mul_scal_exp<EXP> >::type operator* ( - const matrix_mul_scal_exp<EXP,B>& m, - const S& s - ) - { - typedef typename EXP::type type; - return matrix_mul_scal_exp<EXP>(m.m,static_cast<type>(s)*m.s); - } - - template < - typename EXP, - typename S - > - inline typename disable_if<is_matrix<S>, const matrix_mul_scal_exp<EXP> >::type operator* ( - const S& s, - const matrix_exp<EXP>& m - ) - { - typedef typename EXP::type type; - return matrix_mul_scal_exp<EXP>(m.ref(),static_cast<type>(s)); - } - - template < - typename EXP, - typename S, - bool B - > - inline typename disable_if<is_matrix<S>, const matrix_mul_scal_exp<EXP> >::type operator* ( - const S& s, - const matrix_mul_scal_exp<EXP,B>& m - ) - { - typedef typename EXP::type type; - return matrix_mul_scal_exp<EXP>(m.m,static_cast<type>(s)*m.s); - } - - template < - typename EXP , - typename S - > - inline const typename disable_if_c<std::numeric_limits<typename EXP::type>::is_integer, matrix_mul_scal_exp<EXP> >::type operator/ ( - const matrix_exp<EXP>& m, - const S& s - ) - { - typedef typename EXP::type type; - const type one = 1; - return matrix_mul_scal_exp<EXP>(m.ref(),one/static_cast<type>(s)); - } - - template < - typename EXP, - bool B, - typename S - > - inline const typename disable_if_c<std::numeric_limits<typename EXP::type>::is_integer, matrix_mul_scal_exp<EXP> >::type operator/ ( - const matrix_mul_scal_exp<EXP,B>& m, - const S& s - ) - { - typedef typename EXP::type type; - return matrix_mul_scal_exp<EXP>(m.m,m.s/static_cast<type>(s)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_s_div_m : basic_op_m<M> - { - typedef typename M::type type; - - op_s_div_m( const M& m_, const type& s_) : basic_op_m<M>(m_), s(s_){} - - const type s; - - const static long cost = M::cost+1; - typedef const typename M::type const_ret_type; - const_ret_type apply (long r, long c) const - { - return s/this->m(r,c); - } - }; - - template < - typename EXP, - typename S - > - const typename disable_if<is_matrix<S>, matrix_op<op_s_div_m<EXP> > >::type operator/ ( - const S& val, - const matrix_exp<EXP>& m - ) - { - typedef typename EXP::type type; - - typedef op_s_div_m<EXP> op; - return matrix_op<op>(op(m.ref(), static_cast<type>(val))); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - inline const matrix_mul_scal_exp<EXP> operator- ( - const matrix_exp<EXP>& m - ) - { - return matrix_mul_scal_exp<EXP>(m.ref(),-1); - } - - template < - typename EXP, - bool B - > - inline const matrix_mul_scal_exp<EXP> operator- ( - const matrix_mul_scal_exp<EXP,B>& m - ) - { - return matrix_mul_scal_exp<EXP>(m.m,-1*m.s); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_add_scalar : basic_op_m<M> - { - typedef typename M::type type; - - op_add_scalar( const M& m_, const type& s_) : basic_op_m<M>(m_), s(s_){} - - const type s; - - const static long cost = M::cost+1; - typedef const typename M::type const_ret_type; - const_ret_type apply (long r, long c) const - { - return this->m(r,c) + s; - } - }; - - template < - typename EXP, - typename T - > - const typename disable_if<is_matrix<T>, matrix_op<op_add_scalar<EXP> > >::type operator+ ( - const matrix_exp<EXP>& m, - const T& val - ) - { - typedef typename EXP::type type; - - typedef op_add_scalar<EXP> op; - return matrix_op<op>(op(m.ref(), static_cast<type>(val))); - } - - template < - typename EXP, - typename T - > - const typename disable_if<is_matrix<T>, matrix_op<op_add_scalar<EXP> > >::type operator+ ( - const T& val, - const matrix_exp<EXP>& m - ) - { - typedef typename EXP::type type; - - typedef op_add_scalar<EXP> op; - return matrix_op<op>(op(m.ref(), static_cast<type>(val))); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_subl_scalar : basic_op_m<M> - { - typedef typename M::type type; - - op_subl_scalar( const M& m_, const type& s_) : basic_op_m<M>(m_), s(s_){} - - const type s; - - const static long cost = M::cost+1; - typedef const typename M::type const_ret_type; - const_ret_type apply (long r, long c) const - { - return s - this->m(r,c) ; - } - }; - - template < - typename EXP, - typename T - > - const typename disable_if<is_matrix<T>, matrix_op<op_subl_scalar<EXP> > >::type operator- ( - const T& val, - const matrix_exp<EXP>& m - ) - { - typedef typename EXP::type type; - - typedef op_subl_scalar<EXP> op; - return matrix_op<op>(op(m.ref(), static_cast<type>(val))); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_subr_scalar : basic_op_m<M> - { - typedef typename M::type type; - - op_subr_scalar( const M& m_, const type& s_) : basic_op_m<M>(m_), s(s_){} - - const type s; - - const static long cost = M::cost+1; - typedef const typename M::type const_ret_type; - const_ret_type apply (long r, long c) const - { - return this->m(r,c) - s; - } - }; - - template < - typename EXP, - typename T - > - const typename disable_if<is_matrix<T>, matrix_op<op_subr_scalar<EXP> > >::type operator- ( - const matrix_exp<EXP>& m, - const T& val - ) - { - typedef typename EXP::type type; - - typedef op_subr_scalar<EXP> op; - return matrix_op<op>(op(m.ref(), static_cast<type>(val))); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP1, - typename EXP2 - > - bool operator== ( - const matrix_exp<EXP1>& m1, - const matrix_exp<EXP2>& m2 - ) - { - if (m1.nr() == m2.nr() && m1.nc() == m2.nc()) - { - for (long r = 0; r < m1.nr(); ++r) - { - for (long c = 0; c < m1.nc(); ++c) - { - if (m1(r,c) != m2(r,c)) - return false; - } - } - return true; - } - return false; - } - - template < - typename EXP1, - typename EXP2 - > - inline bool operator!= ( - const matrix_exp<EXP1>& m1, - const matrix_exp<EXP2>& m2 - ) { return !(m1 == m2); } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename T> - struct op_pointer_to_mat; - template <typename T> - struct op_pointer_to_col_vect; - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager, - typename layout - > - struct matrix_traits<matrix<T,num_rows, num_cols, mem_manager, layout> > - { - typedef T type; - typedef const T& const_ret_type; - typedef mem_manager mem_manager_type; - typedef layout layout_type; - const static long NR = num_rows; - const static long NC = num_cols; - const static long cost = 1; - - }; - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager, - typename layout - > - class matrix : public matrix_exp<matrix<T,num_rows,num_cols, mem_manager,layout> > - { - - COMPILE_TIME_ASSERT(num_rows >= 0 && num_cols >= 0); - - public: - typedef typename matrix_traits<matrix>::type type; - typedef typename matrix_traits<matrix>::const_ret_type const_ret_type; - typedef typename matrix_traits<matrix>::mem_manager_type mem_manager_type; - typedef typename matrix_traits<matrix>::layout_type layout_type; - const static long NR = matrix_traits<matrix>::NR; - const static long NC = matrix_traits<matrix>::NC; - const static long cost = matrix_traits<matrix>::cost; - typedef T* iterator; - typedef const T* const_iterator; - - matrix () - { - } - - explicit matrix ( - long length - ) - { - // This object you are trying to call matrix(length) on is not a column or - // row vector. - COMPILE_TIME_ASSERT(NR == 1 || NC == 1); - DLIB_ASSERT( length >= 0, - "\tmatrix::matrix(length)" - << "\n\tlength must be at least 0" - << "\n\tlength: " << length - << "\n\tNR: " << NR - << "\n\tNC: " << NC - << "\n\tthis: " << this - ); - - if (NR == 1) - { - DLIB_ASSERT(NC == 0 || NC == length, - "\tmatrix::matrix(length)" - << "\n\tSince this is a statically sized matrix length must equal NC" - << "\n\tlength: " << length - << "\n\tNR: " << NR - << "\n\tNC: " << NC - << "\n\tthis: " << this - ); - - data.set_size(1,length); - } - else - { - DLIB_ASSERT(NR == 0 || NR == length, - "\tvoid matrix::set_size(length)" - << "\n\tSince this is a statically sized matrix length must equal NR" - << "\n\tlength: " << length - << "\n\tNR: " << NR - << "\n\tNC: " << NC - << "\n\tthis: " << this - ); - - data.set_size(length,1); - } - } - - matrix ( - long rows, - long cols - ) - { - DLIB_ASSERT( (NR == 0 || NR == rows) && ( NC == 0 || NC == cols) && - rows >= 0 && cols >= 0, - "\tvoid matrix::matrix(rows, cols)" - << "\n\tYou have supplied conflicting matrix dimensions" - << "\n\trows: " << rows - << "\n\tcols: " << cols - << "\n\tNR: " << NR - << "\n\tNC: " << NC - ); - data.set_size(rows,cols); - } - - template <typename EXP> - matrix ( - const matrix_exp<EXP>& m - ) - { - // You get an error on this line if the matrix m contains a type that isn't - // the same as the type contained in the target matrix. - COMPILE_TIME_ASSERT((is_same_type<typename EXP::type,type>::value == true) || - (is_matrix<typename EXP::type>::value == true)); - - // The matrix you are trying to assign m to is a statically sized matrix and - // m's dimensions don't match that of *this. - COMPILE_TIME_ASSERT(EXP::NR == NR || NR == 0 || EXP::NR == 0); - COMPILE_TIME_ASSERT(EXP::NC == NC || NC == 0 || EXP::NC == 0); - DLIB_ASSERT((NR == 0 || NR == m.nr()) && (NC == 0 || NC == m.nc()), - "\tmatrix& matrix::matrix(const matrix_exp& m)" - << "\n\tYou are trying to assign a dynamically sized matrix to a statically sized matrix with the wrong size" - << "\n\tNR: " << NR - << "\n\tNC: " << NC - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tthis: " << this - ); - - data.set_size(m.nr(),m.nc()); - - matrix_assign(*this, m); - } - - matrix ( - const matrix& m - ) : matrix_exp<matrix>(*this) - { - data.set_size(m.nr(),m.nc()); - matrix_assign(*this, m); - } - -#ifdef DLIB_HAS_INITIALIZER_LISTS - matrix(const std::initializer_list<T>& l) - { - if (NR*NC != 0) - { - DLIB_ASSERT(l.size() == NR*NC, - "\t matrix::matrix(const std::initializer_list& l)" - << "\n\t You are trying to initialize a statically sized matrix with a list that doesn't have a matching size." - << "\n\t l.size(): "<< l.size() - << "\n\t NR*NC: "<< NR*NC); - - data.set_size(NR, NC); - } - else if (NR!=0) - { - DLIB_ASSERT(l.size()%NR == 0, - "\t matrix::matrix(const std::initializer_list& l)" - << "\n\t You are trying to initialize a statically sized matrix with a list that doesn't have a compatible size." - << "\n\t l.size(): "<< l.size() - << "\n\t NR: "<< NR); - - if (l.size() != 0) - data.set_size(NR, l.size()/NR); - } - else if (NC!=0) - { - DLIB_ASSERT(l.size()%NC == 0, - "\t matrix::matrix(const std::initializer_list& l)" - << "\n\t You are trying to initialize a statically sized matrix with a list that doesn't have a compatible size." - << "\n\t l.size(): "<< l.size() - << "\n\t NC: "<< NC); - - if (l.size() != 0) - data.set_size(l.size()/NC, NC); - } - else if (l.size() != 0) - { - data.set_size(l.size(),1); - } - - if (l.size() != 0) - { - T* d = &data(0,0); - for (auto&& v : l) - *d++ = v; - } - - } - - matrix& operator=(const std::initializer_list<T>& l) - { - matrix temp(l); - temp.swap(*this); - return *this; - } -#endif // DLIB_HAS_INITIALIZER_LISTS - -#ifdef DLIB_HAS_RVALUE_REFERENCES - matrix(matrix&& item) - { - #ifdef MATLAB_MEX_FILE - // You can't move memory around when compiled in a matlab mex file and the - // different locations have different ownership settings. - if (data._private_is_owned_by_matlab() == item.data._private_is_owned_by_matlab()) - { - swap(item); - } - else - { - data.set_size(item.nr(),item.nc()); - matrix_assign(*this, item); - } - #else - swap(item); - #endif - } - - matrix& operator= ( - matrix&& rhs - ) - { - #ifdef MATLAB_MEX_FILE - // You can't move memory around when compiled in a matlab mex file and the - // different locations have different ownership settings. - if (data._private_is_owned_by_matlab() == rhs.data._private_is_owned_by_matlab()) - { - swap(rhs); - } - else - { - data.set_size(rhs.nr(),rhs.nc()); - matrix_assign(*this, rhs); - } - #else - swap(rhs); - #endif - return *this; - } -#endif // DLIB_HAS_RVALUE_REFERENCES - - template <typename U, size_t len> - explicit matrix ( - U (&array)[len] - ) - { - COMPILE_TIME_ASSERT(NR*NC == len && len > 0); - size_t idx = 0; - for (long r = 0; r < NR; ++r) - { - for (long c = 0; c < NC; ++c) - { - data(r,c) = static_cast<T>(array[idx]); - ++idx; - } - } - } - - T& operator() ( - long r, - long c - ) - { - DLIB_ASSERT(r < nr() && c < nc() && - r >= 0 && c >= 0, - "\tT& matrix::operator(r,c)" - << "\n\tYou must give a valid row and column" - << "\n\tr: " << r - << "\n\tc: " << c - << "\n\tnr(): " << nr() - << "\n\tnc(): " << nc() - << "\n\tthis: " << this - ); - return data(r,c); - } - - const T& operator() ( - long r, - long c - ) const - { - DLIB_ASSERT(r < nr() && c < nc() && - r >= 0 && c >= 0, - "\tconst T& matrix::operator(r,c)" - << "\n\tYou must give a valid row and column" - << "\n\tr: " << r - << "\n\tc: " << c - << "\n\tnr(): " << nr() - << "\n\tnc(): " << nc() - << "\n\tthis: " << this - ); - return data(r,c); - } - - T& operator() ( - long i - ) - { - // You can only use this operator on column vectors. - COMPILE_TIME_ASSERT(NC == 1 || NC == 0 || NR == 1 || NR == 0); - DLIB_ASSERT(nc() == 1 || nr() == 1, - "\tconst type matrix::operator(i)" - << "\n\tYou can only use this operator on column or row vectors" - << "\n\ti: " << i - << "\n\tnr(): " << nr() - << "\n\tnc(): " << nc() - << "\n\tthis: " << this - ); - DLIB_ASSERT( 0 <= i && i < size(), - "\tconst type matrix::operator(i)" - << "\n\tYou must give a valid row/column number" - << "\n\ti: " << i - << "\n\tsize(): " << size() - << "\n\tthis: " << this - ); - return data(i); - } - - const T& operator() ( - long i - ) const - { - // You can only use this operator on column vectors. - COMPILE_TIME_ASSERT(NC == 1 || NC == 0 || NR == 1 || NR == 0); - DLIB_ASSERT(nc() == 1 || nr() == 1, - "\tconst type matrix::operator(i)" - << "\n\tYou can only use this operator on column or row vectors" - << "\n\ti: " << i - << "\n\tnr(): " << nr() - << "\n\tnc(): " << nc() - << "\n\tthis: " << this - ); - DLIB_ASSERT( 0 <= i && i < size(), - "\tconst type matrix::operator(i)" - << "\n\tYou must give a valid row/column number" - << "\n\ti: " << i - << "\n\tsize(): " << size() - << "\n\tthis: " << this - ); - return data(i); - } - - inline operator const type ( - ) const - { - COMPILE_TIME_ASSERT(NC == 1 || NC == 0); - COMPILE_TIME_ASSERT(NR == 1 || NR == 0); - DLIB_ASSERT( nr() == 1 && nc() == 1 , - "\tmatrix::operator const type" - << "\n\tYou can only attempt to implicit convert a matrix to a scalar if" - << "\n\tthe matrix is a 1x1 matrix" - << "\n\tnr(): " << nr() - << "\n\tnc(): " << nc() - << "\n\tthis: " << this - ); - return data(0); - } - -#ifdef MATLAB_MEX_FILE - void _private_set_mxArray( - mxArray* mem - ) - { - data._private_set_mxArray(mem); - } - - mxArray* _private_release_mxArray( - ) - { - return data._private_release_mxArray(); - } - - void _private_mark_owned_by_matlab() - { - data._private_mark_owned_by_matlab(); - } - - bool _private_is_owned_by_matlab() - { - return data._private_is_owned_by_matlab(); - } -#endif - - void set_size ( - long rows, - long cols - ) - { - DLIB_ASSERT( (NR == 0 || NR == rows) && ( NC == 0 || NC == cols) && - rows >= 0 && cols >= 0, - "\tvoid matrix::set_size(rows, cols)" - << "\n\tYou have supplied conflicting matrix dimensions" - << "\n\trows: " << rows - << "\n\tcols: " << cols - << "\n\tNR: " << NR - << "\n\tNC: " << NC - << "\n\tthis: " << this - ); - if (nr() != rows || nc() != cols) - data.set_size(rows,cols); - } - - void set_size ( - long length - ) - { - // This object you are trying to call set_size(length) on is not a column or - // row vector. - COMPILE_TIME_ASSERT(NR == 1 || NC == 1); - DLIB_ASSERT( length >= 0, - "\tvoid matrix::set_size(length)" - << "\n\tlength must be at least 0" - << "\n\tlength: " << length - << "\n\tNR: " << NR - << "\n\tNC: " << NC - << "\n\tthis: " << this - ); - - if (NR == 1) - { - DLIB_ASSERT(NC == 0 || NC == length, - "\tvoid matrix::set_size(length)" - << "\n\tSince this is a statically sized matrix length must equal NC" - << "\n\tlength: " << length - << "\n\tNR: " << NR - << "\n\tNC: " << NC - << "\n\tthis: " << this - ); - - if (nc() != length) - data.set_size(1,length); - } - else - { - DLIB_ASSERT(NR == 0 || NR == length, - "\tvoid matrix::set_size(length)" - << "\n\tSince this is a statically sized matrix length must equal NR" - << "\n\tlength: " << length - << "\n\tNR: " << NR - << "\n\tNC: " << NC - << "\n\tthis: " << this - ); - - if (nr() != length) - data.set_size(length,1); - } - } - - long nr ( - ) const { return data.nr(); } - - long nc ( - ) const { return data.nc(); } - - long size ( - ) const { return data.nr()*data.nc(); } - - template <typename U, size_t len> - matrix& operator= ( - U (&array)[len] - ) - { - COMPILE_TIME_ASSERT(NR*NC == len && len > 0); - size_t idx = 0; - for (long r = 0; r < NR; ++r) - { - for (long c = 0; c < NC; ++c) - { - data(r,c) = static_cast<T>(array[idx]); - ++idx; - } - } - return *this; - } - - template <typename EXP> - matrix& operator= ( - const matrix_exp<EXP>& m - ) - { - // You get an error on this line if the matrix you are trying to - // assign m to is a statically sized matrix and m's dimensions don't - // match that of *this. - COMPILE_TIME_ASSERT(EXP::NR == NR || NR == 0 || EXP::NR == 0); - COMPILE_TIME_ASSERT(EXP::NC == NC || NC == 0 || EXP::NC == 0); - DLIB_ASSERT((NR == 0 || nr() == m.nr()) && - (NC == 0 || nc() == m.nc()), - "\tmatrix& matrix::operator=(const matrix_exp& m)" - << "\n\tYou are trying to assign a dynamically sized matrix to a statically sized matrix with the wrong size" - << "\n\tnr(): " << nr() - << "\n\tnc(): " << nc() - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tthis: " << this - ); - - // You get an error on this line if the matrix m contains a type that isn't - // the same as the type contained in the target matrix. - COMPILE_TIME_ASSERT((is_same_type<typename EXP::type,type>::value == true) || - (is_matrix<typename EXP::type>::value == true)); - if (m.destructively_aliases(*this) == false) - { - // This if statement is seemingly unnecessary since set_size() contains this - // exact same if statement. However, structuring the code this way causes - // gcc to handle the way it inlines this function in a much more favorable way. - if (data.nr() == m.nr() && data.nc() == m.nc()) - { - matrix_assign(*this, m); - } - else - { - set_size(m.nr(),m.nc()); - matrix_assign(*this, m); - } - } - else - { - // we have to use a temporary matrix object here because - // *this is aliased inside the matrix_exp m somewhere. - matrix temp; - temp.set_size(m.nr(),m.nc()); - matrix_assign(temp, m); - temp.swap(*this); - } - return *this; - } - - template <typename EXP> - matrix& operator += ( - const matrix_exp<EXP>& m - ) - { - // The matrix you are trying to assign m to is a statically sized matrix and - // m's dimensions don't match that of *this. - COMPILE_TIME_ASSERT(EXP::NR == NR || NR == 0 || EXP::NR == 0); - COMPILE_TIME_ASSERT(EXP::NC == NC || NC == 0 || EXP::NC == 0); - COMPILE_TIME_ASSERT((is_same_type<typename EXP::type,type>::value == true)); - if (nr() == m.nr() && nc() == m.nc()) - { - if (m.destructively_aliases(*this) == false) - { - matrix_assign(*this, *this + m); - } - else - { - // we have to use a temporary matrix object here because - // this->data is aliased inside the matrix_exp m somewhere. - matrix temp; - temp.set_size(m.nr(),m.nc()); - matrix_assign(temp, *this + m); - temp.swap(*this); - } - } - else - { - DLIB_ASSERT(size() == 0, - "\t const matrix::operator+=(m)" - << "\n\t You are trying to add two matrices that have incompatible dimensions."); - *this = m; - } - return *this; - } - - - template <typename EXP> - matrix& operator -= ( - const matrix_exp<EXP>& m - ) - { - // The matrix you are trying to assign m to is a statically sized matrix and - // m's dimensions don't match that of *this. - COMPILE_TIME_ASSERT(EXP::NR == NR || NR == 0 || EXP::NR == 0); - COMPILE_TIME_ASSERT(EXP::NC == NC || NC == 0 || EXP::NC == 0); - COMPILE_TIME_ASSERT((is_same_type<typename EXP::type,type>::value == true)); - if (nr() == m.nr() && nc() == m.nc()) - { - if (m.destructively_aliases(*this) == false) - { - matrix_assign(*this, *this - m); - } - else - { - // we have to use a temporary matrix object here because - // this->data is aliased inside the matrix_exp m somewhere. - matrix temp; - temp.set_size(m.nr(),m.nc()); - matrix_assign(temp, *this - m); - temp.swap(*this); - } - } - else - { - DLIB_ASSERT(size() == 0, - "\t const matrix::operator-=(m)" - << "\n\t You are trying to subtract two matrices that have incompatible dimensions."); - *this = -m; - } - return *this; - } - - template <typename EXP> - matrix& operator *= ( - const matrix_exp<EXP>& m - ) - { - *this = *this * m; - return *this; - } - - matrix& operator += ( - const matrix& m - ) - { - const long size = m.nr()*m.nc(); - if (nr() == m.nr() && nc() == m.nc()) - { - for (long i = 0; i < size; ++i) - data(i) += m.data(i); - } - else - { - DLIB_ASSERT(this->size() == 0, - "\t const matrix::operator+=(m)" - << "\n\t You are trying to add two matrices that have incompatible dimensions."); - - set_size(m.nr(), m.nc()); - for (long i = 0; i < size; ++i) - data(i) = m.data(i); - } - return *this; - } - - matrix& operator -= ( - const matrix& m - ) - { - const long size = m.nr()*m.nc(); - if (nr() == m.nr() && nc() == m.nc()) - { - for (long i = 0; i < size; ++i) - data(i) -= m.data(i); - } - else - { - DLIB_ASSERT(this->size() == 0, - "\t const matrix::operator-=(m)" - << "\n\t You are trying to subtract two matrices that have incompatible dimensions."); - set_size(m.nr(), m.nc()); - for (long i = 0; i < size; ++i) - data(i) = -m.data(i); - } - return *this; - } - - matrix& operator += ( - const T val - ) - { - const long size = nr()*nc(); - for (long i = 0; i < size; ++i) - data(i) += val; - - return *this; - } - - matrix& operator -= ( - const T val - ) - { - const long size = nr()*nc(); - for (long i = 0; i < size; ++i) - data(i) -= val; - - return *this; - } - - matrix& operator *= ( - const T a - ) - { - *this = *this * a; - return *this; - } - - matrix& operator /= ( - const T a - ) - { - *this = *this / a; - return *this; - } - - matrix& operator= ( - const matrix& m - ) - { - if (this != &m) - { - set_size(m.nr(),m.nc()); - const long size = m.nr()*m.nc(); - for (long i = 0; i < size; ++i) - data(i) = m.data(i); - } - return *this; - } - - void swap ( - matrix& item - ) - { - data.swap(item.data); - } - - template <typename U> - bool aliases ( - const matrix_exp<U>& - ) const { return false; } - - bool aliases ( - const matrix_exp<matrix<T,num_rows,num_cols, mem_manager,layout> >& item - ) const { return (this == &item); } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& - ) const { return false; } - - // These two aliases() routines are defined in matrix_mat.h - bool aliases ( - const matrix_exp<matrix_op<op_pointer_to_mat<T> > >& item - ) const; - bool aliases ( - const matrix_exp<matrix_op<op_pointer_to_col_vect<T> > >& item - ) const; - - iterator begin() - { - if (size() != 0) - return &data(0,0); - else - return 0; - } - - iterator end() - { - if (size() != 0) - return &data(0,0)+size(); - else - return 0; - } - - const_iterator begin() const - { - if (size() != 0) - return &data(0,0); - else - return 0; - } - - const_iterator end() const - { - if (size() != 0) - return &data(0,0)+size(); - else - return 0; - } - - private: - struct literal_assign_helper - { - /* - This struct is a helper struct returned by the operator<<() function below. It is - used primarily to enable us to put DLIB_CASSERT statements on the usage of the - operator<< form of matrix assignment. - */ - - literal_assign_helper(const literal_assign_helper& item) : m(item.m), r(item.r), c(item.c), has_been_used(false) {} - explicit literal_assign_helper(matrix* m_): m(m_), r(0), c(0),has_been_used(false) {next();} - ~literal_assign_helper() noexcept(false) - { - DLIB_CASSERT(!has_been_used || r == m->nr(), - "You have used the matrix comma based assignment incorrectly by failing to\n" - "supply a full set of values for every element of a matrix object.\n"); - } - - const literal_assign_helper& operator, ( - const T& val - ) const - { - DLIB_CASSERT(r < m->nr() && c < m->nc(), - "You have used the matrix comma based assignment incorrectly by attempting to\n" << - "supply more values than there are elements in the matrix object being assigned to.\n\n" << - "Did you forget to call set_size()?" - << "\n\t r: " << r - << "\n\t c: " << c - << "\n\t m->nr(): " << m->nr() - << "\n\t m->nc(): " << m->nc()); - (*m)(r,c) = val; - next(); - has_been_used = true; - return *this; - } - - private: - - friend class matrix<T,num_rows,num_cols,mem_manager,layout>; - - void next ( - ) const - { - ++c; - if (c == m->nc()) - { - c = 0; - ++r; - } - } - - matrix* m; - mutable long r; - mutable long c; - mutable bool has_been_used; - }; - - public: - - matrix& operator = ( - const literal_assign_helper& val - ) - { - *this = *val.m; - return *this; - } - - const literal_assign_helper operator = ( - const T& val - ) - { - // assign the given value to every spot in this matrix - const long size = nr()*nc(); - for (long i = 0; i < size; ++i) - data(i) = val; - - // Now return the literal_assign_helper so that the user - // can use the overloaded comma notation to initialize - // the matrix if they want to. - return literal_assign_helper(this); - } - - private: - - - typename layout::template layout<T,NR,NC,mem_manager> data; - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - typename mm, - typename l - > - void swap( - matrix<T,NR,NC,mm,l>& a, - matrix<T,NR,NC,mm,l>& b - ) { a.swap(b); } - - template < - typename T, - long NR, - long NC, - typename mm, - typename l - > - void serialize ( - const matrix<T,NR,NC,mm,l>& item, - std::ostream& out - ) - { - try - { - // The reason the serialization is a little funny is because we are trying to - // maintain backwards compatibility with an older serialization format used by - // dlib while also encoding things in a way that lets the array2d and matrix - // objects have compatible serialization formats. - serialize(-item.nr(),out); - serialize(-item.nc(),out); - for (long r = 0; r < item.nr(); ++r) - { - for (long c = 0; c < item.nc(); ++c) - { - serialize(item(r,c),out); - } - } - } - catch (serialization_error& e) - { - throw serialization_error(e.info + "\n while serializing dlib::matrix"); - } - } - - template < - typename T, - long NR, - long NC, - typename mm, - typename l - > - void deserialize ( - matrix<T,NR,NC,mm,l>& item, - std::istream& in - ) - { - try - { - long nr, nc; - deserialize(nr,in); - deserialize(nc,in); - - // this is the newer serialization format - if (nr < 0 || nc < 0) - { - nr *= -1; - nc *= -1; - } - - if (NR != 0 && nr != NR) - throw serialization_error("Error while deserializing a dlib::matrix. Invalid rows"); - if (NC != 0 && nc != NC) - throw serialization_error("Error while deserializing a dlib::matrix. Invalid columns"); - - item.set_size(nr,nc); - for (long r = 0; r < nr; ++r) - { - for (long c = 0; c < nc; ++c) - { - deserialize(item(r,c),in); - } - } - } - catch (serialization_error& e) - { - throw serialization_error(e.info + "\n while deserializing a dlib::matrix"); - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - typename mm, - typename l - > - void serialize ( - const ramdump_t<matrix<T,NR,NC,mm,l>>& item_, - std::ostream& out - ) - { - auto& item = item_.item; - serialize(item.nr(), out); - serialize(item.nc(), out); - if (item.size() != 0) - out.write((char*)&item(0,0), sizeof(item(0,0))*item.size()); - } - - template < - typename T, - long NR, - long NC, - typename mm, - typename l - > - void deserialize ( - ramdump_t<matrix<T,NR,NC,mm,l>>&& item_, - std::istream& in - ) - { - auto& item = item_.item; - long nr, nc; - deserialize(nr, in); - deserialize(nc, in); - item.set_size(nr,nc); - if (item.size() != 0) - in.read((char*)&item(0,0), sizeof(item(0,0))*item.size()); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - std::ostream& operator<< ( - std::ostream& out, - const matrix_exp<EXP>& m - ) - { - using namespace std; - const streamsize old = out.width(); - - // first figure out how wide we should make each field - string::size_type w = 0; - ostringstream sout; - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - sout << m(r,c); - w = std::max(sout.str().size(),w); - sout.str(""); - } - } - - // now actually print it - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - out.width(static_cast<streamsize>(w)); - out << m(r,c) << " "; - } - out << "\n"; - } - out.width(old); - return out; - } - - /* - template < - typename T, - long NR, - long NC, - typename MM, - typename L - > - std::istream& operator>> ( - std::istream& in, - matrix<T,NR,NC,MM,L>& m - ); - - This function is defined inside the matrix_read_from_istream.h file. - */ - -// ---------------------------------------------------------------------------------------- - - class print_matrix_as_csv_helper - { - /*! - This object is used to define an io manipulator for matrix expressions. - In particular, this code allows you to write statements like: - cout << csv << yourmatrix; - and have it print the matrix with commas separating each element. - !*/ - public: - print_matrix_as_csv_helper (std::ostream& out_) : out(out_) {} - - template <typename EXP> - std::ostream& operator<< ( - const matrix_exp<EXP>& m - ) - { - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - if (c+1 == m.nc()) - out << m(r,c) << "\n"; - else - out << m(r,c) << ", "; - } - } - return out; - } - - private: - std::ostream& out; - }; - - class print_matrix_as_csv {}; - const print_matrix_as_csv csv = print_matrix_as_csv(); - inline print_matrix_as_csv_helper operator<< ( - std::ostream& out, - const print_matrix_as_csv& - ) - { - return print_matrix_as_csv_helper(out); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - class const_temp_matrix; - - template < - typename EXP - > - struct matrix_traits<const_temp_matrix<EXP> > - { - typedef typename EXP::type type; - typedef typename EXP::const_ret_type const_ret_type; - typedef typename EXP::mem_manager_type mem_manager_type; - typedef typename EXP::layout_type layout_type; - const static long NR = EXP::NR; - const static long NC = EXP::NC; - const static long cost = 1; - }; - - template <typename EXP> - class const_temp_matrix : public matrix_exp<const_temp_matrix<EXP> >, noncopyable - { - public: - typedef typename matrix_traits<const_temp_matrix>::type type; - typedef typename matrix_traits<const_temp_matrix>::const_ret_type const_ret_type; - typedef typename matrix_traits<const_temp_matrix>::mem_manager_type mem_manager_type; - typedef typename matrix_traits<const_temp_matrix>::layout_type layout_type; - const static long NR = matrix_traits<const_temp_matrix>::NR; - const static long NC = matrix_traits<const_temp_matrix>::NC; - const static long cost = matrix_traits<const_temp_matrix>::cost; - - const_temp_matrix ( - const matrix_exp<EXP>& item - ) : - ref_(item.ref()) - {} - const_temp_matrix ( - const EXP& item - ) : - ref_(item) - {} - - const_ret_type operator() ( - long r, - long c - ) const { return ref_(r,c); } - - const_ret_type operator() ( long i ) const - { return ref_(i); } - - template <typename U> - bool aliases ( - const matrix_exp<U>& item - ) const { return ref_.aliases(item); } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& item - ) const { return ref_.destructively_aliases(item); } - - long nr ( - ) const { return ref_.nr(); } - - long nc ( - ) const { return ref_.nc(); } - - private: - - typename conditional_matrix_temp<const EXP, (EXP::cost <= 1)>::type ref_; - }; - -// ---------------------------------------------------------------------------------------- - - typedef matrix<double,0,0,default_memory_manager,column_major_layout> matrix_colmajor; - typedef matrix<float,0,0,default_memory_manager,column_major_layout> fmatrix_colmajor; - -} - -#ifdef _MSC_VER -// put warnings back to their default settings -#pragma warning(default : 4355) -#pragma warning(default : 4723) -#endif - -#endif // DLIB_MATRIx_ - diff --git a/ml/dlib/dlib/matrix/matrix_abstract.h b/ml/dlib/dlib/matrix/matrix_abstract.h deleted file mode 100644 index 0d05ce981..000000000 --- a/ml/dlib/dlib/matrix/matrix_abstract.h +++ /dev/null @@ -1,857 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_MATRIx_ABSTRACT_ -#ifdef DLIB_MATRIx_ABSTRACT_ - -#include "matrix_exp_abstract.h" -#include "../serialize.h" -#include "../algs.h" -#include "matrix_data_layout_abstract.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - /* - Note that these operator prototypes are not correct C++ (the real versions, which - you can see in the implementation are really complex and so probably would - distract/confuse people if shown here). Think of this as just a list of the - operators available to you and what they do. - */ - - const matrix_exp operator* ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - requires - - m1.nc() == m2.nr() - - m1.size() > 0 && m2.size() > 0 - (you can't multiply any sort of empty matrices together) - - m1 and m2 both contain elements of the same type - ensures - - returns the result of doing the matrix multiplication m1*m2. The resulting - matrix will have m1.nr() rows and m2.nc() columns. - !*/ - - const matrix_exp operator+ ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - requires - - m1.nr() == m2.nr() - - m1.nc() == m2.nc() - - m1 and m2 both contain elements of the same type - ensures - - returns a matrix R such that for all valid r and c: - R(r,c) == m1(r,c) + m2(r,c) - (i.e. returns the result of doing a pairwise addition of the matrices m1 and m2.) - The resulting matrix will have the same dimensions as the originals. - !*/ - - const matrix_exp operator- ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - requires - - m1.nr() == m2.nr() - - m1.nc() == m2.nc() - - m1 and m2 both contain elements of the same type - ensures - - returns a matrix R such that for all valid r and c: - R(r,c) == m1(r,c) - m2(r,c) - (i.e. returns the result of doing a pairwise subtraction of the matrices m1 and m2.) - The resulting matrix will have the same dimensions as the originals. - !*/ - - template <typename T> - const matrix_exp operator* ( - const matrix_exp& m, - const T& value - ); - /*! - ensures - - returns the result of multiplying all the elements of matrix m by the given - scalar value. The resulting matrix will have the same dimensions as m. - !*/ - - template <typename T> - const matrix_exp operator* ( - const T& value, - const matrix_exp& m - ); - /*! - ensures - - returns the result of multiplying all the elements of matrix m by the given - scalar value. The resulting matrix will have the same dimensions as m. - !*/ - - const matrix_exp operator- ( - const matrix_exp& m - ); - /*! - ensures - - returns -1*m - !*/ - - template <typename T> - const matrix_exp operator/ ( - const matrix_exp& m, - const T& value - ); - /*! - ensures - - returns the result of dividing all the elements of matrix m by the given - scalar value. The resulting matrix will have the same dimensions as m. - !*/ - - template <typename T> - const matrix_exp operator/ ( - const T& value, - const matrix_exp& m - ); - /*! - ensures - - returns the result of dividing the given scalar value by all the elements - of matrix m. The resulting matrix will have the same dimensions as m. - !*/ - - template <typename T> - const matrix_exp operator+ ( - const matrix_exp& m, - const T& value - ); - /*! - ensures - - returns the result of adding value to all the elements of matrix m. - The resulting matrix will have the same dimensions as m. - !*/ - - template <typename T> - const matrix_exp operator+ ( - const T& value, - const matrix_exp& m - ); - /*! - ensures - - returns the result of adding value to all the elements of matrix m. - The resulting matrix will have the same dimensions as m. - !*/ - - template <typename T> - const matrix_exp operator- ( - const matrix_exp& m, - const T& value - ); - /*! - ensures - - returns the result of subtracting value from all the elements of matrix m. - The resulting matrix will have the same dimensions as m. - !*/ - - template <typename T> - const matrix_exp operator- ( - const T& value, - const matrix_exp& m - ); - /*! - ensures - - Returns a matrix M such that: - - M has the same dimensions as m - - M contains the same type of element as m - - for all valid r and c: - - M(r,c) == value - m(r,c) - !*/ - - bool operator== ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - ensures - - if (m1.nr() == m2.nr() && m1.nc() == m2.nc() && - for all valid r and c: m1(r,c) == m2(r,c) ) then - - returns true - - else - - returns false - !*/ - - bool operator!= ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - ensures - - returns !(m1 == m2) - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long num_rows = 0, - long num_cols = 0, - typename mem_manager = default_memory_manager, - typename layout = row_major_layout - > - class matrix : public matrix_exp<matrix<T,num_rows,num_cols,mem_manager,layout> > - { - /*! - REQUIREMENTS ON num_rows and num_cols - both must be bigger than or equal to 0 - - REQUIREMENTS ON mem_manager - must be an implementation of memory_manager/memory_manager_kernel_abstract.h or - must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or - must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h - mem_manager::type can be set to anything. - - REQUIREMENTS ON layout - Must be either row_major_layout or column_major_layout - - INITIAL VALUE - - if (num_rows > 0) then - - nr() == num_rows - - else - - nr() == 0 - - - if (num_cols > 0) then - - nc() == num_cols - - else - - nc() == 0 - - WHAT THIS OBJECT REPRESENTS - This object represents a matrix of nr() rows and nc() columns. This object - is also a matrix_exp. Thus it can be used in all of the above - global operators. - - The number of rows and columns of this object are determined by the template - arguments num_rows and num_cols. If num_rows or num_cols are 0 then - the matrix starts out empty (i.e. nr() == 0 and nc() == 0) and you may change - its size via the set_size() member function. - - Setting num_rows or num_cols to something other than 0 causes that dimension - to have a fixed size. Setting a fixed size at compile time is useful because - any errors related to operating on matrices with incompatible dimensions will - be detected at compile time. It also allows the compiler to perform loop - unrolling which can result in substantially faster code. - - Also note that the elements of this matrix are laid out in memory by the layout - object supplied as a template argument to this class. The row_major_layout - sets elements down contiguously in memory and in row major order. Additionally, - all memory allocations are performed using the memory manager object supplied as - a template argument to this class. - !*/ - - public: - typedef T type; - typedef mem_manager mem_manager_type; - typedef layout layout_type; - const static long NR = num_rows; - const static long NC = num_cols; - const static long cost = 1; - typedef T* iterator; - typedef const T* const_iterator; - - matrix ( - ); - /*! - ensures - - #*this is properly initialized - - #aliases(*this) == true - - #ref().aliases(*this) == true - !*/ - - explicit matrix ( - long length - ); - /*! - requires - - NR == 1 || NC == 1 (i.e. this must be a column or row vector) - - length >= 0 - - if (NR == 1 && NC > 0) then - - length == NC - - if (NC == 1 && NR > 0) then - - length == NR - ensures - - #*this is properly initialized - - #aliases(*this) == true - - #ref().aliases(*this) == true - - if (NR == 1) then - - #nr() == 1 - - #nc() == length - - else - - #nr() == length - - #nc() == 1 - !*/ - - matrix ( - long rows, - long cols - ); - /*! - requires - - rows == NR || NR == 0 - - cols == NC || NC == 0 - - rows >= 0 && cols >= 0 - ensures - - #*this is properly initialized - - #aliases(*this) == true - - #ref().aliases(*this) == true - - #nr() == rows - - #nc() == cols - !*/ - - template <typename EXP> - matrix ( - const matrix_exp<EXP>& m - ); - /*! - requires - - matrix_exp<EXP>::type == T - (i.e. m contains the same type as *this does) - - if (NR != 0) then NR == m.nr() - - if (NC != 0) then NC == m.nc() - ensures - - #*this == m - - #aliases(*this) == true - - #ref().aliases(*this) == true - !*/ - - template <typename U, size_t len> - explicit matrix ( - U (&array)[len] - ); - /*! - requires - - NR != 0 && NC != 0 (i.e. you can only use this constructor on statically sized matrices) - - len == nr()*nc() (i.e. the array you give here must be the right size) - ensures - - for all valid r and c: - #(*this)(r,c) == array[r*nc() + c] - (i.e. initializes this matrix with the contents of the given array) - - #aliases(*this) == true - - #ref().aliases(*this) == true - !*/ - - matrix( - const std::initializer_list<T>& l - ); - /*! - requires - - This matrix is capable of having a size() == l.size(). Therefore, if - NR*NC != 0 then l.size() must equal NR*NC. Alternatively, if NR or NC is - != 0 then l.size() must be a multiple of the non-zero NR or NC. - ensures - - #size() == l.size() - - The contents of l are enumerated and read into the matrix in row major order. - - if (NR != 0) then - - #nr() == NR - - #nc() == l.size()/NR - - if (NC != 0) then - - #nr() == l.size()/NC - - #nc() == NC - - if (NR*NC==0) then - - #nr() == l.size() - - #nc() == 1 - - #aliases(*this) == true - - #ref().aliases(*this) == true - !*/ - - T& operator() ( - long r, - long c - ); - /*! - requires - - 0 <= r < nr() - - 0 <= c < nc() - ensures - - returns a reference to the value at the given row and column in - this matrix. - !*/ - - const T& operator() ( - long r, - long c - ) const; - /*! - requires - - 0 <= r < nr() - - 0 <= c < nc() - ensures - - returns a const reference to the value at the given row and column in - this matrix. - !*/ - - T& operator() ( - long i - ); - /*! - requires - - nc() == 1 || nr() == 1 (i.e. this must be a column or row vector) - - 0 <= i < size() - ensures - - if (nc() == 1) then - - returns a reference to (*this)(i,0) - - else - - returns a reference to (*this)(0,i) - !*/ - - const T& operator() ( - long i - ) const; - /*! - requires - - nc() == 1 || nr() == 1 (i.e. this must be a column or row vector) - - 0 <= i < size() - ensures - - if (nc() == 1) then - - returns a reference to (*this)(i,0) - - else - - returns a reference to (*this)(0,i) - !*/ - - operator const type ( - ) const; - /*! - requires - - nr() == 1 - - nc() == 1 - ensures - - returns (*this)(0,0) - !*/ - - long nr( - ) const; - /*! - ensures - - returns the number of rows in this matrix - !*/ - - long nc( - ) const; - /*! - ensures - - returns the number of columns in this matrix - !*/ - - long size ( - ) const; - /*! - ensures - - returns nr()*nc() - !*/ - - void set_size ( - long rows, - long cols - ); - /*! - requires - - rows == NR || NR == 0 - - cols == NC || NC == 0 - - rows >= 0 && cols >= 0 - ensures - - #nr() == rows - - #nc() == cols - !*/ - - void set_size ( - long length - ); - /*! - requires - - NR == 1 || NC == 1 (i.e. this must be a column or row vector) - - length >= 0 - - if (NR == 1 && NC > 0) then - - length == NC - - if (NC == 1 && NR > 0) then - - length == NR - ensures - - if (NR == 1) then - - #nr() == 1 - - #nc() == length - - else - - #nr() == length - - #nc() == 1 - !*/ - - template <typename U, size_t len> - matrix& operator= ( - U (&array)[len] - ); - /*! - requires - - len == nr()*nc() (i.e. the array you give here must be the right size) - ensures - - for all valid r and c: - #(*this)(r,c) == array[r*nc() + c] - (i.e. loads this matrix with the contents of the given array) - - returns *this - !*/ - - matrix& operator=( - const std::initializer_list<T>& l - ); - /*! - requires - - This matrix is capable of having a size() == l.size(). Therefore, if - NR*NC != 0 then l.size() must equal NR*NC. Alternatively, if NR or NC is - != 0 then l.size() must be a multiple of the non-zero NR or NC. - ensures - - Assigns the contents of l to *this by performing: matrix(l).swap(*this) - - returns *this - !*/ - - template <typename EXP> - matrix& operator= ( - const matrix_exp<EXP>& m - ); - /*! - requires - - matrix_exp<EXP>::type == T - (i.e. m contains the same type as *this does) - - if (NR != 0) then NR == m.nr() - - if (NC != 0) then NC == m.nc() - ensures - - copies the given matrix expression m to *this - - returns *this - !*/ - - template <typename EXP> - matrix& operator += ( - const matrix_exp<EXP>& m - ); - /*! - requires - - matrix_exp<EXP>::type == T - - One of the following is true: - - nr() == m.nr() && nc() == m.nc() - - size() == 0 - (i.e. this matrix must have matching dimensions or it must be empty) - ensures - - if (nr() == m.nr() && nc() == m.nc()) then - - #(*this) == *this + m - - else - - #(*this) == m - (i.e. if the dimensions don't match then this function performs a - normal assignment) - - returns *this - !*/ - - template <typename EXP> - matrix& operator -= ( - const matrix_exp<EXP>& m - ); - /*! - requires - - matrix_exp<EXP>::type == T - - One of the following is true: - - nr() == m.nr() && nc() == m.nc() - - size() == 0 - (i.e. this matrix must have matching dimensions or it must be empty) - ensures - - if (nr() == m.nr() && nc() == m.nc()) then - - #(*this) == *this - m - - else - - #(*this) == -m - - returns *this - !*/ - - template <typename EXP> - matrix& operator *= ( - const matrix_exp<EXP>& m - ); - /*! - requires - - matrix_exp<EXP>::type == T - (i.e. m must contain the same type of element as *this) - - nc() == m.nr() - - size() > 0 && m.size() > 0 - (you can't multiply any sort of empty matrices together) - ensures - - #(*this) == *this * m - - returns *this - !*/ - - matrix& operator *= ( - const T& a - ); - /*! - ensures - - #(*this) == *this * a - - returns *this - !*/ - - matrix& operator /= ( - const T& a - ); - /*! - ensures - - #(*this) == *this / a - - returns *this - !*/ - - matrix& operator += ( - const T& a - ); - /*! - ensures - - #(*this) == *this + a - - returns *this - !*/ - - matrix& operator -= ( - const T& a - ); - /*! - ensures - - #(*this) == *this - a - - returns *this - !*/ - - const literal_assign_helper operator = ( - const T& val - ); - /*! - This function is somewhat different than all the others defined in this file. - The purpose of this function is to enable you to easily initialize a matrix object. - For example: - matrix<double> m(2,3); - m = 1,2,3, - 4,5,6; - - The above code creates a matrix m with 2 rows and 3 columns and sets it so that - it contains the matrix | 1 2 3 | - | 4 5 6 | - - You can also use this function to assign to all elements of a matrix. So - saying m = 3; would assign all elements of m equal to 3. - - Note that to use this method of assignment it is required that you supply - exactly m.size() or 1 values so that the matrix is fully initialized. Supplying - fewer or more than that is an error that will cause a dlib::fatal_error to be - thrown. - - Note also that using an expression of the form m = scalar; when m.size() == 0 - is legal but has no effect on m. - !*/ - - void swap ( - matrix& item - ); - /*! - ensures - - swaps *this and item - !*/ - - iterator begin( - ); - /*! - ensures - - returns a random access iterator pointing to the first element in this - matrix. - - The iterator will iterate over the elements of the matrix in row major - order if layout is row_major_layout or in column major order if layout is - column_major_layout. - !*/ - - iterator end( - ); - /*! - ensures - - returns a random access iterator pointing to one past the end of the last - element in this matrix. - !*/ - - const_iterator begin( - ) const; - /*! - ensures - - returns a random access iterator pointing to the first element in this - matrix. - - The iterator will iterate over the elements of the matrix in row major - order if layout is row_major_layout or in column major order if layout is - column_major_layout. - !*/ - - const_iterator end( - ) const; - /*! - ensures - - returns a random access iterator pointing to one past the end of the last - element in this matrix. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - /*!A matrix_colmajor - This is just a typedef of the matrix object that uses column major layout. - !*/ - typedef matrix<double,0,0,default_memory_manager,column_major_layout> matrix_colmajor; - - /*!A fmatrix_colmajor - This is just a typedef of the matrix object that uses column major layout. - !*/ - typedef matrix<float,0,0,default_memory_manager,column_major_layout> fmatrix_colmajor; - -// ---------------------------------------------------------------------------------------- -template < - typename T, - long NR, - long NC, - typename mm, - typename l - > - void swap( - matrix<T,NR,NC,mm,l>& a, - matrix<T,NR,NC,mm,l>& b - ) { a.swap(b); } - /*! - Provides a global swap function - !*/ - - template < - typename T, - long NR, - long NC, - typename mm, - typename l - > - void serialize ( - const matrix<T,NR,NC,mm,l>& item, - std::ostream& out - ); - /*! - Provides serialization support. Note that the serialization formats used by the - dlib::matrix and dlib::array2d objects are compatible. That means you can load the - serialized data from one into another and it will work properly. - !*/ - - template < - typename T, - long NR, - long NC, - typename mm, - typename l - > - void deserialize ( - matrix<T,NR,NC,mm,l>& item, - std::istream& in - ); - /*! - Provides deserialization support - !*/ - - template < - typename EXP - > - std::ostream& operator<< ( - std::ostream& out, - const matrix_exp<EXP>& m - ); - /*! - ensures - - writes m to the given out stream in a form suitable for human consumption. - - returns out - !*/ - - template < - typename T, - long NR, - long NC, - typename MM, - typename L - > - std::istream& operator>> ( - std::istream& in, - matrix<T,NR,NC,MM,L>& m - ); - /*! - ensures - - Tries to read a matrix from the given input stream and store it into #m. - - The format expected is the text format output by the above operator<<(). - That is, the format should be a grid of text such as: - 2 3 4 - 5 2 6 - - The separation between numbers can be any number of whitespace characters or - commas. - - The matrix data is assumed to end upon the first blank line or end-of-file, - whichever comes first. This means you can create an input stream with - multiple matrices in it by separating them with empty lines. - - returns in. - - If there was a formatting error or something which prevents the input data - from being parsed into a matrix then #in.fail() == true. - !*/ - - /*!A csv - This object is used to define an io manipulator for matrix expressions. In - particular, you can write statements like: - cout << csv << yourmatrix; - and have it print the matrix with commas separating each element. - !*/ - some_undefined_iomnaip_type csv; - -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - class const_temp_matrix : public matrix_exp<const_temp_matrix<EXP> >, noncopyable - { - /*! - REQUIREMENTS ON EXP - - must be an object that inherits publicly from matrix_exp. - - WHAT THIS OBJECT REPRESENTS - This object represents a copy of a matrix expression. The twist - is that it only actually makes a copy of its input matrix expression - if that matrix expression is costly to evaluate. If it has - low cost then this object just stores a reference. - - This class is useful in cases where you write a function that - takes a matrix_exp object as input and you want to do some - intensive computation that looks at each element of that matrix_exp - many times. If the input matrix_exp has a high cost then you want - to store it into a temporary matrix. But if it has low cost then - it is faster if you just use a reference to it. The const_temp_matrix - makes doing this easy. - !*/ - public: - - const_temp_matrix ( - const matrix_exp<EXP>& item - ); - /*! - ensures - - #*this == item - - if (EXP::cost <= 1) then - - this const_temp_matrix stores a reference to the item matrix - - else - - this const_temp_matrix creates a temporary matrix and copies - item into it - !*/ - - const_temp_matrix ( - const EXP& item - ); - /*! - ensures - - #*this == item - - if (EXP::cost <= 1) then - - this const_temp_matrix stores a reference to the item matrix - - else - - this const_temp_matrix creates a temporary matrix and copies - item into it - !*/ - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_ABSTRACT_ - diff --git a/ml/dlib/dlib/matrix/matrix_assign.h b/ml/dlib/dlib/matrix/matrix_assign.h deleted file mode 100644 index da53050b1..000000000 --- a/ml/dlib/dlib/matrix/matrix_assign.h +++ /dev/null @@ -1,978 +0,0 @@ -// Copyright (C) 2008 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_ASSIGn_ -#define DLIB_MATRIx_ASSIGn_ - -#include "matrix.h" -#include "matrix_utilities.h" -#include "matrix_subexp.h" -#include "../enable_if.h" -#include "matrix_assign_fwd.h" -#include "matrix_default_mul.h" -#include "matrix_conj_trans.h" -#include "matrix_mat.h" - -namespace dlib -{ - /* - This file contains some templates that are used inside the matrix_blas_bindings.h - file to bind various matrix expressions to optimized code for carrying them out. - */ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - namespace blas_bindings - { - - // ------------------------------------------------------------------------------------ - - template <typename T> - void zero_matrix ( - T& m - ) - { - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - m(r,c) = 0; - } - } - } - - // ------------------------------------------------------------------------------------ - - // This template struct is used to tell us if a matrix expression contains a matrix multiply. - template <typename T> - struct has_matrix_multiply - { - const static bool value = false; - }; - - template <typename T, typename U> - struct has_matrix_multiply<matrix_multiply_exp<T,U> > - { const static bool value = true; }; - - template <typename T, typename U> - struct has_matrix_multiply<matrix_add_exp<T,U> > - { const static bool value = has_matrix_multiply<T>::value || has_matrix_multiply<U>::value; }; - - template <typename T, typename U> - struct has_matrix_multiply<matrix_subtract_exp<T,U> > - { const static bool value = has_matrix_multiply<T>::value || has_matrix_multiply<U>::value; }; - - template <typename T, bool Tb> - struct has_matrix_multiply<matrix_mul_scal_exp<T,Tb> > - { const static bool value = true; }; - - template <typename T> - struct has_matrix_multiply<matrix_div_scal_exp<T> > - { const static bool value = has_matrix_multiply<T>::value; }; - - template <typename T> - struct has_matrix_multiply<matrix_op<T> > - { const static bool value = has_matrix_multiply<T>::value; }; - - template <typename T> - struct has_matrix_multiply<op_trans<T> > - { const static bool value = has_matrix_multiply<T>::value; }; - - template <typename T> - struct has_matrix_multiply<op_conj_trans<T> > - { const static bool value = has_matrix_multiply<T>::value; }; - - template <typename T> - struct has_matrix_multiply<op_conj<T> > - { const static bool value = has_matrix_multiply<T>::value; }; - - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - - const int unknown_matrix = 0; - const int general_matrix = 1; - const int row_matrix = 2; - const int column_matrix = 3; - - // ------------------------------------------------------------------------------------ - - template <typename T> - struct matrix_type_id - { - const static int value = unknown_matrix; - }; - - template <typename T, long NR, long NC, typename MM, typename L> - struct matrix_type_id<matrix<T,NR,NC,MM,L> > - { - const static int value = general_matrix; - }; - - template <typename T, long NR, typename MM, typename L> - struct matrix_type_id<matrix<T,NR,1,MM,L> > - { - const static int value = column_matrix; - }; - - template <typename T, typename MM, typename L> - struct matrix_type_id<matrix<T,1,1,MM,L> > - { - const static int value = column_matrix; - }; - - template <typename T, long NC, typename MM, typename L> - struct matrix_type_id<matrix<T,1,NC,MM,L> > - { - const static int value = row_matrix; - }; - - // ------------------------------------------------------------------------------------ - - template <typename T, long NR, long NC, typename MM, typename L> - struct matrix_type_id<matrix_op<op_colm<matrix<T,NR,NC,MM,L> > > > - { - const static int value = column_matrix; - }; - - template <typename T, long NR, long NC, typename MM, typename L> - struct matrix_type_id<matrix_op<op_rowm<matrix<T,NR,NC,MM,L> > > > - { - const static int value = row_matrix; - }; - - template <typename T, long NR, long NC, typename MM, typename L> - struct matrix_type_id<matrix_op<op_colm2<matrix<T,NR,NC,MM,L> > > > - { - const static int value = column_matrix; - }; - - template <typename T, long NR, long NC, typename MM, typename L> - struct matrix_type_id<matrix_op<op_rowm2<matrix<T,NR,NC,MM,L> > > > - { - const static int value = row_matrix; - }; - - template <typename T, long NR, long NC, typename MM, typename L> - struct matrix_type_id<matrix_op<op_subm<matrix<T,NR,NC,MM,L> > > > - { - const static int value = general_matrix; - }; - - template < typename T, typename MM > - struct matrix_type_id<matrix_op<op_array2d_to_mat<array2d<T,MM> > > > - { const static int value = general_matrix; }; - - template < typename T, typename MM > - struct matrix_type_id<matrix_op<op_array_to_mat<array<T,MM> > > > - { const static int value = column_matrix; }; - - template < typename value_type, typename alloc > - struct matrix_type_id<matrix_op<op_std_vect_to_mat<std::vector<value_type,alloc> > > > - { const static int value = column_matrix; }; - - template < typename value_type, typename alloc > - struct matrix_type_id<matrix_op<op_std_vect_to_mat<std_vector_c<value_type,alloc> > > > - { const static int value = column_matrix; }; - - template < typename T > - struct matrix_type_id<matrix_op<op_pointer_to_col_vect<T> > > - { const static int value = column_matrix; }; - template < typename T > - struct matrix_type_id<matrix_op<op_pointer_to_mat<T> > > - { const static int value = general_matrix; }; - - // ------------------------------------------------------------------------------------ - - template <typename T, typename U> - struct same_matrix - { - const static int T_id = matrix_type_id<T>::value; - const static int U_id = matrix_type_id<U>::value; - // The check for unknown_matrix is here so that we can be sure that matrix types - // other than the ones specifically enumerated above never get pushed into - // any of the BLAS bindings. So saying they are never the same as anything - // else prevents them from matching any of the BLAS bindings. - const static bool value = (T_id == U_id) && (T_id != unknown_matrix); - }; - - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - - // This template struct is used to tell us if two matrix expressions both contain the same - // sequence of operators, expressions. It also only has a value of true if the T expression - // contains only matrices with the given layout. - template <typename T, typename U, typename layout> - struct same_exp - { - const static bool value = (is_same_type<typename T::exp_type, typename U::exp_type>::value || - same_matrix<typename T::exp_type, typename U::exp_type>::value) && - is_same_type<typename T::layout_type,layout>::value; - - }; - - // Used only below. They help strip off the const and & qualifiers that can show up - // in the LHS_ref_type and RHS_ref_type typedefs. - template <typename T> struct noref{ typedef T type;}; - template <typename T> struct noref<T&>{ typedef T type;}; - template <typename T> struct noref<const T&>{ typedef T type;}; - template <typename T> struct noref<const T>{ typedef T type;}; - - template <typename Tlhs, typename Ulhs, typename Trhs, typename Urhs, typename layout> - struct same_exp<matrix_multiply_exp<Tlhs,Trhs>, matrix_multiply_exp<Ulhs,Urhs>,layout > - { - // The reason this case is more complex than the others is because the matrix_multiply_exp - // will use a temporary matrix instead of Tlhs or Trhs in the event that one of these - // types corresponds to an expensive expression. So we have to use the type that really - // gets used. The following typedefs are here to pick out that true type. - typedef typename matrix_multiply_exp<Tlhs,Trhs>::LHS_ref_type T_LHS_ref_type; - typedef typename matrix_multiply_exp<Tlhs,Trhs>::RHS_ref_type T_RHS_ref_type; - typedef typename noref<T_LHS_ref_type>::type T_lhs_type; - typedef typename noref<T_RHS_ref_type>::type T_rhs_type; - - typedef typename matrix_multiply_exp<Ulhs,Urhs>::LHS_ref_type U_LHS_ref_type; - typedef typename matrix_multiply_exp<Ulhs,Urhs>::RHS_ref_type U_RHS_ref_type; - typedef typename noref<U_LHS_ref_type>::type U_lhs_type; - typedef typename noref<U_RHS_ref_type>::type U_rhs_type; - - const static bool value = same_exp<T_lhs_type,U_lhs_type,layout>::value && - same_exp<T_rhs_type,U_rhs_type,layout>::value; - }; - - template <typename Tlhs, typename Ulhs, typename Trhs, typename Urhs, typename layout> - struct same_exp<matrix_add_exp<Tlhs,Trhs>, matrix_add_exp<Ulhs,Urhs>, layout > - { const static bool value = same_exp<Tlhs,Ulhs,layout>::value && same_exp<Trhs,Urhs,layout>::value; }; - - template <typename Tlhs, typename Ulhs, typename Trhs, typename Urhs, typename layout> - struct same_exp<matrix_subtract_exp<Tlhs,Trhs>, matrix_subtract_exp<Ulhs,Urhs>, layout > - { const static bool value = same_exp<Tlhs,Ulhs,layout>::value && same_exp<Trhs,Urhs,layout>::value; }; - - template <typename T, typename U, bool Tb, bool Ub, typename layout> - struct same_exp<matrix_mul_scal_exp<T,Tb>, matrix_mul_scal_exp<U,Ub>, layout > - { const static bool value = same_exp<T,U,layout>::value; }; - - template <typename T, typename U, typename layout> - struct same_exp<matrix_div_scal_exp<T>, matrix_div_scal_exp<U>, layout > - { const static bool value = same_exp<T,U,layout>::value; }; - - template <typename T, typename U, typename layout> - struct same_exp<matrix_op<op_trans<T> >, matrix_op<op_trans<U> >, layout > - { const static bool value = same_exp<T,U,layout>::value; }; - - template <typename T, typename U, typename layout> - struct same_exp<matrix_op<op_conj<T> >, matrix_op<op_conj<U> >, layout > - { const static bool value = same_exp<T,U,layout>::value; }; - - template <typename T, typename U, typename layout> - struct same_exp<matrix_op<op_conj_trans<T> >, matrix_op<op_conj_trans<U> >, layout > - { const static bool value = same_exp<T,U,layout>::value; }; - - // ------------------------------------------------------------------------------------ - - struct yes_type - { - char ch; - }; - struct no_type - { - yes_type a, b; - }; - - // This is a helper that is used below to apply the same_exp template to matrix expressions. - template <typename T, typename layout, typename U> - typename enable_if<same_exp<T,U,layout>,yes_type>::type test(U); - template <typename T, typename layout, typename U> - typename disable_if<same_exp<T,U,layout>,no_type>::type test(U); - - // ------------------------------------------------------------------------------------ - - template < - typename dest_exp, - typename src_exp, - typename enabled = void - > - struct matrix_assign_blas_helper - { - // We are in the default version of the blas helper so this - // means there wasn't any more specific overload. So just - // let the default matrix assignment happen. - template <typename EXP> - static void assign ( - dest_exp& dest, - const EXP& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ) - { - if (transpose == false) - matrix_assign_default(dest,src,alpha,add_to); - else - matrix_assign_default(dest,trans(src),alpha,add_to); - } - - // If we know this is a matrix multiply then apply the - // default dlib matrix multiply to speed things up a bit more - // than the above default function would. - template <typename EXP1, typename EXP2> - static void assign ( - dest_exp& dest, - const matrix_multiply_exp<EXP1,EXP2>& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ) - { - // At some point I need to improve the default (i.e. non BLAS) matrix - // multiplication algorithm... - - if (alpha == static_cast<typename src_exp::type>(1)) - { - if (add_to == false) - { - zero_matrix(dest); - } - - if (transpose == false) - default_matrix_multiply(dest, src.lhs, src.rhs); - else - default_matrix_multiply(dest, trans(src.rhs), trans(src.lhs)); - } - else - { - if (add_to) - { - typename dest_exp::matrix_type temp(dest.nr(),dest.nc()); - zero_matrix(temp); - - if (transpose == false) - default_matrix_multiply(temp, src.lhs, src.rhs); - else - default_matrix_multiply(temp, trans(src.rhs), trans(src.lhs)); - - matrix_assign_default(dest,temp, alpha,true); - } - else - { - zero_matrix(dest); - - if (transpose == false) - default_matrix_multiply(dest, src.lhs, src.rhs); - else - default_matrix_multiply(dest, trans(src.rhs), trans(src.lhs)); - - matrix_assign_default(dest,dest, alpha, false); - } - } - } - }; - - // This is a macro to help us add overloads for the matrix_assign_blas_helper template. - // Using this macro it is easy to add overloads for arbitrary matrix expressions. -#define DLIB_ADD_BLAS_BINDING(src_expression) \ - template <typename T, typename L> struct BOOST_JOIN(blas,__LINE__) \ - { const static bool value = sizeof(yes_type) == sizeof(test<T,L>(src_expression)); }; \ - \ - template < typename dest_exp, typename src_exp > \ - struct matrix_assign_blas_helper<dest_exp, src_exp, \ - typename enable_if<BOOST_JOIN(blas,__LINE__)<src_exp,typename dest_exp::layout_type> >::type > { \ - static void assign ( \ - dest_exp& dest, \ - const src_exp& src, \ - typename src_exp::type alpha, \ - bool add_to, \ - bool DLIB_NO_WARN_UNUSED transpose \ - ) { \ - DLIB_NO_WARN_UNUSED typedef typename dest_exp::type T; - -#define DLIB_END_BLAS_BINDING }}; - - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - - // ------------------- Forward Declarations ------------------- - - template < - typename dest_exp, - typename src_exp - > - void matrix_assign_blas_proxy ( - dest_exp& dest, - const src_exp& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ); - /*! - requires - - src.aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - !*/ - - template < - typename dest_exp, - typename src_exp, typename src_exp2 - > - void matrix_assign_blas_proxy ( - dest_exp& dest, - const matrix_add_exp<src_exp, src_exp2>& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ); - /*! - requires - - src.aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - !*/ - - template < - typename dest_exp, - typename src_exp, bool Sb - > - void matrix_assign_blas_proxy ( - dest_exp& dest, - const matrix_mul_scal_exp<src_exp,Sb>& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ); - /*! - requires - - src.aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - !*/ - - template < - typename dest_exp, - typename src_exp - > - void matrix_assign_blas_proxy ( - dest_exp& dest, - const matrix_op<op_trans<src_exp> >& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ); - /*! - requires - - src.aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - !*/ - - template < - typename dest_exp, - typename src_exp, typename src_exp2 - > - void matrix_assign_blas_proxy ( - dest_exp& dest, - const matrix_subtract_exp<src_exp, src_exp2>& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ); - /*! - requires - - src.aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - !*/ - - // ------------------------------------------------------------------------------------ - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - void matrix_assign_blas ( - matrix<T,NR,NC,MM,L>& dest, - const src_exp& src - ); - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - void matrix_assign_blas ( - matrix<T,NR,NC,MM,L>& dest, - const matrix_add_exp<matrix<T,NR,NC,MM,L> ,src_exp>& src - ); - /*! - This function catches the expressions of the form: - M = M + exp; - and converts them into the appropriate matrix_assign_blas() call. - This is an important case to catch because it is the expression used - to represent the += matrix operator. - !*/ - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - void matrix_assign_blas ( - matrix<T,NR,NC,MM,L>& dest, - const matrix_add_exp<src_exp, matrix<T,NR,NC,MM,L> >& src - ); - /*! - This function catches the expressions of the form: - M = exp + M; - and converts them into the appropriate matrix_assign_blas() call. - This is an important case to catch because it is the expression used - to represent the += matrix operator. - !*/ - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - void matrix_assign_blas ( - matrix<T,NR,NC,MM,L>& dest, - const matrix_subtract_exp<matrix<T,NR,NC,MM,L> ,src_exp>& src - ); - /*! - This function catches the expressions of the form: - M = M - exp; - and converts them into the appropriate matrix_assign_blas() call. - This is an important case to catch because it is the expression used - to represent the -= matrix operator. - !*/ - - - // End of forward declarations for overloaded matrix_assign_blas functions - - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - - template < - typename dest_exp, - typename src_exp - > - void matrix_assign_blas_proxy ( - dest_exp& dest, - const src_exp& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ) - { - matrix_assign_blas_helper<dest_exp,src_exp>::assign(dest,src,alpha,add_to, transpose); - } - - // ------------------------------------------------------------------------------------ - - template < - typename dest_exp, - typename src_exp, typename src_exp2 - > - void matrix_assign_blas_proxy ( - dest_exp& dest, - const matrix_add_exp<src_exp, src_exp2>& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ) - { - if (has_matrix_multiply<src_exp>::value || has_matrix_multiply<src_exp2>::value) - { - matrix_assign_blas_proxy(dest, src.lhs, alpha, add_to, transpose); - matrix_assign_blas_proxy(dest, src.rhs, alpha, true, transpose); - } - else - { - if (transpose == false) - matrix_assign_default(dest, src, alpha, add_to); - else - matrix_assign_default(dest, trans(src), alpha, add_to); - } - } - - // ------------------------------------------------------------------------------------ - - template < - typename dest_exp, - typename src_exp, bool Sb - > - void matrix_assign_blas_proxy ( - dest_exp& dest, - const matrix_mul_scal_exp<src_exp,Sb>& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ) - { - matrix_assign_blas_proxy(dest, src.m, alpha*src.s, add_to, transpose); - } - - // ------------------------------------------------------------------------------------ - - template < - typename dest_exp, - typename src_exp - > - void matrix_assign_blas_proxy ( - dest_exp& dest, - const matrix_op<op_trans<src_exp> >& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ) - { - matrix_assign_blas_proxy(dest, src.op.m, alpha, add_to, !transpose); - } - - // ------------------------------------------------------------------------------------ - - template < - typename dest_exp, - typename src_exp, typename src_exp2 - > - void matrix_assign_blas_proxy ( - dest_exp& dest, - const matrix_subtract_exp<src_exp, src_exp2>& src, - typename src_exp::type alpha, - bool add_to, - bool transpose - ) - { - - if (has_matrix_multiply<src_exp>::value || has_matrix_multiply<src_exp2>::value) - { - matrix_assign_blas_proxy(dest, src.lhs, alpha, add_to, transpose); - matrix_assign_blas_proxy(dest, src.rhs, -alpha, true, transpose); - } - else - { - if (transpose == false) - matrix_assign_default(dest, src, alpha, add_to); - else - matrix_assign_default(dest, trans(src), alpha, add_to); - } - } - - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - - // Once we get into this function it means that we are dealing with a matrix of float, - // double, complex<float>, or complex<double> and the src_exp contains at least one - // matrix multiply. - - template < - typename T, long NR, long NC, typename MM, typename L, - long NR2, long NC2, bool Sb - > - void matrix_assign_blas ( - matrix<T,NR,NC,MM,L>& dest, - const matrix_mul_scal_exp<matrix<T,NR2,NC2,MM,L>,Sb>& src - ) - { - // It's ok that we don't check for aliasing in this case because there isn't - // any complex unrolling of successive + or - operators in this expression. - matrix_assign_blas_proxy(dest,src.m,src.s,false, false); - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - void matrix_assign_blas ( - matrix<T,NR,NC,MM,L>& dest, - const src_exp& src - ) - { - if (src.aliases(dest)) - { - matrix<T,NR,NC,MM,L> temp(dest.nr(),dest.nc()); - matrix_assign_blas_proxy(temp,src,1,false, false); - temp.swap(dest); - } - else - { - matrix_assign_blas_proxy(dest,src,1,false, false); - } - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - void matrix_assign_blas ( - assignable_sub_matrix<T,NR,NC,MM,L>& dest, - const src_exp& src - ) - { - if (src.aliases(dest.m)) - { - matrix<T,NR,NC,MM,L> temp(dest.nr(),dest.nc()); - matrix_assign_blas_proxy(temp,src,1,false, false); - matrix_assign_default(dest,temp); - } - else - { - matrix_assign_blas_proxy(dest,src,1,false, false); - } - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, - typename src_exp - > - void matrix_assign_blas ( - assignable_ptr_matrix<T>& dest, - const src_exp& src - ) - { - if (src.aliases(mat(dest.ptr,dest.height,dest.width))) - { - matrix<T> temp(dest.nr(),dest.nc()); - matrix_assign_blas_proxy(temp,src,1,false, false); - matrix_assign_default(dest,temp); - } - else - { - matrix_assign_blas_proxy(dest,src,1,false, false); - } - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - void matrix_assign_blas ( - assignable_row_matrix<T,NR,NC,MM,L>& dest, - const src_exp& src - ) - { - if (src.aliases(dest.m)) - { - matrix<T,NR,NC,MM,L> temp(dest.nr(),dest.nc()); - matrix_assign_blas_proxy(temp,src,1,false, false); - matrix_assign_default(dest,temp); - } - else - { - matrix_assign_blas_proxy(dest,src,1,false, false); - } - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - void matrix_assign_blas ( - assignable_col_matrix<T,NR,NC,MM,L>& dest, - const src_exp& src - ) - { - if (src.aliases(dest.m)) - { - matrix<T,NR,NC,MM,L> temp(dest.nr(),dest.nc()); - matrix_assign_blas_proxy(temp,src,1,false, false); - matrix_assign_default(dest,temp); - } - else - { - matrix_assign_blas_proxy(dest,src,1,false, false); - } - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - void matrix_assign_blas ( - matrix<T,NR,NC,MM,L>& dest, - const matrix_add_exp<matrix<T,NR,NC,MM,L> ,src_exp>& src - ) - { - if (src.rhs.aliases(dest) == false) - { - if (&src.lhs != &dest) - { - dest = src.lhs; - } - - matrix_assign_blas_proxy(dest, src.rhs, 1, true, false); - } - else - { - matrix<T,NR,NC,MM,L> temp(src.lhs); - matrix_assign_blas_proxy(temp, src.rhs, 1, true, false); - temp.swap(dest); - } - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - void matrix_assign_blas ( - matrix<T,NR,NC,MM,L>& dest, - const matrix_add_exp<src_exp, matrix<T,NR,NC,MM,L> >& src - ) - { - // Just switch around the left and right hand sides of the incoming - // add expression and pass it back into matrix_assign_blas() so that - // the above function will be called. - typedef matrix_add_exp<matrix<T,NR,NC,MM,L> ,src_exp> swapped_add_exp; - matrix_assign_blas(dest, swapped_add_exp(src.rhs, src.lhs)); - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - void matrix_assign_blas ( - matrix<T,NR,NC,MM,L>& dest, - const matrix_subtract_exp<matrix<T,NR,NC,MM,L> ,src_exp>& src - ) - { - if (src.rhs.aliases(dest) == false) - { - if (&src.lhs != &dest) - { - dest = src.lhs; - } - - matrix_assign_blas_proxy(dest, src.rhs, -1, true, false); - } - else - { - matrix<T,NR,NC,MM,L> temp(src.lhs); - matrix_assign_blas_proxy(temp, src.rhs, -1, true, false); - temp.swap(dest); - } - } - - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - - } // end of namespace blas_bindings - - // ------------------------------------------------------------------------------------ - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - inline typename enable_if_c<(is_same_type<T,float>::value || - is_same_type<T,double>::value || - is_same_type<T,std::complex<float> >::value || - is_same_type<T,std::complex<double> >::value) && - blas_bindings::has_matrix_multiply<src_exp>::value - >::type matrix_assign_big ( - matrix<T,NR,NC,MM,L>& dest, - const src_exp& src - ) - { - blas_bindings::matrix_assign_blas(dest,src); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - inline typename enable_if_c<(is_same_type<T,float>::value || - is_same_type<T,double>::value || - is_same_type<T,std::complex<float> >::value || - is_same_type<T,std::complex<double> >::value) && - blas_bindings::has_matrix_multiply<src_exp>::value - >::type matrix_assign_big ( - assignable_sub_matrix<T,NR,NC,MM,L>& dest, - const src_exp& src - ) - { - blas_bindings::matrix_assign_blas(dest,src); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - typename src_exp - > - inline typename enable_if_c<(is_same_type<T,float>::value || - is_same_type<T,double>::value || - is_same_type<T,std::complex<float> >::value || - is_same_type<T,std::complex<double> >::value) && - blas_bindings::has_matrix_multiply<src_exp>::value - >::type matrix_assign_big ( - assignable_ptr_matrix<T>& dest, - const src_exp& src - ) - { - blas_bindings::matrix_assign_blas(dest,src); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - inline typename enable_if_c<(is_same_type<T,float>::value || - is_same_type<T,double>::value || - is_same_type<T,std::complex<float> >::value || - is_same_type<T,std::complex<double> >::value) && - blas_bindings::has_matrix_multiply<src_exp>::value - >::type matrix_assign_big ( - assignable_row_matrix<T,NR,NC,MM,L>& dest, - const src_exp& src - ) - { - blas_bindings::matrix_assign_blas(dest,src); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, long NR, long NC, typename MM, typename L, - typename src_exp - > - inline typename enable_if_c<(is_same_type<T,float>::value || - is_same_type<T,double>::value || - is_same_type<T,std::complex<float> >::value || - is_same_type<T,std::complex<double> >::value) && - blas_bindings::has_matrix_multiply<src_exp>::value - >::type matrix_assign_big ( - assignable_col_matrix<T,NR,NC,MM,L>& dest, - const src_exp& src - ) - { - blas_bindings::matrix_assign_blas(dest,src); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_ASSIGn_ - diff --git a/ml/dlib/dlib/matrix/matrix_assign_fwd.h b/ml/dlib/dlib/matrix/matrix_assign_fwd.h deleted file mode 100644 index 7d29baf0a..000000000 --- a/ml/dlib/dlib/matrix/matrix_assign_fwd.h +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (C) 2008 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_ASSIGn_FWD_ -#define DLIB_MATRIx_ASSIGn_FWD_ - -// GCC 4.8 gives false alarms about some variables being uninitialized. Disable these -// false warnings. -#if defined(__GNUC__) && ((__GNUC__ >= 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4)) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif - -#include "../enable_if.h" -#include "matrix_data_layout.h" -#include "../algs.h" - -namespace dlib -{ - - /* - The point of the matrix_assign() functions is to contain all the various - optimizations that help the matrix assign a matrix_exp to an actual matrix - object quickly. - */ - -// ---------------------------------------------------------------------------------------- - - namespace ma - { - // This template here controls how big a compile time sized matrix needs - // to be for it to get passed into the optimized versions of the - // matrix_assign() function. So small matrices are evaluated with a simple - // loop like the ones in this file and bigger matrices may get sent to BLAS - // routines or some other kind of optimized thing. - template < typename EXP, typename enable = void > - struct is_small_matrix { static const bool value = false; }; - template < typename EXP > - struct is_small_matrix<EXP, typename enable_if_c<EXP::NR>=1 && EXP::NC>=1 && - EXP::NR<=17 && EXP::NC<=17 && (EXP::cost <= 70)>::type> { static const bool value = true; }; - - // I wouldn't use this mul object to do the multiply but visual studio 7.1 wouldn't - // compile otherwise. - template <long a, long b> - struct mul { const static long value = a*b; }; - - template < typename EXP, typename enable = void > - struct is_very_small_matrix { static const bool value = false; }; - template < typename EXP > - struct is_very_small_matrix<EXP, typename enable_if_c<EXP::NR>=1 && EXP::NC>=1 && - (mul<EXP::NR,EXP::NC>::value <= 16) && (EXP::cost <= 70)>::type> { static const bool value = true; }; - - - template < typename EXP, typename enable = void > - struct has_column_major_layout { static const bool value = false; }; - template < typename EXP > - struct has_column_major_layout<EXP, typename enable_if<is_same_type<typename EXP::layout_type, column_major_layout> >::type > - { static const bool value = true; }; - - - - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - class matrix_exp; - -// ---------------------------------------------------------------------------------------- - - template <typename EXP1, typename EXP2> - inline typename disable_if<ma::has_column_major_layout<EXP1> >::type - matrix_assign_default ( - EXP1& dest, - const EXP2& src - ) - /*! - requires - - src.destructively_aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - ensures - - #dest == src - !*/ - { - for (long r = 0; r < src.nr(); ++r) - { - for (long c = 0; c < src.nc(); ++c) - { - dest(r,c) = src(r,c); - } - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename EXP1, typename EXP2> - inline typename enable_if<ma::has_column_major_layout<EXP1> >::type - matrix_assign_default ( - EXP1& dest, - const EXP2& src - ) - /*! - requires - - src.destructively_aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - ensures - - #dest == src - !*/ - { - for (long c = 0; c < src.nc(); ++c) - { - for (long r = 0; r < src.nr(); ++r) - { - dest(r,c) = src(r,c); - } - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename EXP1, typename EXP2> - inline typename disable_if<ma::has_column_major_layout<EXP1> >::type - matrix_assign_default ( - EXP1& dest, - const EXP2& src, - typename EXP2::type alpha, - bool add_to - ) - /*! - requires - - src.destructively_aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - ensures - - if (add_to == false) then - - #dest == alpha*src - - else - - #dest == dest + alpha*src - !*/ - { - if (add_to) - { - if (alpha == static_cast<typename EXP2::type>(1)) - { - for (long r = 0; r < src.nr(); ++r) - { - for (long c = 0; c < src.nc(); ++c) - { - dest(r,c) += src(r,c); - } - } - } - else if (alpha == static_cast<typename EXP2::type>(-1)) - { - for (long r = 0; r < src.nr(); ++r) - { - for (long c = 0; c < src.nc(); ++c) - { - dest(r,c) -= src(r,c); - } - } - } - else - { - for (long r = 0; r < src.nr(); ++r) - { - for (long c = 0; c < src.nc(); ++c) - { - dest(r,c) += alpha*src(r,c); - } - } - } - } - else - { - if (alpha == static_cast<typename EXP2::type>(1)) - { - for (long r = 0; r < src.nr(); ++r) - { - for (long c = 0; c < src.nc(); ++c) - { - dest(r,c) = src(r,c); - } - } - } - else - { - for (long r = 0; r < src.nr(); ++r) - { - for (long c = 0; c < src.nc(); ++c) - { - dest(r,c) = alpha*src(r,c); - } - } - } - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename EXP1, typename EXP2> - inline typename enable_if<ma::has_column_major_layout<EXP1> >::type - matrix_assign_default ( - EXP1& dest, - const EXP2& src, - typename EXP2::type alpha, - bool add_to - ) - /*! - requires - - src.destructively_aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - ensures - - if (add_to == false) then - - #dest == alpha*src - - else - - #dest == dest + alpha*src - !*/ - { - if (add_to) - { - if (alpha == static_cast<typename EXP2::type>(1)) - { - for (long c = 0; c < src.nc(); ++c) - { - for (long r = 0; r < src.nr(); ++r) - { - dest(r,c) += src(r,c); - } - } - } - else if (alpha == static_cast<typename EXP2::type>(-1)) - { - for (long c = 0; c < src.nc(); ++c) - { - for (long r = 0; r < src.nr(); ++r) - { - dest(r,c) -= src(r,c); - } - } - } - else - { - for (long c = 0; c < src.nc(); ++c) - { - for (long r = 0; r < src.nr(); ++r) - { - dest(r,c) += alpha*src(r,c); - } - } - } - } - else - { - if (alpha == static_cast<typename EXP2::type>(1)) - { - for (long c = 0; c < src.nc(); ++c) - { - for (long r = 0; r < src.nr(); ++r) - { - dest(r,c) = src(r,c); - } - } - } - else - { - for (long c = 0; c < src.nc(); ++c) - { - for (long r = 0; r < src.nr(); ++r) - { - dest(r,c) = alpha*src(r,c); - } - } - } - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename matrix_dest_type, - typename src_exp - > - void matrix_assign_big ( - matrix_dest_type& dest, - const matrix_exp<src_exp>& src - ) - { - matrix_assign_default(dest,src); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename matrix_dest_type, - typename src_exp - > - inline typename disable_if<ma::is_small_matrix<src_exp> >::type matrix_assign ( - matrix_dest_type& dest, - const matrix_exp<src_exp>& src - ) - /*! - requires - - src.destructively_aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - ensures - - #dest == src - !*/ - { - // Call src.ref() here so that the derived type of the matrix_exp shows - // up so we can overload matrix_assign_big() based on various matrix expression - // types. - matrix_assign_big(dest,src.ref()); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - -// this code is here to perform an unrolled version of the matrix_assign() function - template < typename DEST, typename SRC, long NR, long NC, - long R = 0, long C = 0, bool base_case = (R==NR) > - struct matrix_unroll_helper - { - inline static void go ( DEST& dest, const SRC& src) - { - dest(R,C) = src(R,C); - matrix_unroll_helper<DEST,SRC,NR,NC, R + (C+1)/NC, (C+1)%NC>::go(dest,src); - } - }; - - template < typename DEST, typename SRC, long NR, long NC, long R, long C > - struct matrix_unroll_helper<DEST,SRC,NR,NC,R,C,true> - { inline static void go ( DEST& , const SRC& ) {} }; - - template <typename DEST, typename SRC> - inline void matrix_assign_unrolled ( - DEST& dest, - const SRC& src - ) - /*! - requires - - src.destructively_aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - ensures - - #dest == src - !*/ - { - COMPILE_TIME_ASSERT(SRC::NR*SRC::NC != 0); - matrix_unroll_helper<DEST,SRC, SRC::NR, SRC::NC>::go(dest,src); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template < - typename matrix_dest_type, - typename src_exp - > - inline typename enable_if_c<ma::is_small_matrix<src_exp>::value && ma::is_very_small_matrix<src_exp>::value==false >::type matrix_assign ( - matrix_dest_type& dest, - const matrix_exp<src_exp>& src - ) - /*! - requires - - src.destructively_aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - ensures - - #dest == src - !*/ - { - matrix_assign_default(dest,src.ref()); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename matrix_dest_type, - typename src_exp - > - inline typename enable_if_c<ma::is_small_matrix<src_exp>::value && ma::is_very_small_matrix<src_exp>::value==true >::type matrix_assign ( - matrix_dest_type& dest, - const matrix_exp<src_exp>& src - ) - /*! - requires - - src.destructively_aliases(dest) == false - - dest.nr() == src.nr() - - dest.nc() == src.nc() - ensures - - #dest == src - !*/ - { - matrix_assign_unrolled(dest,src.ref()); - } - -// ---------------------------------------------------------------------------------------- - -} - -#if defined(__GNUC__) && ((__GNUC__ >= 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4)) -#pragma GCC diagnostic pop -#endif - -#endif // DLIB_MATRIx_ASSIGn_FWD_ - - diff --git a/ml/dlib/dlib/matrix/matrix_blas_bindings.h b/ml/dlib/dlib/matrix/matrix_blas_bindings.h deleted file mode 100644 index b65e29cdd..000000000 --- a/ml/dlib/dlib/matrix/matrix_blas_bindings.h +++ /dev/null @@ -1,1637 +0,0 @@ -// Copyright (C) 2008 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_BLAS_BINDINGS_ -#define DLIB_MATRIx_BLAS_BINDINGS_ - -#ifndef DLIB_USE_BLAS -#error "DLIB_USE_BLAS should be defined if you want to use the BLAS bindings" -#endif - -#include "matrix_assign.h" -#include "matrix_conj_trans.h" -#include "cblas_constants.h" - -//#include <iostream> -//using namespace std; - -namespace dlib -{ - - - namespace blas_bindings - { - -#ifdef DLIB_TEST_BLAS_BINDINGS - int& counter_gemm(); - int& counter_gemv(); - int& counter_ger(); - int& counter_dot(); - int& counter_axpy(); - int& counter_scal(); - - #define DLIB_TEST_BLAS_BINDING_GEMM ++counter_gemm(); - #define DLIB_TEST_BLAS_BINDING_GEMV ++counter_gemv(); - #define DLIB_TEST_BLAS_BINDING_GER ++counter_ger(); - #define DLIB_TEST_BLAS_BINDING_DOT ++counter_dot(); - #define DLIB_TEST_BLAS_BINDING_AXPY ++counter_axpy(); - #define DLIB_TEST_BLAS_BINDING_SCAL ++counter_scal(); -#else - #define DLIB_TEST_BLAS_BINDING_GEMM - #define DLIB_TEST_BLAS_BINDING_GEMV - #define DLIB_TEST_BLAS_BINDING_GER - #define DLIB_TEST_BLAS_BINDING_DOT - #define DLIB_TEST_BLAS_BINDING_AXPY - #define DLIB_TEST_BLAS_BINDING_SCAL -#endif - -#ifndef CBLAS_H - extern "C" - { - // Here we declare the prototypes for the CBLAS calls used by the BLAS bindings below - - void cblas_saxpy(const int N, const float alpha, const float *X, - const int incX, float *Y, const int incY); - void cblas_daxpy(const int N, const double alpha, const double *X, - const int incX, double *Y, const int incY); - void cblas_caxpy(const int N, const void *alpha, const void *X, - const int incX, void *Y, const int incY); - void cblas_zaxpy(const int N, const void *alpha, const void *X, - const int incX, void *Y, const int incY); - - void cblas_sscal(const int N, const float alpha, float *X, const int incX); - void cblas_dscal(const int N, const double alpha, double *X, const int incX); - void cblas_cscal(const int N, const void *alpha, void *X, const int incX); - void cblas_zscal(const int N, const void *alpha, void *X, const int incX); - - void cblas_sgemm(const CBLAS_ORDER Order, const CBLAS_TRANSPOSE TransA, - const CBLAS_TRANSPOSE TransB, const int M, const int N, - const int K, const float alpha, const float *A, - const int lda, const float *B, const int ldb, - const float beta, float *C, const int ldc); - void cblas_dgemm(const CBLAS_ORDER Order, const CBLAS_TRANSPOSE TransA, - const CBLAS_TRANSPOSE TransB, const int M, const int N, - const int K, const double alpha, const double *A, - const int lda, const double *B, const int ldb, - const double beta, double *C, const int ldc); - void cblas_cgemm(const CBLAS_ORDER Order, const CBLAS_TRANSPOSE TransA, - const CBLAS_TRANSPOSE TransB, const int M, const int N, - const int K, const void *alpha, const void *A, - const int lda, const void *B, const int ldb, - const void *beta, void *C, const int ldc); - void cblas_zgemm(const CBLAS_ORDER Order, const CBLAS_TRANSPOSE TransA, - const CBLAS_TRANSPOSE TransB, const int M, const int N, - const int K, const void *alpha, const void *A, - const int lda, const void *B, const int ldb, - const void *beta, void *C, const int ldc); - void cblas_sgemv(const CBLAS_ORDER order, - const CBLAS_TRANSPOSE TransA, const int M, const int N, - const float alpha, const float *A, const int lda, - const float *X, const int incX, const float beta, - float *Y, const int incY); - void cblas_dgemv(const CBLAS_ORDER order, - const CBLAS_TRANSPOSE TransA, const int M, const int N, - const double alpha, const double *A, const int lda, - const double *X, const int incX, const double beta, - double *Y, const int incY); - void cblas_cgemv(const CBLAS_ORDER order, - const CBLAS_TRANSPOSE TransA, const int M, const int N, - const void *alpha, const void *A, const int lda, - const void *X, const int incX, const void *beta, - void *Y, const int incY); - void cblas_zgemv(const CBLAS_ORDER order, - const CBLAS_TRANSPOSE TransA, const int M, const int N, - const void *alpha, const void *A, const int lda, - const void *X, const int incX, const void *beta, - void *Y, const int incY); - void cblas_sger(const CBLAS_ORDER order, const int M, const int N, - const float alpha, const float *X, const int incX, - const float *Y, const int incY, float *A, const int lda); - void cblas_dger(const CBLAS_ORDER order, const int M, const int N, - const double alpha, const double *X, const int incX, - const double *Y, const int incY, double *A, const int lda); - void cblas_cgerc(const CBLAS_ORDER order, const int M, const int N, - const void *alpha, const void *X, const int incX, - const void *Y, const int incY, void *A, const int lda); - void cblas_zgerc(const CBLAS_ORDER order, const int M, const int N, - const void *alpha, const void *X, const int incX, - const void *Y, const int incY, void *A, const int lda); - float cblas_sdot(const int N, const float *X, const int incX, - const float *Y, const int incY); - double cblas_ddot(const int N, const double *X, const int incX, - const double *Y, const int incY); - void cblas_cdotu_sub(const int N, const void *X, const int incX, - const void *Y, const int incY, void *dotu); - void cblas_zdotu_sub(const int N, const void *X, const int incX, - const void *Y, const int incY, void *dotu); - void cblas_cdotc_sub(const int N, const void *X, const int incX, - const void *Y, const int incY, void *dotc); - void cblas_zdotc_sub(const int N, const void *X, const int incX, - const void *Y, const int incY, void *dotc); - void cblas_cgeru(const CBLAS_ORDER order, const int M, const int N, - const void *alpha, const void *X, const int incX, - const void *Y, const int incY, void *A, const int lda); - void cblas_zgeru(const CBLAS_ORDER order, const int M, const int N, - const void *alpha, const void *X, const int incX, - const void *Y, const int incY, void *A, const int lda); - } -#endif // if not CBLAS_H - - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - - inline void cblas_axpy(const int N, const float alpha, const float *X, - const int incX, float *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_AXPY; - cblas_saxpy(N, alpha, X, incX, Y, incY); - } - - inline void cblas_axpy(const int N, const double alpha, const double *X, - const int incX, double *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_AXPY; - cblas_daxpy(N, alpha, X, incX, Y, incY); - } - - inline void cblas_axpy(const int N, const std::complex<float>& alpha, const std::complex<float> *X, - const int incX, std::complex<float> *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_AXPY; - cblas_caxpy(N, &alpha, X, incX, Y, incY); - } - - inline void cblas_axpy(const int N, const std::complex<double>& alpha, const std::complex<double> *X, - const int incX, std::complex<double> *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_AXPY; - cblas_zaxpy(N, &alpha, X, incX, Y, incY); - } - - // ---------------------------------------------------------------------------------------- - - inline void cblas_scal(const int N, const float alpha, float *X) - { - DLIB_TEST_BLAS_BINDING_SCAL; - cblas_sscal(N, alpha, X, 1); - } - - inline void cblas_scal(const int N, const double alpha, double *X) - { - DLIB_TEST_BLAS_BINDING_SCAL; - cblas_dscal(N, alpha, X, 1); - } - - inline void cblas_scal(const int N, const std::complex<float>& alpha, std::complex<float> *X) - { - DLIB_TEST_BLAS_BINDING_SCAL; - cblas_cscal(N, &alpha, X, 1); - } - - inline void cblas_scal(const int N, const std::complex<double>& alpha, std::complex<double> *X) - { - DLIB_TEST_BLAS_BINDING_SCAL; - cblas_zscal(N, &alpha, X, 1); - } - - // ---------------------------------------------------------------------------------------- - - inline void cblas_gemm( const CBLAS_ORDER Order, const CBLAS_TRANSPOSE TransA, - const CBLAS_TRANSPOSE TransB, const int M, const int N, - const int K, const float alpha, const float *A, - const int lda, const float *B, const int ldb, - const float beta, float *C, const int ldc) - { - DLIB_TEST_BLAS_BINDING_GEMM; - cblas_sgemm( Order, TransA, TransB, M, N, - K, alpha, A, lda, B, ldb, beta, C, ldc); - } - - inline void cblas_gemm(const CBLAS_ORDER Order, const CBLAS_TRANSPOSE TransA, - const CBLAS_TRANSPOSE TransB, const int M, const int N, - const int K, const double alpha, const double *A, - const int lda, const double *B, const int ldb, - const double beta, double *C, const int ldc) - { - DLIB_TEST_BLAS_BINDING_GEMM; - cblas_dgemm( Order, TransA, TransB, M, N, - K, alpha, A, lda, B, ldb, beta, C, ldc); - } - - inline void cblas_gemm(const CBLAS_ORDER Order, const CBLAS_TRANSPOSE TransA, - const CBLAS_TRANSPOSE TransB, const int M, const int N, - const int K, const std::complex<float>& alpha, const std::complex<float> *A, - const int lda, const std::complex<float> *B, const int ldb, - const std::complex<float>& beta, std::complex<float> *C, const int ldc) - { - DLIB_TEST_BLAS_BINDING_GEMM; - cblas_cgemm( Order, TransA, TransB, M, N, - K, &alpha, A, lda, B, ldb, &beta, C, ldc); - } - - inline void cblas_gemm(const CBLAS_ORDER Order, const CBLAS_TRANSPOSE TransA, - const CBLAS_TRANSPOSE TransB, const int M, const int N, - const int K, const std::complex<double>& alpha, const std::complex<double> *A, - const int lda, const std::complex<double> *B, const int ldb, - const std::complex<double>& beta, std::complex<double> *C, const int ldc) - { - DLIB_TEST_BLAS_BINDING_GEMM; - cblas_zgemm( Order, TransA, TransB, M, N, - K, &alpha, A, lda, B, ldb, &beta, C, ldc); - } - - // ---------------------------------------------------------------------------------------- - - inline void cblas_gemv(const CBLAS_ORDER order, - const CBLAS_TRANSPOSE TransA, const int M, const int N, - const float alpha, const float *A, const int lda, - const float *X, const int incX, const float beta, - float *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_GEMV; - cblas_sgemv(order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } - - inline void cblas_gemv(const CBLAS_ORDER order, - const CBLAS_TRANSPOSE TransA, const int M, const int N, - const double alpha, const double *A, const int lda, - const double *X, const int incX, const double beta, - double *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_GEMV; - cblas_dgemv(order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } - - inline void cblas_gemv(const CBLAS_ORDER order, - const CBLAS_TRANSPOSE TransA, const int M, const int N, - const std::complex<float>& alpha, const std::complex<float> *A, const int lda, - const std::complex<float> *X, const int incX, const std::complex<float>& beta, - std::complex<float> *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_GEMV; - cblas_cgemv(order, TransA, M, N, &alpha, A, lda, X, incX, &beta, Y, incY); - } - - inline void cblas_gemv(const CBLAS_ORDER order, - const CBLAS_TRANSPOSE TransA, const int M, const int N, - const std::complex<double>& alpha, const std::complex<double> *A, const int lda, - const std::complex<double> *X, const int incX, const std::complex<double>& beta, - std::complex<double> *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_GEMV; - cblas_zgemv(order, TransA, M, N, &alpha, A, lda, X, incX, &beta, Y, incY); - } - - // ---------------------------------------------------------------------------------------- - - inline void cblas_ger(const CBLAS_ORDER order, const int M, const int N, - const std::complex<float>& alpha, const std::complex<float> *X, const int incX, - const std::complex<float> *Y, const int incY, std::complex<float> *A, const int lda) - { - DLIB_TEST_BLAS_BINDING_GER; - cblas_cgeru (order, M, N, &alpha, X, incX, Y, incY, A, lda); - } - - inline void cblas_ger(const CBLAS_ORDER order, const int M, const int N, - const std::complex<double>& alpha, const std::complex<double> *X, const int incX, - const std::complex<double> *Y, const int incY, std::complex<double> *A, const int lda) - { - DLIB_TEST_BLAS_BINDING_GER; - cblas_zgeru (order, M, N, &alpha, X, incX, Y, incY, A, lda); - } - - inline void cblas_ger(const CBLAS_ORDER order, const int M, const int N, - const float alpha, const float *X, const int incX, - const float *Y, const int incY, float *A, const int lda) - { - DLIB_TEST_BLAS_BINDING_GER; - cblas_sger (order, M, N, alpha, X, incX, Y, incY, A, lda); - } - - inline void cblas_ger(const CBLAS_ORDER order, const int M, const int N, - const double alpha, const double *X, const int incX, - const double *Y, const int incY, double *A, const int lda) - { - DLIB_TEST_BLAS_BINDING_GER; - cblas_dger (order, M, N, alpha, X, incX, Y, incY, A, lda); - } - - // ---------------------------------------------------------------------------------------- - - inline void cblas_gerc(const CBLAS_ORDER order, const int M, const int N, - const std::complex<float>& alpha, const std::complex<float> *X, const int incX, - const std::complex<float> *Y, const int incY, std::complex<float> *A, const int lda) - { - DLIB_TEST_BLAS_BINDING_GER; - cblas_cgerc (order, M, N, &alpha, X, incX, Y, incY, A, lda); - } - - inline void cblas_gerc(const CBLAS_ORDER order, const int M, const int N, - const std::complex<double>& alpha, const std::complex<double> *X, const int incX, - const std::complex<double> *Y, const int incY, std::complex<double> *A, const int lda) - { - DLIB_TEST_BLAS_BINDING_GER; - cblas_zgerc (order, M, N, &alpha, X, incX, Y, incY, A, lda); - } - - // ---------------------------------------------------------------------------------------- - - inline float cblas_dot(const int N, const float *X, const int incX, - const float *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_DOT; - return cblas_sdot(N, X, incX, Y, incY); - } - - inline double cblas_dot(const int N, const double *X, const int incX, - const double *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_DOT; - return cblas_ddot(N, X, incX, Y, incY); - } - - inline std::complex<float> cblas_dot(const int N, const std::complex<float> *X, const int incX, - const std::complex<float> *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_DOT; - std::complex<float> result; - cblas_cdotu_sub(N, X, incX, Y, incY, &result); - return result; - } - - inline std::complex<double> cblas_dot(const int N, const std::complex<double> *X, const int incX, - const std::complex<double> *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_DOT; - std::complex<double> result; - cblas_zdotu_sub(N, X, incX, Y, incY, &result); - return result; - } - - // ---------------------------------------------------------------------------------------- - - inline std::complex<float> cblas_dotc(const int N, const std::complex<float> *X, const int incX, - const std::complex<float> *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_DOT; - std::complex<float> result; - cblas_cdotc_sub(N, X, incX, Y, incY, &result); - return result; - } - - inline std::complex<double> cblas_dotc(const int N, const std::complex<double> *X, const int incX, - const std::complex<double> *Y, const int incY) - { - DLIB_TEST_BLAS_BINDING_DOT; - std::complex<double> result; - cblas_zdotc_sub(N, X, incX, Y, incY, &result); - return result; - } - - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - // Helpers for determining the data pointer, LDA, and incX arguments to BLAS functions. - - template <typename T, long NR, long NC, typename MM> - int get_ld (const matrix<T,NR,NC,MM,row_major_layout>& m) { return m.nc(); } - - template <typename T, long NR, long NC, typename MM> - int get_ld (const matrix<T,NR,NC,MM,column_major_layout>& m) { return m.nr(); } - - - template <typename T, long NR, long NC, typename MM> - int get_ld (const matrix_op<op_subm<matrix<T,NR,NC,MM,row_major_layout> > >& m) { return m.op.m.nc(); } - - template <typename T, long NR, long NC, typename MM> - int get_ld (const matrix_op<op_subm<matrix<T,NR,NC,MM,column_major_layout> > >& m) { return m.op.m.nr(); } - - template <typename T, long NR, long NC, typename MM> - int get_ld (const assignable_sub_matrix<T,NR,NC,MM,row_major_layout>& m) { return m.m.nc(); } - - template <typename T, long NR, long NC, typename MM> - int get_ld (const assignable_sub_matrix<T,NR,NC,MM,column_major_layout>& m) { return m.m.nr(); } - - template <typename T, long NR, long NC, typename MM> - int get_ld (const assignable_col_matrix<T,NR,NC,MM,row_major_layout>& m) { return m.m.nc(); } - - template <typename T, long NR, long NC, typename MM> - int get_ld (const assignable_col_matrix<T,NR,NC,MM,column_major_layout>& m) { return m.m.nr(); } - - template <typename T, long NR, long NC, typename MM> - int get_ld (const assignable_row_matrix<T,NR,NC,MM,row_major_layout>& m) { return m.m.nc(); } - - template <typename T, long NR, long NC, typename MM> - int get_ld (const assignable_row_matrix<T,NR,NC,MM,column_major_layout>& m) { return m.m.nr(); } - - template <typename T> - int get_ld (const assignable_ptr_matrix<T>& m) { return m.nc(); } - - template <typename T, typename MM> - int get_ld (const matrix_op<op_array2d_to_mat<array2d<T,MM> > >& m) { return m.nc(); } - template <typename T, typename MM> - int get_ld (const matrix_op<op_array_to_mat<array<T,MM> > >& m) { return m.nc(); } - template < typename value_type, typename alloc > - int get_ld (const matrix_op<op_std_vect_to_mat<std::vector<value_type,alloc> > >& m) { return m.nc(); } - template < typename value_type, typename alloc > - int get_ld (const matrix_op<op_std_vect_to_mat<std_vector_c<value_type,alloc> > >& m) { return m.nc(); } - template <typename T> - int get_ld (const matrix_op<op_pointer_to_col_vect<T> >& m) { return m.nc(); } - template <typename T> - int get_ld (const matrix_op<op_pointer_to_mat<T> >& m) { return m.op.stride; } - - // -------- - - // get_inc() returns the offset from one element to another. If an object has a - // non-uniform offset between elements then returns 0 (e.g. a subm() view could - // have a non-uniform offset between elements). - - template <typename T, typename MM> - int get_inc (const matrix_op<op_array2d_to_mat<array2d<T,MM> > >& ) { return 1; } - template <typename T, typename MM> - int get_inc (const matrix_op<op_array_to_mat<array<T,MM> > >& ) { return 1; } - template < typename value_type, typename alloc > - int get_inc (const matrix_op<op_std_vect_to_mat<std::vector<value_type,alloc> > >& ) { return 1; } - template < typename value_type, typename alloc > - int get_inc (const matrix_op<op_std_vect_to_mat<std_vector_c<value_type,alloc> > >& ) { return 1; } - template <typename T> - int get_inc (const matrix_op<op_pointer_to_col_vect<T> >& ) { return 1; } - template <typename T> - int get_inc (const matrix_op<op_pointer_to_mat<T> >& m) { return m.op.stride==m.op.cols ? 1 : 0; } - - template <typename T, long NR, long NC, typename MM, typename L> - int get_inc (const matrix<T,NR,NC,MM,L>& ) { return 1; } - - template <typename T, long NR, long NC, typename MM> - int get_inc (const matrix_op<op_subm<matrix<T,NR,NC,MM,row_major_layout> > >& m) - { - // if the sub-view doesn't cover all the columns then it can't have a uniform - // layout. - if (m.nc() < m.op.m.nc()) - return 0; - else - return 1; - } - - template <typename T, long NR, long NC, typename MM> - int get_inc (const matrix_op<op_subm<matrix<T,NR,NC,MM,column_major_layout> > >& m) - { - if (m.nr() < m.op.m.nr()) - return 0; - else - return 1; - } - - template <typename T, long NR, long NC, typename MM> - int get_inc (const assignable_sub_matrix<T,NR,NC,MM,row_major_layout>& m) - { - if (m.nc() < m.m.nc()) - return 0; - else - return 1; - } - template <typename T, long NR, long NC, typename MM> - int get_inc (const assignable_sub_matrix<T,NR,NC,MM,column_major_layout>& m) - { - if (m.nr() < m.m.nr()) - return 0; - else - return 1; - } - - template <typename T> - int get_inc (const assignable_ptr_matrix<T>& ) { return 1; } - - template <typename T, long NR, long NC, typename MM> - int get_inc(const matrix_op<op_colm<matrix<T,NR,NC,MM,row_major_layout> > >& m) - { - return m.op.m.nc(); - } - - template <typename T, long NR, long NC, typename MM> - int get_inc(const matrix_op<op_rowm<matrix<T,NR,NC,MM,row_major_layout> > >& ) - { - return 1; - } - - template <typename T, long NR, long NC, typename MM> - int get_inc(const matrix_op<op_colm2<matrix<T,NR,NC,MM,row_major_layout> > >& m) - { - return m.op.m.nc(); - } - - template <typename T, long NR, long NC, typename MM> - int get_inc(const matrix_op<op_rowm2<matrix<T,NR,NC,MM,row_major_layout> > >& ) - { - return 1; - } - - - - template <typename T, long NR, long NC, typename MM> - int get_inc(const matrix_op<op_colm<matrix<T,NR,NC,MM,column_major_layout> > >& ) - { - return 1; - } - - template <typename T, long NR, long NC, typename MM> - int get_inc(const matrix_op<op_rowm<matrix<T,NR,NC,MM,column_major_layout> > >& m) - { - return m.op.m.nr(); - } - - template <typename T, long NR, long NC, typename MM> - int get_inc(const matrix_op<op_colm2<matrix<T,NR,NC,MM,column_major_layout> > >& ) - { - return 1; - } - - template <typename T, long NR, long NC, typename MM> - int get_inc(const matrix_op<op_rowm2<matrix<T,NR,NC,MM,column_major_layout> > >& m) - { - return m.op.m.nr(); - } - - - - template <typename T, long NR, long NC, typename MM> - int get_inc(const assignable_row_matrix<T,NR,NC,MM,row_major_layout>& ) - { - return 1; - } - - template <typename T, long NR, long NC, typename MM> - int get_inc(const assignable_row_matrix<T,NR,NC,MM,column_major_layout>& m) - { - return m.m.nr(); - } - - template <typename T, long NR, long NC, typename MM> - int get_inc(const assignable_col_matrix<T,NR,NC,MM,row_major_layout>& m) - { - return m.m.nc(); - } - - template <typename T, long NR, long NC, typename MM> - int get_inc(const assignable_col_matrix<T,NR,NC,MM,column_major_layout>& ) - { - return 1; - } - - // -------- - - template <typename T, long NR, long NC, typename MM, typename L> - const T* get_ptr (const matrix<T,NR,NC,MM,L>& m) { return &m(0,0); } - - template <typename T, long NR, long NC, typename MM, typename L> - T* get_ptr (matrix<T,NR,NC,MM,L>& m) { return &m(0,0); } - - template <typename T, long NR, long NC, typename MM, typename L> - const T* get_ptr (const matrix_op<op_subm<matrix<T,NR,NC,MM,L> > >& m) { return &m.op.m(m.op.r_,m.op.c_); } - - template <typename T, long NR, long NC, typename MM, typename L> - const T* get_ptr (const matrix_op<op_colm<matrix<T,NR,NC,MM,L> > >& m) { return &m.op.m(0,m.op.col); } - - template <typename T, long NR, long NC, typename MM, typename L> - const T* get_ptr (const matrix_op<op_rowm<matrix<T,NR,NC,MM,L> > >& m) { return &m.op.m(m.op.row,0); } - - template <typename T, long NR, long NC, typename MM, typename L> - const T* get_ptr (const matrix_op<op_colm2<matrix<T,NR,NC,MM,L> > >& m) { return &m.op.m(0,m.op.col); } - - template <typename T, long NR, long NC, typename MM, typename L> - const T* get_ptr (const matrix_op<op_rowm2<matrix<T,NR,NC,MM,L> > >& m) { return &m.op.m(m.op.row,0); } - - - template <typename T, long NR, long NC, typename MM, typename L> - T* get_ptr (assignable_col_matrix<T,NR,NC,MM,L>& m) { return &m(0,0); } - - template <typename T, long NR, long NC, typename MM, typename L> - T* get_ptr (assignable_row_matrix<T,NR,NC,MM,L>& m) { return &m(0,0); } - - template <typename T, long NR, long NC, typename MM, typename L> - T* get_ptr (assignable_sub_matrix<T,NR,NC,MM,L>& m) { return &m(0,0); } - - template <typename T> - T* get_ptr (assignable_ptr_matrix<T>& m) { return m.ptr; } - - template <typename T, typename MM> - const T* get_ptr (const matrix_op<op_array2d_to_mat<array2d<T,MM> > >& m) { return &m.op.array[0][0]; } - template <typename T, typename MM> - const T* get_ptr (const matrix_op<op_array_to_mat<array<T,MM> > >& m) { return &m.op.vect[0]; } - template < typename T, typename alloc > - const T* get_ptr (const matrix_op<op_std_vect_to_mat<std::vector<T,alloc> > >& m) { return &m.op.vect[0]; } - template < typename T, typename alloc > - const T* get_ptr (const matrix_op<op_std_vect_to_mat<std_vector_c<T,alloc> > >& m) { return &m.op.vect[0]; } - template <typename T> - const T* get_ptr (const matrix_op<op_pointer_to_col_vect<T> >& m) { return m.op.ptr; } - template <typename T> - const T* get_ptr (const matrix_op<op_pointer_to_mat<T> >& m) { return m.op.ptr; } - - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - - // Here we declare some matrix objects for use in the DLIB_ADD_BLAS_BINDING macro. These - // extern declarations don't actually correspond to any real matrix objects. They are - // simply here so we can build matrix expressions with the DLIB_ADD_BLAS_BINDING marco. - - - // Note that the fact that these are double matrices isn't important, it is just a placeholder in this case. - extern matrix<double> m; // general matrix - extern matrix<double,1,0> rv; // general row vector - extern matrix<double,0,1> cv; // general column vector - extern const double s; - - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - // AXPY/SCAL overloads - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - - DLIB_ADD_BLAS_BINDING(m) - { - - const int N = static_cast<int>(src.size()); - if (transpose == false && N != 0) - { - if (add_to) - { - if (get_inc(src) && get_inc(dest)) - cblas_axpy(N, alpha, get_ptr(src), get_inc(src), get_ptr(dest), get_inc(dest)); - else - matrix_assign_default(dest, src, alpha, add_to); - } - else - { - if (get_ptr(src) == get_ptr(dest)) - cblas_scal(N, alpha, get_ptr(dest)); - else - matrix_assign_default(dest, src, alpha, add_to); - } - } - else - { - matrix_assign_default(dest, trans(src), alpha, add_to); - } - - } DLIB_END_BLAS_BINDING - - DLIB_ADD_BLAS_BINDING(rv) - { - - const int N = static_cast<int>(src.size()); - if (transpose == false && N != 0) - { - if (add_to) - { - if (get_inc(src) && get_inc(dest)) - cblas_axpy(N, alpha, get_ptr(src), get_inc(src), get_ptr(dest), get_inc(dest)); - else - matrix_assign_default(dest, src, alpha, add_to); - } - else - { - if (get_ptr(src) == get_ptr(dest)) - cblas_scal(N, alpha, get_ptr(dest)); - else - matrix_assign_default(dest, src, alpha, add_to); - } - } - else - { - matrix_assign_default(dest, trans(src), alpha, add_to); - } - - } DLIB_END_BLAS_BINDING - - DLIB_ADD_BLAS_BINDING(cv) - { - - const int N = static_cast<int>(src.size()); - if (transpose == false && N != 0) - { - if (add_to) - { - if (get_inc(src) && get_inc(dest)) - cblas_axpy(N, alpha, get_ptr(src), get_inc(src), get_ptr(dest), get_inc(dest)); - else - matrix_assign_default(dest, src, alpha, add_to); - } - else - { - if (get_ptr(src) == get_ptr(dest)) - cblas_scal(N, alpha, get_ptr(dest)); - else - matrix_assign_default(dest, src, alpha, add_to); - } - } - else - { - matrix_assign_default(dest, trans(src), alpha, add_to); - } - - } DLIB_END_BLAS_BINDING - - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - // GEMM overloads - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - - DLIB_ADD_BLAS_BINDING(m*m) - { - //cout << "BLAS GEMM: m*m" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const int M = static_cast<int>(src.nr()); - const int N = static_cast<int>(src.nc()); - const int K = static_cast<int>(src.lhs.nc()); - const T* A = get_ptr(src.lhs); - const int lda = get_ld(src.lhs); - const T* B = get_ptr(src.rhs); - const int ldb = get_ld(src.rhs); - - const T beta = static_cast<T>(add_to?1:0); - T* C = get_ptr(dest); - const int ldc = get_ld(dest); - - if (transpose == false) - cblas_gemm(Order, CblasNoTrans, CblasNoTrans, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); - else - cblas_gemm(Order, CblasTrans, CblasTrans, N, M, K, alpha, B, ldb, A, lda, beta, C, ldc); - - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(m)*m) - { - //cout << "BLAS GEMM: trans(m)*m" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasTrans; - const CBLAS_TRANSPOSE TransB = CblasNoTrans; - const int M = static_cast<int>(src.nr()); - const int N = static_cast<int>(src.nc()); - const int K = static_cast<int>(src.lhs.nc()); - const T* A = get_ptr(src.lhs.op.m); - const int lda = get_ld(src.lhs.op.m); - const T* B = get_ptr(src.rhs); - const int ldb = get_ld(src.rhs); - - const T beta = static_cast<T>(add_to?1:0); - T* C = get_ptr(dest); - const int ldc = get_ld(dest); - - if (transpose == false) - cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); - else - cblas_gemm(Order, TransA, TransB, N, M, K, alpha, B, ldb, A, lda, beta, C, ldc); - - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(m*trans(m)) - { - //cout << "BLAS GEMM: m*trans(m)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasNoTrans; - const CBLAS_TRANSPOSE TransB = CblasTrans; - const int M = static_cast<int>(src.nr()); - const int N = static_cast<int>(src.nc()); - const int K = static_cast<int>(src.lhs.nc()); - const T* A = get_ptr(src.lhs); - const int lda = get_ld(src.lhs); - const T* B = get_ptr(src.rhs.op.m); - const int ldb = get_ld(src.rhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* C = get_ptr(dest); - const int ldc = get_ld(dest); - - if (transpose == false) - cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); - else - cblas_gemm(Order, TransA, TransB, N, M, K, alpha, B, ldb, A, lda, beta, C, ldc); - - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(m)*trans(m)) - { - //cout << "BLAS GEMM: trans(m)*trans(m)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const int M = static_cast<int>(src.nr()); - const int N = static_cast<int>(src.nc()); - const int K = static_cast<int>(src.lhs.nc()); - const T* A = get_ptr(src.lhs.op.m); - const int lda = get_ld(src.lhs.op.m); - const T* B = get_ptr(src.rhs.op.m); - const int ldb = get_ld(src.rhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* C = get_ptr(dest); - const int ldc = get_ld(dest); - - if (transpose == false) - cblas_gemm(Order, CblasTrans, CblasTrans, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); - else - cblas_gemm(Order, CblasNoTrans, CblasNoTrans, N, M, K, alpha, B, ldb, A, lda, beta, C, ldc); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - // -------------------------------------- - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(conj(m))*m) - { - //cout << "BLAS GEMM: trans(conj(m))*m" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasConjTrans; - const CBLAS_TRANSPOSE TransB = CblasNoTrans; - const int M = static_cast<int>(src.nr()); - const int N = static_cast<int>(src.nc()); - const int K = static_cast<int>(src.lhs.nc()); - const T* A = get_ptr(src.lhs.op.m); - const int lda = get_ld(src.lhs.op.m); - const T* B = get_ptr(src.rhs); - const int ldb = get_ld(src.rhs); - - const T beta = static_cast<T>(add_to?1:0); - T* C = get_ptr(dest); - const int ldc = get_ld(dest); - - if (transpose == false) - cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); - else - matrix_assign_default(dest, trans(src), alpha, add_to); - - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(conj(m))*trans(m)) - { - //cout << "BLAS GEMM: trans(conj(m))*trans(m)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasConjTrans; - const CBLAS_TRANSPOSE TransB = CblasTrans; - const int M = static_cast<int>(src.nr()); - const int N = static_cast<int>(src.nc()); - const int K = static_cast<int>(src.lhs.nc()); - const T* A = get_ptr(src.lhs.op.m); - const int lda = get_ld(src.lhs.op.m); - const T* B = get_ptr(src.rhs.op.m); - const int ldb = get_ld(src.rhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* C = get_ptr(dest); - const int ldc = get_ld(dest); - - if (transpose == false) - cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); - else - matrix_assign_default(dest, trans(src), alpha, add_to); - - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(m*trans(conj(m))) - { - //cout << "BLAS GEMM: m*trans(conj(m))" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasNoTrans; - const CBLAS_TRANSPOSE TransB = CblasConjTrans; - const int M = static_cast<int>(src.nr()); - const int N = static_cast<int>(src.nc()); - const int K = static_cast<int>(src.lhs.nc()); - const T* A = get_ptr(src.lhs); - const int lda = get_ld(src.lhs); - const T* B = get_ptr(src.rhs.op.m); - const int ldb = get_ld(src.rhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* C = get_ptr(dest); - const int ldc = get_ld(dest); - - if (transpose == false) - cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); - else - matrix_assign_default(dest, trans(src), alpha, add_to); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(m)*trans(conj(m))) - { - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasTrans; - const CBLAS_TRANSPOSE TransB = CblasConjTrans; - const int M = static_cast<int>(src.nr()); - const int N = static_cast<int>(src.nc()); - const int K = static_cast<int>(src.lhs.nc()); - const T* A = get_ptr(src.lhs.op.m); - const int lda = get_ld(src.lhs.op.m); - const T* B = get_ptr(src.rhs.op.m); - const int ldb = get_ld(src.rhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* C = get_ptr(dest); - const int ldc = get_ld(dest); - - if (transpose == false) - cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); - else - matrix_assign_default(dest, trans(src), alpha, add_to); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(conj(m))*trans(conj(m))) - { - //cout << "BLAS GEMM: trans(conj(m))*trans(conj(m))" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasConjTrans; - const CBLAS_TRANSPOSE TransB = CblasConjTrans; - const int M = static_cast<int>(src.nr()); - const int N = static_cast<int>(src.nc()); - const int K = static_cast<int>(src.lhs.nc()); - const T* A = get_ptr(src.lhs.op.m); - const int lda = get_ld(src.lhs.op.m); - const T* B = get_ptr(src.rhs.op.m); - const int ldb = get_ld(src.rhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* C = get_ptr(dest); - const int ldc = get_ld(dest); - - if (transpose == false) - cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); - else - matrix_assign_default(dest, trans(src), alpha, add_to); - } DLIB_END_BLAS_BINDING - - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - // GEMV overloads - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - - DLIB_ADD_BLAS_BINDING(m*cv) - { - //cout << "BLAS GEMV: m*cv" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasNoTrans; - const int M = static_cast<int>(src.lhs.nr()); - const int N = static_cast<int>(src.lhs.nc()); - const T* A = get_ptr(src.lhs); - const int lda = get_ld(src.lhs); - const T* X = get_ptr(src.rhs); - const int incX = get_inc(src.rhs); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(rv*m) - { - // Note that rv*m is the same as trans(m)*trans(rv) - - //cout << "BLAS GEMV: rv*m" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasTrans; - const int M = static_cast<int>(src.rhs.nr()); - const int N = static_cast<int>(src.rhs.nc()); - const T* A = get_ptr(src.rhs); - const int lda = get_ld(src.rhs); - const T* X = get_ptr(src.lhs); - const int incX = get_inc(src.lhs); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(cv)*m) - { - // Note that trans(cv)*m is the same as trans(m)*cv - - //cout << "BLAS GEMV: trans(cv)*m" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasTrans; - const int M = static_cast<int>(src.rhs.nr()); - const int N = static_cast<int>(src.rhs.nc()); - const T* A = get_ptr(src.rhs); - const int lda = get_ld(src.rhs); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(m*trans(rv)) - { - //cout << "BLAS GEMV: m*trans(rv)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasNoTrans; - const int M = static_cast<int>(src.lhs.nr()); - const int N = static_cast<int>(src.lhs.nc()); - const T* A = get_ptr(src.lhs); - const int lda = get_ld(src.lhs); - const T* X = get_ptr(src.rhs.op.m); - const int incX = get_inc(src.rhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - // -------------------------------------- - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(m)*cv) - { - //cout << "BLAS GEMV: trans(m)*cv" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasTrans; - const int M = static_cast<int>(src.lhs.op.m.nr()); - const int N = static_cast<int>(src.lhs.op.m.nc()); - const T* A = get_ptr(src.lhs.op.m); - const int lda = get_ld(src.lhs.op.m); - const T* X = get_ptr(src.rhs); - const int incX = get_inc(src.rhs); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(rv*trans(m)) - { - // Note that rv*trans(m) is the same as m*trans(rv) - - //cout << "BLAS GEMV: rv*trans(m)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasNoTrans; - const int M = static_cast<int>(src.rhs.op.m.nr()); - const int N = static_cast<int>(src.rhs.op.m.nc()); - const T* A = get_ptr(src.rhs.op.m); - const int lda = get_ld(src.rhs.op.m); - const T* X = get_ptr(src.lhs); - const int incX = get_inc(src.lhs); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(cv)*trans(m)) - { - // Note that trans(cv)*trans(m) is the same as m*cv - - //cout << "BLAS GEMV: trans(cv)*trans(m)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasNoTrans; - const int M = static_cast<int>(src.rhs.op.m.nr()); - const int N = static_cast<int>(src.rhs.op.m.nc()); - const T* A = get_ptr(src.rhs.op.m); - const int lda = get_ld(src.rhs.op.m); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(m)*trans(rv)) - { - //cout << "BLAS GEMV: trans(m)*trans(rv)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasTrans; - const int M = static_cast<int>(src.lhs.op.m.nr()); - const int N = static_cast<int>(src.lhs.op.m.nc()); - const T* A = get_ptr(src.lhs.op.m); - const int lda = get_ld(src.lhs.op.m); - const T* X = get_ptr(src.rhs.op.m); - const int incX = get_inc(src.rhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - // -------------------------------------- - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(cv)*conj(m)) - { - // Note that trans(cv)*conj(m) == conj(trans(m))*cv - //cout << "BLAS GEMV: trans(cv)*conj(m)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasConjTrans; - const int M = static_cast<int>(src.rhs.op.m.nr()); - const int N = static_cast<int>(src.rhs.op.m.nc()); - const T* A = get_ptr(src.rhs.op.m); - const int lda = get_ld(src.rhs.op.m); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(rv*conj(m)) - { - // Note that rv*conj(m) == conj(trans(m))*cv - //cout << "BLAS GEMV: rv*conj(m)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasConjTrans; - const int M = static_cast<int>(src.rhs.op.m.nr()); - const int N = static_cast<int>(src.rhs.op.m.nc()); - const T* A = get_ptr(src.rhs.op.m); - const int lda = get_ld(src.rhs.op.m); - const T* X = get_ptr(src.lhs); - const int incX = get_inc(src.lhs); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(conj(m))*cv) - { - //cout << "BLAS GEMV: trans(conj(m))*cv" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasConjTrans; - const int M = static_cast<int>(src.lhs.op.m.nr()); - const int N = static_cast<int>(src.lhs.op.m.nc()); - const T* A = get_ptr(src.lhs.op.m); - const int lda = get_ld(src.lhs.op.m); - const T* X = get_ptr(src.rhs); - const int incX = get_inc(src.rhs); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(conj(m))*trans(rv)) - { - //cout << "BLAS GEMV: trans(conj(m))*trans(rv)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const CBLAS_TRANSPOSE TransA = CblasConjTrans; - const int M = static_cast<int>(src.lhs.op.m.nr()); - const int N = static_cast<int>(src.lhs.op.m.nc()); - const T* A = get_ptr(src.lhs.op.m); - const int lda = get_ld(src.lhs.op.m); - const T* X = get_ptr(src.rhs.op.m); - const int incX = get_inc(src.rhs.op.m); - - const T beta = static_cast<T>(add_to?1:0); - T* Y = get_ptr(dest); - const int incY = get_inc(dest); - - cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); - } DLIB_END_BLAS_BINDING - - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - // GER overloads - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - - DLIB_ADD_BLAS_BINDING(cv*rv) - { - //cout << "BLAS GER: cv*rv" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const int M = static_cast<int>(dest.nr()); - const int N = static_cast<int>(dest.nc()); - const T* X = get_ptr(src.lhs); - const int incX = get_inc(src.lhs); - const T* Y = get_ptr(src.rhs); - const int incY = get_inc(src.rhs); - - if (add_to == false) - zero_matrix(dest); - - T* A = get_ptr(dest); - const int lda = get_ld(dest); - - if (transpose == false) - cblas_ger(Order, M, N, alpha, X, incX, Y, incY, A, lda); - else - cblas_ger(Order, M, N, alpha, Y, incY, X, incX, A, lda); - - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(rv)*rv) - { - //cout << "BLAS GER: trans(rv)*rv" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const int M = static_cast<int>(dest.nr()); - const int N = static_cast<int>(dest.nc()); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - const T* Y = get_ptr(src.rhs); - const int incY = get_inc(src.rhs); - - if (add_to == false) - zero_matrix(dest); - - T* A = get_ptr(dest); - const int lda = get_ld(dest); - - if (transpose == false) - cblas_ger(Order, M, N, alpha, X, incX, Y, incY, A, lda); - else - cblas_ger(Order, M, N, alpha, Y, incY, X, incX, A, lda); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(cv*trans(cv)) - { - //cout << "BLAS GER: cv*trans(cv)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const int M = static_cast<int>(dest.nr()); - const int N = static_cast<int>(dest.nc()); - const T* X = get_ptr(src.lhs); - const int incX = get_inc(src.lhs); - const T* Y = get_ptr(src.rhs.op.m); - const int incY = get_inc(src.rhs.op.m); - - if (add_to == false) - zero_matrix(dest); - - T* A = get_ptr(dest); - const int lda = get_ld(dest); - - if (transpose == false) - cblas_ger(Order, M, N, alpha, X, incX, Y, incY, A, lda); - else - cblas_ger(Order, M, N, alpha, Y, incY, X, incX, A, lda); - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(rv)*trans(cv)) - { - //cout << "BLAS GER: trans(rv)*trans(cv)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const int M = static_cast<int>(dest.nr()); - const int N = static_cast<int>(dest.nc()); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - const T* Y = get_ptr(src.rhs.op.m); - const int incY = get_inc(src.rhs.op.m); - - if (add_to == false) - zero_matrix(dest); - - T* A = get_ptr(dest); - const int lda = get_ld(dest); - - if (transpose == false) - cblas_ger(Order, M, N, alpha, X, incX, Y, incY, A, lda); - else - cblas_ger(Order, M, N, alpha, Y, incY, X, incX, A, lda); - } DLIB_END_BLAS_BINDING - - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - // GERC overloads - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - - /* - DLIB_ADD_BLAS_BINDING(cv*conj(rv)) - { - //cout << "BLAS GERC: cv*conj(rv)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const int M = static_cast<int>(dest.nr()); - const int N = static_cast<int>(dest.nc()); - const T* X = get_ptr(src.lhs); - const int incX = get_inc(src.lhs); - const T* Y = get_ptr(src.rhs.op.m); - const int incY = get_inc(src.rhs.op.m); - - if (add_to == false) - zero_matrix(dest); - - T* A = get_ptr(dest); - const int lda = get_ld(dest); - - if (transpose == false) - cblas_gerc(Order, M, N, alpha, X, incX, Y, incY, A, lda); - else - cblas_gerc(Order, M, N, alpha, Y, incY, X, incX, A, lda); - } DLIB_END_BLAS_BINDING - */ - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(cv*conj(trans(cv))) - { - //cout << "BLAS GERC: cv*conj(trans(cv))" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const int M = static_cast<int>(dest.nr()); - const int N = static_cast<int>(dest.nc()); - const T* X = get_ptr(src.lhs); - const int incX = get_inc(src.lhs); - const T* Y = get_ptr(src.rhs.op.m); - const int incY = get_inc(src.rhs.op.m); - - - if (transpose == false) - { - T* A = get_ptr(dest); - const int lda = get_ld(dest); - - if (add_to == false) - zero_matrix(dest); - - cblas_gerc(Order, M, N, alpha, X, incX, Y, incY, A, lda); - } - else - { - matrix_assign_default(dest,trans(src),alpha,add_to); - //cblas_gerc(Order, M, N, alpha, Y, incY, X, incX, A, lda); - } - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(rv)*conj(trans(cv))) - { - //cout << "BLAS GERC: trans(rv)*conj(trans(cv))" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const int M = static_cast<int>(dest.nr()); - const int N = static_cast<int>(dest.nc()); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - const T* Y = get_ptr(src.rhs.op.m); - const int incY = get_inc(src.rhs.op.m); - - - if (transpose == false) - { - if (add_to == false) - zero_matrix(dest); - - T* A = get_ptr(dest); - const int lda = get_ld(dest); - - cblas_gerc(Order, M, N, alpha, X, incX, Y, incY, A, lda); - } - else - { - matrix_assign_default(dest,trans(src),alpha,add_to); - //cblas_gerc(Order, M, N, alpha, Y, incY, X, incX, A, lda); - } - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - /* - DLIB_ADD_BLAS_BINDING(trans(rv)*conj(rv)) - { - //cout << "BLAS GERC: trans(rv)*conj(rv)" << endl; - const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; - const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; - const int M = static_cast<int>(dest.nr()); - const int N = static_cast<int>(dest.nc()); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - const T* Y = get_ptr(src.rhs.op.m); - const int incY = get_inc(src.rhs.op.m); - - if (add_to == false) - zero_matrix(dest); - - T* A = get_ptr(dest); - const int lda = get_ld(dest); - - if (transpose == false) - cblas_gerc(Order, M, N, alpha, X, incX, Y, incY, A, lda); - else - cblas_gerc(Order, M, N, alpha, Y, incY, X, incX, A, lda); - } DLIB_END_BLAS_BINDING - */ - - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - // DOT overloads - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - - DLIB_ADD_BLAS_BINDING(rv*cv) - { - //cout << "BLAS DOT: rv*cv" << endl; - const int N = static_cast<int>(src.lhs.size()); - const T* X = get_ptr(src.lhs); - const int incX = get_inc(src.lhs); - const T* Y = get_ptr(src.rhs); - const int incY = get_inc(src.rhs); - - if (add_to == false) - dest(0) = alpha*cblas_dot(N, X, incX, Y, incY); - else - dest(0) += alpha*cblas_dot(N, X, incX, Y, incY); - - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(cv)*cv) - { - //cout << "BLAS DOT: trans(cv)*cv" << endl; - const int N = static_cast<int>(src.lhs.size()); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - const T* Y = get_ptr(src.rhs); - const int incY = get_inc(src.rhs); - - if (add_to == false) - dest(0) = alpha*cblas_dot(N, X, incX, Y, incY); - else - dest(0) += alpha*cblas_dot(N, X, incX, Y, incY); - - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(rv*trans(rv)) - { - //cout << "BLAS DOT: rv*trans(rv)" << endl; - const int N = static_cast<int>(src.lhs.size()); - const T* X = get_ptr(src.lhs); - const int incX = get_inc(src.lhs); - const T* Y = get_ptr(src.rhs.op.m); - const int incY = get_inc(src.rhs.op.m); - - if (add_to == false) - dest(0) = alpha*cblas_dot(N, X, incX, Y, incY); - else - dest(0) += alpha*cblas_dot(N, X, incX, Y, incY); - - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(cv)*trans(rv)) - { - //cout << "BLAS DOT: trans(cv)*trans(rv)" << endl; - const int N = static_cast<int>(src.lhs.op.m.size()); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - const T* Y = get_ptr(src.rhs.op.m); - const int incY = get_inc(src.rhs.op.m); - - if (add_to == false) - dest(0) = alpha*cblas_dot(N, X, incX, Y, incY); - else - dest(0) += alpha*cblas_dot(N, X, incX, Y, incY); - - } DLIB_END_BLAS_BINDING - - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - // DOTC overloads - // ---------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------- - - DLIB_ADD_BLAS_BINDING(conj(rv)*cv) - { - //cout << "BLAS DOTC: conj(rv)*cv" << endl; - const int N = static_cast<int>(src.lhs.op.m.size()); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - const T* Y = get_ptr(src.rhs); - const int incY = get_inc(src.rhs); - - if (add_to == false) - dest(0) = alpha*cblas_dotc(N, X, incX, Y, incY); - else - dest(0) += alpha*cblas_dotc(N, X, incX, Y, incY); - - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(conj(trans(cv))*cv) - { - //cout << "BLAS DOTC: conj(trans(cv))*cv" << endl; - const int N = static_cast<int>(src.lhs.op.m.size()); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - const T* Y = get_ptr(src.rhs); - const int incY = get_inc(src.rhs); - - if (add_to == false) - dest(0) = alpha*cblas_dotc(N, X, incX, Y, incY); - else - dest(0) += alpha*cblas_dotc(N, X, incX, Y, incY); - - } DLIB_END_BLAS_BINDING - - // -------------------------------------- - - DLIB_ADD_BLAS_BINDING(trans(conj(cv))*trans(rv)) - { - //cout << "BLAS DOTC: trans(conj(cv))*trans(rv)" << endl; - const int N = static_cast<int>(src.lhs.op.m.size()); - const T* X = get_ptr(src.lhs.op.m); - const int incX = get_inc(src.lhs.op.m); - const T* Y = get_ptr(src.rhs.op.m); - const int incY = get_inc(src.rhs.op.m); - - if (add_to == false) - dest(0) = alpha*cblas_dotc(N, X, incX, Y, incY); - else - dest(0) += alpha*cblas_dotc(N, X, incX, Y, incY); - - } DLIB_END_BLAS_BINDING - - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_BLAS_BINDINGS_ - diff --git a/ml/dlib/dlib/matrix/matrix_cholesky.h b/ml/dlib/dlib/matrix/matrix_cholesky.h deleted file mode 100644 index fc1140692..000000000 --- a/ml/dlib/dlib/matrix/matrix_cholesky.h +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (C) 2009 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -// This code was adapted from code from the JAMA part of NIST's TNT library. -// See: http://math.nist.gov/tnt/ -#ifndef DLIB_MATRIX_CHOLESKY_DECOMPOSITION_H -#define DLIB_MATRIX_CHOLESKY_DECOMPOSITION_H - -#include "matrix.h" -#include "matrix_utilities.h" -#include "matrix_subexp.h" -#include <cmath> - -#ifdef DLIB_USE_LAPACK -#include "lapack/potrf.h" -#endif - -#include "matrix_trsm.h" - -namespace dlib -{ - - template < - typename matrix_exp_type - > - class cholesky_decomposition - { - - public: - - const static long NR = matrix_exp_type::NR; - const static long NC = matrix_exp_type::NC; - typedef typename matrix_exp_type::type type; - typedef typename matrix_exp_type::mem_manager_type mem_manager_type; - typedef typename matrix_exp_type::layout_type layout_type; - - typedef matrix<type,0,0,mem_manager_type,layout_type> matrix_type; - typedef matrix<type,NR,1,mem_manager_type,layout_type> column_vector_type; - - // You have supplied an invalid type of matrix_exp_type. You have - // to use this object with matrices that contain float or double type data. - COMPILE_TIME_ASSERT((is_same_type<float, type>::value || - is_same_type<double, type>::value )); - - - - template <typename EXP> - cholesky_decomposition( - const matrix_exp<EXP>& A - ); - - bool is_spd( - ) const; - - const matrix_type& get_l( - ) const; - - template <typename EXP> - const typename EXP::matrix_type solve ( - const matrix_exp<EXP>& B - ) const; - - private: - - matrix_type L_; // lower triangular factor - bool isspd; // true if matrix to be factored was SPD - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Member functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - bool cholesky_decomposition<matrix_exp_type>:: - is_spd( - ) const - { - return isspd; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename cholesky_decomposition<matrix_exp_type>::matrix_type& cholesky_decomposition<matrix_exp_type>:: - get_l( - ) const - { - return L_; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - template <typename EXP> - cholesky_decomposition<matrix_exp_type>:: - cholesky_decomposition( - const matrix_exp<EXP>& A_ - ) - { - using std::sqrt; - COMPILE_TIME_ASSERT((is_same_type<type, typename EXP::type>::value)); - - // make sure requires clause is not broken - DLIB_ASSERT(A_.nr() == A_.nc() && A_.size() > 0, - "\tcholesky_decomposition::cholesky_decomposition(A_)" - << "\n\tYou can only use this on square matrices" - << "\n\tA_.nr(): " << A_.nr() - << "\n\tA_.nc(): " << A_.nc() - << "\n\tA_.size(): " << A_.size() - << "\n\tthis: " << this - ); - -#ifdef DLIB_USE_LAPACK - L_ = A_; - const type eps = max(abs(diag(L_)))*std::sqrt(std::numeric_limits<type>::epsilon())/100; - - // check if the matrix is actually symmetric - bool is_symmetric = true; - for (long r = 0; r < L_.nr() && is_symmetric; ++r) - { - for (long c = r+1; c < L_.nc() && is_symmetric; ++c) - { - // this is approximately doing: is_symmetric = is_symmetric && ( L_(k,j) == L_(j,k)) - is_symmetric = is_symmetric && (std::abs(L_(r,c) - L_(c,r)) < eps ); - } - } - - // now compute the actual cholesky decomposition - int info = lapack::potrf('L', L_); - - // check if it's really SPD - if (info == 0 && is_symmetric && min(abs(diag(L_))) > eps*100) - isspd = true; - else - isspd = false; - - L_ = lowerm(L_); -#else - const_temp_matrix<EXP> A(A_); - - - isspd = true; - - const long n = A.nc(); - L_.set_size(n,n); - - const type eps = max(abs(diag(A)))*std::sqrt(std::numeric_limits<type>::epsilon())/100; - - // Main loop. - for (long j = 0; j < n; j++) - { - type d(0.0); - for (long k = 0; k < j; k++) - { - type s(0.0); - for (long i = 0; i < k; i++) - { - s += L_(k,i)*L_(j,i); - } - - // if L_(k,k) != 0 - if (std::abs(L_(k,k)) > eps) - { - s = (A(j,k) - s)/L_(k,k); - } - else - { - s = (A(j,k) - s); - isspd = false; - } - - L_(j,k) = s; - - d = d + s*s; - - // this is approximately doing: isspd = isspd && ( A(k,j) == A(j,k)) - isspd = isspd && (std::abs(A(k,j) - A(j,k)) < eps ); - } - d = A(j,j) - d; - isspd = isspd && (d > eps); - L_(j,j) = sqrt(d > 0.0 ? d : 0.0); - for (long k = j+1; k < n; k++) - { - L_(j,k) = 0.0; - } - } -#endif - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - template <typename EXP> - const typename EXP::matrix_type cholesky_decomposition<matrix_exp_type>:: - solve( - const matrix_exp<EXP>& B - ) const - { - COMPILE_TIME_ASSERT((is_same_type<type, typename EXP::type>::value)); - - // make sure requires clause is not broken - DLIB_ASSERT(L_.nr() == B.nr(), - "\tconst matrix cholesky_decomposition::solve(B)" - << "\n\tInvalid arguments were given to this function." - << "\n\tL_.nr(): " << L_.nr() - << "\n\tB.nr(): " << B.nr() - << "\n\tthis: " << this - ); - - matrix<type, NR, EXP::NC, mem_manager_type, layout_type> X(B); - - using namespace blas_bindings; - // Solve L*y = b; - triangular_solver(CblasLeft, CblasLower, CblasNoTrans, CblasNonUnit, L_, X); - // Solve L'*X = Y; - triangular_solver(CblasLeft, CblasLower, CblasTrans, CblasNonUnit, L_, X); - return X; - } - -// ---------------------------------------------------------------------------------------- - - - -} - -#endif // DLIB_MATRIX_CHOLESKY_DECOMPOSITION_H - - - - diff --git a/ml/dlib/dlib/matrix/matrix_conj_trans.h b/ml/dlib/dlib/matrix/matrix_conj_trans.h deleted file mode 100644 index 3c319ccaf..000000000 --- a/ml/dlib/dlib/matrix/matrix_conj_trans.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (C) 2009 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_CONJ_TRANS_FUNCTIONS -#define DLIB_MATRIx_CONJ_TRANS_FUNCTIONS - -#include "matrix_utilities.h" -#include "matrix_math_functions.h" -#include "matrix.h" -#include "../algs.h" -#include <cmath> -#include <complex> -#include <limits> - - -namespace dlib -{ - /*! - The point of the two functions defined in this file is to make statements - of the form conj(trans(m)) and trans(conj(m)) look the same so that it is - easier to map them to BLAS functions later on. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_conj_trans - { - op_conj_trans( const M& m_) : m(m_){} - const M& m; - - const static long cost = M::cost+1; - const static long NR = M::NC; - const static long NC = M::NR; - typedef typename M::type type; - typedef typename M::type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply (long r, long c) const { return std::conj(m(c,r)); } - - long nr () const { return m.nc(); } - long nc () const { return m.nr(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template <typename EXP> - const matrix_op<op_conj_trans<EXP> > trans ( - const matrix_op<op_conj<EXP> >& m - ) - { - typedef op_conj_trans<EXP> op; - return matrix_op<op>(op(m.op.m)); - } - - template <typename EXP> - const matrix_op<op_conj_trans<EXP> > conj ( - const matrix_op<op_trans<EXP> >& m - ) - { - typedef op_conj_trans<EXP> op; - return matrix_op<op>(op(m.op.m)); - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_CONJ_TRANS_FUNCTIONS - - diff --git a/ml/dlib/dlib/matrix/matrix_conv.h b/ml/dlib/dlib/matrix/matrix_conv.h deleted file mode 100644 index b90c388bc..000000000 --- a/ml/dlib/dlib/matrix/matrix_conv.h +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright (C) 2011 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_CONV_Hh_ -#define DLIB_MATRIx_CONV_Hh_ - -#include "matrix_conv_abstract.h" -#include "matrix.h" -#include "matrix_fft.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - template <typename T> - const T& conj(const T& item) { return item; } - template <typename T> - std::complex<T> conj(const std::complex<T>& item) { return std::conj(item); } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2, bool flip_m2 = false> - struct op_conv - { - op_conv( const M1& m1_, const M2& m2_) : - m1(m1_), - m2(m2_), - nr_(m1.nr()+m2.nr()-1), - nc_(m1.nc()+m2.nc()-1) - { - if (nr_ < 0 || m1.size() == 0 || m2.size() == 0) - nr_ = 0; - if (nc_ < 0 || m1.size() == 0 || m2.size() == 0) - nc_ = 0; - } - - const M1& m1; - const M2& m2; - long nr_; - long nc_; - - const static long cost = (M1::cost+M2::cost)*10; - const static long NR = (M1::NR*M2::NR==0) ? (0) : (M1::NR+M2::NR-1); - const static long NC = (M1::NC*M2::NC==0) ? (0) : (M1::NC+M2::NC-1); - typedef typename M1::type type; - typedef type const_ret_type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - - const_ret_type apply (long r, long c) const - { - type temp = 0; - - const long min_rr = std::max<long>(r-m2.nr()+1, 0); - const long max_rr = std::min<long>(m1.nr()-1, r); - - const long min_cc = std::max<long>(c-m2.nc()+1, 0); - const long max_cc = std::min<long>(m1.nc()-1, c); - - for (long rr = min_rr; rr <= max_rr; ++rr) - { - for (long cc = min_cc; cc <= max_cc; ++cc) - { - if (flip_m2) - temp += m1(rr,cc)*dlib::impl::conj(m2(m2.nr()-r+rr-1, m2.nc()-c+cc-1)); - else - temp += m1(rr,cc)*m2(r-rr,c-cc); - } - } - - return temp; - } - - long nr () const { return nr_; } - long nc () const { return nc_; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m1.aliases(item) || m2.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m1.aliases(item) || m2.aliases(item); } - - }; - - template < - typename M1, - typename M2 - > - const matrix_op<op_conv<M1,M2> > conv ( - const matrix_exp<M1>& m1, - const matrix_exp<M2>& m2 - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true)); - - typedef op_conv<M1,M2> op; - return matrix_op<op>(op(m1.ref(),m2.ref())); - } - - template < - typename M1, - typename M2 - > - const matrix_op<op_conv<M1,M2,true> > xcorr ( - const matrix_exp<M1>& m1, - const matrix_exp<M2>& m2 - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true)); - - typedef op_conv<M1,M2,true> op; - return matrix_op<op>(op(m1.ref(),m2.ref())); - } - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - inline size_t bounding_power_of_two ( - size_t n - ) - { - size_t s = 1; - for (unsigned int i = 0; i < sizeof(s)*8 && s < n; ++i) - s <<= 1; - return s; - } - } - - template < - typename EXP1, - typename EXP2 - > - typename EXP1::matrix_type xcorr_fft( - const matrix_exp<EXP1>& u, - const matrix_exp<EXP2>& v - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type, typename EXP2::type>::value == true)); - using T = typename EXP1::type; - COMPILE_TIME_ASSERT((is_same_type<double,T>::value || is_same_type<float,T>::value || is_same_type<long double,T>::value )); - - const long pad_nr = impl::bounding_power_of_two(u.nr() + v.nr() - 1); - const long pad_nc = impl::bounding_power_of_two(u.nc() + v.nc() - 1); - - matrix<std::complex<T>> U(pad_nr, pad_nc), V(pad_nr,pad_nc); - - U = 0; - V = 0; - set_subm(U,U.nr()-u.nr(),U.nc()-u.nc(),u.nr(),u.nc()) = u; - set_subm(V,get_rect(v)) = v; - - fft_inplace(U); - fft_inplace(V); - - return subm(real(ifft(pointwise_multiply(U, conj(V)))), - U.nr()-u.nr()-v.nr()+1, - U.nc()-u.nc()-v.nc()+1, - u.nr()+v.nr()-1, - u.nc()+v.nc()-1 - ); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2, bool flip_m2 = false> - struct op_conv_same - { - op_conv_same( const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_),nr_(m1.nr()),nc_(m1.nc()) - { - if (m1.size() == 0 || m2.size() == 0) - nr_ = 0; - if (m1.size() == 0 || m2.size() == 0) - nc_ = 0; - } - - const M1& m1; - const M2& m2; - long nr_; - long nc_; - - const static long cost = (M1::cost+M2::cost)*10; - const static long NR = M1::NR; - const static long NC = M1::NC; - typedef typename M1::type type; - typedef type const_ret_type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - - const_ret_type apply (long r, long c) const - { - r += m2.nr()/2; - c += m2.nc()/2; - - type temp = 0; - - const long min_rr = std::max<long>(r-m2.nr()+1, 0); - const long max_rr = std::min<long>(m1.nr()-1, r); - - const long min_cc = std::max<long>(c-m2.nc()+1, 0); - const long max_cc = std::min<long>(m1.nc()-1, c); - - for (long rr = min_rr; rr <= max_rr; ++rr) - { - for (long cc = min_cc; cc <= max_cc; ++cc) - { - if (flip_m2) - temp += m1(rr,cc)*dlib::impl::conj(m2(m2.nr()-r+rr-1, m2.nc()-c+cc-1)); - else - temp += m1(rr,cc)*m2(r-rr,c-cc); - } - } - - return temp; - } - - long nr () const { return nr_; } - long nc () const { return nc_; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m1.aliases(item) || m2.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m1.aliases(item) || m2.aliases(item); } - - }; - - template < - typename M1, - typename M2 - > - const matrix_op<op_conv_same<M1,M2> > conv_same ( - const matrix_exp<M1>& m1, - const matrix_exp<M2>& m2 - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true)); - - typedef op_conv_same<M1,M2> op; - return matrix_op<op>(op(m1.ref(),m2.ref())); - } - - template < - typename M1, - typename M2 - > - const matrix_op<op_conv_same<M1,M2,true> > xcorr_same ( - const matrix_exp<M1>& m1, - const matrix_exp<M2>& m2 - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true)); - - typedef op_conv_same<M1,M2,true> op; - return matrix_op<op>(op(m1.ref(),m2.ref())); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2, bool flip_m2 = false> - struct op_conv_valid - { - op_conv_valid( const M1& m1_, const M2& m2_) : - m1(m1_),m2(m2_), - nr_(m1.nr()-m2.nr()+1), - nc_(m1.nc()-m2.nc()+1) - { - if (nr_ < 0 || nc_ <= 0 || m1.size() == 0 || m2.size() == 0) - nr_ = 0; - if (nc_ < 0 || nr_ <= 0 || m1.size() == 0 || m2.size() == 0) - nc_ = 0; - } - - const M1& m1; - const M2& m2; - long nr_; - long nc_; - - const static long cost = (M1::cost+M2::cost)*10; - const static long NR = (M1::NR*M2::NR==0) ? (0) : (M1::NR-M2::NR+1); - const static long NC = (M1::NC*M2::NC==0) ? (0) : (M1::NC-M2::NC+1); - typedef typename M1::type type; - typedef type const_ret_type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - - const_ret_type apply (long r, long c) const - { - r += m2.nr()-1; - c += m2.nc()-1; - - type temp = 0; - - const long min_rr = std::max<long>(r-m2.nr()+1, 0); - const long max_rr = std::min<long>(m1.nr()-1, r); - - const long min_cc = std::max<long>(c-m2.nc()+1, 0); - const long max_cc = std::min<long>(m1.nc()-1, c); - - for (long rr = min_rr; rr <= max_rr; ++rr) - { - for (long cc = min_cc; cc <= max_cc; ++cc) - { - if (flip_m2) - temp += m1(rr,cc)*dlib::impl::conj(m2(m2.nr()-r+rr-1, m2.nc()-c+cc-1)); - else - temp += m1(rr,cc)*m2(r-rr,c-cc); - } - } - - return temp; - } - - long nr () const { return nr_; } - long nc () const { return nc_; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m1.aliases(item) || m2.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m1.aliases(item) || m2.aliases(item); } - - }; - - template < - typename M1, - typename M2 - > - const matrix_op<op_conv_valid<M1,M2> > conv_valid ( - const matrix_exp<M1>& m1, - const matrix_exp<M2>& m2 - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true)); - - typedef op_conv_valid<M1,M2> op; - return matrix_op<op>(op(m1.ref(),m2.ref())); - } - - template < - typename M1, - typename M2 - > - const matrix_op<op_conv_valid<M1,M2,true> > xcorr_valid ( - const matrix_exp<M1>& m1, - const matrix_exp<M2>& m2 - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true)); - - typedef op_conv_valid<M1,M2,true> op; - return matrix_op<op>(op(m1.ref(),m2.ref())); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_CONV_Hh_ - diff --git a/ml/dlib/dlib/matrix/matrix_conv_abstract.h b/ml/dlib/dlib/matrix/matrix_conv_abstract.h deleted file mode 100644 index b342f2668..000000000 --- a/ml/dlib/dlib/matrix/matrix_conv_abstract.h +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (C) 2011 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_MATRIx_CONV_ABSTRACT_Hh_ -#ifdef DLIB_MATRIx_CONV_ABSTRACT_Hh_ - -#include "matrix_abstract.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp conv ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - requires - - m1 and m2 both contain elements of the same type - ensures - - returns a matrix R such that: - - R is the convolution of m1 with m2. In particular, this function is - equivalent to performing the following in matlab: R = conv2(m1,m2). - - R::type == the same type that was in m1 and m2. - - R.nr() == m1.nr()+m2.nr()-1 - - R.nc() == m1.nc()+m2.nc()-1 - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp xcorr ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - requires - - m1 and m2 both contain elements of the same type - ensures - - returns a matrix R such that: - - R is the cross-correlation of m1 with m2. In particular, this - function returns conv(m1,flip(m2)) if the matrices contain real - elements and conv(m1,flip(conj(m2))) if they are complex. - - R::type == the same type that was in m1 and m2. - - R.nr() == m1.nr()+m2.nr()-1 - - R.nc() == m1.nc()+m2.nc()-1 - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp xcorr_fft ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - requires - - m1 and m2 both contain elements of the same type - - m1 and m2 contain real or complex values and must be double, float, or long - double valued. (e.g. not integers) - ensures - - This function is identical to xcorr() except that it uses a fast Fourier - transform to do the convolution and is therefore much faster when both m1 and - m2 are large. - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp conv_same ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - requires - - m1 and m2 both contain elements of the same type - ensures - - returns a matrix R such that: - - R is the convolution of m1 with m2. In particular, this function is - equivalent to performing the following in matlab: R = conv2(m1,m2,'same'). - In particular, this means the result will have the same dimensions as m1 and will - contain the central part of the full convolution. Therefore, conv_same(m1,m2) is - equivalent to subm(conv(m1,m2), m2.nr()/2, m2.nc()/2, m1.nr(), m1.nc()). - - R::type == the same type that was in m1 and m2. - - R.nr() == m1.nr() - - R.nc() == m1.nc() - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp xcorr_same ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - requires - - m1 and m2 both contain elements of the same type - ensures - - returns a matrix R such that: - - R is the cross-correlation of m1 with m2. In particular, this - function returns conv_same(m1,flip(m2)) if the matrices contain real - elements and conv_same(m1,flip(conj(m2))) if they are complex. - - R::type == the same type that was in m1 and m2. - - R.nr() == m1.nr() - - R.nc() == m1.nc() - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp conv_valid ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - requires - - m1 and m2 both contain elements of the same type - ensures - - returns a matrix R such that: - - R is the convolution of m1 with m2. In particular, this function is - equivalent to performing the following in matlab: R = conv2(m1,m2,'valid'). - In particular, this means only elements of the convolution which don't require - zero padding are included in the result. - - R::type == the same type that was in m1 and m2. - - if (m1 has larger dimensions than m2) then - - R.nr() == m1.nr()-m2.nr()+1 - - R.nc() == m1.nc()-m2.nc()+1 - - else - - R.nr() == 0 - - R.nc() == 0 - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp xcorr_valid ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - requires - - m1 and m2 both contain elements of the same type - ensures - - returns a matrix R such that: - - R is the cross-correlation of m1 with m2. In particular, this - function returns conv_valid(m1,flip(m2)) if the matrices contain real - elements and conv_valid(m1,flip(conj(m2))) if they are complex. - - R::type == the same type that was in m1 and m2. - - if (m1 has larger dimensions than m2) then - - R.nr() == m1.nr()-m2.nr()+1 - - R.nc() == m1.nc()-m2.nc()+1 - - else - - R.nr() == 0 - - R.nc() == 0 - !*/ - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_CONV_ABSTRACT_Hh_ - - diff --git a/ml/dlib/dlib/matrix/matrix_data_layout.h b/ml/dlib/dlib/matrix/matrix_data_layout.h deleted file mode 100644 index 22891c228..000000000 --- a/ml/dlib/dlib/matrix/matrix_data_layout.h +++ /dev/null @@ -1,1271 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_DATA_LAYOUT_ -#define DLIB_MATRIx_DATA_LAYOUT_ - -#include "../algs.h" -#include "matrix_fwd.h" -#include "matrix_data_layout_abstract.h" -#ifdef MATLAB_MEX_FILE -#include <mex.h> -#endif - -// GCC 4.8 gives false alarms about some matrix operations going out of bounds. Disable -// these false warnings. -#if defined(__GNUC__) && ((__GNUC__ >= 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4)) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warray-bounds" -#endif - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - /*! - A matrix layout object is any object that contains a templated class called "layout" - with an interface identical to one below: - (Note that all the template arguments are just the template arguments from the dlib::matrix - object and the member functions are defined identically to the ones with the same - signatures inside the matrix object.) - - struct matrix_layout - { - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager - > - class layout - { - public: - - T& operator() ( - long r, - long c - ); - - const T& operator() ( - long r, - long c - ); - - T& operator() ( - long i - ); - - const T& operator() ( - long i - ) const; - - void swap( - layout& item - ); - - long nr ( - ) const; - - long nc ( - ) const; - - void set_size ( - long nr_, - long nc_ - ); - }; - }; - !*/ - -// ---------------------------------------------------------------------------------------- - - struct row_major_layout - { - // if a matrix is bigger than this many bytes then don't put it on the stack - const static size_t max_stack_based_size = 256; - - // this is a hack to avoid a compile time error in visual studio 8. I would just - // use sizeof(T) and be done with it but that won't compile. The idea here - // is to avoid using the stack allocation of the layout object if it - // is going to contain another matrix and also avoid asking for the sizeof() - // the contained matrix. - template <typename T> - struct get_sizeof_helper - { - const static std::size_t val = sizeof(T); - }; - - template <typename T, long NR, long NC, typename mm, typename l> - struct get_sizeof_helper<matrix<T,NR,NC,mm,l> > - { - const static std::size_t val = 1000000; - }; - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager, - int val = static_switch < - // when the sizes are all non zero and small - (num_rows*num_cols*get_sizeof_helper<T>::val <= max_stack_based_size) && (num_rows != 0 && num_cols != 0), - // when the sizes are all non zero and big - (num_rows*num_cols*get_sizeof_helper<T>::val > max_stack_based_size) && (num_rows != 0 && num_cols != 0), - num_rows == 0 && num_cols != 0, - num_rows != 0 && num_cols == 0, - num_rows == 0 && num_cols == 0 - >::value - > - class layout ; - /*! - WHAT THIS OBJECT REPRESENTS - This object represents the actual allocation of space for a matrix. - Small matrices allocate all their data on the stack and bigger ones - use a memory_manager to get their memory. - !*/ - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager - > - class layout<T,num_rows,num_cols,mem_manager,1> : noncopyable // when the sizes are all non zero and small - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout() {} - - T& operator() ( - long r, - long c - ) { return *(data+r*num_cols + c); } - - const T& operator() ( - long r, - long c - ) const { return *(data+r*num_cols + c); } - - T& operator() ( - long i - ) { return data[i]; } - - const T& operator() ( - long i - ) const { return data[i]; } - - void swap( - layout& item - ) - { - for (long r = 0; r < num_rows; ++r) - { - for (long c = 0; c < num_cols; ++c) - { - exchange((*this)(r,c),item(r,c)); - } - } - } - - long nr ( - ) const { return num_rows; } - - long nc ( - ) const { return num_cols; } - - void set_size ( - long , - long - ) - { - } - -#ifdef MATLAB_MEX_FILE - void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } - mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } - void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); } - bool _private_is_owned_by_matlab() const { return false; } -#endif - - private: - T data[num_rows*num_cols]; - }; - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager - > - class layout<T,num_rows,num_cols,mem_manager,2> : noncopyable // when the sizes are all non zero and big - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout ( - ) { data = pool.allocate_array(num_rows*num_cols); } - - ~layout () - { pool.deallocate_array(data); } - - T& operator() ( - long r, - long c - ) { return data[r*num_cols + c]; } - - const T& operator() ( - long r, - long c - ) const { return data[r*num_cols + c]; } - - T& operator() ( - long i - ) { return data[i]; } - - const T& operator() ( - long i - ) const { return data[i]; } - - void swap( - layout& item - ) - { - std::swap(item.data,data); - pool.swap(item.pool); - } - - long nr ( - ) const { return num_rows; } - - long nc ( - ) const { return num_cols; } - - void set_size ( - long , - long - ) - { - } - -#ifdef MATLAB_MEX_FILE - void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } - mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } - void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); } - bool _private_is_owned_by_matlab() const { return false; } -#endif - - private: - - T* data; - typename mem_manager::template rebind<T>::other pool; - }; - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager - > - class layout<T,num_rows,num_cols,mem_manager,3> : noncopyable // when num_rows == 0 && num_cols != 0, - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout ( - ):data(0), nr_(0) { } - - ~layout () - { - if (data) - pool.deallocate_array(data); - } - - T& operator() ( - long r, - long c - ) { return data[r*num_cols + c]; } - - const T& operator() ( - long r, - long c - ) const { return data[r*num_cols + c]; } - - T& operator() ( - long i - ) { return data[i]; } - - const T& operator() ( - long i - ) const { return data[i]; } - - void swap( - layout& item - ) - { - std::swap(item.data,data); - std::swap(item.nr_,nr_); - pool.swap(item.pool); - } - - long nr ( - ) const { return nr_; } - - long nc ( - ) const { return num_cols; } - - void set_size ( - long nr, - long nc - ) - { - if (data) - { - pool.deallocate_array(data); - } - data = pool.allocate_array(nr*nc); - nr_ = nr; - } - -#ifdef MATLAB_MEX_FILE - void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } - mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } - void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); } - bool _private_is_owned_by_matlab() const { return false; } -#endif - - private: - - T* data; - long nr_; - typename mem_manager::template rebind<T>::other pool; - }; - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager - > - class layout<T,num_rows,num_cols,mem_manager,4> : noncopyable // when num_rows != 0 && num_cols == 0 - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout ( - ):data(0), nc_(0) { } - - ~layout () - { - if (data) - { - pool.deallocate_array(data); - } - } - - T& operator() ( - long r, - long c - ) { return data[r*nc_ + c]; } - - const T& operator() ( - long r, - long c - ) const { return data[r*nc_ + c]; } - - T& operator() ( - long i - ) { return data[i]; } - - const T& operator() ( - long i - ) const { return data[i]; } - - void swap( - layout& item - ) - { - std::swap(item.data,data); - std::swap(item.nc_,nc_); - pool.swap(item.pool); - } - - long nr ( - ) const { return num_rows; } - - long nc ( - ) const { return nc_; } - - void set_size ( - long nr, - long nc - ) - { - if (data) - { - pool.deallocate_array(data); - } - data = pool.allocate_array(nr*nc); - nc_ = nc; - } - -#ifdef MATLAB_MEX_FILE - void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } - mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } - void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); } - bool _private_is_owned_by_matlab() const { return false; } -#endif - - private: - - T* data; - long nc_; - typename mem_manager::template rebind<T>::other pool; - }; - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager - > - class layout<T,num_rows,num_cols,mem_manager,5> : noncopyable // when num_rows == 0 && num_cols == 0 - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout ( - ):data(0), nr_(0), nc_(0) { } - - ~layout () - { - if (data) - { - pool.deallocate_array(data); - } - } - - T& operator() ( - long r, - long c - ) { return data[r*nc_ + c]; } - - const T& operator() ( - long r, - long c - ) const { return data[r*nc_ + c]; } - - T& operator() ( - long i - ) { return data[i]; } - - const T& operator() ( - long i - ) const { return data[i]; } - - void swap( - layout& item - ) - { - std::swap(item.data,data); - std::swap(item.nc_,nc_); - std::swap(item.nr_,nr_); - pool.swap(item.pool); - } - - long nr ( - ) const { return nr_; } - - long nc ( - ) const { return nc_; } - - void set_size ( - long nr, - long nc - ) - { - if (data) - { - pool.deallocate_array(data); - } - data = pool.allocate_array(nr*nc); - nr_ = nr; - nc_ = nc; - } - -#ifdef MATLAB_MEX_FILE - void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } - mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } - void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); } - bool _private_is_owned_by_matlab() const { return false; } -#endif - private: - T* data; - long nr_; - long nc_; - typename mem_manager::template rebind<T>::other pool; - }; - - }; - -// ---------------------------------------------------------------------------------------- - - struct column_major_layout - { - // if a matrix is bigger than this many bytes then don't put it on the stack - const static size_t max_stack_based_size = 256; - - - // this is a hack to avoid a compile time error in visual studio 8. I would just - // use sizeof(T) and be done with it but that won't compile. The idea here - // is to avoid using the stack allocation of the layout object if it - // is going to contain another matrix and also avoid asking for the sizeof() - // the contained matrix. - template <typename T> - struct get_sizeof_helper - { - const static std::size_t val = sizeof(T); - }; - - template <typename T, long NR, long NC, typename mm, typename l> - struct get_sizeof_helper<matrix<T,NR,NC,mm,l> > - { - const static std::size_t val = 1000000; - }; - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager, - int val = static_switch < - // when the sizes are all non zero and small - (num_rows*num_cols*get_sizeof_helper<T>::val <= max_stack_based_size) && (num_rows != 0 && num_cols != 0), - // when the sizes are all non zero and big - (num_rows*num_cols*get_sizeof_helper<T>::val > max_stack_based_size) && (num_rows != 0 && num_cols != 0), - num_rows == 0 && num_cols != 0, - num_rows != 0 && num_cols == 0, - num_rows == 0 && num_cols == 0 - >::value - > - class layout ; - /*! - WHAT THIS OBJECT REPRESENTS - This object represents the actual allocation of space for a matrix. - Small matrices allocate all their data on the stack and bigger ones - use a memory_manager to get their memory. - !*/ - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager - > - class layout<T,num_rows,num_cols,mem_manager,1> : noncopyable // when the sizes are all non zero and small - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout() {} - - T& operator() ( - long r, - long c - ) { return *(data+c*num_rows + r); } - - const T& operator() ( - long r, - long c - ) const { return *(data+c*num_rows + r); } - - T& operator() ( - long i - ) { return data[i]; } - - const T& operator() ( - long i - ) const { return data[i]; } - - void swap( - layout& item - ) - { - for (long r = 0; r < num_rows; ++r) - { - for (long c = 0; c < num_cols; ++c) - { - exchange((*this)(r,c),item(r,c)); - } - } - } - - long nr ( - ) const { return num_rows; } - - long nc ( - ) const { return num_cols; } - - void set_size ( - long, - long - ) - { - } - -#ifdef MATLAB_MEX_FILE - void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } - mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } - void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); } - bool _private_is_owned_by_matlab() const { return false; } -#endif - - private: - T data[num_cols*num_rows]; - }; - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager - > - class layout<T,num_rows,num_cols,mem_manager,2> : noncopyable // when the sizes are all non zero and big - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout ( - ) { data = pool.allocate_array(num_rows*num_cols); } - - ~layout () - { pool.deallocate_array(data); } - - T& operator() ( - long r, - long c - ) { return data[c*num_rows + r]; } - - const T& operator() ( - long r, - long c - ) const { return data[c*num_rows + r]; } - - T& operator() ( - long i - ) { return data[i]; } - - const T& operator() ( - long i - ) const { return data[i]; } - - void swap( - layout& item - ) - { - std::swap(item.data,data); - pool.swap(item.pool); - } - - long nr ( - ) const { return num_rows; } - - long nc ( - ) const { return num_cols; } - - void set_size ( - long , - long - ) - { - } - -#ifdef MATLAB_MEX_FILE - void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } - mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } - void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); } - bool _private_is_owned_by_matlab() const { return false; } -#endif - - private: - - T* data; - typename mem_manager::template rebind<T>::other pool; - }; - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager - > - class layout<T,num_rows,num_cols,mem_manager,3> : noncopyable // when num_rows == 0 && num_cols != 0, - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout ( - ):data(0), nr_(0) { } - - ~layout () - { - if (data) - pool.deallocate_array(data); - } - - T& operator() ( - long r, - long c - ) { return data[c*nr_ + r]; } - - const T& operator() ( - long r, - long c - ) const { return data[c*nr_ + r]; } - - T& operator() ( - long i - ) { return data[i]; } - - const T& operator() ( - long i - ) const { return data[i]; } - - void swap( - layout& item - ) - { - std::swap(item.data,data); - std::swap(item.nr_,nr_); - pool.swap(item.pool); - } - - long nr ( - ) const { return nr_; } - - long nc ( - ) const { return num_cols; } - - void set_size ( - long nr, - long nc - ) - { - if (data) - { - pool.deallocate_array(data); - } - data = pool.allocate_array(nr*nc); - nr_ = nr; - } - -#ifdef MATLAB_MEX_FILE - void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } - mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } - void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); } - bool _private_is_owned_by_matlab() const { return false; } -#endif - - private: - - T* data; - long nr_; - typename mem_manager::template rebind<T>::other pool; - }; - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager - > - class layout<T,num_rows,num_cols,mem_manager,4> : noncopyable // when num_rows != 0 && num_cols == 0 - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout ( - ):data(0), nc_(0) { } - - ~layout () - { - if (data) - { - pool.deallocate_array(data); - } - } - - T& operator() ( - long r, - long c - ) { return data[c*num_rows + r]; } - - const T& operator() ( - long r, - long c - ) const { return data[c*num_rows + r]; } - - T& operator() ( - long i - ) { return data[i]; } - - const T& operator() ( - long i - ) const { return data[i]; } - - void swap( - layout& item - ) - { - std::swap(item.data,data); - std::swap(item.nc_,nc_); - pool.swap(item.pool); - } - - long nr ( - ) const { return num_rows; } - - long nc ( - ) const { return nc_; } - - void set_size ( - long nr, - long nc - ) - { - if (data) - { - pool.deallocate_array(data); - } - data = pool.allocate_array(nr*nc); - nc_ = nc; - } - -#ifdef MATLAB_MEX_FILE - void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } - mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } - void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); } - bool _private_is_owned_by_matlab() const { return false; } -#endif - - private: - - T* data; - long nc_; - typename mem_manager::template rebind<T>::other pool; - }; - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long num_rows, - long num_cols, - typename mem_manager - > - class layout<T,num_rows,num_cols,mem_manager,5> : noncopyable // when num_rows == 0 && num_cols == 0 - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout ( - ):data(0), nr_(0), nc_(0) { } - - ~layout () - { - if (data) - { - pool.deallocate_array(data); - } - } - - T& operator() ( - long r, - long c - ) { return data[c*nr_ + r]; } - - const T& operator() ( - long r, - long c - ) const { return data[c*nr_ + r]; } - - T& operator() ( - long i - ) { return data[i]; } - - const T& operator() ( - long i - ) const { return data[i]; } - - void swap( - layout& item - ) - { - std::swap(item.data,data); - std::swap(item.nc_,nc_); - std::swap(item.nr_,nr_); - pool.swap(item.pool); - } - -#ifdef MATLAB_MEX_FILE - void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } - mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } - void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); } - bool _private_is_owned_by_matlab() const { return false; } -#endif - - long nr ( - ) const { return nr_; } - - long nc ( - ) const { return nc_; } - - void set_size ( - long nr, - long nc - ) - { - if (data) - { - pool.deallocate_array(data); - } - data = pool.allocate_array(nr*nc); - nr_ = nr; - nc_ = nc; - } - - private: - T* data; - long nr_; - long nc_; - typename mem_manager::template rebind<T>::other pool; - }; - -#ifdef MATLAB_MEX_FILE - template < - long num_rows, - long num_cols - > - class layout<double,num_rows,num_cols,default_memory_manager,5> : noncopyable // when num_rows == 0 && num_cols == 0 - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout ( - ): data(0), nr_(0), nc_(0), owned_by_matlab(false),set_by_private_set_mxArray(false),mem(0) { } - - ~layout () - { - if (owned_by_matlab) - { - if (!set_by_private_set_mxArray && mem) - { - mxDestroyArray(mem); - mem = 0; - data = 0; - } - } - else if (data) - { - delete [] data; - data = 0; - } - } - - double& operator() ( - long r, - long c - ) { return data[c*nr_ + r]; } - - const double& operator() ( - long r, - long c - ) const { return data[c*nr_ + r]; } - - double& operator() ( - long i - ) { return data[i]; } - - const double& operator() ( - long i - ) const { return data[i]; } - - void _private_set_mxArray ( - mxArray* mem_ - ) - { - DLIB_CASSERT(mem == 0 && data == 0,"You can't call this function on an already allocated matrix."); - // We don't own the pointer, so make note of that so we won't try to free - // it. - set_by_private_set_mxArray = true; - owned_by_matlab = true; - mem = mem_; - data = mxGetPr(mem); - nr_ = mxGetM(mem); - nc_ = mxGetN(mem); - } - - mxArray* _private_release_mxArray() - { - DLIB_CASSERT(owned_by_matlab,""); - mxArray* temp = mem; - mem = 0; - set_by_private_set_mxArray = false; - data = 0; - nr_ = 0; - nc_ = 0; - return temp; - } - - void _private_mark_owned_by_matlab() - { - DLIB_CASSERT(mem == 0 && data == 0,"You can't say a matrix should be owned by matlab after it's been allocated."); - owned_by_matlab = true; - } - bool _private_is_owned_by_matlab() const - { - return owned_by_matlab; - } - - void swap( - layout& item - ) - { - std::swap(item.owned_by_matlab,owned_by_matlab); - std::swap(item.set_by_private_set_mxArray,set_by_private_set_mxArray); - std::swap(item.mem,mem); - std::swap(item.data,data); - std::swap(item.nc_,nc_); - std::swap(item.nr_,nr_); - } - - long nr ( - ) const { return nr_; } - - long nc ( - ) const { return nc_; } - - void set_size ( - long nr, - long nc - ) - { - if (owned_by_matlab) - { - if (!set_by_private_set_mxArray && mem) - { - mxDestroyArray(mem); - mem = 0; - data = 0; - } - set_by_private_set_mxArray = false; - - mem = mxCreateDoubleMatrix(nr, nc, mxREAL); - if (mem == 0) - throw std::bad_alloc(); - data = mxGetPr(mem); - } - else - { - if (data) - delete [] data; - data = new double[nr*nc]; - } - nr_ = nr; - nc_ = nc; - } - - private: - double* data; - long nr_; - long nc_; - bool owned_by_matlab; - bool set_by_private_set_mxArray; - mxArray* mem; - }; - - template < - long num_rows, - long num_cols - > - class layout<float,num_rows,num_cols,default_memory_manager,5> : noncopyable // when num_rows == 0 && num_cols == 0 - { - public: - const static long NR = num_rows; - const static long NC = num_cols; - - layout ( - ): data(0), nr_(0), nc_(0), owned_by_matlab(false),set_by_private_set_mxArray(false),mem(0) { } - - ~layout () - { - if (owned_by_matlab) - { - if (!set_by_private_set_mxArray && mem) - { - mxDestroyArray(mem); - mem = 0; - data = 0; - } - } - else if (data) - { - delete [] data; - data = 0; - } - } - - float& operator() ( - long r, - long c - ) { return data[c*nr_ + r]; } - - const float& operator() ( - long r, - long c - ) const { return data[c*nr_ + r]; } - - float& operator() ( - long i - ) { return data[i]; } - - const float& operator() ( - long i - ) const { return data[i]; } - - void _private_set_mxArray ( - mxArray* mem_ - ) - { - DLIB_CASSERT(mem == 0 && data == 0,"You can't call this function on an already allocated matrix."); - // We don't own the pointer, so make note of that so we won't try to free - // it. - set_by_private_set_mxArray = true; - owned_by_matlab = true; - mem = mem_; - data = (float*)mxGetData(mem); - nr_ = mxGetM(mem); - nc_ = mxGetN(mem); - } - - mxArray* _private_release_mxArray() - { - DLIB_CASSERT(owned_by_matlab,""); - mxArray* temp = mem; - mem = 0; - set_by_private_set_mxArray = false; - data = 0; - nr_ = 0; - nc_ = 0; - return temp; - } - - void _private_mark_owned_by_matlab() - { - DLIB_CASSERT(mem == 0 && data == 0,"You can't say a matrix should be owned by matlab after it's been allocated."); - owned_by_matlab = true; - } - bool _private_is_owned_by_matlab() const - { - return owned_by_matlab; - } - - void swap( - layout& item - ) - { - std::swap(item.owned_by_matlab,owned_by_matlab); - std::swap(item.set_by_private_set_mxArray,set_by_private_set_mxArray); - std::swap(item.mem,mem); - std::swap(item.data,data); - std::swap(item.nc_,nc_); - std::swap(item.nr_,nr_); - } - - long nr ( - ) const { return nr_; } - - long nc ( - ) const { return nc_; } - - void set_size ( - long nr, - long nc - ) - { - if (owned_by_matlab) - { - if (!set_by_private_set_mxArray && mem) - { - mxDestroyArray(mem); - mem = 0; - data = 0; - } - set_by_private_set_mxArray = false; - - mem = mxCreateNumericMatrix(nr, nc, mxSINGLE_CLASS, mxREAL); - if (mem == 0) - throw std::bad_alloc(); - data = (float*)mxGetData(mem); - } - else - { - if (data) - delete [] data; - data = new float[nr*nc]; - } - nr_ = nr; - nc_ = nc; - } - - private: - float* data; - long nr_; - long nc_; - bool owned_by_matlab; - bool set_by_private_set_mxArray; - mxArray* mem; - }; -#endif - - }; - -// ---------------------------------------------------------------------------------------- - -} - -#if defined(__GNUC__) && ((__GNUC__ >= 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4)) -#pragma GCC diagnostic pop -#endif - -#endif // DLIB_MATRIx_DATA_LAYOUT_ - diff --git a/ml/dlib/dlib/matrix/matrix_data_layout_abstract.h b/ml/dlib/dlib/matrix/matrix_data_layout_abstract.h deleted file mode 100644 index c3fa02be2..000000000 --- a/ml/dlib/dlib/matrix/matrix_data_layout_abstract.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (C) 2008 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_MATRIx_DATA_LAYOUT_ABSTRACT_ -#ifdef DLIB_MATRIx_DATA_LAYOUT_ABSTRACT_ - -#include "../algs.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - struct row_major_layout - { - /*! - This is the default matrix layout. Any matrix object that uses this - layout will be laid out in memory in row major order. Additionally, - all elements are contiguous (e.g. there isn't any padding at the ends of - rows or anything like that) - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - struct column_major_layout - { - /*! - Any matrix object that uses this layout will be laid out in memory in - column major order. Additionally, all elements are contiguous (e.g. - there isn't any padding at the ends of rows or anything like that) - !*/ - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_DATA_LAYOUT_ABSTRACT_ - - diff --git a/ml/dlib/dlib/matrix/matrix_default_mul.h b/ml/dlib/dlib/matrix/matrix_default_mul.h deleted file mode 100644 index 493c641a8..000000000 --- a/ml/dlib/dlib/matrix/matrix_default_mul.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (C) 2008 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_DEFAULT_MULTIPLY_ -#define DLIB_MATRIx_DEFAULT_MULTIPLY_ - -#include "../geometry/rectangle.h" -#include "matrix.h" -#include "matrix_utilities.h" -#include "../enable_if.h" - -namespace dlib -{ - -// ------------------------------------------------------------------------------------ - - namespace ma - { - template < typename EXP, typename enable = void > - struct matrix_is_vector { static const bool value = false; }; - template < typename EXP > - struct matrix_is_vector<EXP, typename enable_if_c<EXP::NR==1 || EXP::NC==1>::type > { static const bool value = true; }; - } - -// ------------------------------------------------------------------------------------ - - /*! This file defines the default_matrix_multiply() function. It is a function - that conforms to the following definition: - - template < - typename matrix_dest_type, - typename EXP1, - typename EXP2 - > - void default_matrix_multiply ( - matrix_dest_type& dest, - const EXP1& lhs, - const EXP2& rhs - ); - requires - - (lhs*rhs).destructively_aliases(dest) == false - - dest.nr() == (lhs*rhs).nr() - - dest.nc() == (lhs*rhs).nc() - ensures - - #dest == dest + lhs*rhs - !*/ - -// ------------------------------------------------------------------------------------ - - template < - typename matrix_dest_type, - typename EXP1, - typename EXP2 - > - typename enable_if_c<ma::matrix_is_vector<EXP1>::value == true || ma::matrix_is_vector<EXP2>::value == true>::type - default_matrix_multiply ( - matrix_dest_type& dest, - const EXP1& lhs, - const EXP2& rhs - ) - { - matrix_assign_default(dest, lhs*rhs, 1, true); - } - -// ------------------------------------------------------------------------------------ - - template < - typename matrix_dest_type, - typename EXP1, - typename EXP2 - > - typename enable_if_c<ma::matrix_is_vector<EXP1>::value == false && ma::matrix_is_vector<EXP2>::value == false>::type - default_matrix_multiply ( - matrix_dest_type& dest, - const EXP1& lhs, - const EXP2& rhs - ) - { - const long bs = 90; - - // if the matrices are small enough then just use the simple multiply algorithm - if (lhs.nc() <= 2 || rhs.nc() <= 2 || lhs.nr() <= 2 || rhs.nr() <= 2 || (lhs.size() <= bs*10 && rhs.size() <= bs*10) ) - { - matrix_assign_default(dest, lhs*rhs, 1, true); - } - else - { - // if the lhs and rhs matrices are big enough we should use a cache friendly - // algorithm that computes the matrix multiply in blocks. - - - // Loop over all the blocks in the lhs matrix - for (long r = 0; r < lhs.nr(); r+=bs) - { - for (long c = 0; c < lhs.nc(); c+=bs) - { - // make a rect for the block from lhs - rectangle lhs_block(c, r, std::min(c+bs-1,lhs.nc()-1), std::min(r+bs-1,lhs.nr()-1)); - - // now loop over all the rhs blocks we have to multiply with the current lhs block - for (long i = 0; i < rhs.nc(); i += bs) - { - // make a rect for the block from rhs - rectangle rhs_block(i, c, std::min(i+bs-1,rhs.nc()-1), std::min(c+bs-1,rhs.nr()-1)); - - // make a target rect in res - rectangle res_block(rhs_block.left(),lhs_block.top(), rhs_block.right(), lhs_block.bottom()); - - // This loop is optimized assuming that the data is laid out in - // row major order in memory. - for (long r = lhs_block.top(); r <= lhs_block.bottom(); ++r) - { - for (long c = lhs_block.left(); c<= lhs_block.right(); ++c) - { - const typename EXP2::type temp = lhs(r,c); - for (long i = rhs_block.left(); i <= rhs_block.right(); ++i) - { - dest(r,i) += rhs(c,i)*temp; - } - } - } - } - } - } - } - - - } - -// ------------------------------------------------------------------------------------ - -} - -#endif // DLIB_MATRIx_DEFAULT_MULTIPLY_ - diff --git a/ml/dlib/dlib/matrix/matrix_eigenvalue.h b/ml/dlib/dlib/matrix/matrix_eigenvalue.h deleted file mode 100644 index 3dc47e105..000000000 --- a/ml/dlib/dlib/matrix/matrix_eigenvalue.h +++ /dev/null @@ -1,1379 +0,0 @@ -// Copyright (C) 2009 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -// This code was adapted from code from the JAMA part of NIST's TNT library. -// See: http://math.nist.gov/tnt/ -#ifndef DLIB_MATRIX_EIGENVALUE_DECOMPOSITION_H -#define DLIB_MATRIX_EIGENVALUE_DECOMPOSITION_H - -#include "matrix.h" -#include "matrix_utilities.h" -#include "matrix_subexp.h" -#include <algorithm> -#include <complex> -#include <cmath> - -#ifdef DLIB_USE_LAPACK -#include "lapack/geev.h" -#include "lapack/syev.h" -#include "lapack/syevr.h" -#endif - -#define DLIB_LAPACK_EIGENVALUE_DECOMP_SIZE_THRESH 4 - -namespace dlib -{ - - template < - typename matrix_exp_type - > - class eigenvalue_decomposition - { - - public: - - const static long NR = matrix_exp_type::NR; - const static long NC = matrix_exp_type::NC; - typedef typename matrix_exp_type::type type; - typedef typename matrix_exp_type::mem_manager_type mem_manager_type; - typedef typename matrix_exp_type::layout_type layout_type; - - typedef typename matrix_exp_type::matrix_type matrix_type; - typedef matrix<type,NR,1,mem_manager_type,layout_type> column_vector_type; - - typedef matrix<std::complex<type>,0,0,mem_manager_type,layout_type> complex_matrix_type; - typedef matrix<std::complex<type>,NR,1,mem_manager_type,layout_type> complex_column_vector_type; - - - // You have supplied an invalid type of matrix_exp_type. You have - // to use this object with matrices that contain float or double type data. - COMPILE_TIME_ASSERT((is_same_type<float, type>::value || - is_same_type<double, type>::value )); - - - template <typename EXP> - eigenvalue_decomposition( - const matrix_exp<EXP>& A - ); - - template <typename EXP> - eigenvalue_decomposition( - const matrix_op<op_make_symmetric<EXP> >& A - ); - - long dim ( - ) const; - - const complex_column_vector_type get_eigenvalues ( - ) const; - - const column_vector_type& get_real_eigenvalues ( - ) const; - - const column_vector_type& get_imag_eigenvalues ( - ) const; - - const complex_matrix_type get_v ( - ) const; - - const complex_matrix_type get_d ( - ) const; - - const matrix_type& get_pseudo_v ( - ) const; - - const matrix_type get_pseudo_d ( - ) const; - - private: - - /** Row and column dimension (square matrix). */ - long n; - - bool issymmetric; - - /** Arrays for internal storage of eigenvalues. */ - - column_vector_type d; /* real part */ - column_vector_type e; /* img part */ - - /** Array for internal storage of eigenvectors. */ - matrix_type V; - - /** Array for internal storage of nonsymmetric Hessenberg form. - @serial internal storage of nonsymmetric Hessenberg form. - */ - matrix_type H; - - - /** Working storage for nonsymmetric algorithm. - @serial working storage for nonsymmetric algorithm. - */ - column_vector_type ort; - - // Symmetric Householder reduction to tridiagonal form. - void tred2(); - - - // Symmetric tridiagonal QL algorithm. - void tql2 (); - - - // Nonsymmetric reduction to Hessenberg form. - void orthes (); - - - // Complex scalar division. - type cdivr, cdivi; - void cdiv_(type xr, type xi, type yr, type yi); - - - // Nonsymmetric reduction from Hessenberg to real Schur form. - void hqr2 (); - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Public member functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - template <typename EXP> - eigenvalue_decomposition<matrix_exp_type>:: - eigenvalue_decomposition( - const matrix_exp<EXP>& A_ - ) - { - COMPILE_TIME_ASSERT((is_same_type<type, typename EXP::type>::value)); - - - const_temp_matrix<EXP> A(A_); - - // make sure requires clause is not broken - DLIB_ASSERT(A.nr() == A.nc() && A.size() > 0, - "\teigenvalue_decomposition::eigenvalue_decomposition(A)" - << "\n\tYou can only use this on square matrices" - << "\n\tA.nr(): " << A.nr() - << "\n\tA.nc(): " << A.nc() - << "\n\tA.size(): " << A.size() - << "\n\tthis: " << this - ); - - - n = A.nc(); - V.set_size(n,n); - d.set_size(n); - e.set_size(n); - - - issymmetric = true; - for (long j = 0; (j < n) && issymmetric; j++) - { - for (long i = 0; (i < n) && issymmetric; i++) - { - issymmetric = (A(i,j) == A(j,i)); - } - } - - if (issymmetric) - { - V = A; - -#ifdef DLIB_USE_LAPACK - if (A.nr() > DLIB_LAPACK_EIGENVALUE_DECOMP_SIZE_THRESH) - { - e = 0; - - // We could compute the result using syev() - //lapack::syev('V', 'L', V, d); - - // Instead, we use syevr because its faster and maybe more stable. - matrix_type tempA(A); - matrix<lapack::integer,0,0,mem_manager_type,layout_type> isupz; - - lapack::integer temp; - lapack::syevr('V','A','L',tempA,0,0,0,0,-1,temp,d,V,isupz); - return; - } -#endif - // Tridiagonalize. - tred2(); - - // Diagonalize. - tql2(); - - } - else - { - -#ifdef DLIB_USE_LAPACK - if (A.nr() > DLIB_LAPACK_EIGENVALUE_DECOMP_SIZE_THRESH) - { - matrix<type,0,0,mem_manager_type, column_major_layout> temp, vl, vr; - temp = A; - lapack::geev('N', 'V', temp, d, e, vl, vr); - V = vr; - return; - } -#endif - H = A; - - ort.set_size(n); - - // Reduce to Hessenberg form. - orthes(); - - // Reduce Hessenberg to real Schur form. - hqr2(); - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - template <typename EXP> - eigenvalue_decomposition<matrix_exp_type>:: - eigenvalue_decomposition( - const matrix_op<op_make_symmetric<EXP> >& A - ) - { - COMPILE_TIME_ASSERT((is_same_type<type, typename EXP::type>::value)); - - - // make sure requires clause is not broken - DLIB_ASSERT(A.nr() == A.nc() && A.size() > 0, - "\teigenvalue_decomposition::eigenvalue_decomposition(A)" - << "\n\tYou can only use this on square matrices" - << "\n\tA.nr(): " << A.nr() - << "\n\tA.nc(): " << A.nc() - << "\n\tA.size(): " << A.size() - << "\n\tthis: " << this - ); - - - n = A.nc(); - V.set_size(n,n); - d.set_size(n); - e.set_size(n); - - - V = A; - -#ifdef DLIB_USE_LAPACK - if (A.nr() > DLIB_LAPACK_EIGENVALUE_DECOMP_SIZE_THRESH) - { - e = 0; - - // We could compute the result using syev() - //lapack::syev('V', 'L', V, d); - - // Instead, we use syevr because its faster and maybe more stable. - matrix_type tempA(A); - matrix<lapack::integer,0,0,mem_manager_type,layout_type> isupz; - - lapack::integer temp; - lapack::syevr('V','A','L',tempA,0,0,0,0,-1,temp,d,V,isupz); - return; - } -#endif - // Tridiagonalize. - tred2(); - - // Diagonalize. - tql2(); - - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename eigenvalue_decomposition<matrix_exp_type>::matrix_type& eigenvalue_decomposition<matrix_exp_type>:: - get_pseudo_v ( - ) const - { - return V; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - long eigenvalue_decomposition<matrix_exp_type>:: - dim ( - ) const - { - return V.nr(); - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename eigenvalue_decomposition<matrix_exp_type>::complex_column_vector_type eigenvalue_decomposition<matrix_exp_type>:: - get_eigenvalues ( - ) const - { - return complex_matrix(get_real_eigenvalues(), get_imag_eigenvalues()); - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename eigenvalue_decomposition<matrix_exp_type>::column_vector_type& eigenvalue_decomposition<matrix_exp_type>:: - get_real_eigenvalues ( - ) const - { - return d; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename eigenvalue_decomposition<matrix_exp_type>::column_vector_type& eigenvalue_decomposition<matrix_exp_type>:: - get_imag_eigenvalues ( - ) const - { - return e; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename eigenvalue_decomposition<matrix_exp_type>::complex_matrix_type eigenvalue_decomposition<matrix_exp_type>:: - get_d ( - ) const - { - return diagm(complex_matrix(get_real_eigenvalues(), get_imag_eigenvalues())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename eigenvalue_decomposition<matrix_exp_type>::complex_matrix_type eigenvalue_decomposition<matrix_exp_type>:: - get_v ( - ) const - { - complex_matrix_type CV(n,n); - - for (long i = 0; i < n; i++) - { - if (e(i) > 0) - { - set_colm(CV,i) = complex_matrix(colm(V,i), colm(V,i+1)); - } - else if (e(i) < 0) - { - set_colm(CV,i) = complex_matrix(colm(V,i), colm(V,i-1)); - } - else - { - set_colm(CV,i) = complex_matrix(colm(V,i), uniform_matrix<type>(n,1,0)); - } - } - - return CV; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename eigenvalue_decomposition<matrix_exp_type>::matrix_type eigenvalue_decomposition<matrix_exp_type>:: - get_pseudo_d ( - ) const - { - matrix_type D(n,n); - - for (long i = 0; i < n; i++) - { - for (long j = 0; j < n; j++) - { - D(i,j) = 0.0; - } - D(i,i) = d(i); - if (e(i) > 0) - { - D(i,i+1) = e(i); - } - else if (e(i) < 0) - { - D(i,i-1) = e(i); - } - } - - return D; - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Private member functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - -// Symmetric Householder reduction to tridiagonal form. - template <typename matrix_exp_type> - void eigenvalue_decomposition<matrix_exp_type>:: - tred2() - { - using std::abs; - using std::sqrt; - - // This is derived from the Algol procedures tred2 by - // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for - // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding - // Fortran subroutine in EISPACK. - - for (long j = 0; j < n; j++) - { - d(j) = V(n-1,j); - } - - // Householder reduction to tridiagonal form. - - for (long i = n-1; i > 0; i--) - { - - // Scale to avoid under/overflow. - - type scale = 0.0; - type h = 0.0; - for (long k = 0; k < i; k++) - { - scale = scale + abs(d(k)); - } - if (scale == 0.0) - { - e(i) = d(i-1); - for (long j = 0; j < i; j++) - { - d(j) = V(i-1,j); - V(i,j) = 0.0; - V(j,i) = 0.0; - } - } - else - { - - // Generate Householder vector. - - for (long k = 0; k < i; k++) - { - d(k) /= scale; - h += d(k) * d(k); - } - type f = d(i-1); - type g = sqrt(h); - if (f > 0) - { - g = -g; - } - e(i) = scale * g; - h = h - f * g; - d(i-1) = f - g; - for (long j = 0; j < i; j++) - { - e(j) = 0.0; - } - - // Apply similarity transformation to remaining columns. - - for (long j = 0; j < i; j++) - { - f = d(j); - V(j,i) = f; - g = e(j) + V(j,j) * f; - for (long k = j+1; k <= i-1; k++) - { - g += V(k,j) * d(k); - e(k) += V(k,j) * f; - } - e(j) = g; - } - f = 0.0; - for (long j = 0; j < i; j++) - { - e(j) /= h; - f += e(j) * d(j); - } - type hh = f / (h + h); - for (long j = 0; j < i; j++) - { - e(j) -= hh * d(j); - } - for (long j = 0; j < i; j++) - { - f = d(j); - g = e(j); - for (long k = j; k <= i-1; k++) - { - V(k,j) -= (f * e(k) + g * d(k)); - } - d(j) = V(i-1,j); - V(i,j) = 0.0; - } - } - d(i) = h; - } - - // Accumulate transformations. - - for (long i = 0; i < n-1; i++) - { - V(n-1,i) = V(i,i); - V(i,i) = 1.0; - type h = d(i+1); - if (h != 0.0) - { - for (long k = 0; k <= i; k++) - { - d(k) = V(k,i+1) / h; - } - for (long j = 0; j <= i; j++) - { - type g = 0.0; - for (long k = 0; k <= i; k++) - { - g += V(k,i+1) * V(k,j); - } - for (long k = 0; k <= i; k++) - { - V(k,j) -= g * d(k); - } - } - } - for (long k = 0; k <= i; k++) - { - V(k,i+1) = 0.0; - } - } - for (long j = 0; j < n; j++) - { - d(j) = V(n-1,j); - V(n-1,j) = 0.0; - } - V(n-1,n-1) = 1.0; - e(0) = 0.0; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - void eigenvalue_decomposition<matrix_exp_type>:: - tql2 () - { - using std::pow; - using std::min; - using std::max; - using std::abs; - - // This is derived from the Algol procedures tql2, by - // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for - // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding - // Fortran subroutine in EISPACK. - - for (long i = 1; i < n; i++) - { - e(i-1) = e(i); - } - e(n-1) = 0.0; - - type f = 0.0; - type tst1 = 0.0; - const type eps = std::numeric_limits<type>::epsilon(); - for (long l = 0; l < n; l++) - { - - // Find small subdiagonal element - - tst1 = max(tst1,abs(d(l)) + abs(e(l))); - long m = l; - - // Original while-loop from Java code - while (m < n) - { - if (abs(e(m)) <= eps*tst1) - { - break; - } - m++; - } - if (m == n) - --m; - - - // If m == l, d(l) is an eigenvalue, - // otherwise, iterate. - - if (m > l) - { - long iter = 0; - do - { - iter = iter + 1; // (Could check iteration count here.) - - // Compute implicit shift - - type g = d(l); - type p = (d(l+1) - g) / (2.0 * e(l)); - type r = hypot(p,(type)1.0); - if (p < 0) - { - r = -r; - } - d(l) = e(l) / (p + r); - d(l+1) = e(l) * (p + r); - type dl1 = d(l+1); - type h = g - d(l); - for (long i = l+2; i < n; i++) - { - d(i) -= h; - } - f = f + h; - - // Implicit QL transformation. - - p = d(m); - type c = 1.0; - type c2 = c; - type c3 = c; - type el1 = e(l+1); - type s = 0.0; - type s2 = 0.0; - for (long i = m-1; i >= l; i--) - { - c3 = c2; - c2 = c; - s2 = s; - g = c * e(i); - h = c * p; - r = hypot(p,e(i)); - e(i+1) = s * r; - s = e(i) / r; - c = p / r; - p = c * d(i) - s * g; - d(i+1) = h + s * (c * g + s * d(i)); - - // Accumulate transformation. - - for (long k = 0; k < n; k++) - { - h = V(k,i+1); - V(k,i+1) = s * V(k,i) + c * h; - V(k,i) = c * V(k,i) - s * h; - } - } - p = -s * s2 * c3 * el1 * e(l) / dl1; - e(l) = s * p; - d(l) = c * p; - - // Check for convergence. - - } while (abs(e(l)) > eps*tst1); - } - d(l) = d(l) + f; - e(l) = 0.0; - } - - /* - The code to sort the eigenvalues and eigenvectors - has been removed from here since, in the non-symmetric case, - we can't sort the eigenvalues in a meaningful way. If we left this - code in here then the user might supply what they thought was a symmetric - matrix but was actually slightly non-symmetric due to rounding error - and then they would end up in the non-symmetric eigenvalue solver - where the eigenvalues don't end up getting sorted. So to avoid - any possible user confusion I'm just removing this. - */ - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - void eigenvalue_decomposition<matrix_exp_type>:: - orthes () - { - using std::abs; - using std::sqrt; - - // This is derived from the Algol procedures orthes and ortran, - // by Martin and Wilkinson, Handbook for Auto. Comp., - // Vol.ii-Linear Algebra, and the corresponding - // Fortran subroutines in EISPACK. - - long low = 0; - long high = n-1; - - for (long m = low+1; m <= high-1; m++) - { - - // Scale column. - - type scale = 0.0; - for (long i = m; i <= high; i++) - { - scale = scale + abs(H(i,m-1)); - } - if (scale != 0.0) - { - - // Compute Householder transformation. - - type h = 0.0; - for (long i = high; i >= m; i--) - { - ort(i) = H(i,m-1)/scale; - h += ort(i) * ort(i); - } - type g = sqrt(h); - if (ort(m) > 0) - { - g = -g; - } - h = h - ort(m) * g; - ort(m) = ort(m) - g; - - // Apply Householder similarity transformation - // H = (I-u*u'/h)*H*(I-u*u')/h) - - for (long j = m; j < n; j++) - { - type f = 0.0; - for (long i = high; i >= m; i--) - { - f += ort(i)*H(i,j); - } - f = f/h; - for (long i = m; i <= high; i++) - { - H(i,j) -= f*ort(i); - } - } - - for (long i = 0; i <= high; i++) - { - type f = 0.0; - for (long j = high; j >= m; j--) - { - f += ort(j)*H(i,j); - } - f = f/h; - for (long j = m; j <= high; j++) - { - H(i,j) -= f*ort(j); - } - } - ort(m) = scale*ort(m); - H(m,m-1) = scale*g; - } - } - - // Accumulate transformations (Algol's ortran). - - for (long i = 0; i < n; i++) - { - for (long j = 0; j < n; j++) - { - V(i,j) = (i == j ? 1.0 : 0.0); - } - } - - for (long m = high-1; m >= low+1; m--) - { - if (H(m,m-1) != 0.0) - { - for (long i = m+1; i <= high; i++) - { - ort(i) = H(i,m-1); - } - for (long j = m; j <= high; j++) - { - type g = 0.0; - for (long i = m; i <= high; i++) - { - g += ort(i) * V(i,j); - } - // Double division avoids possible underflow - g = (g / ort(m)) / H(m,m-1); - for (long i = m; i <= high; i++) - { - V(i,j) += g * ort(i); - } - } - } - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - void eigenvalue_decomposition<matrix_exp_type>:: - cdiv_(type xr, type xi, type yr, type yi) - { - using std::abs; - type r,d; - if (abs(yr) > abs(yi)) - { - r = yi/yr; - d = yr + r*yi; - cdivr = (xr + r*xi)/d; - cdivi = (xi - r*xr)/d; - } - else - { - r = yr/yi; - d = yi + r*yr; - cdivr = (r*xr + xi)/d; - cdivi = (r*xi - xr)/d; - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - void eigenvalue_decomposition<matrix_exp_type>:: - hqr2 () - { - using std::pow; - using std::min; - using std::max; - using std::abs; - using std::sqrt; - - // This is derived from the Algol procedure hqr2, - // by Martin and Wilkinson, Handbook for Auto. Comp., - // Vol.ii-Linear Algebra, and the corresponding - // Fortran subroutine in EISPACK. - - // Initialize - - long nn = this->n; - long n = nn-1; - long low = 0; - long high = nn-1; - const type eps = std::numeric_limits<type>::epsilon(); - type exshift = 0.0; - type p=0,q=0,r=0,s=0,z=0,t,w,x,y; - - // Store roots isolated by balanc and compute matrix norm - - type norm = 0.0; - for (long i = 0; i < nn; i++) - { - if ((i < low) || (i > high)) - { - d(i) = H(i,i); - e(i) = 0.0; - } - for (long j = max(i-1,0L); j < nn; j++) - { - norm = norm + abs(H(i,j)); - } - } - - // Outer loop over eigenvalue index - - long iter = 0; - while (n >= low) - { - - // Look for single small sub-diagonal element - - long l = n; - while (l > low) - { - s = abs(H(l-1,l-1)) + abs(H(l,l)); - if (s == 0.0) - { - s = norm; - } - if (abs(H(l,l-1)) < eps * s) - { - break; - } - l--; - } - - // Check for convergence - // One root found - - if (l == n) - { - H(n,n) = H(n,n) + exshift; - d(n) = H(n,n); - e(n) = 0.0; - n--; - iter = 0; - - // Two roots found - - } - else if (l == n-1) - { - w = H(n,n-1) * H(n-1,n); - p = (H(n-1,n-1) - H(n,n)) / 2.0; - q = p * p + w; - z = sqrt(abs(q)); - H(n,n) = H(n,n) + exshift; - H(n-1,n-1) = H(n-1,n-1) + exshift; - x = H(n,n); - - // type pair - - if (q >= 0) - { - if (p >= 0) - { - z = p + z; - } - else - { - z = p - z; - } - d(n-1) = x + z; - d(n) = d(n-1); - if (z != 0.0) - { - d(n) = x - w / z; - } - e(n-1) = 0.0; - e(n) = 0.0; - x = H(n,n-1); - s = abs(x) + abs(z); - p = x / s; - q = z / s; - r = sqrt(p * p+q * q); - p = p / r; - q = q / r; - - // Row modification - - for (long j = n-1; j < nn; j++) - { - z = H(n-1,j); - H(n-1,j) = q * z + p * H(n,j); - H(n,j) = q * H(n,j) - p * z; - } - - // Column modification - - for (long i = 0; i <= n; i++) - { - z = H(i,n-1); - H(i,n-1) = q * z + p * H(i,n); - H(i,n) = q * H(i,n) - p * z; - } - - // Accumulate transformations - - for (long i = low; i <= high; i++) - { - z = V(i,n-1); - V(i,n-1) = q * z + p * V(i,n); - V(i,n) = q * V(i,n) - p * z; - } - - // Complex pair - - } - else - { - d(n-1) = x + p; - d(n) = x + p; - e(n-1) = z; - e(n) = -z; - } - n = n - 2; - iter = 0; - - // No convergence yet - - } - else - { - - // Form shift - - x = H(n,n); - y = 0.0; - w = 0.0; - if (l < n) - { - y = H(n-1,n-1); - w = H(n,n-1) * H(n-1,n); - } - - // Wilkinson's original ad hoc shift - - if (iter == 10) - { - exshift += x; - for (long i = low; i <= n; i++) - { - H(i,i) -= x; - } - s = abs(H(n,n-1)) + abs(H(n-1,n-2)); - x = y = 0.75 * s; - w = -0.4375 * s * s; - } - - // MATLAB's new ad hoc shift - - if (iter == 30) - { - s = (y - x) / 2.0; - s = s * s + w; - if (s > 0) - { - s = sqrt(s); - if (y < x) - { - s = -s; - } - s = x - w / ((y - x) / 2.0 + s); - for (long i = low; i <= n; i++) - { - H(i,i) -= s; - } - exshift += s; - x = y = w = 0.964; - } - } - - iter = iter + 1; // (Could check iteration count here.) - - // Look for two consecutive small sub-diagonal elements - - long m = n-2; - while (m >= l) - { - z = H(m,m); - r = x - z; - s = y - z; - p = (r * s - w) / H(m+1,m) + H(m,m+1); - q = H(m+1,m+1) - z - r - s; - r = H(m+2,m+1); - s = abs(p) + abs(q) + abs(r); - p = p / s; - q = q / s; - r = r / s; - if (m == l) - { - break; - } - if (abs(H(m,m-1)) * (abs(q) + abs(r)) < - eps * (abs(p) * (abs(H(m-1,m-1)) + abs(z) + - abs(H(m+1,m+1))))) - { - break; - } - m--; - } - - for (long i = m+2; i <= n; i++) - { - H(i,i-2) = 0.0; - if (i > m+2) - { - H(i,i-3) = 0.0; - } - } - - // Double QR step involving rows l:n and columns m:n - - for (long k = m; k <= n-1; k++) - { - long notlast = (k != n-1); - if (k != m) - { - p = H(k,k-1); - q = H(k+1,k-1); - r = (notlast ? H(k+2,k-1) : 0.0); - x = abs(p) + abs(q) + abs(r); - if (x != 0.0) - { - p = p / x; - q = q / x; - r = r / x; - } - } - if (x == 0.0) - { - break; - } - s = sqrt(p * p + q * q + r * r); - if (p < 0) - { - s = -s; - } - if (s != 0) - { - if (k != m) - { - H(k,k-1) = -s * x; - } - else if (l != m) - { - H(k,k-1) = -H(k,k-1); - } - p = p + s; - x = p / s; - y = q / s; - z = r / s; - q = q / p; - r = r / p; - - // Row modification - - for (long j = k; j < nn; j++) - { - p = H(k,j) + q * H(k+1,j); - if (notlast) - { - p = p + r * H(k+2,j); - H(k+2,j) = H(k+2,j) - p * z; - } - H(k,j) = H(k,j) - p * x; - H(k+1,j) = H(k+1,j) - p * y; - } - - // Column modification - - for (long i = 0; i <= min(n,k+3); i++) - { - p = x * H(i,k) + y * H(i,k+1); - if (notlast) - { - p = p + z * H(i,k+2); - H(i,k+2) = H(i,k+2) - p * r; - } - H(i,k) = H(i,k) - p; - H(i,k+1) = H(i,k+1) - p * q; - } - - // Accumulate transformations - - for (long i = low; i <= high; i++) - { - p = x * V(i,k) + y * V(i,k+1); - if (notlast) - { - p = p + z * V(i,k+2); - V(i,k+2) = V(i,k+2) - p * r; - } - V(i,k) = V(i,k) - p; - V(i,k+1) = V(i,k+1) - p * q; - } - } // (s != 0) - } // k loop - } // check convergence - } // while (n >= low) - - // Backsubstitute to find vectors of upper triangular form - - if (norm == 0.0) - { - return; - } - - for (n = nn-1; n >= 0; n--) - { - p = d(n); - q = e(n); - - // Real vector - - if (q == 0) - { - long l = n; - H(n,n) = 1.0; - for (long i = n-1; i >= 0; i--) - { - w = H(i,i) - p; - r = 0.0; - for (long j = l; j <= n; j++) - { - r = r + H(i,j) * H(j,n); - } - if (e(i) < 0.0) - { - z = w; - s = r; - } - else - { - l = i; - if (e(i) == 0.0) - { - if (w != 0.0) - { - H(i,n) = -r / w; - } - else - { - H(i,n) = -r / (eps * norm); - } - - // Solve real equations - - } - else - { - x = H(i,i+1); - y = H(i+1,i); - q = (d(i) - p) * (d(i) - p) + e(i) * e(i); - t = (x * s - z * r) / q; - H(i,n) = t; - if (abs(x) > abs(z)) - { - H(i+1,n) = (-r - w * t) / x; - } - else - { - H(i+1,n) = (-s - y * t) / z; - } - } - - // Overflow control - - t = abs(H(i,n)); - if ((eps * t) * t > 1) - { - for (long j = i; j <= n; j++) - { - H(j,n) = H(j,n) / t; - } - } - } - } - - // Complex vector - - } - else if (q < 0) - { - long l = n-1; - - // Last vector component imaginary so matrix is triangular - - if (abs(H(n,n-1)) > abs(H(n-1,n))) - { - H(n-1,n-1) = q / H(n,n-1); - H(n-1,n) = -(H(n,n) - p) / H(n,n-1); - } - else - { - cdiv_(0.0,-H(n-1,n),H(n-1,n-1)-p,q); - H(n-1,n-1) = cdivr; - H(n-1,n) = cdivi; - } - H(n,n-1) = 0.0; - H(n,n) = 1.0; - for (long i = n-2; i >= 0; i--) - { - type ra,sa,vr,vi; - ra = 0.0; - sa = 0.0; - for (long j = l; j <= n; j++) - { - ra = ra + H(i,j) * H(j,n-1); - sa = sa + H(i,j) * H(j,n); - } - w = H(i,i) - p; - - if (e(i) < 0.0) - { - z = w; - r = ra; - s = sa; - } - else - { - l = i; - if (e(i) == 0) - { - cdiv_(-ra,-sa,w,q); - H(i,n-1) = cdivr; - H(i,n) = cdivi; - } - else - { - - // Solve complex equations - - x = H(i,i+1); - y = H(i+1,i); - vr = (d(i) - p) * (d(i) - p) + e(i) * e(i) - q * q; - vi = (d(i) - p) * 2.0 * q; - if ((vr == 0.0) && (vi == 0.0)) - { - vr = eps * norm * (abs(w) + abs(q) + - abs(x) + abs(y) + abs(z)); - } - cdiv_(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi); - H(i,n-1) = cdivr; - H(i,n) = cdivi; - if (abs(x) > (abs(z) + abs(q))) - { - H(i+1,n-1) = (-ra - w * H(i,n-1) + q * H(i,n)) / x; - H(i+1,n) = (-sa - w * H(i,n) - q * H(i,n-1)) / x; - } - else - { - cdiv_(-r-y*H(i,n-1),-s-y*H(i,n),z,q); - H(i+1,n-1) = cdivr; - H(i+1,n) = cdivi; - } - } - - // Overflow control - - t = max(abs(H(i,n-1)),abs(H(i,n))); - if ((eps * t) * t > 1) - { - for (long j = i; j <= n; j++) - { - H(j,n-1) = H(j,n-1) / t; - H(j,n) = H(j,n) / t; - } - } - } - } - } - } - - // Vectors of isolated roots - - for (long i = 0; i < nn; i++) - { - if (i < low || i > high) - { - for (long j = i; j < nn; j++) - { - V(i,j) = H(i,j); - } - } - } - - // Back transformation to get eigenvectors of original matrix - - for (long j = nn-1; j >= low; j--) - { - for (long i = low; i <= high; i++) - { - z = 0.0; - for (long k = low; k <= min(j,high); k++) - { - z = z + V(i,k) * H(k,j); - } - V(i,j) = z; - } - } - } - -// ---------------------------------------------------------------------------------------- - - -} - -#endif // DLIB_MATRIX_EIGENVALUE_DECOMPOSITION_H - - - - diff --git a/ml/dlib/dlib/matrix/matrix_exp.h b/ml/dlib/dlib/matrix/matrix_exp.h deleted file mode 100644 index c0afb54c0..000000000 --- a/ml/dlib/dlib/matrix/matrix_exp.h +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_EXP_h_ -#define DLIB_MATRIx_EXP_h_ - -#include "../algs.h" -#include "../is_kind.h" -#include "matrix_fwd.h" -#include "matrix_exp_abstract.h" -#include <iterator> - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - // We want to return the compile time constant if our NR and NC dimensions - // aren't zero but if they are then we want to call ref_.nx() and return - // the correct values. - template < typename exp_type, long NR > - struct get_nr_helper - { - static inline long get(const exp_type&) { return NR; } - }; - - template < typename exp_type > - struct get_nr_helper<exp_type,0> - { - static inline long get(const exp_type& m) { return m.nr(); } - }; - - template < typename exp_type, long NC > - struct get_nc_helper - { - static inline long get(const exp_type&) { return NC; } - }; - - template < typename exp_type > - struct get_nc_helper<exp_type,0> - { - static inline long get(const exp_type& m) { return m.nc(); } - }; - - template <typename EXP> - struct matrix_traits - { - typedef typename EXP::type type; - typedef typename EXP::const_ret_type const_ret_type; - typedef typename EXP::mem_manager_type mem_manager_type; - typedef typename EXP::layout_type layout_type; - const static long NR = EXP::NR; - const static long NC = EXP::NC; - const static long cost = EXP::cost; - }; - -// ---------------------------------------------------------------------------------------- - - template <typename EXP> class matrix_exp; - template <typename EXP> - class matrix_exp_iterator : public std::iterator<std::forward_iterator_tag, typename matrix_traits<EXP>::type> - { - friend class matrix_exp<EXP>; - matrix_exp_iterator(const EXP& m_, long r_, long c_) - { - r = r_; - c = c_; - nc = m_.nc(); - m = &m_; - } - - public: - - matrix_exp_iterator() : r(0), c(0), nc(0), m(0) {} - - typedef typename matrix_traits<EXP>::type type; - typedef type value_type; - typedef typename matrix_traits<EXP>::const_ret_type const_ret_type; - - - bool operator == ( const matrix_exp_iterator& itr) const - { return r == itr.r && c == itr.c; } - - bool operator != ( const matrix_exp_iterator& itr) const - { return !(*this == itr); } - - matrix_exp_iterator& operator++() - { - ++c; - if (c==nc) - { - c = 0; - ++r; - } - return *this; - } - - matrix_exp_iterator operator++(int) - { - matrix_exp_iterator temp(*this); - ++(*this); - return temp; - } - - const_ret_type operator* () const { return (*m)(r,c); } - - private: - long r, c; - long nc; - const EXP* m; - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - class matrix_exp - { - /*! - REQUIREMENTS ON EXP - EXP should be something convertible to a matrix_exp. That is, - it should inherit from matrix_exp - !*/ - - public: - typedef typename matrix_traits<EXP>::type type; - typedef type value_type; - typedef typename matrix_traits<EXP>::const_ret_type const_ret_type; - typedef typename matrix_traits<EXP>::mem_manager_type mem_manager_type; - typedef typename matrix_traits<EXP>::layout_type layout_type; - const static long NR = matrix_traits<EXP>::NR; - const static long NC = matrix_traits<EXP>::NC; - const static long cost = matrix_traits<EXP>::cost; - - typedef matrix<type,NR,NC,mem_manager_type,layout_type> matrix_type; - typedef EXP exp_type; - typedef matrix_exp_iterator<EXP> iterator; - typedef matrix_exp_iterator<EXP> const_iterator; - - inline const_ret_type operator() ( - long r, - long c - ) const - { - DLIB_ASSERT(r < nr() && c < nc() && r >= 0 && c >= 0, - "\tconst type matrix_exp::operator(r,c)" - << "\n\tYou must give a valid row and column" - << "\n\tr: " << r - << "\n\tc: " << c - << "\n\tnr(): " << nr() - << "\n\tnc(): " << nc() - << "\n\tthis: " << this - ); - return ref()(r,c); - } - - const_ret_type operator() ( - long i - ) const - { - COMPILE_TIME_ASSERT(NC == 1 || NC == 0 || NR == 1 || NR == 0); - DLIB_ASSERT(nc() == 1 || nr() == 1, - "\tconst type matrix_exp::operator(i)" - << "\n\tYou can only use this operator on column or row vectors" - << "\n\ti: " << i - << "\n\tnr(): " << nr() - << "\n\tnc(): " << nc() - << "\n\tthis: " << this - ); - DLIB_ASSERT( ((nc() == 1 && i < nr()) || (nr() == 1 && i < nc())) && i >= 0, - "\tconst type matrix_exp::operator(i)" - << "\n\tYou must give a valid row/column number" - << "\n\ti: " << i - << "\n\tnr(): " << nr() - << "\n\tnc(): " << nc() - << "\n\tthis: " << this - ); - if (nc() == 1) - return ref()(i,0); - else - return ref()(0,i); - } - - long size ( - ) const { return nr()*nc(); } - - long nr ( - ) const { return get_nr_helper<exp_type,NR>::get(ref()); } - - long nc ( - ) const { return get_nc_helper<exp_type,NC>::get(ref()); } - - template <typename U> - bool aliases ( - const matrix_exp<U>& item - ) const { return ref().aliases(item); } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& item - ) const { return ref().destructively_aliases(item); } - - inline const exp_type& ref ( - ) const { return *static_cast<const exp_type*>(this); } - - inline operator const type ( - ) const - { - COMPILE_TIME_ASSERT(NC == 1 || NC == 0); - COMPILE_TIME_ASSERT(NR == 1 || NR == 0); - DLIB_ASSERT(nr() == 1 && nc() == 1, - "\tmatrix_exp::operator const type() const" - << "\n\tYou can only use this operator on a 1x1 matrix" - << "\n\tnr(): " << nr() - << "\n\tnc(): " << nc() - << "\n\tthis: " << this - ); - - // Put the expression contained in this matrix_exp into - // a temporary 1x1 matrix so that the expression will encounter - // all the overloads of matrix_assign() and have the chance to - // go through any applicable optimizations. - matrix<type,1,1,mem_manager_type,layout_type> temp(ref()); - return temp(0); - } - - const_iterator begin() const { return matrix_exp_iterator<EXP>(ref(),0,0); } - const_iterator end() const { return matrix_exp_iterator<EXP>(ref(),nr(),0); } - - protected: - matrix_exp() {} - matrix_exp(const matrix_exp& ) {} - - private: - - matrix_exp& operator= (const matrix_exp&); - }; - -// ---------------------------------------------------------------------------------------- - - // something is a matrix if it is convertible to a matrix_exp object - template <typename T> - struct is_matrix<T, typename enable_if<is_convertible<T, const matrix_exp<typename T::exp_type>& > >::type > - { static const bool value = true; }; - /* - is_matrix<T>::value == 1 if T is a matrix type else 0 - */ - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - class matrix_diag_exp : public matrix_exp<EXP> - { - /*! - This is a matrix expression type used to represent diagonal matrices. - That is, square matrices with all off diagonal elements equal to 0. - !*/ - - protected: - matrix_diag_exp() {} - matrix_diag_exp(const matrix_diag_exp& item ):matrix_exp<EXP>(item) {} - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_EXP_h_ - diff --git a/ml/dlib/dlib/matrix/matrix_exp_abstract.h b/ml/dlib/dlib/matrix/matrix_exp_abstract.h deleted file mode 100644 index 14ad143c2..000000000 --- a/ml/dlib/dlib/matrix/matrix_exp_abstract.h +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_MATRIx_EXP_ABSTRACT_ -#ifdef DLIB_MATRIx_EXP_ABSTRACT_ - -#include "matrix_fwd.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - class matrix_exp - { - /*! - REQUIREMENTS ON EXP - - must be an object that inherits publicly from matrix_exp (this class). - - WHAT THIS OBJECT REPRESENTS - This object represents an expression that evaluates to a matrix - of nr() rows and nc() columns. - - The reason for having an object that represents an expression is that it - allows us to use the "expression templates" technique to eliminate the - temporary matrix objects that would normally be returned from expressions - such as M = A+B+C+D; Normally each invocation of the + operator would - construct and return a temporary matrix object but using this technique we - can avoid creating all of these temporary objects and receive a large - speed boost. - - Note that every time you invoke operator() on this object it recomputes - its result which may not be what you want to do. For example, if you - are going to be accessing the same element over and over it might - be faster to assign the matrix_exp to a temporary matrix and then - use that temporary. - - - const_ret_type typedef (defined below) - The purpose of the const_ret_type typedef is to allow matrix expressions - to return their elements by reference when appropriate. So const_ret_type - should be one of the following types: - - const type - - const type& - !*/ - - public: - typedef typename EXP::type type; - typedef type value_type; // Redefined for compatibility with the STL - typedef typename EXP::const_ret_type const_ret_type; - typedef typename EXP::mem_manager_type mem_manager_type; - typedef typename EXP::layout_type layout_type; - const static long cost = EXP::cost; - const static long NR = EXP::NR; - const static long NC = EXP::NC; - typedef matrix<type,NR,NC, mem_manager_type,layout_type> matrix_type; - typedef EXP exp_type; - typedef matrix_exp_iterator<EXP> iterator; - typedef matrix_exp_iterator<EXP> const_iterator; - - const_ret_type operator() ( - long r, - long c - ) const; - /*! - requires - - 0 <= r < nr() - - 0 <= c < nc() - ensures - - returns ref()(r,c) - (i.e. returns the value at the given row and column that would be in - the matrix represented by this matrix expression) - !*/ - - const_ret_type operator() ( - long i - ) const; - /*! - requires - - nc() == 1 || nr() == 1 (i.e. this must be a column or row vector) - - if (nc() == 1) then - - 0 <= i < nr() - - else - - 0 <= i < nc() - ensures - - if (nc() == 1) then - - returns (*this)(i,0) - - else - - returns (*this)(0,i) - !*/ - - operator const type ( - ) const; - /*! - requires - - nr() == 1 - - nc() == 1 - ensures - - returns (*this)(0,0) - !*/ - - long nr ( - ) const; - /*! - ensures - - returns the number of rows in this matrix expression. - !*/ - - long nc ( - ) const; - /*! - ensures - - returns the number of columns in this matrix expression. - !*/ - - long size ( - ) const; - /*! - ensures - - returns nr()*nc() - !*/ - - template <typename U> - bool aliases ( - const matrix_exp<U>& item - ) const; - /*! - ensures - - if (A change to the state of item could cause a change to the state of *this - matrix_exp object. ) then - - returns true - - This happens when this matrix_exp contains item in some way. - - else - - returns false - !*/ - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& item - ) const; - /*! - ensures - - if (aliases(item)) then - - if (nr() != item.nr() || nc() != item.nc() - - returns true - (i.e. if this expression has different dimensions than item then - we have destructive aliasing) - - - returns true if the following assignment would evaluate incorrectly: - for (long r = 0; r < nr(); ++r) - for (long c = 0; c < nc(); ++c) - item(r,c) = (*this)(r,c) - - That is, if this matrix expression aliases item in such a way that a modification - to element item(r,c) causes a change in the value of something other than - (*this)(r,c) then this function returns true. - - - returns false if none of the above conditions say we should return true - - else - - returns false - !*/ - - inline const exp_type& ref ( - ) const; - /*! - ensures - - returns a reference to the expression contained in *this. - (i.e. returns *static_cast<const exp_type*>(this) ) - !*/ - - const_iterator begin( - ) const; - /*! - ensures - - returns a forward access iterator pointing to the first element in this - matrix expression. - - Since matrix_exp objects represent immutable views of a matrix, the - returned iterator does not allow the user to modify the matrix - expression's elements. - - The iterator will iterate over the elements of the matrix in row major - order. - !*/ - - const_iterator end( - ) const; - /*! - ensures - - returns a forward access iterator pointing to one past the end of the - last element in this matrix expression. - !*/ - - protected: - - // Only derived classes of matrix_exp may call the matrix_exp constructors. - matrix_exp(const matrix_exp&); - matrix_exp(); - - private: - // no one may ever use the assignment operator on a matrix_exp - matrix_exp& operator= (const matrix_exp&); - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_EXP_ABSTRACT_ - - diff --git a/ml/dlib/dlib/matrix/matrix_expressions.h b/ml/dlib/dlib/matrix/matrix_expressions.h deleted file mode 100644 index 9f057d076..000000000 --- a/ml/dlib/dlib/matrix/matrix_expressions.h +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_EXPRESSIONS_H_ -#define DLIB_MATRIx_EXPRESSIONS_H_ - -#include "matrix_fwd.h" - -#ifdef _MSC_VER -// This #pragma directive is also located in the algs.h file but for whatever -// reason visual studio 9 just ignores it when it is only there. - -// this is to disable the "'this' : used in base member initializer list" -// warning you get from some of the GUI objects since all the objects -// require that their parent class be passed into their constructor. -// In this case though it is totally safe so it is ok to disable this warning. -#pragma warning(disable : 4355) -#endif - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Helper templates for making operators used by expression objects -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename T> - class matrix_range_exp; - - template <typename T> - struct matrix_traits<matrix_range_exp<T> > - { - typedef T type; - typedef const T const_ret_type; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - const static long NR = 1; - const static long NC = 0; - const static long cost = 1; - }; - - template <typename T> - class matrix_range_exp : public matrix_exp<matrix_range_exp<T> > - { - public: - typedef typename matrix_traits<matrix_range_exp>::type type; - typedef typename matrix_traits<matrix_range_exp>::const_ret_type const_ret_type; - typedef typename matrix_traits<matrix_range_exp>::mem_manager_type mem_manager_type; - const static long NR = matrix_traits<matrix_range_exp>::NR; - const static long NC = matrix_traits<matrix_range_exp>::NC; - const static long cost = matrix_traits<matrix_range_exp>::cost; - typedef typename matrix_traits<matrix_range_exp>::layout_type layout_type; - - - matrix_range_exp ( - T start_, - T end_ - ) - { - start = start_; - if (start_ <= end_) - inc = 1; - else - inc = -1; - nc_ = std::abs(end_ - start_) + 1; - } - matrix_range_exp ( - T start_, - T inc_, - T end_ - ) - { - start = start_; - nc_ = std::abs(end_ - start_)/inc_ + 1; - if (start_ <= end_) - inc = inc_; - else - inc = -inc_; - } - - matrix_range_exp ( - T start_, - T end_, - long num, - bool - ) - { - start = start_; - nc_ = num; - if (num > 1) - { - inc = (end_-start_)/(num-1); - } - else - { - inc = 0; - start = end_; - } - - } - - const_ret_type operator() ( - long, - long c - ) const { return start + c*inc; } - - const_ret_type operator() ( - long c - ) const { return start + c*inc; } - - template <typename U> - bool aliases ( - const matrix_exp<U>& - ) const { return false; } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& - ) const { return false; } - - long nr ( - ) const { return NR; } - - long nc ( - ) const { return nc_; } - - long nc_; - T start; - T inc; - }; - -// ---------------------------------------------------------------------------------------- - - template <typename T> - class matrix_log_range_exp; - - template <typename T> - struct matrix_traits<matrix_log_range_exp<T> > - { - typedef T type; - typedef const T const_ret_type; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - const static long NR = 1; - const static long NC = 0; - const static long cost = 1; - }; - - template <typename T> - class matrix_log_range_exp : public matrix_exp<matrix_log_range_exp<T> > - { - public: - typedef typename matrix_traits<matrix_log_range_exp>::type type; - typedef typename matrix_traits<matrix_log_range_exp>::const_ret_type const_ret_type; - typedef typename matrix_traits<matrix_log_range_exp>::mem_manager_type mem_manager_type; - const static long NR = matrix_traits<matrix_log_range_exp>::NR; - const static long NC = matrix_traits<matrix_log_range_exp>::NC; - const static long cost = matrix_traits<matrix_log_range_exp>::cost; - typedef typename matrix_traits<matrix_log_range_exp>::layout_type layout_type; - - - matrix_log_range_exp ( - T start_, - T end_, - long num - ) - { - start = start_; - nc_ = num; - if (num > 1) - { - inc = (end_-start_)/(num-1); - } - else - { - inc = 0; - start = end_; - } - - } - - const_ret_type operator() ( - long, - long c - ) const { return std::pow((T)10,start + c*inc); } - - const_ret_type operator() ( - long c - ) const { return std::pow((T)10,start + c*inc); } - - template <typename U> - bool aliases ( - const matrix_exp<U>& - ) const { return false; } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& - ) const { return false; } - - long nr ( - ) const { return NR; } - - long nc ( - ) const { return nc_; } - - long nc_; - T start; - T inc; - }; - -// ---------------------------------------------------------------------------------------- - - template <long start, long inc_, long end> - class matrix_range_static_exp; - - template <long start, long inc_, long end> - struct matrix_traits<matrix_range_static_exp<start,inc_,end> > - { - typedef long type; - typedef const long const_ret_type; - typedef default_memory_manager mem_manager_type; - const static long NR = 1; - const static long NC = tabs<(end - start)>::value/inc_ + 1; - const static long cost = 1; - typedef row_major_layout layout_type; - }; - - template <long start, long inc_, long end_> - class matrix_range_static_exp : public matrix_exp<matrix_range_static_exp<start,inc_,end_> > - { - public: - typedef typename matrix_traits<matrix_range_static_exp>::type type; - typedef typename matrix_traits<matrix_range_static_exp>::const_ret_type const_ret_type; - typedef typename matrix_traits<matrix_range_static_exp>::mem_manager_type mem_manager_type; - const static long NR = matrix_traits<matrix_range_static_exp>::NR; - const static long NC = matrix_traits<matrix_range_static_exp>::NC; - const static long cost = matrix_traits<matrix_range_static_exp>::cost; - typedef typename matrix_traits<matrix_range_static_exp>::layout_type layout_type; - - const static long inc = (start <= end_)?inc_:-inc_; - - - matrix_range_static_exp ( - ) {} - - const_ret_type operator() ( - long , - long c - ) const { return start + c*inc; } - - const_ret_type operator() ( - long c - ) const { return start + c*inc; } - - template <typename U> - bool aliases ( - const matrix_exp<U>& - ) const { return false; } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& - ) const { return false; } - - long nr ( - ) const { return NR; } - - long nc ( - ) const { return NC; } - - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_EXPRESSIONS_H_ - diff --git a/ml/dlib/dlib/matrix/matrix_fft.h b/ml/dlib/dlib/matrix/matrix_fft.h deleted file mode 100644 index fbca6d344..000000000 --- a/ml/dlib/dlib/matrix/matrix_fft.h +++ /dev/null @@ -1,846 +0,0 @@ -// Copyright (C) 2013 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_FFt_Hh_ -#define DLIB_FFt_Hh_ - -#include "matrix_fft_abstract.h" -#include "matrix_utilities.h" -#include "../hash.h" -#include "../algs.h" - -#ifdef DLIB_USE_MKL_FFT -#include <mkl_dfti.h> -#endif - -// No using FFTW until it becomes thread safe! -#if 0 -#ifdef DLIB_USE_FFTW -#include <fftw3.h> -#endif // DLIB_USE_FFTW -#endif - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - inline bool is_power_of_two ( - const unsigned long& value - ) - { - if (value == 0) - return true; - else - return count_bits(value) == 1; - } - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - - // ------------------------------------------------------------------------------------ - - /* - The next few functions related to doing FFTs are derived from Stefan - Gustavson's (stegu@itn.liu.se) public domain 2D Fourier transformation code. - The code has a long history, originally a FORTRAN implementation published in: - Programming for Digital Signal Processing, IEEE Press 1979, Section 1, by G. D. - Bergland and M. T. Dolan. In 2003 it was cleaned up and turned into modern C - by Steven Gustavson. Davis King then rewrote it in modern C++ in 2014 and also - changed the transform so that the outputs are identical to those given from FFTW. - */ - - // ------------------------------------------------------------------------------------ - - /* Get binary log of integer argument - exact if n is a power of 2 */ - inline long fastlog2(long n) - { - long log = -1; - while(n) { - log++; - n >>= 1; - } - return log ; - } - - // ------------------------------------------------------------------------------------ - - /* Radix-2 iteration subroutine */ - template <typename T> - void R2TX(int nthpo, std::complex<T> *c0, std::complex<T> *c1) - { - for(int k=0; k<nthpo; k+=2) - { - std::complex<T> temp = c0[k] + c1[k]; - c1[k] = c0[k] - c1[k]; - c0[k] = temp; - } - } - - // ------------------------------------------------------------------------------------ - - /* Radix-4 iteration subroutine */ - template <typename T> - void R4TX(int nthpo, std::complex<T> *c0, std::complex<T> *c1, - std::complex<T> *c2, std::complex<T> *c3) - { - for(int k=0;k<nthpo;k+=4) - { - std::complex<T> t1, t2, t3, t4; - t1 = c0[k] + c2[k]; - t2 = c0[k] - c2[k]; - t3 = c1[k] + c3[k]; - t4 = c1[k] - c3[k]; - - c0[k] = t1 + t3; - c1[k] = t1 - t3; - c2[k] = std::complex<T>(t2.real()-t4.imag(), t2.imag()+t4.real()); - c3[k] = std::complex<T>(t2.real()+t4.imag(), t2.imag()-t4.real()); - } - } - - // ------------------------------------------------------------------------------------ - - template <typename T> - class twiddles - { - /*! - The point of this object is to cache the twiddle values so we don't - recompute them over and over inside R8TX(). - !*/ - public: - - twiddles() - { - data.resize(64); - } - - const std::complex<T>* get_twiddles ( - int p - ) - /*! - requires - - 0 <= p <= 64 - ensures - - returns a pointer to the twiddle factors needed by R8TX if nxtlt == 2^p - !*/ - { - // Compute the twiddle factors for this p value if we haven't done so - // already. - if (data[p].size() == 0) - { - const int nxtlt = 0x1 << p; - data[p].reserve(nxtlt*7); - const T twopi = 6.2831853071795865; /* 2.0 * pi */ - const T scale = twopi/(nxtlt*8.0); - std::complex<T> cs[7]; - for (int j = 0; j < nxtlt; ++j) - { - const T arg = j*scale; - cs[0] = std::complex<T>(std::cos(arg),std::sin(arg)); - cs[1] = cs[0]*cs[0]; - cs[2] = cs[1]*cs[0]; - cs[3] = cs[1]*cs[1]; - cs[4] = cs[2]*cs[1]; - cs[5] = cs[2]*cs[2]; - cs[6] = cs[3]*cs[2]; - data[p].insert(data[p].end(), cs, cs+7); - } - } - - return &data[p][0]; - } - - private: - std::vector<std::vector<std::complex<T> > > data; - }; - - // ---------------------------------------------------------------------------------------- - - /* Radix-8 iteration subroutine */ - template <typename T> - void R8TX(int nxtlt, int nthpo, int length, const std::complex<T>* cs, - std::complex<T> *cc0, std::complex<T> *cc1, std::complex<T> *cc2, std::complex<T> *cc3, - std::complex<T> *cc4, std::complex<T> *cc5, std::complex<T> *cc6, std::complex<T> *cc7) - { - const T irt2 = 0.707106781186548; /* 1.0/sqrt(2.0) */ - - for(int j=0; j<nxtlt; j++) - { - for(int k=j;k<nthpo;k+=length) - { - std::complex<T> a0, a1, a2, a3, a4, a5, a6, a7; - std::complex<T> b0, b1, b2, b3, b4, b5, b6, b7; - a0 = cc0[k] + cc4[k]; - a1 = cc1[k] + cc5[k]; - a2 = cc2[k] + cc6[k]; - a3 = cc3[k] + cc7[k]; - a4 = cc0[k] - cc4[k]; - a5 = cc1[k] - cc5[k]; - a6 = cc2[k] - cc6[k]; - a7 = cc3[k] - cc7[k]; - - b0 = a0 + a2; - b1 = a1 + a3; - b2 = a0 - a2; - b3 = a1 - a3; - - b4 = std::complex<T>(a4.real()-a6.imag(), a4.imag()+a6.real()); - b5 = std::complex<T>(a5.real()-a7.imag(), a5.imag()+a7.real()); - b6 = std::complex<T>(a4.real()+a6.imag(), a4.imag()-a6.real()); - b7 = std::complex<T>(a5.real()+a7.imag(), a5.imag()-a7.real()); - - const std::complex<T> tmp0(-b3.imag(), b3.real()); - const std::complex<T> tmp1(irt2*(b5.real()-b5.imag()), irt2*(b5.real()+b5.imag())); - const std::complex<T> tmp2(-irt2*(b7.real()+b7.imag()), irt2*(b7.real()-b7.imag())); - - cc0[k] = b0 + b1; - cc1[k] = b0 - b1; - cc2[k] = b2 + tmp0; - cc3[k] = b2 - tmp0; - cc4[k] = b4 + tmp1; - cc5[k] = b4 - tmp1; - cc6[k] = b6 + tmp2; - cc7[k] = b6 - tmp2; - if(j>0) - { - cc1[k] *= cs[3]; - cc2[k] *= cs[1]; - cc3[k] *= cs[5]; - cc4[k] *= cs[0]; - cc5[k] *= cs[4]; - cc6[k] *= cs[2]; - cc7[k] *= cs[6]; - } - } - - cs += 7; - } - } - - // ------------------------------------------------------------------------------------ - - template <typename T, long NR, long NC, typename MM, typename layout> - void fft1d_inplace(matrix<std::complex<T>,NR,NC,MM,layout>& data, bool do_backward_fft, twiddles<T>& cs) - /*! - requires - - is_vector(data) == true - - is_power_of_two(data.size()) == true - ensures - - This routine replaces the input std::complex<double> vector by its finite - discrete complex fourier transform if do_backward_fft==true. It replaces - the input std::complex<double> vector by its finite discrete complex - inverse fourier transform if do_backward_fft==false. - - The implementation is a radix-2 FFT, but with faster shortcuts for - radix-4 and radix-8. It performs as many radix-8 iterations as possible, - and then finishes with a radix-2 or -4 iteration if needed. - !*/ - { - COMPILE_TIME_ASSERT((is_same_type<double,T>::value || is_same_type<float,T>::value || is_same_type<long double,T>::value )); - - if (data.size() == 0) - return; - - std::complex<T>* const b = &data(0); - int L[16],L1,L2,L3,L4,L5,L6,L7,L8,L9,L10,L11,L12,L13,L14,L15; - int j1,j2,j3,j4,j5,j6,j7,j8,j9,j10,j11,j12,j13,j14; - int j, ij, ji; - int n2pow, n8pow, nthpo, ipass, nxtlt, length; - - n2pow = fastlog2(data.size()); - nthpo = data.size(); - - n8pow = n2pow/3; - - if(n8pow) - { - /* Radix 8 iterations */ - for(ipass=1;ipass<=n8pow;ipass++) - { - const int p = n2pow - 3*ipass; - nxtlt = 0x1 << p; - length = 8*nxtlt; - R8TX(nxtlt, nthpo, length, cs.get_twiddles(p), - b, b+nxtlt, b+2*nxtlt, b+3*nxtlt, - b+4*nxtlt, b+5*nxtlt, b+6*nxtlt, b+7*nxtlt); - } - } - - if(n2pow%3 == 1) - { - /* A final radix 2 iteration is needed */ - R2TX(nthpo, b, b+1); - } - - if(n2pow%3 == 2) - { - /* A final radix 4 iteration is needed */ - R4TX(nthpo, b, b+1, b+2, b+3); - } - - for(j=1;j<=15;j++) - { - L[j] = 1; - if(j-n2pow <= 0) L[j] = 0x1 << (n2pow + 1 - j); - } - - L15=L[1];L14=L[2];L13=L[3];L12=L[4];L11=L[5];L10=L[6];L9=L[7]; - L8=L[8];L7=L[9];L6=L[10];L5=L[11];L4=L[12];L3=L[13];L2=L[14];L1=L[15]; - - ij = 0; - - for(j1=0;j1<L1;j1++) - for(j2=j1;j2<L2;j2+=L1) - for(j3=j2;j3<L3;j3+=L2) - for(j4=j3;j4<L4;j4+=L3) - for(j5=j4;j5<L5;j5+=L4) - for(j6=j5;j6<L6;j6+=L5) - for(j7=j6;j7<L7;j7+=L6) - for(j8=j7;j8<L8;j8+=L7) - for(j9=j8;j9<L9;j9+=L8) - for(j10=j9;j10<L10;j10+=L9) - for(j11=j10;j11<L11;j11+=L10) - for(j12=j11;j12<L12;j12+=L11) - for(j13=j12;j13<L13;j13+=L12) - for(j14=j13;j14<L14;j14+=L13) - for(ji=j14;ji<L15;ji+=L14) - { - if(ij<ji) - swap(b[ij], b[ji]); - ij++; - } - - - // unscramble outputs - if(!do_backward_fft) - { - for(long i=1, j=data.size()-1; i<data.size()/2; i++,j--) - { - swap(b[j], b[i]); - } - } - } - - // ------------------------------------------------------------------------------------ - - template < typename T, long NR, long NC, typename MM, typename L > - void fft2d_inplace( - matrix<std::complex<T>,NR,NC,MM,L>& data, - bool do_backward_fft - ) - { - if (data.size() == 0) - return; - - matrix<std::complex<double> > buff; - twiddles<double> cs; - - // Compute transform row by row - for(long r=0; r<data.nr(); ++r) - { - buff = matrix_cast<std::complex<double> >(rowm(data,r)); - fft1d_inplace(buff, do_backward_fft, cs); - set_rowm(data,r) = matrix_cast<std::complex<T> >(buff); - } - - // Compute transform column by column - for(long c=0; c<data.nc(); ++c) - { - buff = matrix_cast<std::complex<double> >(colm(data,c)); - fft1d_inplace(buff, do_backward_fft, cs); - set_colm(data,c) = matrix_cast<std::complex<T> >(buff); - } - } - - // ---------------------------------------------------------------------------------------- - - template < - typename EXP, - typename T - > - void fft2d( - const matrix_exp<EXP>& data, - matrix<std::complex<T> >& data_out, - bool do_backward_fft - ) - { - // make sure requires clause is not broken - DLIB_CASSERT(is_power_of_two(data.nr()) && is_power_of_two(data.nc()), - "\t matrix fft(data)" - << "\n\t The number of rows and columns must be powers of two." - << "\n\t data.nr(): "<< data.nr() - << "\n\t data.nc(): "<< data.nc() - << "\n\t is_power_of_two(data.nr()): " << is_power_of_two(data.nr()) - << "\n\t is_power_of_two(data.nc()): " << is_power_of_two(data.nc()) - ); - - if (data.size() == 0) - return; - - matrix<std::complex<double> > buff; - data_out.set_size(data.nr(), data.nc()); - twiddles<double> cs; - - // Compute transform row by row - for(long r=0; r<data.nr(); ++r) - { - buff = matrix_cast<std::complex<double> >(rowm(data,r)); - fft1d_inplace(buff, do_backward_fft, cs); - set_rowm(data_out,r) = matrix_cast<std::complex<T> >(buff); - } - - // Compute transform column by column - for(long c=0; c<data_out.nc(); ++c) - { - buff = matrix_cast<std::complex<double> >(colm(data_out,c)); - fft1d_inplace(buff, do_backward_fft, cs); - set_colm(data_out,c) = matrix_cast<std::complex<T> >(buff); - } - } - - // ------------------------------------------------------------------------------------ - - } // end namespace impl - -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - matrix<typename EXP::type> fft (const matrix_exp<EXP>& data) - { - // You have to give a complex matrix - COMPILE_TIME_ASSERT(is_complex<typename EXP::type>::value); - // make sure requires clause is not broken - DLIB_CASSERT(is_power_of_two(data.nr()) && is_power_of_two(data.nc()), - "\t matrix fft(data)" - << "\n\t The number of rows and columns must be powers of two." - << "\n\t data.nr(): "<< data.nr() - << "\n\t data.nc(): "<< data.nc() - << "\n\t is_power_of_two(data.nr()): " << is_power_of_two(data.nr()) - << "\n\t is_power_of_two(data.nc()): " << is_power_of_two(data.nc()) - ); - - if (data.nr() == 1 || data.nc() == 1) - { - matrix<typename EXP::type> temp(data); - impl::twiddles<typename EXP::type::value_type> cs; - impl::fft1d_inplace(temp, false, cs); - return temp; - } - else - { - matrix<typename EXP::type> temp; - impl::fft2d(data, temp, false); - return temp; - } - } - - template <typename EXP> - matrix<typename EXP::type> ifft (const matrix_exp<EXP>& data) - { - // You have to give a complex matrix - COMPILE_TIME_ASSERT(is_complex<typename EXP::type>::value); - // make sure requires clause is not broken - DLIB_CASSERT(is_power_of_two(data.nr()) && is_power_of_two(data.nc()), - "\t matrix ifft(data)" - << "\n\t The number of rows and columns must be powers of two." - << "\n\t data.nr(): "<< data.nr() - << "\n\t data.nc(): "<< data.nc() - << "\n\t is_power_of_two(data.nr()): " << is_power_of_two(data.nr()) - << "\n\t is_power_of_two(data.nc()): " << is_power_of_two(data.nc()) - ); - - matrix<typename EXP::type> temp; - if (data.size() == 0) - return temp; - - if (data.nr() == 1 || data.nc() == 1) - { - temp = data; - impl::twiddles<typename EXP::type::value_type> cs; - impl::fft1d_inplace(temp, true, cs); - } - else - { - impl::fft2d(data, temp, true); - } - temp /= data.size(); - return temp; - } - -// ---------------------------------------------------------------------------------------- - - template < typename T, long NR, long NC, typename MM, typename L > - typename enable_if_c<NR==1||NC==1>::type fft_inplace (matrix<std::complex<T>,NR,NC,MM,L>& data) - // Note that we don't divide the outputs by data.size() so this isn't quite the inverse. - { - // make sure requires clause is not broken - DLIB_CASSERT(is_power_of_two(data.nr()) && is_power_of_two(data.nc()), - "\t void fft_inplace(data)" - << "\n\t The number of rows and columns must be powers of two." - << "\n\t data.nr(): "<< data.nr() - << "\n\t data.nc(): "<< data.nc() - << "\n\t is_power_of_two(data.nr()): " << is_power_of_two(data.nr()) - << "\n\t is_power_of_two(data.nc()): " << is_power_of_two(data.nc()) - ); - - impl::twiddles<T> cs; - impl::fft1d_inplace(data, false, cs); - } - - template < typename T, long NR, long NC, typename MM, typename L > - typename disable_if_c<NR==1||NC==1>::type fft_inplace (matrix<std::complex<T>,NR,NC,MM,L>& data) - // Note that we don't divide the outputs by data.size() so this isn't quite the inverse. - { - // make sure requires clause is not broken - DLIB_CASSERT(is_power_of_two(data.nr()) && is_power_of_two(data.nc()), - "\t void fft_inplace(data)" - << "\n\t The number of rows and columns must be powers of two." - << "\n\t data.nr(): "<< data.nr() - << "\n\t data.nc(): "<< data.nc() - << "\n\t is_power_of_two(data.nr()): " << is_power_of_two(data.nr()) - << "\n\t is_power_of_two(data.nc()): " << is_power_of_two(data.nc()) - ); - - impl::fft2d_inplace(data, false); - } - -// ---------------------------------------------------------------------------------------- - - template < typename T, long NR, long NC, typename MM, typename L > - typename enable_if_c<NR==1||NC==1>::type ifft_inplace (matrix<std::complex<T>,NR,NC,MM,L>& data) - { - // make sure requires clause is not broken - DLIB_CASSERT(is_power_of_two(data.nr()) && is_power_of_two(data.nc()), - "\t void ifft_inplace(data)" - << "\n\t The number of rows and columns must be powers of two." - << "\n\t data.nr(): "<< data.nr() - << "\n\t data.nc(): "<< data.nc() - << "\n\t is_power_of_two(data.nr()): " << is_power_of_two(data.nr()) - << "\n\t is_power_of_two(data.nc()): " << is_power_of_two(data.nc()) - ); - - impl::twiddles<T> cs; - impl::fft1d_inplace(data, true, cs); - } - - template < typename T, long NR, long NC, typename MM, typename L > - typename disable_if_c<NR==1||NC==1>::type ifft_inplace (matrix<std::complex<T>,NR,NC,MM,L>& data) - { - // make sure requires clause is not broken - DLIB_CASSERT(is_power_of_two(data.nr()) && is_power_of_two(data.nc()), - "\t void ifft_inplace(data)" - << "\n\t The number of rows and columns must be powers of two." - << "\n\t data.nr(): "<< data.nr() - << "\n\t data.nc(): "<< data.nc() - << "\n\t is_power_of_two(data.nr()): " << is_power_of_two(data.nr()) - << "\n\t is_power_of_two(data.nc()): " << is_power_of_two(data.nc()) - ); - - impl::fft2d_inplace(data, true); - } - -// ---------------------------------------------------------------------------------------- - - /* - I'm disabling any use of the FFTW bindings because FFTW is, as of this writing, not - threadsafe as a library. This means that if multiple threads were to make - concurrent calls to these fft routines then the program could crash. If at some - point FFTW is fixed I'll turn these bindings back on. - - See https://github.com/FFTW/fftw3/issues/16 - */ -#if 0 -#ifdef DLIB_USE_FFTW - - template <long NR, long NC, typename MM, typename L> - matrix<std::complex<double>,NR,NC,MM,L> call_fftw_fft( - const matrix<std::complex<double>,NR,NC,MM,L>& data - ) - { - // make sure requires clause is not broken - DLIB_CASSERT(is_power_of_two(data.nr()) && is_power_of_two(data.nc()), - "\t matrix fft(data)" - << "\n\t The number of rows and columns must be powers of two." - << "\n\t data.nr(): "<< data.nr() - << "\n\t data.nc(): "<< data.nc() - << "\n\t is_power_of_two(data.nr()): " << is_power_of_two(data.nr()) - << "\n\t is_power_of_two(data.nc()): " << is_power_of_two(data.nc()) - ); - - if (data.size() == 0) - return data; - - matrix<std::complex<double>,NR,NC,MM,L> m2(data.nr(),data.nc()); - fftw_complex *in, *out; - fftw_plan p; - in = (fftw_complex*)&data(0,0); - out = (fftw_complex*)&m2(0,0); - if (data.nr() == 1 || data.nc() == 1) - p = fftw_plan_dft_1d(data.size(), in, out, FFTW_FORWARD, FFTW_ESTIMATE); - else - p = fftw_plan_dft_2d(data.nr(), data.nc(), in, out, FFTW_FORWARD, FFTW_ESTIMATE); - fftw_execute(p); - fftw_destroy_plan(p); - return m2; - } - - template <long NR, long NC, typename MM, typename L> - matrix<std::complex<double>,NR,NC,MM,L> call_fftw_ifft( - const matrix<std::complex<double>,NR,NC,MM,L>& data - ) - { - // make sure requires clause is not broken - DLIB_CASSERT(is_power_of_two(data.nr()) && is_power_of_two(data.nc()), - "\t matrix ifft(data)" - << "\n\t The number of rows and columns must be powers of two." - << "\n\t data.nr(): "<< data.nr() - << "\n\t data.nc(): "<< data.nc() - << "\n\t is_power_of_two(data.nr()): " << is_power_of_two(data.nr()) - << "\n\t is_power_of_two(data.nc()): " << is_power_of_two(data.nc()) - ); - - if (data.size() == 0) - return data; - - matrix<std::complex<double>,NR,NC,MM,L> m2(data.nr(),data.nc()); - fftw_complex *in, *out; - fftw_plan p; - in = (fftw_complex*)&data(0,0); - out = (fftw_complex*)&m2(0,0); - if (data.nr() == 1 || data.nc() == 1) - p = fftw_plan_dft_1d(data.size(), in, out, FFTW_BACKWARD, FFTW_ESTIMATE); - else - p = fftw_plan_dft_2d(data.nr(), data.nc(), in, out, FFTW_BACKWARD, FFTW_ESTIMATE); - fftw_execute(p); - fftw_destroy_plan(p); - return m2; - } - -// ---------------------------------------------------------------------------------------- - -// call FFTW for these cases: - inline matrix<std::complex<double>,0,1> fft (const matrix<std::complex<double>,0,1>& data) {return call_fftw_fft(data);} - inline matrix<std::complex<double>,0,1> ifft(const matrix<std::complex<double>,0,1>& data) {return call_fftw_ifft(data)/data.size();} - inline matrix<std::complex<double>,1,0> fft (const matrix<std::complex<double>,1,0>& data) {return call_fftw_fft(data);} - inline matrix<std::complex<double>,1,0> ifft(const matrix<std::complex<double>,1,0>& data) {return call_fftw_ifft(data)/data.size();} - inline matrix<std::complex<double> > fft (const matrix<std::complex<double> >& data) {return call_fftw_fft(data);} - inline matrix<std::complex<double> > ifft(const matrix<std::complex<double> >& data) {return call_fftw_ifft(data)/data.size();} - - inline void fft_inplace (matrix<std::complex<double>,0,1>& data) {data = call_fftw_fft(data);} - inline void ifft_inplace(matrix<std::complex<double>,0,1>& data) {data = call_fftw_ifft(data);} - inline void fft_inplace (matrix<std::complex<double>,1,0>& data) {data = call_fftw_fft(data);} - inline void ifft_inplace(matrix<std::complex<double>,1,0>& data) {data = call_fftw_ifft(data);} - inline void fft_inplace (matrix<std::complex<double> >& data) {data = call_fftw_fft(data);} - inline void ifft_inplace(matrix<std::complex<double> >& data) {data = call_fftw_ifft(data);} - -#endif // DLIB_USE_FFTW -#endif // end of #if 0 - -// ---------------------------------------------------------------------------------------- - -#ifdef DLIB_USE_MKL_FFT - -#define DLIB_DFTI_CHECK_STATUS(s) \ - if((s) != 0 && !DftiErrorClass((s), DFTI_NO_ERROR)) \ - { \ - throw dlib::error(DftiErrorMessage((s))); \ - } - - template < long NR, long NC, typename MM, typename L > - matrix<std::complex<double>,NR,NC,MM,L> call_mkl_fft( - const matrix<std::complex<double>,NR,NC,MM,L>& data, - bool do_backward_fft) - { - // make sure requires clause is not broken - DLIB_CASSERT(is_power_of_two(data.nr()) && is_power_of_two(data.nc()), - "\t matrix fft(data)" - << "\n\t The number of rows and columns must be powers of two." - << "\n\t data.nr(): "<< data.nr() - << "\n\t data.nc(): "<< data.nc() - << "\n\t is_power_of_two(data.nr()): " << is_power_of_two(data.nr()) - << "\n\t is_power_of_two(data.nc()): " << is_power_of_two(data.nc()) - ); - - if (data.size() == 0) - return data; - - DFTI_DESCRIPTOR_HANDLE h; - MKL_LONG status; - - if (data.nr() == 1 || data.nc() == 1) - { - status = DftiCreateDescriptor(&h, DFTI_DOUBLE, DFTI_COMPLEX, 1, data.size()); - DLIB_DFTI_CHECK_STATUS(status); - } - else - { - MKL_LONG size[2]; - size[0] = data.nr(); - size[1] = data.nc(); - - status = DftiCreateDescriptor(&h, DFTI_DOUBLE, DFTI_COMPLEX, 2, size); - DLIB_DFTI_CHECK_STATUS(status); - - MKL_LONG strides[3]; - strides[0] = 0; - strides[1] = size[1]; - strides[2] = 1; - - status = DftiSetValue(h, DFTI_INPUT_STRIDES, strides); - DLIB_DFTI_CHECK_STATUS(status); - status = DftiSetValue(h, DFTI_OUTPUT_STRIDES, strides); - DLIB_DFTI_CHECK_STATUS(status); - } - - status = DftiSetValue(h, DFTI_PLACEMENT, DFTI_NOT_INPLACE); - DLIB_DFTI_CHECK_STATUS(status); - - // Unless we use sequential mode, the fft results are not correct. - status = DftiSetValue(h, DFTI_THREAD_LIMIT, 1); - DLIB_DFTI_CHECK_STATUS(status); - - status = DftiCommitDescriptor(h); - DLIB_DFTI_CHECK_STATUS(status); - - matrix<std::complex<double>,NR,NC,MM,L> out(data.nr(), data.nc()); - - if (do_backward_fft) - status = DftiComputeBackward(h, (void *)(&data(0, 0)), &out(0,0)); - else - status = DftiComputeForward(h, (void *)(&data(0, 0)), &out(0,0)); - DLIB_DFTI_CHECK_STATUS(status); - - status = DftiFreeDescriptor(&h); - DLIB_DFTI_CHECK_STATUS(status); - - return out; - } - - template < long NR, long NC, typename MM, typename L > - void call_mkl_fft_inplace( - matrix<std::complex<double>,NR,NC,MM,L>& data, - bool do_backward_fft - ) - { - // make sure requires clause is not broken - DLIB_CASSERT(is_power_of_two(data.nr()) && is_power_of_two(data.nc()), - "\t void ifft_inplace(data)" - << "\n\t The number of rows and columns must be powers of two." - << "\n\t data.nr(): "<< data.nr() - << "\n\t data.nc(): "<< data.nc() - << "\n\t is_power_of_two(data.nr()): " << is_power_of_two(data.nr()) - << "\n\t is_power_of_two(data.nc()): " << is_power_of_two(data.nc()) - ); - - if (data.size() == 0) - return; - - DFTI_DESCRIPTOR_HANDLE h; - MKL_LONG status; - - if (data.nr() == 1 || data.nc() == 1) - { - status = DftiCreateDescriptor(&h, DFTI_DOUBLE, DFTI_COMPLEX, 1, data.size()); - DLIB_DFTI_CHECK_STATUS(status); - } - else - { - MKL_LONG size[2]; - size[0] = data.nr(); - size[1] = data.nc(); - - status = DftiCreateDescriptor(&h, DFTI_DOUBLE, DFTI_COMPLEX, 2, size); - DLIB_DFTI_CHECK_STATUS(status); - - MKL_LONG strides[3]; - strides[0] = 0; - strides[1] = size[1]; - strides[2] = 1; - - status = DftiSetValue(h, DFTI_INPUT_STRIDES, strides); - DLIB_DFTI_CHECK_STATUS(status); - } - - // Unless we use sequential mode, the fft results are not correct. - status = DftiSetValue(h, DFTI_THREAD_LIMIT, 1); - DLIB_DFTI_CHECK_STATUS(status); - - status = DftiCommitDescriptor(h); - DLIB_DFTI_CHECK_STATUS(status); - - if (do_backward_fft) - status = DftiComputeBackward(h, &data(0, 0)); - else - status = DftiComputeForward(h, &data(0, 0)); - DLIB_DFTI_CHECK_STATUS(status); - - status = DftiFreeDescriptor(&h); - DLIB_DFTI_CHECK_STATUS(status); - - return; - } - -// ---------------------------------------------------------------------------------------- - - // Call the MKL DFTI implementation in these cases - - inline matrix<std::complex<double>,0,1> fft (const matrix<std::complex<double>,0,1>& data) - { - return call_mkl_fft(data, false); - } - inline matrix<std::complex<double>,0,1> ifft(const matrix<std::complex<double>,0,1>& data) - { - return call_mkl_fft(data, true) / data.size(); - } - inline matrix<std::complex<double>,1,0> fft (const matrix<std::complex<double>,1,0>& data) - { - return call_mkl_fft(data, false); - } - inline matrix<std::complex<double>,1,0> ifft(const matrix<std::complex<double>,1,0>& data) - { - return call_mkl_fft(data, true) / data.size(); - } - inline matrix<std::complex<double> > fft (const matrix<std::complex<double> >& data) - { - return call_mkl_fft(data, false); - } - inline matrix<std::complex<double> > ifft(const matrix<std::complex<double> >& data) - { - return call_mkl_fft(data, true) / data.size(); - } - - inline void fft_inplace (matrix<std::complex<double>,0,1>& data) - { - call_mkl_fft_inplace(data, false); - } - inline void ifft_inplace(matrix<std::complex<double>,0,1>& data) - { - call_mkl_fft_inplace(data, true); - } - inline void fft_inplace (matrix<std::complex<double>,1,0>& data) - { - call_mkl_fft_inplace(data, false); - } - inline void ifft_inplace(matrix<std::complex<double>,1,0>& data) - { - call_mkl_fft_inplace(data, true); - } - - inline void fft_inplace (matrix<std::complex<double> >& data) - { - call_mkl_fft_inplace(data, false); - } - inline void ifft_inplace(matrix<std::complex<double> >& data) - { - call_mkl_fft_inplace(data, true); - } - -#endif // DLIB_USE_MKL_FFT - -// ---------------------------------------------------------------------------------------- -} - -#endif // DLIB_FFt_Hh_ - diff --git a/ml/dlib/dlib/matrix/matrix_fft_abstract.h b/ml/dlib/dlib/matrix/matrix_fft_abstract.h deleted file mode 100644 index 25cdfcaee..000000000 --- a/ml/dlib/dlib/matrix/matrix_fft_abstract.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (C) 2013 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_FFt_ABSTRACT_Hh_ -#ifdef DLIB_FFt_ABSTRACT_Hh_ - -#include "matrix_abstract.h" -#include "../algs.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - bool is_power_of_two ( - const unsigned long& value - ); - /*! - ensures - - returns true if value contains a power of two and false otherwise. As a - special case, we also consider 0 to be a power of two. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - typename EXP::matrix_type fft ( - const matrix_exp<EXP>& data - ); - /*! - requires - - data contains elements of type std::complex<> that itself contains double, float, or long double. - - is_power_of_two(data.nr()) == true - - is_power_of_two(data.nc()) == true - ensures - - Computes the 1 or 2 dimensional discrete Fourier transform of the given data - matrix and returns it. In particular, we return a matrix D such that: - - D.nr() == data.nr() - - D.nc() == data.nc() - - D(0,0) == the DC term of the Fourier transform. - - starting with D(0,0), D contains progressively higher frequency components - of the input data. - - ifft(D) == D - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - typename EXP::matrix_type ifft ( - const matrix_exp<EXP>& data - ); - /*! - requires - - data contains elements of type std::complex<> that itself contains double, float, or long double. - - is_power_of_two(data.nr()) == true - - is_power_of_two(data.nc()) == true - ensures - - Computes the 1 or 2 dimensional inverse discrete Fourier transform of the - given data vector and returns it. In particular, we return a matrix D such - that: - - D.nr() == data.nr() - - D.nc() == data.nc() - - fft(D) == data - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - typename MM, - typename L - > - void fft_inplace ( - matrix<std::complex<T>,NR,NC,MM,L>& data - ); - /*! - requires - - data contains elements of type std::complex<> that itself contains double, float, or long double. - - is_power_of_two(data.nr()) == true - - is_power_of_two(data.nc()) == true - ensures - - This function is identical to fft() except that it does the FFT in-place. - That is, after this function executes we will have: - - #data == fft(data) - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - typename MM, - typename L - > - void ifft_inplace ( - matrix<std::complex<T>,NR,NC,MM,L>& data - ); - /*! - requires - - data contains elements of type std::complex<> that itself contains double, float, or long double. - - is_power_of_two(data.nr()) == true - - is_power_of_two(data.nc()) == true - ensures - - This function is identical to ifft() except that it does the inverse FFT - in-place. That is, after this function executes we will have: - - #data == ifft(data)*data.size() - - Note that the output needs to be divided by data.size() to complete the - inverse transformation. - !*/ - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_FFt_ABSTRACT_Hh_ - diff --git a/ml/dlib/dlib/matrix/matrix_fwd.h b/ml/dlib/dlib/matrix/matrix_fwd.h deleted file mode 100644 index 1f40a17a8..000000000 --- a/ml/dlib/dlib/matrix/matrix_fwd.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_FWD -#define DLIB_MATRIx_FWD - -#include "../algs.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - struct row_major_layout; - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long num_rows = 0, - long num_cols = 0, - typename mem_manager = default_memory_manager, - typename layout = row_major_layout - > - class matrix; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_FWD - diff --git a/ml/dlib/dlib/matrix/matrix_generic_image.h b/ml/dlib/dlib/matrix/matrix_generic_image.h deleted file mode 100644 index 0455af205..000000000 --- a/ml/dlib/dlib/matrix/matrix_generic_image.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (C) 2014 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIX_GENERIC_iMAGE_Hh_ -#define DLIB_MATRIX_GENERIC_iMAGE_Hh_ - -#include "matrix.h" -#include "../image_processing/generic_image.h" - -namespace dlib -{ - template < - typename T, - long NR, - long NC, - typename MM - > - struct image_traits<matrix<T,NR,NC,MM> > - { - typedef T pixel_type; - }; - - template < - typename T, - long NR, - long NC, - typename MM - > - struct image_traits<const matrix<T,NR,NC,MM> > - { - typedef T pixel_type; - }; - - template < - typename T, - long NR, - long NC, - typename MM - > - inline long num_rows( const matrix<T,NR,NC,MM>& img) { return img.nr(); } - - template < - typename T, - long NR, - long NC, - typename MM - > - inline long num_columns( const matrix<T,NR,NC,MM>& img) { return img.nc(); } - - template < - typename T, - long NR, - long NC, - typename MM - > - inline void set_image_size( - matrix<T,NR,NC,MM>& img, - long rows, - long cols - ) { img.set_size(rows,cols); } - - template < - typename T, - long NR, - long NC, - typename MM - > - inline void* image_data( - matrix<T,NR,NC,MM>& img - ) - { - if (img.size() != 0) - return &img(0,0); - else - return 0; - } - - template < - typename T, - long NR, - long NC, - typename MM - > - inline const void* image_data( - const matrix<T,NR,NC,MM>& img - ) - { - if (img.size() != 0) - return &img(0,0); - else - return 0; - } - - template < - typename T, - long NR, - long NC, - typename MM - > - inline long width_step( - const matrix<T,NR,NC,MM>& img - ) - { - return img.nc()*sizeof(T); - } - -} - -#endif // DLIB_MATRIX_GENERIC_iMAGE_Hh_ - - diff --git a/ml/dlib/dlib/matrix/matrix_la.h b/ml/dlib/dlib/matrix/matrix_la.h deleted file mode 100644 index 35b5b42e2..000000000 --- a/ml/dlib/dlib/matrix/matrix_la.h +++ /dev/null @@ -1,1807 +0,0 @@ -// Copyright (C) 2009 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_LA_FUNCTS_ -#define DLIB_MATRIx_LA_FUNCTS_ - -#include "matrix_la_abstract.h" -#include "matrix_utilities.h" -#include "../sparse_vector.h" -#include "../optimization/optimization_line_search.h" - -// The 4 decomposition objects described in the matrix_la_abstract.h file are -// actually implemented in the following 4 files. -#include "matrix_lu.h" -#include "matrix_qr.h" -#include "matrix_cholesky.h" -#include "matrix_eigenvalue.h" - -#ifdef DLIB_USE_LAPACK -#include "lapack/potrf.h" -#include "lapack/pbtrf.h" -#include "lapack/gesdd.h" -#include "lapack/gesvd.h" -#endif - -#include "../threads.h" - -#include <iostream> - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - enum svd_u_mode - { - SVD_NO_U, - SVD_SKINNY_U, - SVD_FULL_U - }; - - template < - typename EXP, - long qN, long qX, - long uM, long uN, - long vM, long vN, - typename MM1, - typename MM2, - typename MM3, - typename L1 - > - long svd4 ( - svd_u_mode u_mode, - bool withv, - const matrix_exp<EXP>& a, - matrix<typename EXP::type,uM,uN,MM1,L1>& u, - matrix<typename EXP::type,qN,qX,MM2,L1>& q, - matrix<typename EXP::type,vM,vN,MM3,L1>& v - ) - { - /* - Singular value decomposition. Translated to 'C' from the - original Algol code in "Handbook for Automatic Computation, - vol. II, Linear Algebra", Springer-Verlag. Note that this - published algorithm is considered to be the best and numerically - stable approach to computing the real-valued svd and is referenced - repeatedly in ieee journal papers, etc where the svd is used. - - This is almost an exact translation from the original, except that - an iteration counter is added to prevent stalls. This corresponds - to similar changes in other translations. - - Returns an error code = 0, if no errors and 'k' if a failure to - converge at the 'kth' singular value. - - USAGE: given the singular value decomposition a = u * diagm(q) * trans(v) for an m*n - matrix a with m >= n ... - After the svd call u is an m x m matrix which is columnwise - orthogonal. q will be an n element vector consisting of singular values - and v an n x n orthogonal matrix. eps and tol are tolerance constants. - Suitable values are eps=1e-16 and tol=(1e-300)/eps if T == double. - - If u_mode == SVD_NO_U then u won't be computed and similarly if withv == false - then v won't be computed. If u_mode == SVD_SKINNY_U then u will be m x n instead of m x m. - */ - - - DLIB_ASSERT(a.nr() >= a.nc(), - "\tconst matrix_exp svd4()" - << "\n\tYou have given an invalidly sized matrix" - << "\n\ta.nr(): " << a.nr() - << "\n\ta.nc(): " << a.nc() - ); - - - typedef typename EXP::type T; - -#ifdef DLIB_USE_LAPACK - matrix<typename EXP::type,0,0,MM1,L1> temp(a), vtemp; - - char jobu = 'A'; - char jobvt = 'A'; - if (u_mode == SVD_NO_U) - jobu = 'N'; - else if (u_mode == SVD_SKINNY_U) - jobu = 'S'; - if (withv == false) - jobvt = 'N'; - - int info; - if (jobu == jobvt) - { - info = lapack::gesdd(jobu, temp, q, u, vtemp); - } - else - { - info = lapack::gesvd(jobu, jobvt, temp, q, u, vtemp); - } - - // pad q with zeros if it isn't the length we want - if (q.nr() < a.nc()) - q = join_cols(q, zeros_matrix<T>(a.nc()-q.nr(),1)); - - if (withv) - v = trans(vtemp); - - return info; -#else - using std::abs; - using std::sqrt; - - T eps = std::numeric_limits<T>::epsilon(); - T tol = std::numeric_limits<T>::min()/eps; - - const long m = a.nr(); - const long n = a.nc(); - long i, j, k, l = 0, l1, iter, retval; - T c, f, g, h, s, x, y, z; - - matrix<T,qN,1,MM2> e(n,1); - q.set_size(n,1); - if (u_mode == SVD_FULL_U) - u.set_size(m,m); - else - u.set_size(m,n); - retval = 0; - - if (withv) - { - v.set_size(n,n); - } - - /* Copy 'a' to 'u' */ - for (i=0; i<m; i++) - { - for (j=0; j<n; j++) - u(i,j) = a(i,j); - } - - /* Householder's reduction to bidiagonal form. */ - g = x = 0.0; - for (i=0; i<n; i++) - { - e(i) = g; - s = 0.0; - l = i + 1; - - for (j=i; j<m; j++) - s += (u(j,i) * u(j,i)); - - if (s < tol) - g = 0.0; - else - { - f = u(i,i); - g = (f < 0) ? sqrt(s) : -sqrt(s); - h = f * g - s; - u(i,i) = f - g; - - for (j=l; j<n; j++) - { - s = 0.0; - - for (k=i; k<m; k++) - s += (u(k,i) * u(k,j)); - - f = s / h; - - for (k=i; k<m; k++) - u(k,j) += (f * u(k,i)); - } /* end j */ - } /* end s */ - - q(i) = g; - s = 0.0; - - for (j=l; j<n; j++) - s += (u(i,j) * u(i,j)); - - if (s < tol) - g = 0.0; - else - { - f = u(i,i+1); - g = (f < 0) ? sqrt(s) : -sqrt(s); - h = f * g - s; - u(i,i+1) = f - g; - - for (j=l; j<n; j++) - e(j) = u(i,j) / h; - - for (j=l; j<m; j++) - { - s = 0.0; - - for (k=l; k<n; k++) - s += (u(j,k) * u(i,k)); - - for (k=l; k<n; k++) - u(j,k) += (s * e(k)); - } /* end j */ - } /* end s */ - - y = abs(q(i)) + abs(e(i)); - if (y > x) - x = y; - } /* end i */ - - /* accumulation of right-hand transformations */ - if (withv) - { - for (i=n-1; i>=0; i--) - { - if (g != 0.0) - { - h = u(i,i+1) * g; - - for (j=l; j<n; j++) - v(j,i) = u(i,j)/h; - - for (j=l; j<n; j++) - { - s = 0.0; - - for (k=l; k<n; k++) - s += (u(i,k) * v(k,j)); - - for (k=l; k<n; k++) - v(k,j) += (s * v(k,i)); - } /* end j */ - } /* end g */ - - for (j=l; j<n; j++) - v(i,j) = v(j,i) = 0.0; - - v(i,i) = 1.0; - g = e(i); - l = i; - } /* end i */ - } /* end withv, parens added for clarity */ - - /* accumulation of left-hand transformations */ - if (u_mode != SVD_NO_U) - { - for (i=n; i<u.nr(); i++) - { - for (j=n;j<u.nc();j++) - u(i,j) = 0.0; - - if (i < u.nc()) - u(i,i) = 1.0; - } - } - - if (u_mode != SVD_NO_U) - { - for (i=n-1; i>=0; i--) - { - l = i + 1; - g = q(i); - - for (j=l; j<u.nc(); j++) - u(i,j) = 0.0; - - if (g != 0.0) - { - h = u(i,i) * g; - - for (j=l; j<u.nc(); j++) - { - s = 0.0; - - for (k=l; k<m; k++) - s += (u(k,i) * u(k,j)); - - f = s / h; - - for (k=i; k<m; k++) - u(k,j) += (f * u(k,i)); - } /* end j */ - - for (j=i; j<m; j++) - u(j,i) /= g; - } /* end g */ - else - { - for (j=i; j<m; j++) - u(j,i) = 0.0; - } - - u(i,i) += 1.0; - } /* end i*/ - } - - /* diagonalization of the bidiagonal form */ - eps *= x; - - for (k=n-1; k>=0; k--) - { - iter = 0; - -test_f_splitting: - - for (l=k; l>=0; l--) - { - if (abs(e(l)) <= eps) - goto test_f_convergence; - - if (abs(q(l-1)) <= eps) - goto cancellation; - } /* end l */ - - /* cancellation of e(l) if l > 0 */ - -cancellation: - - c = 0.0; - s = 1.0; - l1 = l - 1; - - for (i=l; i<=k; i++) - { - f = s * e(i); - e(i) *= c; - - if (abs(f) <= eps) - goto test_f_convergence; - - g = q(i); - h = q(i) = sqrt(f*f + g*g); - c = g / h; - s = -f / h; - - if (u_mode != SVD_NO_U) - { - for (j=0; j<m; j++) - { - y = u(j,l1); - z = u(j,i); - u(j,l1) = y * c + z * s; - u(j,i) = -y * s + z * c; - } /* end j */ - } - } /* end i */ - -test_f_convergence: - - z = q(k); - if (l == k) - goto convergence; - - /* shift from bottom 2x2 minor */ - iter++; - if (iter > 300) - { - retval = k; - break; - } - x = q(l); - y = q(k-1); - g = e(k-1); - h = e(k); - f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2 * h * y); - g = sqrt(f * f + 1.0); - f = ((x - z) * (x + z) + h * (y / ((f < 0)?(f - g) : (f + g)) - h)) / x; - - /* next QR transformation */ - c = s = 1.0; - - for (i=l+1; i<=k; i++) - { - g = e(i); - y = q(i); - h = s * g; - g *= c; - e(i-1) = z = sqrt(f * f + h * h); - c = f / z; - s = h / z; - f = x * c + g * s; - g = -x * s + g * c; - h = y * s; - y *= c; - - if (withv) - { - for (j=0;j<n;j++) - { - x = v(j,i-1); - z = v(j,i); - v(j,i-1) = x * c + z * s; - v(j,i) = -x * s + z * c; - } /* end j */ - } /* end withv, parens added for clarity */ - - q(i-1) = z = sqrt(f * f + h * h); - if (z != 0) - { - c = f / z; - s = h / z; - } - f = c * g + s * y; - x = -s * g + c * y; - if (u_mode != SVD_NO_U) - { - for (j=0; j<m; j++) - { - y = u(j,i-1); - z = u(j,i); - u(j,i-1) = y * c + z * s; - u(j,i) = -y * s + z * c; - } /* end j */ - } - } /* end i */ - - e(l) = 0.0; - e(k) = f; - q(k) = x; - - goto test_f_splitting; - -convergence: - - if (z < 0.0) - { - /* q(k) is made non-negative */ - q(k) = -z; - if (withv) - { - for (j=0; j<n; j++) - v(j,k) = -v(j,k); - } /* end withv, parens added for clarity */ - } /* end z */ - } /* end k */ - - return retval; -#endif - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP, - long qN, long qX, - long uM, - long vN, - typename MM1, - typename MM2, - typename MM3, - typename L1 - > - long svd2 ( - bool withu, - bool withv, - const matrix_exp<EXP>& a, - matrix<typename EXP::type,uM,uM,MM1,L1>& u, - matrix<typename EXP::type,qN,qX,MM2,L1>& q, - matrix<typename EXP::type,vN,vN,MM3,L1>& v - ) - { - const long NR = matrix_exp<EXP>::NR; - const long NC = matrix_exp<EXP>::NC; - - // make sure the output matrices have valid dimensions if they are statically dimensioned - COMPILE_TIME_ASSERT(qX == 0 || qX == 1); - COMPILE_TIME_ASSERT(NR == 0 || uM == 0 || NR == uM); - COMPILE_TIME_ASSERT(NC == 0 || vN == 0 || NC == vN); - - DLIB_ASSERT(a.nr() >= a.nc(), - "\tconst matrix_exp svd4()" - << "\n\tYou have given an invalidly sized matrix" - << "\n\ta.nr(): " << a.nr() - << "\n\ta.nc(): " << a.nc() - ); - - if (withu) - return svd4(SVD_FULL_U, withv, a,u,q,v); - else - return svd4(SVD_NO_U, withv, a,u,q,v); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - typename MM - > - void orthogonalize ( - matrix<T,NR,NC,MM,row_major_layout>& m - ) - { - // We don't really need to use this temporary, but doing it this way runs a lot - // faster. - matrix<T,NR,NC,MM,column_major_layout> temp; - qr_decomposition<matrix<T,NR,NC,MM,row_major_layout>>(m).get_q(temp); - m = temp; - } - - template < - typename T, - long NR, - long NC, - typename MM - > - void orthogonalize ( - matrix<T,NR,NC,MM,column_major_layout>& m - ) - { - qr_decomposition<matrix<T,NR,NC,MM,column_major_layout>>(m).get_q(m); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long Anr, long Anc, - typename MM, - typename L - > - void find_matrix_range ( - const matrix<T,Anr,Anc,MM,L>& A, - unsigned long l, - matrix<T,Anr,0,MM,L>& Q, - unsigned long q - ) - /*! - requires - - A.nr() >= l - ensures - - #Q.nr() == A.nr() - - #Q.nc() == l - - #Q == an orthonormal matrix whose range approximates the range of the - matrix A. - - This function implements the randomized subspace iteration defined - in the algorithm 4.4 box of the paper: - Finding Structure with Randomness: Probabilistic Algorithms for - Constructing Approximate Matrix Decompositions by Halko et al. - - q defines the number of extra subspace iterations this algorithm will - perform. Often q == 0 is fine, but performing more iterations can lead to a - more accurate approximation of the range of A if A has slowly decaying - singular values. In these cases, using a q of 1 or 2 is good. - !*/ - { - DLIB_ASSERT(A.nr() >= (long)l, "Invalid inputs were given to this function."); - Q = A*matrix_cast<T>(gaussian_randm(A.nc(), l)); - - orthogonalize(Q); - - // Do some extra iterations of the power method to make sure we get Q into the - // span of the most important singular vectors of A. - if (q != 0) - { - for (unsigned long itr = 0; itr < q; ++itr) - { - Q = trans(A)*Q; - orthogonalize(Q); - - Q = A*Q; - orthogonalize(Q); - } - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long Anr, long Anc, - long Unr, long Unc, - long Wnr, long Wnc, - long Vnr, long Vnc, - typename MM, - typename L - > - void svd_fast ( - const matrix<T,Anr,Anc,MM,L>& A, - matrix<T,Unr,Unc,MM,L>& u, - matrix<T,Wnr,Wnc,MM,L>& w, - matrix<T,Vnr,Vnc,MM,L>& v, - unsigned long l, - unsigned long q = 1 - ) - { - const unsigned long k = std::min(l, std::min<unsigned long>(A.nr(),A.nc())); - - DLIB_ASSERT(l > 0 && A.size() > 0, - "\t void svd_fast()" - << "\n\t Invalid inputs were given to this function." - << "\n\t l: " << l - << "\n\t A.size(): " << A.size() - ); - - matrix<T,Anr,0,MM,L> Q; - find_matrix_range(A, k, Q, q); - - // Compute trans(B) = trans(Q)*A. The reason we store B transposed - // is so that when we take its SVD later using svd3() it doesn't consume - // a whole lot of RAM. That is, we make sure the square matrix coming out - // of svd3() has size lxl rather than the potentially much larger nxn. - matrix<T,0,0,MM,L> B = trans(A)*Q; - svd3(B, v,w,u); - u = Q*u; - } - -// ---------------------------------------------------------------------------------------- - - template < - typename sparse_vector_type, - typename T, - typename MM, - typename L - > - void find_matrix_range ( - const std::vector<sparse_vector_type>& A, - unsigned long l, - matrix<T,0,0,MM,L>& Q, - unsigned long q - ) - /*! - requires - - A.size() >= l - ensures - - #Q.nr() == A.size() - - #Q.nc() == l - - #Q == an orthonormal matrix whose range approximates the range of the - matrix A. In this case, we interpret A as a matrix of A.size() rows, - where each row is defined by a sparse vector. - - This function implements the randomized subspace iteration defined - in the algorithm 4.4 box of the paper: - Finding Structure with Randomness: Probabilistic Algorithms for - Constructing Approximate Matrix Decompositions by Halko et al. - - q defines the number of extra subspace iterations this algorithm will - perform. Often q == 0 is fine, but performing more iterations can lead to a - more accurate approximation of the range of A if A has slowly decaying - singular values. In these cases, using a q of 1 or 2 is good. - !*/ - { - DLIB_ASSERT(A.size() >= l, "Invalid inputs were given to this function."); - Q.set_size(A.size(), l); - - // Compute Q = A*gaussian_randm() - parallel_for(0, Q.nr(), [&](long r) - { - for (long c = 0; c < Q.nc(); ++c) - { - Q(r,c) = dot(A[r], gaussian_randm(std::numeric_limits<long>::max(), 1, c)); - } - }); - - orthogonalize(Q); - - // Do some extra iterations of the power method to make sure we get Q into the - // span of the most important singular vectors of A. - if (q != 0) - { - dlib::mutex mut; - const unsigned long n = max_index_plus_one(A); - for (unsigned long itr = 0; itr < q; ++itr) - { - matrix<T,0,0,MM> Z; - // Compute Z = trans(A)*Q - parallel_for_blocked(0, A.size(), [&](long begin, long end) - { - matrix<T,0,0,MM> Zlocal(n,l); - Zlocal = 0; - for (long m = begin; m < end; ++m) - { - for (unsigned long r = 0; r < l; ++r) - { - for (auto& i : A[m]) - { - const auto c = i.first; - const auto val = i.second; - - Zlocal(c,r) += Q(m,r)*val; - } - } - } - auto_mutex lock(mut); - Z += Zlocal; - },1); - - Q.set_size(0,0); // free RAM - orthogonalize(Z); - - // Compute Q = A*Z - Q.set_size(A.size(), l); - parallel_for(0, Q.nr(), [&](long r) - { - for (long c = 0; c < Q.nc(); ++c) - { - Q(r,c) = dot(A[r], colm(Z,c)); - } - }); - - Z.set_size(0,0); // free RAM - orthogonalize(Q); - } - } - } - -// ---------------------------------------------------------------------------------------- - - namespace simpl - { - template < - typename sparse_vector_type, - typename T, - long Unr, long Unc, - long Wnr, long Wnc, - long Vnr, long Vnc, - typename MM, - typename L - > - void svd_fast ( - bool compute_u, - const std::vector<sparse_vector_type>& A, - matrix<T,Unr,Unc,MM,L>& u, - matrix<T,Wnr,Wnc,MM,L>& w, - matrix<T,Vnr,Vnc,MM,L>& v, - unsigned long l, - unsigned long q - ) - { - const long n = max_index_plus_one(A); - const unsigned long k = std::min(l, std::min<unsigned long>(A.size(),n)); - - DLIB_ASSERT(l > 0 && A.size() > 0 && n > 0, - "\t void svd_fast()" - << "\n\t Invalid inputs were given to this function." - << "\n\t l: " << l - << "\n\t n (i.e. max_index_plus_one(A)): " << n - << "\n\t A.size(): " << A.size() - ); - - matrix<T,0,0,MM,L> Q; - find_matrix_range(A, k, Q, q); - - // Compute trans(B) = trans(Q)*A. The reason we store B transposed - // is so that when we take its SVD later using svd3() it doesn't consume - // a whole lot of RAM. That is, we make sure the square matrix coming out - // of svd3() has size lxl rather than the potentially much larger nxn. - matrix<T,0,0,MM> B; - dlib::mutex mut; - parallel_for_blocked(0, A.size(), [&](long begin, long end) - { - matrix<T,0,0,MM> Blocal(n,k); - Blocal = 0; - for (long m = begin; m < end; ++m) - { - for (unsigned long r = 0; r < k; ++r) - { - for (auto& i : A[m]) - { - const auto c = i.first; - const auto val = i.second; - - Blocal(c,r) += Q(m,r)*val; - } - } - } - auto_mutex lock(mut); - B += Blocal; - },1); - - svd3(B, v,w,u); - if (compute_u) - u = Q*u; - } - } - - template < - typename sparse_vector_type, - typename T, - long Unr, long Unc, - long Wnr, long Wnc, - long Vnr, long Vnc, - typename MM, - typename L - > - void svd_fast ( - const std::vector<sparse_vector_type>& A, - matrix<T,Unr,Unc,MM,L>& u, - matrix<T,Wnr,Wnc,MM,L>& w, - matrix<T,Vnr,Vnc,MM,L>& v, - unsigned long l, - unsigned long q = 1 - ) - { - simpl::svd_fast(true, A,u,w,v,l,q); - } - - template < - typename sparse_vector_type, - typename T, - long Wnr, long Wnc, - long Vnr, long Vnc, - typename MM, - typename L - > - void svd_fast ( - const std::vector<sparse_vector_type>& A, - matrix<T,Wnr,Wnc,MM,L>& w, - matrix<T,Vnr,Vnc,MM,L>& v, - unsigned long l, - unsigned long q = 1 - ) - { - matrix<T,0,0,MM,L> u; - simpl::svd_fast(false, A,u,w,v,l,q); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template < - typename EXP, - long N - > - struct inv_helper - { - static const typename matrix_exp<EXP>::matrix_type inv ( - const matrix_exp<EXP>& m - ) - { - // you can't invert a non-square matrix - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NR == matrix_exp<EXP>::NC || - matrix_exp<EXP>::NR == 0 || - matrix_exp<EXP>::NC == 0); - DLIB_ASSERT(m.nr() == m.nc(), - "\tconst matrix_exp::type inv(const matrix_exp& m)" - << "\n\tYou can only apply inv() to a square matrix" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - typedef typename matrix_exp<EXP>::type type; - - lu_decomposition<EXP> lu(m); - return lu.solve(identity_matrix<type>(m.nr())); - } - }; - - template < - typename EXP - > - struct inv_helper<EXP,1> - { - static const typename matrix_exp<EXP>::matrix_type inv ( - const matrix_exp<EXP>& m - ) - { - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NR == matrix_exp<EXP>::NC); - typedef typename matrix_exp<EXP>::type type; - - matrix<type, 1, 1, typename EXP::mem_manager_type> a; - // if m is invertible - if (m(0) != 0) - a(0) = 1/m(0); - else - a(0) = 1; - return a; - } - }; - - template < - typename EXP - > - struct inv_helper<EXP,2> - { - static const typename matrix_exp<EXP>::matrix_type inv ( - const matrix_exp<EXP>& m - ) - { - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NR == matrix_exp<EXP>::NC); - typedef typename matrix_exp<EXP>::type type; - - matrix<type, 2, 2, typename EXP::mem_manager_type> a; - type d = det(m); - if (d != 0) - { - d = static_cast<type>(1.0/d); - a(0,0) = m(1,1)*d; - a(0,1) = m(0,1)*-d; - a(1,0) = m(1,0)*-d; - a(1,1) = m(0,0)*d; - } - else - { - // Matrix isn't invertible so just return the identity matrix. - a = identity_matrix<type,2>(); - } - return a; - } - }; - - template < - typename EXP - > - struct inv_helper<EXP,3> - { - static const typename matrix_exp<EXP>::matrix_type inv ( - const matrix_exp<EXP>& m - ) - { - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NR == matrix_exp<EXP>::NC); - typedef typename matrix_exp<EXP>::type type; - - matrix<type, 3, 3, typename EXP::mem_manager_type> ret; - type de = det(m); - if (de != 0) - { - de = static_cast<type>(1.0/de); - const type a = m(0,0); - const type b = m(0,1); - const type c = m(0,2); - const type d = m(1,0); - const type e = m(1,1); - const type f = m(1,2); - const type g = m(2,0); - const type h = m(2,1); - const type i = m(2,2); - - ret(0,0) = (e*i - f*h)*de; - ret(1,0) = (f*g - d*i)*de; - ret(2,0) = (d*h - e*g)*de; - - ret(0,1) = (c*h - b*i)*de; - ret(1,1) = (a*i - c*g)*de; - ret(2,1) = (b*g - a*h)*de; - - ret(0,2) = (b*f - c*e)*de; - ret(1,2) = (c*d - a*f)*de; - ret(2,2) = (a*e - b*d)*de; - } - else - { - ret = identity_matrix<type,3>(); - } - - return ret; - } - }; - - template < - typename EXP - > - struct inv_helper<EXP,4> - { - static const typename matrix_exp<EXP>::matrix_type inv ( - const matrix_exp<EXP>& m - ) - { - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NR == matrix_exp<EXP>::NC); - typedef typename matrix_exp<EXP>::type type; - - matrix<type, 4, 4, typename EXP::mem_manager_type> ret; - type de = det(m); - if (de != 0) - { - de = static_cast<type>(1.0/de); - ret(0,0) = det(removerc<0,0>(m)); - ret(0,1) = -det(removerc<0,1>(m)); - ret(0,2) = det(removerc<0,2>(m)); - ret(0,3) = -det(removerc<0,3>(m)); - - ret(1,0) = -det(removerc<1,0>(m)); - ret(1,1) = det(removerc<1,1>(m)); - ret(1,2) = -det(removerc<1,2>(m)); - ret(1,3) = det(removerc<1,3>(m)); - - ret(2,0) = det(removerc<2,0>(m)); - ret(2,1) = -det(removerc<2,1>(m)); - ret(2,2) = det(removerc<2,2>(m)); - ret(2,3) = -det(removerc<2,3>(m)); - - ret(3,0) = -det(removerc<3,0>(m)); - ret(3,1) = det(removerc<3,1>(m)); - ret(3,2) = -det(removerc<3,2>(m)); - ret(3,3) = det(removerc<3,3>(m)); - - return trans(ret)*de; - } - else - { - return identity_matrix<type,4>(); - } - } - }; - - template < - typename EXP - > - inline const typename matrix_exp<EXP>::matrix_type inv ( - const matrix_exp<EXP>& m - ) { return inv_helper<EXP,matrix_exp<EXP>::NR>::inv(m); } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_diag_inv - { - template <typename EXP> - op_diag_inv( const matrix_exp<EXP>& m_) : m(m_){} - - - const static long cost = 1; - const static long NR = ((M::NC!=0)&&(M::NR!=0))? (tmax<M::NR,M::NC>::value) : (0); - const static long NC = NR; - typedef typename M::type type; - typedef const type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - - - // hold the matrix by value - const matrix<type,NR,1,mem_manager_type,layout_type> m; - - const_ret_type apply ( long r, long c) const - { - if (r==c) - return m(r); - else - return 0; - } - - long nr () const { return m.size(); } - long nc () const { return m.size(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_diag_op<op_diag_inv<EXP> > inv ( - const matrix_diag_exp<EXP>& m - ) - { - typedef op_diag_inv<EXP> op; - return matrix_diag_op<op>(op(reciprocal(diag(m)))); - } - - template < - typename EXP - > - const matrix_diag_op<op_diag_inv<EXP> > pinv ( - const matrix_diag_exp<EXP>& m - ) - { - typedef op_diag_inv<EXP> op; - return matrix_diag_op<op>(op(reciprocal(diag(m)))); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const matrix_diag_op<op_diag_inv<EXP> > pinv ( - const matrix_diag_exp<EXP>& m, - double tol - ) - { - DLIB_ASSERT(tol >= 0, - "\tconst matrix_exp::type pinv(const matrix_exp& m)" - << "\n\t tol can't be negative" - << "\n\t tol: "<<tol - ); - typedef op_diag_inv<EXP> op; - return matrix_diag_op<op>(op(reciprocal(round_zeros(diag(m),tol)))); - } - -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - const typename matrix_exp<EXP>::matrix_type inv_lower_triangular ( - const matrix_exp<EXP>& A - ) - { - DLIB_ASSERT(A.nr() == A.nc(), - "\tconst matrix inv_lower_triangular(const matrix_exp& A)" - << "\n\tA must be a square matrix" - << "\n\tA.nr(): " << A.nr() - << "\n\tA.nc(): " << A.nc() - ); - - typedef typename matrix_exp<EXP>::matrix_type matrix_type; - - matrix_type m(A); - - for(long c = 0; c < m.nc(); ++c) - { - if( m(c,c) == 0 ) - { - // there isn't an inverse so just give up - return m; - } - - // compute m(c,c) - m(c,c) = 1/m(c,c); - - // compute the values in column c that are below m(c,c). - // We do this by just doing the same thing we do for upper triangular - // matrices because we take the transpose of m which turns m into an - // upper triangular matrix. - for(long r = 0; r < c; ++r) - { - const long n = c-r; - m(c,r) = -m(c,c)*subm(trans(m),r,r,1,n)*subm(trans(m),r,c,n,1); - } - } - - return m; - - } - -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - const typename matrix_exp<EXP>::matrix_type inv_upper_triangular ( - const matrix_exp<EXP>& A - ) - { - DLIB_ASSERT(A.nr() == A.nc(), - "\tconst matrix inv_upper_triangular(const matrix_exp& A)" - << "\n\tA must be a square matrix" - << "\n\tA.nr(): " << A.nr() - << "\n\tA.nc(): " << A.nc() - ); - - typedef typename matrix_exp<EXP>::matrix_type matrix_type; - - matrix_type m(A); - - for(long c = 0; c < m.nc(); ++c) - { - if( m(c,c) == 0 ) - { - // there isn't an inverse so just give up - return m; - } - - // compute m(c,c) - m(c,c) = 1/m(c,c); - - // compute the values in column c that are above m(c,c) - for(long r = 0; r < c; ++r) - { - const long n = c-r; - m(r,c) = -m(c,c)*subm(m,r,r,1,n)*subm(m,r,c,n,1); - } - } - - return m; - - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - inline const typename matrix_exp<EXP>::matrix_type chol ( - const matrix_exp<EXP>& A - ) - { - DLIB_ASSERT(A.nr() == A.nc(), - "\tconst matrix chol(const matrix_exp& A)" - << "\n\tYou can only apply the chol to a square matrix" - << "\n\tA.nr(): " << A.nr() - << "\n\tA.nc(): " << A.nc() - ); - typename matrix_exp<EXP>::matrix_type L(A.nr(),A.nc()); - - typedef typename EXP::type T; - - bool banded = false; - long bandwidth = 0; - - if (A.nr() > 4) // Only test for banded matrix if matrix is big enough - { - // Detect if matrix is banded and, if so, matrix bandwidth - banded = true; - for (long r = 0; r < A.nr(); ++r) - for (long c = (r + bandwidth + 1); c < A.nc(); ++c) - if (A(r, c) != 0) - { - bandwidth = c - r; - if (bandwidth > A.nr() / 2) - { - banded = false; - goto escape_banded_detection; - } - } - } -escape_banded_detection: - - if (banded) - { - // Store in compact form - use column major for LAPACK - matrix<T,0,0,default_memory_manager,column_major_layout> B(bandwidth + 1, A.nc()); - set_all_elements(B, 0); - - for (long r = 0; r < A.nr(); ++r) - for (long c = r; c < std::min(r + bandwidth + 1, A.nc()); ++c) - B(c - r, r) = A(r, c); - -#ifdef DLIB_USE_LAPACK - - lapack::pbtrf('L', B); - -#else - - // Peform compact Cholesky - for (long k = 0; k < A.nr(); ++k) - { - long last = std::min(k + bandwidth, A.nr() - 1) - k; - for (long j = 1; j <= last; ++j) - { - long i = k + j; - for (long c = 0; c <= (last - j); ++c) - B(c, i) -= B(j, k) / B(0, k) * B(c + j, k); - } - T norm = std::sqrt(B(0, k)); - for (long i = 0; i <= bandwidth; ++i) - B(i, k) /= norm; - } - for (long c = A.nc() - bandwidth + 1; c < A.nc(); ++c) - B(bandwidth, c) = 0; - -#endif - - // Unpack lower triangular area - set_all_elements(L, 0); - for (long c = 0; c < A.nc(); ++c) - for (long i = 0; i <= bandwidth; ++i) - { - long ind = c + i; - if (ind < A.nc()) - L(ind, c) = B(i, c); - } - - return L; - } - -#ifdef DLIB_USE_LAPACK - // Only call LAPACK if the matrix is big enough. Otherwise, - // our own code is faster, especially for statically dimensioned - // matrices. - if (A.nr() > 4) - { - L = A; - lapack::potrf('L', L); - // mask out upper triangular area - return lowerm(L); - } -#endif - set_all_elements(L,0); - - // do nothing if the matrix is empty - if (A.size() == 0) - return L; - - const T eps = std::numeric_limits<T>::epsilon(); - - // compute the upper left corner - if (A(0,0) > 0) - L(0,0) = std::sqrt(A(0,0)); - - // compute the first column - for (long r = 1; r < A.nr(); ++r) - { - // if (L(0,0) > 0) - if (L(0,0) > eps*std::abs(A(r,0))) - L(r,0) = A(r,0)/L(0,0); - else - return L; - } - - // now compute all the other columns - for (long c = 1; c < A.nc(); ++c) - { - // compute the diagonal element - T temp = A(c,c); - for (long i = 0; i < c; ++i) - { - temp -= L(c,i)*L(c,i); - } - if (temp > 0) - L(c,c) = std::sqrt(temp); - - // compute the non diagonal elements - for (long r = c+1; r < A.nr(); ++r) - { - temp = A(r,c); - for (long i = 0; i < c; ++i) - { - temp -= L(r,i)*L(c,i); - } - - // if (L(c,c) > 0) - if (L(c,c) > eps*std::abs(temp)) - L(r,c) = temp/L(c,c); - else - return L; - } - } - - return L; - - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP, - long uNR, - long uNC, - long wN, - long vN, - long wX, - typename MM1, - typename MM2, - typename MM3, - typename L1 - > - inline void svd3 ( - const matrix_exp<EXP>& m, - matrix<typename matrix_exp<EXP>::type, uNR, uNC,MM1,L1>& u, - matrix<typename matrix_exp<EXP>::type, wN, wX,MM2,L1>& w, - matrix<typename matrix_exp<EXP>::type, vN, vN,MM3,L1>& v - ) - { - typedef typename matrix_exp<EXP>::type T; - const long NR = matrix_exp<EXP>::NR; - const long NC = matrix_exp<EXP>::NC; - - // make sure the output matrices have valid dimensions if they are statically dimensioned - COMPILE_TIME_ASSERT(NR == 0 || uNR == 0 || NR == uNR); - COMPILE_TIME_ASSERT(NC == 0 || uNC == 0 || NC == uNC); - COMPILE_TIME_ASSERT(NC == 0 || wN == 0 || NC == wN); - COMPILE_TIME_ASSERT(NC == 0 || vN == 0 || NC == vN); - COMPILE_TIME_ASSERT(wX == 0 || wX == 1); - -#ifdef DLIB_USE_LAPACK - // use LAPACK but only if it isn't a really small matrix we are taking the SVD of. - if (NR*NC == 0 || NR*NC > 3*3) - { - matrix<typename matrix_exp<EXP>::type, uNR, uNC,MM1,L1> temp(m); - lapack::gesvd('S','A', temp, w, u, v); - v = trans(v); - // if u isn't the size we want then pad it (and v) with zeros - if (u.nc() < m.nc()) - { - w = join_cols(w, zeros_matrix<T>(m.nc()-u.nc(),1)); - u = join_rows(u, zeros_matrix<T>(u.nr(), m.nc()-u.nc())); - } - return; - } -#endif - if (m.nr() >= m.nc()) - { - svd4(SVD_SKINNY_U,true, m, u,w,v); - } - else - { - svd4(SVD_FULL_U,true, trans(m), v,w,u); - - // if u isn't the size we want then pad it (and v) with zeros - if (u.nc() < m.nc()) - { - w = join_cols(w, zeros_matrix<T>(m.nc()-u.nc(),1)); - u = join_rows(u, zeros_matrix<T>(u.nr(), m.nc()-u.nc())); - } - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const matrix<typename EXP::type,EXP::NC,EXP::NR,typename EXP::mem_manager_type> pinv_helper ( - const matrix_exp<EXP>& m, - double tol - ) - /*! - ensures - - computes the results of pinv(m) but does so using a method that is fastest - when m.nc() <= m.nr(). So if m.nc() > m.nr() then it is best to use - trans(pinv_helper(trans(m))) to compute pinv(m). - !*/ - { - typename matrix_exp<EXP>::matrix_type u; - typedef typename EXP::mem_manager_type MM1; - typedef typename EXP::layout_type layout_type; - matrix<typename EXP::type, EXP::NC, EXP::NC,MM1, layout_type > v; - - typedef typename matrix_exp<EXP>::type T; - - matrix<T,matrix_exp<EXP>::NC,1,MM1, layout_type> w; - - svd3(m, u,w,v); - - const double machine_eps = std::numeric_limits<typename EXP::type>::epsilon(); - // compute a reasonable epsilon below which we round to zero before doing the - // reciprocal. Unless a non-zero tol is given then we just use tol*max(w). - const double eps = (tol!=0) ? tol*max(w) : machine_eps*std::max(m.nr(),m.nc())*max(w); - - // now compute the pseudoinverse - return tmp(scale_columns(v,reciprocal(round_zeros(w,eps))))*trans(u); - } - - template < - typename EXP - > - const matrix<typename EXP::type,EXP::NC,EXP::NR,typename EXP::mem_manager_type> pinv ( - const matrix_exp<EXP>& m, - double tol = 0 - ) - { - DLIB_ASSERT(tol >= 0, - "\tconst matrix_exp::type pinv(const matrix_exp& m)" - << "\n\t tol can't be negative" - << "\n\t tol: "<<tol - ); - // if m has more columns then rows then it is more efficient to - // compute the pseudo-inverse of its transpose (given the way I'm doing it below). - if (m.nc() > m.nr()) - return trans(pinv_helper(trans(m),tol)); - else - return pinv_helper(m,tol); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP, - long uNR, - long uNC, - long wN, - long vN, - typename MM1, - typename MM2, - typename MM3, - typename L1 - > - inline void svd ( - const matrix_exp<EXP>& m, - matrix<typename matrix_exp<EXP>::type, uNR, uNC,MM1,L1>& u, - matrix<typename matrix_exp<EXP>::type, wN, wN,MM2,L1>& w, - matrix<typename matrix_exp<EXP>::type, vN, vN,MM3,L1>& v - ) - { - typedef typename matrix_exp<EXP>::type T; - const long NR = matrix_exp<EXP>::NR; - const long NC = matrix_exp<EXP>::NC; - - // make sure the output matrices have valid dimensions if they are statically dimensioned - COMPILE_TIME_ASSERT(NR == 0 || uNR == 0 || NR == uNR); - COMPILE_TIME_ASSERT(NC == 0 || uNC == 0 || NC == uNC); - COMPILE_TIME_ASSERT(NC == 0 || wN == 0 || NC == wN); - COMPILE_TIME_ASSERT(NC == 0 || vN == 0 || NC == vN); - - matrix<T,matrix_exp<EXP>::NC,1,MM1, L1> W; - svd3(m,u,W,v); - w = diagm(W); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const typename matrix_exp<EXP>::type trace ( - const matrix_exp<EXP>& m - ) - { - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NR == matrix_exp<EXP>::NC || - matrix_exp<EXP>::NR == 0 || - matrix_exp<EXP>::NC == 0 - ); - DLIB_ASSERT(m.nr() == m.nc(), - "\tconst matrix_exp::type trace(const matrix_exp& m)" - << "\n\tYou can only apply trace() to a square matrix" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - return sum(diag(m)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP, - long N = EXP::NR - > - struct det_helper - { - static const typename matrix_exp<EXP>::type det ( - const matrix_exp<EXP>& m - ) - { - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NR == matrix_exp<EXP>::NC || - matrix_exp<EXP>::NR == 0 || - matrix_exp<EXP>::NC == 0 - ); - DLIB_ASSERT(m.nr() == m.nc(), - "\tconst matrix_exp::type det(const matrix_exp& m)" - << "\n\tYou can only apply det() to a square matrix" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - - return lu_decomposition<EXP>(m).det(); - } - }; - - template < - typename EXP - > - struct det_helper<EXP,1> - { - static const typename matrix_exp<EXP>::type det ( - const matrix_exp<EXP>& m - ) - { - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NR == matrix_exp<EXP>::NC); - - return m(0); - } - }; - - template < - typename EXP - > - struct det_helper<EXP,2> - { - static const typename matrix_exp<EXP>::type det ( - const matrix_exp<EXP>& m - ) - { - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NR == matrix_exp<EXP>::NC); - - return m(0,0)*m(1,1) - m(0,1)*m(1,0); - } - }; - - template < - typename EXP - > - struct det_helper<EXP,3> - { - static const typename matrix_exp<EXP>::type det ( - const matrix_exp<EXP>& m - ) - { - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NR == matrix_exp<EXP>::NC); - typedef typename matrix_exp<EXP>::type type; - - type temp = m(0,0)*(m(1,1)*m(2,2) - m(1,2)*m(2,1)) - - m(0,1)*(m(1,0)*m(2,2) - m(1,2)*m(2,0)) + - m(0,2)*(m(1,0)*m(2,1) - m(1,1)*m(2,0)); - return temp; - } - }; - - - template < - typename EXP - > - inline const typename matrix_exp<EXP>::type det ( - const matrix_exp<EXP>& m - ) { return det_helper<EXP>::det(m); } - - - template < - typename EXP - > - struct det_helper<EXP,4> - { - static const typename matrix_exp<EXP>::type det ( - const matrix_exp<EXP>& m - ) - { - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NR == matrix_exp<EXP>::NC); - typedef typename matrix_exp<EXP>::type type; - - type temp = m(0,0)*(dlib::det(removerc<0,0>(m))) - - m(0,1)*(dlib::det(removerc<0,1>(m))) + - m(0,2)*(dlib::det(removerc<0,2>(m))) - - m(0,3)*(dlib::det(removerc<0,3>(m))); - return temp; - } - }; - -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - const matrix<typename EXP::type, EXP::NR, 1, typename EXP::mem_manager_type, typename EXP::layout_type> real_eigenvalues ( - const matrix_exp<EXP>& m - ) - { - // You can only use this function with matrices that contain float or double values - COMPILE_TIME_ASSERT((is_same_type<typename EXP::type, float>::value || - is_same_type<typename EXP::type, double>::value)); - - DLIB_ASSERT(m.nr() == m.nc(), - "\tconst matrix real_eigenvalues()" - << "\n\tYou have given an invalidly sized matrix" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - - if (m.nr() == 2) - { - typedef typename EXP::type T; - const T m00 = m(0,0); - const T m01 = m(0,1); - const T m10 = m(1,0); - const T m11 = m(1,1); - - const T b = -(m00 + m11); - const T c = m00*m11 - m01*m10; - matrix<T,EXP::NR,1, typename EXP::mem_manager_type, typename EXP::layout_type> v(2); - - - T disc = b*b - 4*c; - if (disc >= 0) - disc = std::sqrt(disc); - else - disc = 0; - - v(0) = (-b + disc)/2; - v(1) = (-b - disc)/2; - return v; - } - else - { - // Call .ref() so that the symmetric matrix overload can take effect if m - // has the appropriate type. - return eigenvalue_decomposition<EXP>(m.ref()).get_real_eigenvalues(); - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - dlib::vector<double,2> max_point_interpolated ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(m.size() > 0, - "\tdlib::vector<double,2> point max_point_interpolated(const matrix_exp& m)" - << "\n\tm can't be empty" - << "\n\tm.size(): " << m.size() - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - const point p = max_point(m); - - // If this is a column vector then just do interpolation along a line. - if (m.nc()==1) - { - const long pos = p.y(); - if (0 < pos && pos+1 < m.nr()) - { - double v1 = dlib::impl::magnitude(m(pos-1)); - double v2 = dlib::impl::magnitude(m(pos)); - double v3 = dlib::impl::magnitude(m(pos+1)); - double y = lagrange_poly_min_extrap(pos-1,pos,pos+1, -v1, -v2, -v3); - return vector<double,2>(0,y); - } - } - // If this is a row vector then just do interpolation along a line. - if (m.nr()==1) - { - const long pos = p.x(); - if (0 < pos && pos+1 < m.nc()) - { - double v1 = dlib::impl::magnitude(m(pos-1)); - double v2 = dlib::impl::magnitude(m(pos)); - double v3 = dlib::impl::magnitude(m(pos+1)); - double x = lagrange_poly_min_extrap(pos-1,pos,pos+1, -v1, -v2, -v3); - return vector<double,2>(x,0); - } - } - - - // If it's on the border then just return the regular max point. - if (shrink_rect(get_rect(m),1).contains(p) == false) - return p; - - //matrix<double> A(9,6); - //matrix<double,0,1> G(9); - - matrix<double,9,1> pix; - long i = 0; - for (long r = -1; r <= +1; ++r) - { - for (long c = -1; c <= +1; ++c) - { - pix(i) = dlib::impl::magnitude(m(p.y()+r,p.y()+c)); - /* - A(i,0) = c*c; - A(i,1) = c*r; - A(i,2) = r*r; - A(i,3) = c; - A(i,4) = r; - A(i,5) = 1; - G(i) = std::exp(-1*(r*r+c*c)/2.0); // Use a gaussian windowing function around p. - */ - ++i; - } - } - - // This bit of code is how we generated the derivative_filters matrix below. - //A = diagm(G)*A; - //std::cout << std::setprecision(20) << inv(trans(A)*A)*trans(A)*diagm(G) << std::endl; exit(1); - - const double m10 = 0.10597077880854270659; - const double m21 = 0.21194155761708535768; - const double m28 = 0.28805844238291455905; - const double m57 = 0.57611688476582878504; - // So this derivative_filters finds the parameters of the quadratic surface that best fits - // the 3x3 region around p. Then we find the maximizer of that surface within that - // small region and return that as the maximum location. - const double derivative_filters[] = { - // xx - m10,-m21,m10, - m28,-m57,m28, - m10,-m21,m10, - - // xy - 0.25 ,0,-0.25, - 0 ,0, 0, - -0.25,0,0.25, - - // yy - m10, m28, m10, - -m21,-m57,-m21, - m10, m28, m10, - - // x - -m10,0,m10, - -m28,0,m28, - -m10,0,m10, - - // y - -m10,-m28,-m10, - 0, 0, 0, - m10, m28, m10 - }; - const matrix<double,5,9> filt(derivative_filters); - // Now w contains the parameters of the quadratic surface - const matrix<double,5,1> w = filt*pix; - - - // Now newton step to the max point on the surface - matrix<double,2,2> H; - matrix<double,2,1> g; - H = 2*w(0), w(1), - w(1), 2*w(2); - g = w(3), - w(4); - const dlib::vector<double,2> delta = -inv(H)*g; - - // if delta isn't in an ascent direction then just use the normal max point. - if (dot(delta, g) < 0) - return p; - else - return vector<double,2>(p)+dlib::clamp(delta, -1, 1); - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_LA_FUNCTS_ - - diff --git a/ml/dlib/dlib/matrix/matrix_la_abstract.h b/ml/dlib/dlib/matrix/matrix_la_abstract.h deleted file mode 100644 index df6a5fd33..000000000 --- a/ml/dlib/dlib/matrix/matrix_la_abstract.h +++ /dev/null @@ -1,1005 +0,0 @@ -// Copyright (C) 2009 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_MATRIx_LA_FUNCTS_ABSTRACT_ -#ifdef DLIB_MATRIx_LA_FUNCTS_ABSTRACT_ - -#include "matrix_abstract.h" -#include <complex> - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Global linear algebra functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - const matrix_exp::matrix_type inv ( - const matrix_exp& m - ); - /*! - requires - - m is a square matrix - ensures - - returns the inverse of m - (Note that if m is singular or so close to being singular that there - is a lot of numerical error then the returned matrix will be bogus. - You can check by seeing if m*inv(m) is an identity matrix) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix pinv ( - const matrix_exp& m, - double tol = 0 - ); - /*! - requires - - tol >= 0 - ensures - - returns the Moore-Penrose pseudoinverse of m. - - The returned matrix has m.nc() rows and m.nr() columns. - - if (tol == 0) then - - singular values less than max(m.nr(),m.nc()) times the machine epsilon - times the largest singular value are ignored. - - else - - singular values less than tol*max(singular value in m) are ignored. - !*/ - -// ---------------------------------------------------------------------------------------- - - void svd ( - const matrix_exp& m, - matrix<matrix_exp::type>& u, - matrix<matrix_exp::type>& w, - matrix<matrix_exp::type>& v - ); - /*! - ensures - - computes the singular value decomposition of m - - m == #u*#w*trans(#v) - - trans(#u)*#u == identity matrix - - trans(#v)*#v == identity matrix - - diag(#w) == the singular values of the matrix m in no - particular order. All non-diagonal elements of #w are - set to 0. - - #u.nr() == m.nr() - - #u.nc() == m.nc() - - #w.nr() == m.nc() - - #w.nc() == m.nc() - - #v.nr() == m.nc() - - #v.nc() == m.nc() - - if DLIB_USE_LAPACK is #defined then the xGESVD routine - from LAPACK is used to compute the SVD. - !*/ - -// ---------------------------------------------------------------------------------------- - - long svd2 ( - bool withu, - bool withv, - const matrix_exp& m, - matrix<matrix_exp::type>& u, - matrix<matrix_exp::type>& w, - matrix<matrix_exp::type>& v - ); - /*! - requires - - m.nr() >= m.nc() - ensures - - computes the singular value decomposition of matrix m - - m == subm(#u,get_rect(m))*diagm(#w)*trans(#v) - - trans(#u)*#u == identity matrix - - trans(#v)*#v == identity matrix - - #w == the singular values of the matrix m in no - particular order. - - #u.nr() == m.nr() - - #u.nc() == m.nr() - - #w.nr() == m.nc() - - #w.nc() == 1 - - #v.nr() == m.nc() - - #v.nc() == m.nc() - - if (widthu == false) then - - ignore the above regarding #u, it isn't computed and its - output state is undefined. - - if (widthv == false) then - - ignore the above regarding #v, it isn't computed and its - output state is undefined. - - returns an error code of 0, if no errors and 'k' if we fail to - converge at the 'kth' singular value. - - if (DLIB_USE_LAPACK is #defined) then - - if (withu == withv) then - - the xGESDD routine from LAPACK is used to compute the SVD. - - else - - the xGESVD routine from LAPACK is used to compute the SVD. - !*/ - -// ---------------------------------------------------------------------------------------- - - void svd3 ( - const matrix_exp& m, - matrix<matrix_exp::type>& u, - matrix<matrix_exp::type>& w, - matrix<matrix_exp::type>& v - ); - /*! - ensures - - computes the singular value decomposition of m - - m == #u*diagm(#w)*trans(#v) - - trans(#u)*#u == identity matrix - - trans(#v)*#v == identity matrix - - #w == the singular values of the matrix m in no - particular order. - - #u.nr() == m.nr() - - #u.nc() == m.nc() - - #w.nr() == m.nc() - - #w.nc() == 1 - - #v.nr() == m.nc() - - #v.nc() == m.nc() - - if DLIB_USE_LAPACK is #defined then the xGESVD routine - from LAPACK is used to compute the SVD. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - void svd_fast ( - const matrix<T>& A, - matrix<T>& u, - matrix<T>& w, - matrix<T>& v, - unsigned long l, - unsigned long q = 1 - ); - /*! - requires - - l > 0 - - A.size() > 0 - (i.e. A can't be an empty matrix) - ensures - - computes the singular value decomposition of A. - - Lets define some constants we use to document the behavior of svd_fast(): - - Let m = A.nr() - - Let n = A.nc() - - Let k = min(l, min(m,n)) - - Therefore, A represents an m by n matrix and svd_fast() is designed - to find a rank-k representation of it. - - if (the rank of A is <= k) then - - A == #u*diagm(#w)*trans(#v) - - else - - A is approximated by #u*diagm(#w)*trans(#v) - (i.e. In this case A can't be represented with a rank-k matrix, so the - matrix you get by trying to reconstruct A from the output of the SVD is - not exactly the same.) - - trans(#u)*#u == identity matrix - - trans(#v)*#v == identity matrix - - #w == the top k singular values of the matrix A (in no particular order). - - #u.nr() == m - - #u.nc() == k - - #w.nr() == k - - #w.nc() == 1 - - #v.nr() == n - - #v.nc() == k - - This function implements the randomized subspace iteration defined in the - algorithm 4.4 and 5.1 boxes of the paper: - Finding Structure with Randomness: Probabilistic Algorithms for - Constructing Approximate Matrix Decompositions by Halko et al. - Therefore, it is very fast and suitable for use with very large matrices. - Moreover, q is the number of subspace iterations performed. Larger - values of q might increase the accuracy of the solution but the default - value should be good for many problems. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename sparse_vector_type, - typename T - > - void svd_fast ( - const std::vector<sparse_vector_type>& A, - matrix<T>& u, - matrix<T>& w, - matrix<T>& v, - unsigned long l, - unsigned long q = 1 - ); - /*! - requires - - A contains a set of sparse vectors. See dlib/svm/sparse_vector_abstract.h - for a definition of what constitutes a sparse vector. - - l > 0 - - max_index_plus_one(A) > 0 - (i.e. A can't be an empty matrix) - ensures - - computes the singular value decomposition of A. In this case, we interpret A - as a matrix of A.size() rows, where each row is defined by a sparse vector. - - Lets define some constants we use to document the behavior of svd_fast(): - - Let m = A.size() - - Let n = max_index_plus_one(A) - - Let k = min(l, min(m,n)) - - Therefore, A represents an m by n matrix and svd_fast() is designed - to find a rank-k representation of it. - - if (the rank of A is <= k) then - - A == #u*diagm(#w)*trans(#v) - - else - - A is approximated by #u*diagm(#w)*trans(#v) - (i.e. In this case A can't be represented with a rank-k matrix, so the - matrix you get by trying to reconstruct A from the output of the SVD is - not exactly the same.) - - trans(#u)*#u == identity matrix - - trans(#v)*#v == identity matrix - - #w == the top k singular values of the matrix A (in no particular order). - - #u.nr() == m - - #u.nc() == k - - #w.nr() == k - - #w.nc() == 1 - - #v.nr() == n - - #v.nc() == k - - This function implements the randomized subspace iteration defined in the - algorithm 4.4 and 5.1 boxes of the paper: - Finding Structure with Randomness: Probabilistic Algorithms for - Constructing Approximate Matrix Decompositions by Halko et al. - Therefore, it is very fast and suitable for use with very large matrices. - Moreover, q is the number of subspace iterations performed. Larger - values of q might increase the accuracy of the solution but the default - value should be good for many problems. - !*/ - - template < - typename sparse_vector_type, - typename T - > - void svd_fast ( - const std::vector<sparse_vector_type>& A, - matrix<T>& w, - matrix<T>& v, - unsigned long l, - unsigned long q = 1 - ); - /*! - This function is identical to the above svd_fast() except it doesn't compute u. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - typename MM, - typename L - > - void orthogonalize ( - matrix<T,NR,NC,MM,L>& m - ); - /*! - requires - - m.nr() >= m.nc() - - m.size() > 0 - ensures - - #m == an orthogonal matrix with the same dimensions as m. In particular, - the columns of #m have the same span as the columns of m. - - trans(#m)*#m == identity matrix - - This function is just shorthand for computing the QR decomposition of m - and then storing the Q factor into #m. - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix real_eigenvalues ( - const matrix_exp& m - ); - /*! - requires - - m.nr() == m.nc() - - matrix_exp::type == float or double - ensures - - returns a matrix E such that: - - E.nr() == m.nr() - - E.nc() == 1 - - E contains the real part of all eigenvalues of the matrix m. - (note that the eigenvalues are not sorted) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::type det ( - const matrix_exp& m - ); - /*! - requires - - m is a square matrix - ensures - - returns the determinant of m - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::type trace ( - const matrix_exp& m - ); - /*! - requires - - m is a square matrix - ensures - - returns the trace of m - (i.e. returns sum(diag(m))) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::matrix_type chol ( - const matrix_exp& A - ); - /*! - requires - - A is a square matrix - ensures - - if (A has a Cholesky Decomposition) then - - returns the decomposition of A. That is, returns a matrix L - such that L*trans(L) == A. L will also be lower triangular. - - else - - returns a matrix with the same dimensions as A but it - will have a bogus value. I.e. it won't be a decomposition. - In this case the algorithm returns a partial decomposition. - - You can tell when chol fails by looking at the lower right - element of the returned matrix. If it is 0 then it means - A does not have a cholesky decomposition. - - - If DLIB_USE_LAPACK is defined then the LAPACK routine xPOTRF - is used to compute the cholesky decomposition. - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::matrix_type inv_lower_triangular ( - const matrix_exp& A - ); - /*! - requires - - A is a square matrix - ensures - - if (A is lower triangular) then - - returns the inverse of A. - - else - - returns a matrix with the same dimensions as A but it - will have a bogus value. I.e. it won't be an inverse. - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::matrix_type inv_upper_triangular ( - const matrix_exp& A - ); - /*! - requires - - A is a square matrix - ensures - - if (A is upper triangular) then - - returns the inverse of A. - - else - - returns a matrix with the same dimensions as A but it - will have a bogus value. I.e. it won't be an inverse. - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Matrix decomposition classes -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template < - typename matrix_exp_type - > - class lu_decomposition - { - /*! - REQUIREMENTS ON matrix_exp_type - must be some kind of matrix expression as defined in the - dlib/matrix/matrix_abstract.h file. (e.g. a dlib::matrix object) - The matrix type must also contain float or double values. - - WHAT THIS OBJECT REPRESENTS - This object represents something that can compute an LU - decomposition of a real valued matrix. That is, for any - matrix A it computes matrices L, U, and a pivot vector P such - that rowm(A,P) == L*U. - - The LU decomposition with pivoting always exists, even if the matrix is - singular, so the constructor will never fail. The primary use of the - LU decomposition is in the solution of square systems of simultaneous - linear equations. This will fail if is_singular() returns true (or - if A is very nearly singular). - - If DLIB_USE_LAPACK is defined then the LAPACK routine xGETRF - is used to compute the LU decomposition. - !*/ - - public: - - const static long NR = matrix_exp_type::NR; - const static long NC = matrix_exp_type::NC; - typedef typename matrix_exp_type::type type; - typedef typename matrix_exp_type::mem_manager_type mem_manager_type; - typedef typename matrix_exp_type::layout_type layout_type; - - typedef matrix<type,0,0,mem_manager_type,layout_type> matrix_type; - typedef matrix<type,NR,1,mem_manager_type,layout_type> column_vector_type; - typedef matrix<long,NR,1,mem_manager_type,layout_type> pivot_column_vector_type; - - template <typename EXP> - lu_decomposition ( - const matrix_exp<EXP> &A - ); - /*! - requires - - EXP::type == lu_decomposition::type - - A.size() > 0 - ensures - - #nr() == A.nr() - - #nc() == A.nc() - - #is_square() == (A.nr() == A.nc()) - - computes the LU factorization of the given A matrix. - !*/ - - bool is_square ( - ) const; - /*! - ensures - - if (the input A matrix was a square matrix) then - - returns true - - else - - returns false - !*/ - - bool is_singular ( - ) const; - /*! - requires - - is_square() == true - ensures - - if (the input A matrix is singular) then - - returns true - - else - - returns false - !*/ - - long nr( - ) const; - /*! - ensures - - returns the number of rows in the input matrix - !*/ - - long nc( - ) const; - /*! - ensures - - returns the number of columns in the input matrix - !*/ - - const matrix_type get_l ( - ) const; - /*! - ensures - - returns the lower triangular L factor of the LU factorization. - - L.nr() == nr() - - L.nc() == min(nr(),nc()) - !*/ - - const matrix_type get_u ( - ) const; - /*! - ensures - - returns the upper triangular U factor of the LU factorization. - - U.nr() == min(nr(),nc()) - - U.nc() == nc() - !*/ - - const pivot_column_vector_type& get_pivot ( - ) const; - /*! - ensures - - returns the pivot permutation vector. That is, - if A is the input matrix then this function - returns a vector P such that: - - rowm(A,P) == get_l()*get_u() - - P.nr() == A.nr() - !*/ - - type det ( - ) const; - /*! - requires - - is_square() == true - ensures - - computes and returns the determinant of the input - matrix using LU factors. - !*/ - - template <typename EXP> - const matrix_type solve ( - const matrix_exp<EXP> &B - ) const; - /*! - requires - - EXP::type == lu_decomposition::type - - is_square() == true - - B.nr() == nr() - ensures - - Let A denote the input matrix to this class's constructor. - Then this function solves A*X == B for X and returns X. - - Note that if A is singular (or very close to singular) then - the X returned by this function won't fit A*X == B very well (if at all). - !*/ - - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename matrix_exp_type - > - class cholesky_decomposition - { - /*! - REQUIREMENTS ON matrix_exp_type - must be some kind of matrix expression as defined in the - dlib/matrix/matrix_abstract.h file. (e.g. a dlib::matrix object) - The matrix type must also contain float or double values. - - WHAT THIS OBJECT REPRESENTS - This object represents something that can compute a cholesky - decomposition of a real valued matrix. That is, for any - symmetric, positive definite matrix A, it computes a lower - triangular matrix L such that A == L*trans(L). - - If the matrix is not symmetric or positive definite, the function - computes only a partial decomposition. This can be tested with - the is_spd() flag. - - If DLIB_USE_LAPACK is defined then the LAPACK routine xPOTRF - is used to compute the cholesky decomposition. - !*/ - - public: - - const static long NR = matrix_exp_type::NR; - const static long NC = matrix_exp_type::NC; - typedef typename matrix_exp_type::type type; - typedef typename matrix_exp_type::mem_manager_type mem_manager_type; - typedef typename matrix_exp_type::layout_type layout_type; - - typedef typename matrix_exp_type::matrix_type matrix_type; - typedef matrix<type,NR,1,mem_manager_type,layout_type> column_vector_type; - - template <typename EXP> - cholesky_decomposition( - const matrix_exp<EXP>& A - ); - /*! - requires - - EXP::type == cholesky_decomposition::type - - A.size() > 0 - - A.nr() == A.nc() - (i.e. A must be a square matrix) - ensures - - if (A is symmetric positive-definite) then - - #is_spd() == true - - Constructs a lower triangular matrix L, such that L*trans(L) == A. - and #get_l() == L - - else - - #is_spd() == false - !*/ - - bool is_spd( - ) const; - /*! - ensures - - if (the input matrix was symmetric positive-definite) then - - returns true - - else - - returns false - !*/ - - const matrix_type& get_l( - ) const; - /*! - ensures - - returns the lower triangular factor, L, such that L*trans(L) == A - (where A is the input matrix to this class's constructor) - - Note that if A is not symmetric positive definite or positive semi-definite - then the equation L*trans(L) == A won't hold. - !*/ - - template <typename EXP> - const matrix solve ( - const matrix_exp<EXP>& B - ) const; - /*! - requires - - EXP::type == cholesky_decomposition::type - - B.nr() == get_l().nr() - (i.e. the number of rows in B must match the number of rows in the - input matrix A) - ensures - - Let A denote the input matrix to this class's constructor. Then - this function solves A*X = B for X and returns X. - - Note that if is_spd() == false or A was really close to being - non-SPD then the solver will fail to find an accurate solution. - !*/ - - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename matrix_exp_type - > - class qr_decomposition - { - /*! - REQUIREMENTS ON matrix_exp_type - must be some kind of matrix expression as defined in the - dlib/matrix/matrix_abstract.h file. (e.g. a dlib::matrix object) - The matrix type must also contain float or double values. - - WHAT THIS OBJECT REPRESENTS - This object represents something that can compute a classical - QR decomposition of an m-by-n real valued matrix A with m >= n. - - The QR decomposition is an m-by-n orthogonal matrix Q and an - n-by-n upper triangular matrix R so that A == Q*R. The QR decomposition - always exists, even if the matrix does not have full rank, so the - constructor will never fail. The primary use of the QR decomposition - is in the least squares solution of non-square systems of simultaneous - linear equations. This will fail if is_full_rank() returns false or - A is very nearly not full rank. - - The Q and R factors can be retrieved via the get_q() and get_r() - methods. Furthermore, a solve() method is provided to find the - least squares solution of Ax=b using the QR factors. - - If DLIB_USE_LAPACK is #defined then the xGEQRF routine - from LAPACK is used to compute the QR decomposition. - !*/ - - public: - - const static long NR = matrix_exp_type::NR; - const static long NC = matrix_exp_type::NC; - typedef typename matrix_exp_type::type type; - typedef typename matrix_exp_type::mem_manager_type mem_manager_type; - typedef typename matrix_exp_type::layout_type layout_type; - - typedef matrix<type,0,0,mem_manager_type,layout_type> matrix_type; - - template <typename EXP> - qr_decomposition( - const matrix_exp<EXP>& A - ); - /*! - requires - - EXP::type == qr_decomposition::type - - A.nr() >= A.nc() - - A.size() > 0 - ensures - - #nr() == A.nr() - - #nc() == A.nc() - - computes the QR decomposition of the given A matrix. - !*/ - - bool is_full_rank( - ) const; - /*! - ensures - - if (the input A matrix had full rank) then - - returns true - - else - - returns false - !*/ - - long nr( - ) const; - /*! - ensures - - returns the number of rows in the input matrix - !*/ - - long nc( - ) const; - /*! - ensures - - returns the number of columns in the input matrix - !*/ - - const matrix_type get_r ( - ) const; - /*! - ensures - - returns a matrix R such that: - - R is the upper triangular factor, R, of the QR factorization - - get_q()*R == input matrix A - - R.nr() == nc() - - R.nc() == nc() - !*/ - - const matrix_type get_q ( - ) const; - /*! - ensures - - returns a matrix Q such that: - - Q is the economy-sized orthogonal factor Q from the QR - factorization. - - trans(Q)*Q == identity matrix - - Q*get_r() == input matrix A - - Q.nr() == nr() - - Q.nc() == nc() - !*/ - - void get_q ( - matrix_type& Q - ) const; - /*! - ensures - - #Q == get_q() - - This function exists to allow a user to get the Q matrix without the - overhead of returning a matrix by value. - !*/ - - template <typename EXP> - const matrix_type solve ( - const matrix_exp<EXP>& B - ) const; - /*! - requires - - EXP::type == qr_decomposition::type - - B.nr() == nr() - ensures - - Let A denote the input matrix to this class's constructor. - Then this function finds the least squares solution to the equation A*X = B - and returns X. X has the following properties: - - X is the matrix that minimizes the two norm of A*X-B. That is, it - minimizes sum(squared(A*X - B)). - - X.nr() == nc() - - X.nc() == B.nc() - - Note that this function will fail to output a good solution if is_full_rank() == false - or the A matrix is close to not being full rank. - !*/ - - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename matrix_exp_type - > - class eigenvalue_decomposition - { - /*! - REQUIREMENTS ON matrix_exp_type - must be some kind of matrix expression as defined in the - dlib/matrix/matrix_abstract.h file. (e.g. a dlib::matrix object) - The matrix type must also contain float or double values. - - WHAT THIS OBJECT REPRESENTS - This object represents something that can compute an eigenvalue - decomposition of a real valued matrix. So it gives - you the set of eigenvalues and eigenvectors for a matrix. - - Let A denote the input matrix to this object's constructor. Then - what this object does is it finds two matrices, D and V, such that - - A*V == V*D - Where V is a square matrix that contains all the eigenvectors - of the A matrix (each column of V is an eigenvector) and - D is a diagonal matrix containing the eigenvalues of A. - - - It is important to note that if A is symmetric or non-symmetric you - get somewhat different results. If A is a symmetric matrix (i.e. A == trans(A)) - then: - - All the eigenvalues and eigenvectors of A are real numbers. - - Because of this there isn't really any point in using the - part of this class's interface that returns complex matrices. - All you need are the get_real_eigenvalues() and - get_pseudo_v() functions. - - V*trans(V) should be equal to the identity matrix. That is, all the - eigenvectors in V should be orthonormal. - - So A == V*D*trans(V) - - If DLIB_USE_LAPACK is #defined then this object uses the xSYEVR LAPACK - routine. - - On the other hand, if A is not symmetric then: - - Some of the eigenvalues and eigenvectors might be complex numbers. - - An eigenvalue is complex if and only if its corresponding eigenvector - is complex. So you can check for this case by just checking - get_imag_eigenvalues() to see if any values are non-zero. You don't - have to check the V matrix as well. - - V*trans(V) won't be equal to the identity matrix but it is usually - invertible. So A == V*D*inv(V) is usually a valid statement but - A == V*D*trans(V) won't be. - - If DLIB_USE_LAPACK is #defined then this object uses the xGEEV LAPACK - routine. - !*/ - - public: - - const static long NR = matrix_exp_type::NR; - const static long NC = matrix_exp_type::NC; - typedef typename matrix_exp_type::type type; - typedef typename matrix_exp_type::mem_manager_type mem_manager_type; - typedef typename matrix_exp_type::layout_type layout_type; - - typedef typename matrix_exp_type::matrix_type matrix_type; - typedef matrix<type,NR,1,mem_manager_type,layout_type> column_vector_type; - - typedef matrix<std::complex<type>,0,0,mem_manager_type,layout_type> complex_matrix_type; - typedef matrix<std::complex<type>,NR,1,mem_manager_type,layout_type> complex_column_vector_type; - - - template <typename EXP> - eigenvalue_decomposition( - const matrix_exp<EXP>& A - ); - /*! - requires - - A.nr() == A.nc() - - A.size() > 0 - - EXP::type == eigenvalue_decomposition::type - ensures - - #dim() == A.nr() - - computes the eigenvalue decomposition of A. - - #get_eigenvalues() == the eigenvalues of A - - #get_v() == all the eigenvectors of A - !*/ - - template <typename EXP> - eigenvalue_decomposition( - const matrix_op<op_make_symmetric<EXP> >& A - ); - /*! - requires - - A.nr() == A.nc() - - A.size() > 0 - - EXP::type == eigenvalue_decomposition::type - ensures - - #dim() == A.nr() - - computes the eigenvalue decomposition of the symmetric matrix A. Does so - using a method optimized for symmetric matrices. - - #get_eigenvalues() == the eigenvalues of A - - #get_v() == all the eigenvectors of A - - moreover, since A is symmetric there won't be any imaginary eigenvalues. So - we will have: - - #get_imag_eigenvalues() == 0 - - #get_real_eigenvalues() == the eigenvalues of A - - #get_pseudo_v() == all the eigenvectors of A - - diagm(#get_real_eigenvalues()) == #get_pseudo_d() - - Note that the symmetric matrix operator is created by the - dlib::make_symmetric() function. This function simply reflects - the lower triangular part of a square matrix into the upper triangular - part to create a symmetric matrix. It can also be used to denote that a - matrix is already symmetric using the C++ type system. - !*/ - - long dim ( - ) const; - /*! - ensures - - dim() == the number of rows/columns in the input matrix A - !*/ - - const complex_column_vector_type get_eigenvalues ( - ) const; - /*! - ensures - - returns diag(get_d()). That is, returns a - vector that contains the eigenvalues of the input - matrix. - - the returned vector has dim() rows - - the eigenvalues are not sorted in any particular way - !*/ - - const column_vector_type& get_real_eigenvalues ( - ) const; - /*! - ensures - - returns the real parts of the eigenvalues. That is, - returns real(get_eigenvalues()) - - the returned vector has dim() rows - - the eigenvalues are not sorted in any particular way - !*/ - - const column_vector_type& get_imag_eigenvalues ( - ) const; - /*! - ensures - - returns the imaginary parts of the eigenvalues. That is, - returns imag(get_eigenvalues()) - - the returned vector has dim() rows - - the eigenvalues are not sorted in any particular way - !*/ - - const complex_matrix_type get_v ( - ) const; - /*! - ensures - - returns the eigenvector matrix V that is - dim() rows by dim() columns - - Each column in V is one of the eigenvectors of the input - matrix - !*/ - - const complex_matrix_type get_d ( - ) const; - /*! - ensures - - returns a matrix D such that: - - D.nr() == dim() - - D.nc() == dim() - - diag(D) == get_eigenvalues() - (i.e. the diagonal of D contains all the eigenvalues in the input matrix) - - all off diagonal elements of D are set to 0 - !*/ - - const matrix_type& get_pseudo_v ( - ) const; - /*! - ensures - - returns a matrix that is dim() rows by dim() columns - - Let A denote the input matrix given to this object's constructor. - - if (A has any imaginary eigenvalues) then - - returns the pseudo-eigenvector matrix V - - The matrix V returned by this function is structured such that: - - A*V == V*get_pseudo_d() - - else - - returns the eigenvector matrix V with A's eigenvectors as - the columns of V - - A*V == V*diagm(get_real_eigenvalues()) - !*/ - - const matrix_type get_pseudo_d ( - ) const; - /*! - ensures - - The returned matrix is dim() rows by dim() columns - - Computes and returns the block diagonal eigenvalue matrix. - If the original matrix A is not symmetric, then the eigenvalue - matrix D is block diagonal with the real eigenvalues in 1-by-1 - blocks and any complex eigenvalues, - a + i*b, in 2-by-2 blocks, (a, b; -b, a). That is, if the complex - eigenvalues look like - - u + iv . . . . . - . u - iv . . . . - . . a + ib . . . - . . . a - ib . . - . . . . x . - . . . . . y - - Then D looks like - - u v . . . . - -v u . . . . - . . a b . . - . . -b a . . - . . . . x . - . . . . . y - - This keeps V (The V you get from get_pseudo_v()) a real matrix in both - symmetric and non-symmetric cases, and A*V = V*D. - - the eigenvalues are not sorted in any particular way - !*/ - - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_LA_FUNCTS_ABSTRACT_ - diff --git a/ml/dlib/dlib/matrix/matrix_lu.h b/ml/dlib/dlib/matrix/matrix_lu.h deleted file mode 100644 index 3e49cd653..000000000 --- a/ml/dlib/dlib/matrix/matrix_lu.h +++ /dev/null @@ -1,361 +0,0 @@ -// Copyright (C) 2009 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -// This code was adapted from code from the JAMA part of NIST's TNT library. -// See: http://math.nist.gov/tnt/ -#ifndef DLIB_MATRIX_LU_DECOMPOSITION_H -#define DLIB_MATRIX_LU_DECOMPOSITION_H - -#include "matrix.h" -#include "matrix_utilities.h" -#include "matrix_subexp.h" -#include "matrix_trsm.h" -#include <algorithm> - -#ifdef DLIB_USE_LAPACK -#include "lapack/getrf.h" -#endif - - -namespace dlib -{ - - template < - typename matrix_exp_type - > - class lu_decomposition - { - public: - - const static long NR = matrix_exp_type::NR; - const static long NC = matrix_exp_type::NC; - typedef typename matrix_exp_type::type type; - typedef typename matrix_exp_type::mem_manager_type mem_manager_type; - typedef typename matrix_exp_type::layout_type layout_type; - - typedef matrix<type,0,0,mem_manager_type,layout_type> matrix_type; - typedef matrix<type,NR,1,mem_manager_type,layout_type> column_vector_type; - typedef matrix<long,NR,1,mem_manager_type,layout_type> pivot_column_vector_type; - - // You have supplied an invalid type of matrix_exp_type. You have - // to use this object with matrices that contain float or double type data. - COMPILE_TIME_ASSERT((is_same_type<float, type>::value || - is_same_type<double, type>::value )); - - template <typename EXP> - lu_decomposition ( - const matrix_exp<EXP> &A - ); - - bool is_square ( - ) const; - - bool is_singular ( - ) const; - - long nr( - ) const; - - long nc( - ) const; - - const matrix_type get_l ( - ) const; - - const matrix_type get_u ( - ) const; - - const pivot_column_vector_type& get_pivot ( - ) const; - - type det ( - ) const; - - template <typename EXP> - const matrix_type solve ( - const matrix_exp<EXP> &B - ) const; - - private: - - /* Array for internal storage of decomposition. */ - matrix<type,0,0,mem_manager_type,column_major_layout> LU; - long m, n, pivsign; - pivot_column_vector_type piv; - - - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Public member functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - template <typename EXP> - lu_decomposition<matrix_exp_type>:: - lu_decomposition ( - const matrix_exp<EXP>& A - ) : - LU(A), - m(A.nr()), - n(A.nc()) - { - using namespace std; - using std::abs; - - COMPILE_TIME_ASSERT((is_same_type<type, typename EXP::type>::value)); - - // make sure requires clause is not broken - DLIB_ASSERT(A.size() > 0, - "\tlu_decomposition::lu_decomposition(A)" - << "\n\tInvalid inputs were given to this function" - << "\n\tA.size(): " << A.size() - << "\n\tthis: " << this - ); - -#ifdef DLIB_USE_LAPACK - matrix<lapack::integer,0,1,mem_manager_type,layout_type> piv_temp; - lapack::getrf(LU, piv_temp); - - pivsign = 1; - - // Turn the piv_temp vector into a more useful form. This way we will have the identity - // rowm(A,piv) == L*U. The permutation vector that comes out of LAPACK is somewhat - // different. - piv = trans(range(0,m-1)); - for (long i = 0; i < piv_temp.size(); ++i) - { - // -1 because FORTRAN is indexed starting with 1 instead of 0 - if (piv(piv_temp(i)-1) != piv(i)) - { - std::swap(piv(i), piv(piv_temp(i)-1)); - pivsign = -pivsign; - } - } - -#else - - // Use a "left-looking", dot-product, Crout/Doolittle algorithm. - - - piv = trans(range(0,m-1)); - pivsign = 1; - - column_vector_type LUcolj(m); - - // Outer loop. - for (long j = 0; j < n; j++) - { - - // Make a copy of the j-th column to localize references. - LUcolj = colm(LU,j); - - // Apply previous transformations. - for (long i = 0; i < m; i++) - { - // Most of the time is spent in the following dot product. - const long kmax = std::min(i,j); - type s; - if (kmax > 0) - s = rowm(LU,i, kmax)*colm(LUcolj,0,kmax); - else - s = 0; - - LU(i,j) = LUcolj(i) -= s; - } - - // Find pivot and exchange if necessary. - long p = j; - for (long i = j+1; i < m; i++) - { - if (abs(LUcolj(i)) > abs(LUcolj(p))) - { - p = i; - } - } - if (p != j) - { - long k=0; - for (k = 0; k < n; k++) - { - type t = LU(p,k); - LU(p,k) = LU(j,k); - LU(j,k) = t; - } - k = piv(p); - piv(p) = piv(j); - piv(j) = k; - pivsign = -pivsign; - } - - // Compute multipliers. - if ((j < m) && (LU(j,j) != 0.0)) - { - for (long i = j+1; i < m; i++) - { - LU(i,j) /= LU(j,j); - } - } - } - -#endif - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - bool lu_decomposition<matrix_exp_type>:: - is_square ( - ) const - { - return m == n; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - long lu_decomposition<matrix_exp_type>:: - nr ( - ) const - { - return m; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - long lu_decomposition<matrix_exp_type>:: - nc ( - ) const - { - return n; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - bool lu_decomposition<matrix_exp_type>:: - is_singular ( - ) const - { - /* Is the matrix singular? - if upper triangular factor U (and hence A) is singular, false otherwise. - */ - // make sure requires clause is not broken - DLIB_ASSERT(is_square() == true, - "\tbool lu_decomposition::is_singular()" - << "\n\tYou can only use this on square matrices" - << "\n\tthis: " << this - ); - - type max_val, min_val; - find_min_and_max (abs(diag(LU)), min_val, max_val); - type eps = max_val; - if (eps != 0) - eps *= std::sqrt(std::numeric_limits<type>::epsilon())/10; - else - eps = 1; // there is no max so just use 1 - - return min_val < eps; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename lu_decomposition<matrix_exp_type>::matrix_type lu_decomposition<matrix_exp_type>:: - get_l ( - ) const - { - if (LU.nr() >= LU.nc()) - return lowerm(LU,1.0); - else - return lowerm(subm(LU,0,0,m,m), 1.0); - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename lu_decomposition<matrix_exp_type>::matrix_type lu_decomposition<matrix_exp_type>:: - get_u ( - ) const - { - if (LU.nr() >= LU.nc()) - return upperm(subm(LU,0,0,n,n)); - else - return upperm(LU); - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename lu_decomposition<matrix_exp_type>::pivot_column_vector_type& lu_decomposition<matrix_exp_type>:: - get_pivot ( - ) const - { - return piv; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - typename lu_decomposition<matrix_exp_type>::type lu_decomposition<matrix_exp_type>:: - det ( - ) const - { - // make sure requires clause is not broken - DLIB_ASSERT(is_square() == true, - "\ttype lu_decomposition::det()" - << "\n\tYou can only use this on square matrices" - << "\n\tthis: " << this - ); - - // Check if it is singular and if it is just return 0. - // We want to do this because a prod() operation can easily - // overcome a single diagonal element that is effectively 0 when - // LU is a big enough matrix. - if (is_singular()) - return 0; - - return prod(diag(LU))*static_cast<type>(pivsign); - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - template <typename EXP> - const typename lu_decomposition<matrix_exp_type>::matrix_type lu_decomposition<matrix_exp_type>:: - solve ( - const matrix_exp<EXP> &B - ) const - { - COMPILE_TIME_ASSERT((is_same_type<type, typename EXP::type>::value)); - - // make sure requires clause is not broken - DLIB_ASSERT(is_square() == true && B.nr() == nr(), - "\ttype lu_decomposition::solve()" - << "\n\tInvalid arguments to this function" - << "\n\tis_square(): " << (is_square()? "true":"false" ) - << "\n\tB.nr(): " << B.nr() - << "\n\tnr(): " << nr() - << "\n\tthis: " << this - ); - - // Copy right hand side with pivoting - matrix<type,0,0,mem_manager_type,column_major_layout> X(rowm(B, piv)); - - using namespace blas_bindings; - // Solve L*Y = B(piv,:) - triangular_solver(CblasLeft, CblasLower, CblasNoTrans, CblasUnit, LU, X); - // Solve U*X = Y; - triangular_solver(CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, LU, X); - return X; - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIX_LU_DECOMPOSITION_H - - diff --git a/ml/dlib/dlib/matrix/matrix_mat.h b/ml/dlib/dlib/matrix/matrix_mat.h deleted file mode 100644 index 803d7d999..000000000 --- a/ml/dlib/dlib/matrix/matrix_mat.h +++ /dev/null @@ -1,733 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_MAT_Hh_ -#define DLIB_MATRIx_MAT_Hh_ - -#include "matrix_mat_abstract.h" -#include "../stl_checked.h" -#include <vector> -#include "matrix_op.h" -#include "../array2d.h" -#include "../array.h" -#include "../image_processing/generic_image.h" - - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const matrix_exp<EXP>& mat ( - const matrix_exp<EXP>& m - ) - { - return m; - } - -// ---------------------------------------------------------------------------------------- - - template <typename image_type, typename pixel_type> - struct op_image_to_mat : does_not_alias - { - op_image_to_mat( const image_type& img) : imgview(img){} - - const_image_view<image_type> imgview; - - const static long cost = 1; - const static long NR = 0; - const static long NC = 0; - typedef pixel_type type; - typedef const pixel_type& const_ret_type; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - - const_ret_type apply (long r, long c ) const { return imgview[r][c]; } - - long nr () const { return imgview.nr(); } - long nc () const { return imgview.nc(); } - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename image_type - > // The reason we disable this if it is a matrix is because this matrix_op claims - // to not alias any matrix. But obviously that would be a problem if we let it - // take a matrix. - const typename disable_if<is_matrix<image_type>,matrix_op<op_image_to_mat<image_type, typename image_traits<image_type>::pixel_type> > >::type mat ( - const image_type& img - ) - { - typedef op_image_to_mat<image_type, typename image_traits<image_type>::pixel_type> op; - return matrix_op<op>(op(img)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename image_type> - struct op_image_view_to_mat : does_not_alias - { - op_image_view_to_mat( const image_view<image_type>& img) : imgview(img){} - - typedef typename image_traits<image_type>::pixel_type pixel_type; - - const image_view<image_type>& imgview; - - const static long cost = 1; - const static long NR = 0; - const static long NC = 0; - typedef pixel_type type; - typedef const pixel_type& const_ret_type; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - - const_ret_type apply (long r, long c ) const { return imgview[r][c]; } - - long nr () const { return imgview.nr(); } - long nc () const { return imgview.nc(); } - }; - - template < - typename image_type - > - const matrix_op<op_image_view_to_mat<image_type> > mat ( - const image_view<image_type>& img - ) - { - typedef op_image_view_to_mat<image_type> op; - return matrix_op<op>(op(img)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename image_type> - struct op_const_image_view_to_mat : does_not_alias - { - op_const_image_view_to_mat( const const_image_view<image_type>& img) : imgview(img){} - - typedef typename image_traits<image_type>::pixel_type pixel_type; - - const const_image_view<image_type>& imgview; - - const static long cost = 1; - const static long NR = 0; - const static long NC = 0; - typedef pixel_type type; - typedef const pixel_type& const_ret_type; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - - const_ret_type apply (long r, long c ) const { return imgview[r][c]; } - - long nr () const { return imgview.nr(); } - long nc () const { return imgview.nc(); } - }; - - template < - typename image_type - > - const matrix_op<op_const_image_view_to_mat<image_type> > mat ( - const const_image_view<image_type>& img - ) - { - typedef op_const_image_view_to_mat<image_type> op; - return matrix_op<op>(op(img)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename T> - struct op_array_to_mat : does_not_alias - { - op_array_to_mat( const T& vect_) : vect(vect_){} - - const T& vect; - - const static long cost = 1; - const static long NR = 0; - const static long NC = 1; - typedef typename T::type type; - typedef const typename T::type& const_ret_type; - typedef typename T::mem_manager_type mem_manager_type; - typedef row_major_layout layout_type; - - const_ret_type apply (long r, long ) const { return vect[r]; } - - long nr () const { return vect.size(); } - long nc () const { return 1; } - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - typename MM - > - const matrix_op<op_array_to_mat<array<T,MM> > > mat ( - const array<T,MM>& m - ) - { - typedef op_array_to_mat<array<T,MM> > op; - return matrix_op<op>(op(m)); - } - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - template <typename U> - struct not_bool { typedef U type; }; - template <> - struct not_bool<const bool&> { typedef bool type; }; - } - - template <typename T> - struct op_std_vect_to_mat : does_not_alias - { - op_std_vect_to_mat( const T& vect_) : vect(vect_){} - - const T& vect; - - const static long cost = 1; - const static long NR = 0; - const static long NC = 1; - typedef typename T::value_type type; - // Since std::vector returns a proxy for bool types we need to make sure we don't - // return an element by reference if it is a bool type. - typedef typename impl::not_bool<const typename T::value_type&>::type const_ret_type; - - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - - const_ret_type apply (long r, long ) const { return vect[r]; } - - long nr () const { return vect.size(); } - long nc () const { return 1; } - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename value_type, - typename alloc - > - const matrix_op<op_std_vect_to_mat<std::vector<value_type,alloc> > > mat ( - const std::vector<value_type,alloc>& vector - ) - { - typedef op_std_vect_to_mat<std::vector<value_type,alloc> > op; - return matrix_op<op>(op(vector)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename value_type, - typename alloc - > - const matrix_op<op_std_vect_to_mat<std_vector_c<value_type,alloc> > > mat ( - const std_vector_c<value_type,alloc>& vector - ) - { - typedef op_std_vect_to_mat<std_vector_c<value_type,alloc> > op; - return matrix_op<op>(op(vector)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename T> - struct op_pointer_to_mat; - - template <typename T> - struct op_pointer_to_col_vect - { - op_pointer_to_col_vect( - const T* ptr_, - const long size_ - ) : ptr(ptr_), size(size_){} - - const T* ptr; - const long size; - - const static long cost = 1; - const static long NR = 0; - const static long NC = 1; - typedef T type; - typedef const T& const_ret_type; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - - const_ret_type apply (long r, long ) const { return ptr[r]; } - - long nr () const { return size; } - long nc () const { return 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& ) const { return false; } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& ) const { return false; } - - template <long num_rows, long num_cols, typename mem_manager, typename layout> - bool aliases ( - const matrix_exp<matrix<T,num_rows,num_cols, mem_manager,layout> >& item - ) const - { - if (item.size() == 0) - return false; - else - return (ptr == &item(0,0)); - } - - inline bool aliases ( - const matrix_exp<matrix_op<op_pointer_to_mat<T> > >& item - ) const; - - bool aliases ( - const matrix_exp<matrix_op<op_pointer_to_col_vect<T> > >& item - ) const - { - return item.ref().op.ptr == ptr; - } - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_op<op_pointer_to_col_vect<T> > mat ( - const T* ptr, - long nr - ) - { - DLIB_ASSERT(nr >= 0 , - "\tconst matrix_exp mat(ptr, nr)" - << "\n\t nr must be >= 0" - << "\n\t nr: " << nr - ); - typedef op_pointer_to_col_vect<T> op; - return matrix_op<op>(op(ptr, nr)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename T> - struct op_pointer_to_mat - { - op_pointer_to_mat( - const T* ptr_, - const long nr_, - const long nc_ - ) : ptr(ptr_), rows(nr_), cols(nc_), stride(nc_){} - - op_pointer_to_mat( - const T* ptr_, - const long nr_, - const long nc_, - const long stride_ - ) : ptr(ptr_), rows(nr_), cols(nc_), stride(stride_){} - - const T* ptr; - const long rows; - const long cols; - const long stride; - - const static long cost = 1; - const static long NR = 0; - const static long NC = 0; - typedef T type; - typedef const T& const_ret_type; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - - const_ret_type apply (long r, long c) const { return ptr[r*stride + c]; } - - long nr () const { return rows; } - long nc () const { return cols; } - - template <typename U> bool aliases ( const matrix_exp<U>& ) const { return false; } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& ) const { return false; } - - template <long num_rows, long num_cols, typename mem_manager, typename layout> - bool aliases ( - const matrix_exp<matrix<T,num_rows,num_cols, mem_manager,layout> >& item - ) const - { - if (item.size() == 0) - return false; - else - return (ptr == &item(0,0)); - } - - bool aliases ( - const matrix_exp<matrix_op<op_pointer_to_mat<T> > >& item - ) const - { - return item.ref().op.ptr == ptr; - } - - bool aliases ( - const matrix_exp<matrix_op<op_pointer_to_col_vect<T> > >& item - ) const - { - return item.ref().op.ptr == ptr; - } - }; - - template <typename T> - bool op_pointer_to_col_vect<T>:: - aliases ( - const matrix_exp<matrix_op<op_pointer_to_mat<T> > >& item - ) const - { - return item.ref().op.ptr == ptr; - } - - template <typename T, long NR, long NC, typename MM, typename L> - bool matrix<T,NR,NC,MM,L>::aliases ( - const matrix_exp<matrix_op<op_pointer_to_mat<T> > >& item - ) const - { - if (size() != 0) - return item.ref().op.ptr == &data(0,0); - else - return false; - } - - template <typename T, long NR, long NC, typename MM, typename L> - bool matrix<T,NR,NC,MM,L>::aliases ( - const matrix_exp<matrix_op<op_pointer_to_col_vect<T> > >& item - ) const - { - if (size() != 0) - return item.ref().op.ptr == &data(0,0); - else - return false; - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_op<op_pointer_to_mat<T> > mat ( - const T* ptr, - long nr, - long nc - ) - { - DLIB_ASSERT(nr >= 0 && nc >= 0 , - "\tconst matrix_exp mat(ptr, nr, nc)" - << "\n\t nr and nc must be >= 0" - << "\n\t nr: " << nr - << "\n\t nc: " << nc - ); - typedef op_pointer_to_mat<T> op; - return matrix_op<op>(op(ptr,nr,nc)); - } - - template < - typename T - > - const matrix_op<op_pointer_to_mat<T> > mat ( - const T* ptr, - long nr, - long nc, - long stride - ) - { - DLIB_ASSERT(nr >= 0 && nc >= 0 && stride > 0 , - "\tconst matrix_exp mat(ptr, nr, nc, stride)" - << "\n\t nr and nc must be >= 0 while stride > 0" - << "\n\t nr: " << nr - << "\n\t nc: " << nc - << "\n\t stride: " << stride - ); - typedef op_pointer_to_mat<T> op; - return matrix_op<op>(op(ptr,nr,nc,stride)); - } - -// ---------------------------------------------------------------------------------------- - -} - -namespace arma -{ - template <typename T> class Mat; -} -namespace dlib -{ - template <typename T> - struct op_arma_Mat_to_mat : does_not_alias - { - op_arma_Mat_to_mat( const T& array_) : array(array_){} - - const T& array; - - const static long cost = 1; - const static long NR = 0; - const static long NC = 0; - typedef typename T::elem_type type; - typedef typename T::elem_type const_ret_type; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - - const_ret_type apply (long r, long c ) const { return array(r,c); } - - long nr () const { return array.n_rows; } - long nc () const { return array.n_cols; } - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_op<op_arma_Mat_to_mat< ::arma::Mat<T> > > mat ( - const ::arma::Mat<T>& array - ) - { - typedef op_arma_Mat_to_mat< ::arma::Mat<T> > op; - return matrix_op<op>(op(array)); - } -} - -namespace Eigen -{ - template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> - class Matrix; -} - -namespace dlib -{ - template <typename T, int _Rows, int _Cols> - struct op_eigen_Matrix_to_mat : does_not_alias - { - op_eigen_Matrix_to_mat( const T& array_) : m(array_){} - - const T& m; - - const static long cost = 1; - const static long NR = (_Rows > 0) ? _Rows : 0; - const static long NC = (_Cols > 0) ? _Cols : 0; - typedef typename T::Scalar type; - typedef typename T::Scalar const_ret_type; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - - const_ret_type apply (long r, long c ) const { return m(r,c); } - - long nr () const { return m.rows(); } - long nc () const { return m.cols(); } - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols - > - const matrix_op<op_eigen_Matrix_to_mat< ::Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>,_Rows,_Cols > > mat ( - const ::Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>& m - ) - { - typedef op_eigen_Matrix_to_mat< ::Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>,_Rows,_Cols > op; - return matrix_op<op>(op(m)); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// DEPRECATED FUNCTIONS -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - -// vector_to_matrix(), array_to_matrix(), pointer_to_matrix(), and -// pointer_to_column_vector() have been deprecated in favor of the more uniform mat() -// function. But they are here for backwards compatibility. - - template < - typename vector_type - > - const typename disable_if<is_matrix<vector_type>, matrix_op<op_array_to_mat<vector_type> > >::type - vector_to_matrix ( - const vector_type& vector - ) - { - typedef op_array_to_mat<vector_type> op; - return matrix_op<op>(op(vector)); - } - - template < - typename vector_type - > - const typename enable_if<is_matrix<vector_type>,vector_type>::type& vector_to_matrix ( - const vector_type& vector - ) - /*! - This overload catches the case where the argument to this function is - already a matrix. - !*/ - { - return vector; - } - - template < - typename value_type, - typename alloc - > - const matrix_op<op_std_vect_to_mat<std::vector<value_type,alloc> > > vector_to_matrix ( - const std::vector<value_type,alloc>& vector - ) - { - typedef op_std_vect_to_mat<std::vector<value_type,alloc> > op; - return matrix_op<op>(op(vector)); - } - - template < - typename value_type, - typename alloc - > - const matrix_op<op_std_vect_to_mat<std_vector_c<value_type,alloc> > > vector_to_matrix ( - const std_vector_c<value_type,alloc>& vector - ) - { - typedef op_std_vect_to_mat<std_vector_c<value_type,alloc> > op; - return matrix_op<op>(op(vector)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename array_type - > - const typename enable_if<is_matrix<array_type>,array_type>::type& - array_to_matrix ( - const array_type& array - ) - { - return array; - } - -// ---------------------------------------------------------------------------------------- - - template <typename T> - struct op_array2d_to_mat : does_not_alias - { - op_array2d_to_mat( const T& array_) : array(array_){} - - const T& array; - - const static long cost = 1; - const static long NR = 0; - const static long NC = 0; - typedef typename T::type type; - typedef const typename T::type& const_ret_type; - typedef typename T::mem_manager_type mem_manager_type; - typedef row_major_layout layout_type; - - const_ret_type apply (long r, long c ) const { return array[r][c]; } - - long nr () const { return array.nr(); } - long nc () const { return array.nc(); } - }; - - // Note that we have this version of mat() because it's slightly faster executing - // than the general one that handles any generic image. This is because it avoids - // calling image_data() which for array2d involves a single if statement but this - // version here has no if statement in its construction. - template < typename T, typename MM > - const matrix_op<op_array2d_to_mat<array2d<T,MM> > > mat ( - const array2d<T,MM>& array - ) - { - typedef op_array2d_to_mat<array2d<T,MM> > op; - return matrix_op<op>(op(array)); - } - - template < - typename array_type - > - const typename disable_if<is_matrix<array_type>,matrix_op<op_array2d_to_mat<array_type> > >::type - array_to_matrix ( - const array_type& array - ) - { - typedef op_array2d_to_mat<array_type> op; - return matrix_op<op>(op(array)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_op<op_pointer_to_mat<T> > pointer_to_matrix ( - const T* ptr, - long nr, - long nc - ) - { - DLIB_ASSERT(nr > 0 && nc > 0 , - "\tconst matrix_exp pointer_to_matrix(ptr, nr, nc)" - << "\n\t nr and nc must be bigger than 0" - << "\n\t nr: " << nr - << "\n\t nc: " << nc - ); - typedef op_pointer_to_mat<T> op; - return matrix_op<op>(op(ptr,nr,nc)); - } - - template < - typename T - > - const matrix_op<op_pointer_to_col_vect<T> > pointer_to_column_vector ( - const T* ptr, - long nr - ) - { - DLIB_ASSERT(nr > 0 , - "\tconst matrix_exp pointer_to_column_vector(ptr, nr)" - << "\n\t nr must be bigger than 0" - << "\n\t nr: " << nr - ); - typedef op_pointer_to_col_vect<T> op; - return matrix_op<op>(op(ptr, nr)); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - inline matrix<double,1,1> mat ( - double value - ) - { - matrix<double,1,1> temp; - temp(0) = value; - return temp; - } - - inline matrix<float,1,1> mat ( - float value - ) - { - matrix<float,1,1> temp; - temp(0) = value; - return temp; - } - - inline matrix<long double,1,1> mat ( - long double value - ) - { - matrix<long double,1,1> temp; - temp(0) = value; - return temp; - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_MAT_Hh_ - - diff --git a/ml/dlib/dlib/matrix/matrix_mat_abstract.h b/ml/dlib/dlib/matrix/matrix_mat_abstract.h deleted file mode 100644 index 7026f60a1..000000000 --- a/ml/dlib/dlib/matrix/matrix_mat_abstract.h +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_MATRIx_MAT_ABSTRACT_Hh_ -#ifdef DLIB_MATRIx_MAT_ABSTRACT_Hh_ - -#include "matrix_abstract.h" -#inclue <vector> -#include "../array/array_kernel_abstract.h" -#include "../array2d/array2d_kernel_abstract.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const matrix_exp<EXP>& mat ( - const matrix_exp<EXP>& m - ); - /*! - ensures - - returns m - (i.e. this function just returns the input matrix without any modifications) - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename image_type - > - const matrix_exp mat ( - const image_type& img - ); - /*! - requires - - image_type == an image object that implements the interface defined in - dlib/image_processing/generic_image.h or image_type is a image_view or - const_image_view object. - ensures - - This function converts any kind of generic image object into a dlib::matrix - expression. Therefore, it is capable of converting objects like dlib::array2d - of dlib::cv_image. - - returns a matrix R such that: - - R.nr() == array.nr() - - R.nc() == array.nc() - - for all valid r and c: - R(r, c) == array[r][c] - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - typename MM - > - const matrix_exp mat ( - const array<T,MM>& m - ); - /*! - ensures - - returns a matrix R such that: - - is_col_vector(R) == true - - R.size() == m.size() - - for all valid r: - R(r) == m[r] - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename value_type, - typename alloc - > - const matrix_exp mat ( - const std::vector<value_type,alloc>& vector - ); - /*! - ensures - - returns a matrix R such that: - - is_col_vector(R) == true - - R.size() == vector.size() - - for all valid r: - R(r) == vector[r] - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename value_type, - typename alloc - > - const matrix_exp mat ( - const std_vector_c<value_type,alloc>& vector - ); - /*! - ensures - - returns a matrix R such that: - - is_col_vector(R) == true - - R.size() == vector.size() - - for all valid r: - R(r) == vector[r] - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_exp mat ( - const T* ptr, - long nr - ); - /*! - requires - - nr >= 0 - - ptr == a pointer to at least nr T objects (or the NULL pointer if nr==0) - ensures - - returns a matrix M such that: - - M.nr() == nr - - m.nc() == 1 - - for all valid i: - M(i) == ptr[i] - - Note that the returned matrix doesn't take "ownership" of - the pointer and thus will not delete or free it. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_exp mat ( - const T* ptr, - long nr, - long nc - ); - /*! - requires - - nr >= 0 - - nc >= 0 - - ptr == a pointer to at least nr*nc T objects (or the NULL pointer if nr*nc==0) - ensures - - returns a matrix M such that: - - M.nr() == nr - - m.nc() == nc - - for all valid r and c: - M(r,c) == ptr[r*nc + c] - (i.e. the pointer is interpreted as a matrix laid out in memory - in row major order) - - Note that the returned matrix doesn't take "ownership" of - the pointer and thus will not delete or free it. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_exp mat ( - const T* ptr, - long nr, - long nc, - long stride - ); - /*! - requires - - nr >= 0 - - nc >= 0 - - stride > 0 - - ptr == a pointer to at least (nr-1)*stride+nc T objects (or the NULL pointer if nr*nc==0) - ensures - - returns a matrix M such that: - - M.nr() == nr - - m.nc() == nc - - for all valid r and c: - M(r,c) == ptr[r*stride + c] - (i.e. the pointer is interpreted as a matrix laid out in memory - in row major order, with a row stride of the given stride amount.) - - Note that the returned matrix doesn't take "ownership" of - the pointer and thus will not delete or free it. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_exp mat ( - const ::arma::Mat<T>& m - ); - /*! - ensures - - Converts a matrix from the Armadillo library into a dlib matrix. - - returns a matrix R such that: - - R.nr() == m.n_rows - - R.nc() == m.n_cols - - for all valid r: - R(r,c) == m(r,c) - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename _Scalar, - int _Rows, - int _Cols, - int _Options, - int _MaxRows, - int _MaxCols - > - const matrix_exp mat ( - const ::Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>& m - ); - /*! - ensures - - Converts a matrix from the Eigen library into a dlib matrix. - - returns a matrix R such that: - - R.nr() == m.rows() - - R.nc() == m.cols() - - for all valid r: - R(r,c) == m(r,c) - !*/ - -// ---------------------------------------------------------------------------------------- - - matrix<double,1,1> mat (double value); - matrix<float,1,1> mat (float value); - matrix<long double,1,1> mat (long double value); - /*! - ensures - - Converts a scalar into a matrix containing just that scalar and returns the - results. - !*/ - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_MAT_ABSTRACT_Hh_ - - diff --git a/ml/dlib/dlib/matrix/matrix_math_functions.h b/ml/dlib/dlib/matrix/matrix_math_functions.h deleted file mode 100644 index d1db3ed14..000000000 --- a/ml/dlib/dlib/matrix/matrix_math_functions.h +++ /dev/null @@ -1,448 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_MATH_FUNCTIONS -#define DLIB_MATRIx_MATH_FUNCTIONS - -#include "matrix_math_functions_abstract.h" -#include "matrix_op.h" -#include "matrix_utilities.h" -#include "matrix.h" -#include "../algs.h" -#include <cmath> -#include <complex> -#include <limits> - - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - DLIB_DEFINE_FUNCTION_M(op_sqrt, sqrt, std::sqrt ,7); - DLIB_DEFINE_FUNCTION_M(op_log, log, std::log ,7); - DLIB_DEFINE_FUNCTION_M(op_log10, log10, std::log10 ,7); - DLIB_DEFINE_FUNCTION_M(op_exp, exp, std::exp ,7); - - DLIB_DEFINE_FUNCTION_M(op_conj, conj, std::conj ,2); - - DLIB_DEFINE_FUNCTION_M(op_ceil, ceil, std::ceil ,7); - DLIB_DEFINE_FUNCTION_M(op_floor, floor, std::floor ,7); - - DLIB_DEFINE_FUNCTION_M(op_sin, sin, std::sin ,7); - DLIB_DEFINE_FUNCTION_M(op_cos, cos, std::cos ,7); - DLIB_DEFINE_FUNCTION_M(op_tan, tan, std::tan ,7); - DLIB_DEFINE_FUNCTION_M(op_sinh, sinh, std::sinh ,7); - DLIB_DEFINE_FUNCTION_M(op_cosh, cosh, std::cosh ,7); - DLIB_DEFINE_FUNCTION_M(op_tanh, tanh, std::tanh ,7); - DLIB_DEFINE_FUNCTION_M(op_asin, asin, std::asin ,7); - DLIB_DEFINE_FUNCTION_M(op_acos, acos, std::acos ,7); - DLIB_DEFINE_FUNCTION_M(op_atan, atan, std::atan ,7); - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - template <typename type> - inline type sigmoid (const type& val) - { - return static_cast<type>(1/(1 + std::exp(-val))); - } - - template <typename type, typename S> - inline type round_zeros_eps (const type& val, const S& eps) - { - // you can only round matrices that contain built in scalar types like double, long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<type>::value); - - if (val >= eps || val <= -eps) - return val; - else - return 0; - } - - template <typename type> - inline type round_zeros (const type& val) - { - // you can only round matrices that contain built in scalar types like double, long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<type>::value); - - const type eps = 10*std::numeric_limits<type>::epsilon(); - if (val >= eps || val <= -eps) - return val; - else - return 0; - } - - template <typename type> - inline type squared (const type& val) - { - return val*val; - } - - template <typename type> - inline type sign (const type& val) - { - if (val >= 0) - return +1; - else - return -1; - } - - template <typename type> - type cubed (const type& val) - { - return val*val*val; - } - - template <typename type, typename S> - inline type pow1 (const type& val, const S& s) - { - // you can only call pow() on matrices that contain floats, doubles or long doubles. - COMPILE_TIME_ASSERT(( - is_same_type<type,float>::value == true || - is_same_type<type,double>::value == true || - is_same_type<type,long double>::value == true - )); - - return std::pow(val,static_cast<type>(s)); - } - - template <typename type, typename S> - inline type pow2 (const S& s, const type& val) - { - // you can only call pow() on matrices that contain floats, doubles or long doubles. - COMPILE_TIME_ASSERT(( - is_same_type<type,float>::value == true || - is_same_type<type,double>::value == true || - is_same_type<type,long double>::value == true - )); - - return std::pow(static_cast<type>(s),val); - } - - template <typename type> - inline type reciprocal (const type& val) - { - // you can only compute reciprocal matrices that contain floats, doubles or long doubles. - COMPILE_TIME_ASSERT(( - is_same_type<type,float>::value == true || - is_same_type<type,double>::value == true || - is_same_type<type,long double>::value == true || - is_same_type<type,std::complex<float> >::value == true || - is_same_type<type,std::complex<double> >::value == true || - is_same_type<type,std::complex<long double> >::value == true - )); - - if (val != static_cast<type>(0)) - return static_cast<type>((type)1.0/val); - else - return 0; - } - - template <typename type> - inline type reciprocal_max (const type& val) - { - // you can only compute reciprocal_max matrices that contain floats, doubles or long doubles. - COMPILE_TIME_ASSERT(( - is_same_type<type,float>::value == true || - is_same_type<type,double>::value == true || - is_same_type<type,long double>::value == true - )); - - if (val != static_cast<type>(0)) - return static_cast<type>((type)1.0/val); - else - return std::numeric_limits<type>::max(); - } - - } - - DLIB_DEFINE_FUNCTION_M(op_sigmoid, sigmoid, impl::sigmoid, 7); - DLIB_DEFINE_FUNCTION_MS(op_round_zeros, round_zeros, impl::round_zeros_eps, 7); - DLIB_DEFINE_FUNCTION_M(op_round_zeros2, round_zeros, impl::round_zeros, 7); - DLIB_DEFINE_FUNCTION_M(op_cubed, cubed, impl::cubed, 7); - DLIB_DEFINE_FUNCTION_M(op_squared, squared, impl::squared, 6); - DLIB_DEFINE_FUNCTION_M(op_sign, sign, impl::sign, 6); - DLIB_DEFINE_FUNCTION_MS(op_pow1, pow, impl::pow1, 7); - DLIB_DEFINE_FUNCTION_SM(op_pow2, pow, impl::pow2, 7); - DLIB_DEFINE_FUNCTION_M(op_reciprocal, reciprocal, impl::reciprocal, 6); - DLIB_DEFINE_FUNCTION_M(op_reciprocal_max, reciprocal_max, impl::reciprocal_max, 6); - -// ---------------------------------------------------------------------------------------- - - template <typename M, typename enabled = void> - struct op_round : basic_op_m<M> - { - op_round( const M& m_) : basic_op_m<M>(m_){} - - const static long cost = M::cost+7; - typedef typename M::type type; - typedef const typename M::type const_ret_type; - const_ret_type apply (long r, long c) const - { - return static_cast<type>(std::floor(this->m(r,c)+0.5)); - } - }; - - template <typename M> - struct op_round<M,typename enable_if_c<std::numeric_limits<typename M::type>::is_integer>::type > - : basic_op_m<M> - { - op_round( const M& m_) : basic_op_m<M>(m_){} - - const static long cost = M::cost; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - const_ret_type apply (long r, long c) const - { - return this->m(r,c); - } - }; - - template < - typename EXP - > - const matrix_op<op_round<EXP> > round ( - const matrix_exp<EXP>& m - ) - { - // you can only round matrices that contain built in scalar types like double, long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_round<EXP> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_normalize : basic_op_m<M> - { - typedef typename M::type type; - - op_normalize( const M& m_, const type& s_) : basic_op_m<M>(m_), s(s_){} - - const type s; - - const static long cost = M::cost+5; - typedef const typename M::type const_ret_type; - const_ret_type apply (long r, long c) const - { - return this->m(r,c)*s; - } - }; - - template < - typename EXP - > - const matrix_op<op_normalize<EXP> > normalize ( - const matrix_exp<EXP>& m - ) - { - // you can only compute normalized matrices that contain floats, doubles or long doubles. - COMPILE_TIME_ASSERT(( - is_same_type<typename EXP::type,float>::value == true || - is_same_type<typename EXP::type,double>::value == true || - is_same_type<typename EXP::type,long double>::value == true - )); - - - typedef op_normalize<EXP> op; - typename EXP::type temp = std::sqrt(sum(squared(m))); - if (temp != 0.0) - temp = 1.0/temp; - - return matrix_op<op>(op(m.ref(),temp)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M, typename return_type = typename M::type> - struct op_abs : basic_op_m<M> - { - op_abs( const M& m_) : basic_op_m<M>(m_){} - - const static long cost = M::cost+7; - typedef typename M::type type; - typedef const typename M::type const_ret_type; - const_ret_type apply ( long r, long c) const - { - return static_cast<type>(std::abs(this->m(r,c))); - } - }; - - template <typename M, typename T> - struct op_abs<M, std::complex<T> > : basic_op_m<M> - { - op_abs( const M& m_) : basic_op_m<M>(m_){} - - const static long cost = M::cost; - typedef T type; - typedef const T const_ret_type; - const_ret_type apply ( long r, long c) const - { - return static_cast<type>(std::abs(this->m(r,c))); - } - }; - - template < - typename EXP - > - const matrix_op<op_abs<EXP> > abs ( - const matrix_exp<EXP>& m - ) - { - typedef op_abs<EXP> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_complex_matrix : basic_op_m<M> - { - op_complex_matrix( const M& m_) : basic_op_m<M>(m_){} - - const static long cost = M::cost+1; - typedef std::complex<typename M::type> type; - typedef const std::complex<typename M::type> const_ret_type; - const_ret_type apply ( long r, long c) const - { - return type(this->m(r,c)); - } - }; - - template < - typename EXP - > - const matrix_op<op_complex_matrix<EXP> > complex_matrix ( - const matrix_exp<EXP>& m - ) - { - typedef op_complex_matrix<EXP> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_complex_matrix2 : basic_op_mm<M1,M2> - { - op_complex_matrix2( const M1& m1_, const M2& m2_) : basic_op_mm<M1,M2>(m1_,m2_){} - - const static long cost = M1::cost+M2::cost+1; - typedef std::complex<typename M1::type> type; - typedef const std::complex<typename M1::type> const_ret_type; - - const_ret_type apply ( long r, long c) const - { return type(this->m1(r,c), this->m2(r,c)); } - }; - - template < - typename EXP1, - typename EXP2 - > - const matrix_op<op_complex_matrix2<EXP1,EXP2> > complex_matrix ( - const matrix_exp<EXP1>& real_part, - const matrix_exp<EXP2>& imag_part - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); - COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0); - - DLIB_ASSERT(real_part.nr() == imag_part.nr() && - real_part.nc() == imag_part.nc(), - "\tconst matrix_exp::type complex_matrix(real_part, imag_part)" - << "\n\tYou can only make a complex matrix from two equally sized matrices" - << "\n\treal_part.nr(): " << real_part.nr() - << "\n\treal_part.nc(): " << real_part.nc() - << "\n\timag_part.nr(): " << imag_part.nr() - << "\n\timag_part.nc(): " << imag_part.nc() - ); - - typedef op_complex_matrix2<EXP1,EXP2> op; - return matrix_op<op>(op(real_part.ref(),imag_part.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_norm : basic_op_m<M> - { - op_norm( const M& m_) : basic_op_m<M>(m_){} - - const static long cost = M::cost+6; - typedef typename M::type::value_type type; - typedef const typename M::type::value_type const_ret_type; - const_ret_type apply ( long r, long c) const - { return std::norm(this->m(r,c)); } - }; - - template < - typename EXP - > - const matrix_op<op_norm<EXP> > norm ( - const matrix_exp<EXP>& m - ) - { - typedef op_norm<EXP> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_real : basic_op_m<M> - { - op_real( const M& m_) : basic_op_m<M>(m_){} - - const static long cost = M::cost; - typedef typename M::type::value_type type; - typedef const typename M::type::value_type const_ret_type; - const_ret_type apply ( long r, long c) const - { return std::real(this->m(r,c)); } - }; - - template < - typename EXP - > - const matrix_op<op_real<EXP> > real ( - const matrix_exp<EXP>& m - ) - { - typedef op_real<EXP> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_imag : basic_op_m<M> - { - op_imag( const M& m_) : basic_op_m<M>(m_){} - - const static long cost = M::cost; - typedef typename M::type::value_type type; - typedef const typename M::type::value_type const_ret_type; - const_ret_type apply (long r, long c) const - { return std::imag(this->m(r,c)); } - }; - - template < - typename EXP - > - const matrix_op<op_imag<EXP> > imag ( - const matrix_exp<EXP>& m - ) - { - typedef op_imag<EXP> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_MATH_FUNCTIONS - diff --git a/ml/dlib/dlib/matrix/matrix_math_functions_abstract.h b/ml/dlib/dlib/matrix/matrix_math_functions_abstract.h deleted file mode 100644 index 09210270d..000000000 --- a/ml/dlib/dlib/matrix/matrix_math_functions_abstract.h +++ /dev/null @@ -1,595 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_MATRIx_MATH_FUNCTIONS_ABSTRACT_ -#ifdef DLIB_MATRIx_MATH_FUNCTIONS_ABSTRACT_ - -#include "matrix_abstract.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Exponential Functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - const matrix_exp exp ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::exp(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp log10 ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::log10(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp log ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::log(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp sqrt ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == sqrt(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename T> - const matrix_exp pow ( - const matrix_exp& m, - const T& e - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == pow(m(r,c),e) - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename T> - const matrix_exp pow ( - const T& b, - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == pow(b, m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp squared ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == m(r,c)*m(r,c) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp cubed ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == m(r,c)*m(r,c)*m(r,c) - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Miscellaneous -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - const matrix_exp sign ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix that tells the sign of each element in m. In particular: - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - - if (m(r,c) >= 0) then - - R(r,c) == +1 - - else - - R(r,c) == -1 - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp sigmoid ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == 1/(1 + exp(-m(r,c))) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp abs ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - if (m contains std::complex<T> objects) then - - R::type == T - - else - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::abs(m(r,c)) - (note that if m is complex then std::abs(val) performs sqrt(std::norm(val)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp reciprocal ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, long double, std::complex<float>, - std::complex<double>, or std::complex<long double> - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - - if (m(r,c) != 0) then - - R(r,c) == 1.0/m(r,c) - - else - - R(r,c) == 0 - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp reciprocal_max ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - - if (m(r,c) != 0) then - - R(r,c) == 1.0/m(r,c) - - else - - R(r,c) == std::numeric_limits<R::type>::max() - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp normalize ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - if (sqrt(sum(squared(m))) != 0) then - - returns m/sqrt(sum(squared(m))) - - else - - returns m - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Rounding numbers one way or another -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - const matrix_exp round ( - const matrix_exp& m - ); - /*! - requires - - is_built_in_scalar_type<matrix_exp::type>::value == true - (i.e. m must contain a type like int, float, double, long, etc.) - ensures - - if (m contains integers) then - - returns m unmodified - - else - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == m(r,c) rounded to the nearest integral value - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp ceil ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::ceil(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp floor ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::floor(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp round_zeros ( - const matrix_exp& m - ); - /*! - requires - - is_built_in_scalar_type<matrix_exp::type>::value == true - (i.e. m must contain a type like int, float, double, long, etc.) - ensures - - if (m contains integers) then - - returns m unmodified - - else - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - let eps == 10*std::numeric_limits<matrix_exp::type>::epsilon() - - for all valid r and c: - - if (abs(m(r,c)) >= eps) then - - R(r,c) == m(r,c) - - else - - R(r,c) == 0 - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp round_zeros ( - const matrix_exp& m, - matrix_exp::type eps - ); - /*! - requires - - is_built_in_scalar_type<matrix_exp::type>::value == true - (i.e. m must contain a type like int, float, double, long, etc.) - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - - if (abs(m(r,c)) >= eps) then - - R(r,c) == m(r,c) - - else - - R(r,c) == 0 - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Complex number utility functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - const matrix_exp conj ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == std::complex<T> - ensures - - returns a matrix R such that: - - R::type == std::complex<T> - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::conj(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp norm ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == std::complex<T> - ensures - - returns a matrix R such that: - - R::type == T - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::norm(m(r,c)) - (note that std::norm(val) == val.real()*val.real() + val.imag()*val.imag()) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp imag ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == std::complex<T> - ensures - - returns a matrix R such that: - - R::type == T - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::imag(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp real ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == std::complex<T> - ensures - - returns a matrix R such that: - - R::type == T - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::real(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp complex_matrix ( - const matrix_exp& real_part - ); - /*! - ensures - - returns a matrix R such that: - - R::type == std::complex<T> where T is whatever type real_part used. - - R has the same dimensions as real_part. - - for all valid r and c: - R(r,c) == std::complex(real_part(r,c), 0) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp complex_matrix ( - const matrix_exp& real_part, - const matrix_exp& imag_part - ); - /*! - requires - - real_part.nr() == imag_part.nr() - - real_part.nc() == imag_part.nc() - - real_part and imag_part both contain the same type of element - ensures - - returns a matrix R such that: - - R::type == std::complex<T> where T is whatever type real_part and imag_part used. - - R has the same dimensions as real_part and imag_part - - for all valid r and c: - R(r,c) == std::complex(real_part(r,c),imag_part(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Trigonometric Functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - const matrix_exp sin ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::sin(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp cos ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::cos(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp tan ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::tan(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp asin ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::asin(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp acos ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::acos(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp atan ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::atan(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp sinh ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::sinh(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp cosh ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::cosh(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp tanh ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == float, double, or long double - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R(r,c) == std::tanh(m(r,c)) - !*/ - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_MATH_FUNCTIONS_ABSTRACT_ - diff --git a/ml/dlib/dlib/matrix/matrix_op.h b/ml/dlib/dlib/matrix/matrix_op.h deleted file mode 100644 index 524a775eb..000000000 --- a/ml/dlib/dlib/matrix/matrix_op.h +++ /dev/null @@ -1,479 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_OP_H_ -#define DLIB_MATRIx_OP_H_ - -#include "matrix_exp.h" - - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - template <typename OP > - class matrix_op; - - template < typename OP > - struct matrix_traits<matrix_op<OP> > - { - typedef typename OP::type type; - typedef typename OP::const_ret_type const_ret_type; - typedef typename OP::mem_manager_type mem_manager_type; - typedef typename OP::layout_type layout_type; - const static long NR = OP::NR; - const static long NC = OP::NC; - const static long cost = OP::cost; - }; - - template < - typename OP - > - class matrix_op : public matrix_exp<matrix_op<OP> > - { - /*! - WHAT THIS OBJECT REPRESENTS - The matrix_op is simply a tool for reducing the amount of boilerplate - you need to write when creating matrix expressions. - !*/ - - public: - typedef typename matrix_traits<matrix_op>::type type; - typedef typename matrix_traits<matrix_op>::const_ret_type const_ret_type; - typedef typename matrix_traits<matrix_op>::mem_manager_type mem_manager_type; - typedef typename matrix_traits<matrix_op>::layout_type layout_type; - const static long NR = matrix_traits<matrix_op>::NR; - const static long NC = matrix_traits<matrix_op>::NC; - const static long cost = matrix_traits<matrix_op>::cost; - - private: - // This constructor exists simply for the purpose of causing a compile time error if - // someone tries to create an instance of this object with the wrong kind of object. - template <typename T1> - matrix_op (T1); - public: - - matrix_op ( - const OP& op_ - ) : - op(op_) - {} - - const_ret_type operator() ( - long r, - long c - ) const { return op.apply(r,c); } - - const_ret_type operator() ( long i ) const - { return matrix_exp<matrix_op>::operator()(i); } - - template <typename U> - bool aliases ( - const matrix_exp<U>& item - ) const { return op.aliases(item); } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& item - ) const { return op.destructively_aliases(item); } - - long nr ( - ) const { return op.nr(); } - - long nc ( - ) const { return op.nc(); } - - - const OP op; - }; - -// ---------------------------------------------------------------------------------------- - - template <typename OP > - class matrix_diag_op; - - template < typename OP > - struct matrix_traits<matrix_diag_op<OP> > - { - typedef typename OP::type type; - typedef typename OP::const_ret_type const_ret_type; - typedef typename OP::mem_manager_type mem_manager_type; - typedef typename OP::layout_type layout_type; - const static long NR = OP::NR; - const static long NC = OP::NC; - const static long cost = OP::cost; - }; - - template < - typename OP - > - class matrix_diag_op : public matrix_diag_exp<matrix_diag_op<OP> > - { - /*! - WHAT THIS OBJECT REPRESENTS - The matrix_diag_op is simply a tool for reducing the amount of boilerplate - you need to write when creating matrix expressions. - !*/ - - public: - typedef typename matrix_traits<matrix_diag_op>::type type; - typedef typename matrix_traits<matrix_diag_op>::const_ret_type const_ret_type; - typedef typename matrix_traits<matrix_diag_op>::mem_manager_type mem_manager_type; - typedef typename matrix_traits<matrix_diag_op>::layout_type layout_type; - const static long NR = matrix_traits<matrix_diag_op>::NR; - const static long NC = matrix_traits<matrix_diag_op>::NC; - const static long cost = matrix_traits<matrix_diag_op>::cost; - - private: - // This constructor exists simply for the purpose of causing a compile time error if - // someone tries to create an instance of this object with the wrong kind of object. - template <typename T1> - matrix_diag_op (T1); - public: - - matrix_diag_op ( - const OP& op_ - ) : - op(op_) - {} - - const_ret_type operator() ( - long r, - long c - ) const { return op.apply(r,c); } - - const_ret_type operator() ( long i ) const - { return matrix_exp<matrix_diag_op>::operator()(i); } - - template <typename U> - bool aliases ( - const matrix_exp<U>& item - ) const { return op.aliases(item); } - - template <typename U> - bool destructively_aliases ( - const matrix_exp<U>& item - ) const { return op.destructively_aliases(item); } - - long nr ( - ) const { return op.nr(); } - - long nc ( - ) const { return op.nc(); } - - - const OP op; - }; - -// ---------------------------------------------------------------------------------------- - - struct does_not_alias - { - /*! - This is a partial implementation of a matrix operator that never aliases - another expression. - !*/ - - template <typename U> bool aliases ( const U& ) const { return false; } - template <typename U> bool destructively_aliases ( const U& ) const { return false; } - }; - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct basic_op_m - { - /*! - This is a partial implementation of a matrix operator that preserves - the dimensions of its argument and doesn't have destructive aliasing. - !*/ - - private: - // This constructor exists simply for the purpose of causing a compile time error if - // someone tries to create an instance of this object with the wrong kind of object. - template <typename T1> - basic_op_m (T1); - public: - - basic_op_m( - const M& m_ - ) : m(m_){} - - const M& m; - - const static long NR = M::NR; - const static long NC = M::NC; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - - long nr () const { return m.nr(); } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m.destructively_aliases(item); } - - }; - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct basic_op_mm - { - /*! - This is a partial implementation of a matrix operator that preserves - the dimensions of its arguments and doesn't have destructive aliasing. - !*/ - - private: - // This constructor exists simply for the purpose of causing a compile time error if - // someone tries to create an instance of this object with the wrong kind of object. - template <typename T1, typename T2> - basic_op_mm (T1, T2); - public: - - basic_op_mm( - const M1& m1_, - const M2& m2_ - ) : m1(m1_), m2(m2_){} - - const M1& m1; - const M2& m2; - - const static long NR = M1::NR; - const static long NC = M1::NC; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - - long nr () const { return m1.nr(); } - long nc () const { return m1.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.destructively_aliases(item) || m2.destructively_aliases(item); } - - }; - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2, typename M3> - struct basic_op_mmm - { - /*! - This is a partial implementation of a matrix operator that preserves - the dimensions of its arguments and doesn't have destructive aliasing. - !*/ - - private: - // This constructor exists simply for the purpose of causing a compile time error if - // someone tries to create an instance of this object with the wrong kind of object. - template <typename T1, typename T2, typename T3> - basic_op_mmm (T1, T2, T3); - public: - - basic_op_mmm( - const M1& m1_, - const M2& m2_, - const M3& m3_ - ) : m1(m1_), m2(m2_), m3(m3_){} - - const M1& m1; - const M2& m2; - const M3& m3; - - const static long NR = M1::NR; - const static long NC = M1::NC; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - - long nr () const { return m1.nr(); } - long nc () const { return m1.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.destructively_aliases(item) || m2.destructively_aliases(item) || - m3.destructively_aliases(item);} - - }; - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2, typename M3, typename M4> - struct basic_op_mmmm - { - /*! - This is a partial implementation of a matrix operator that preserves - the dimensions of its arguments and doesn't have destructive aliasing. - !*/ - - private: - // This constructor exists simply for the purpose of causing a compile time error if - // someone tries to create an instance of this object with the wrong kind of object. - template <typename T1, typename T2, typename T3, typename T4> - basic_op_mmmm (T1, T2, T3, T4); - public: - - basic_op_mmmm( - const M1& m1_, - const M2& m2_, - const M3& m3_, - const M4& m4_ - ) : m1(m1_), m2(m2_), m3(m3_), m4(m4_){} - - const M1& m1; - const M2& m2; - const M3& m3; - const M4& m4; - - const static long NR = M1::NR; - const static long NC = M1::NC; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - - long nr () const { return m1.nr(); } - long nc () const { return m1.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item) || m4.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.destructively_aliases(item) || m2.destructively_aliases(item) || - m3.destructively_aliases(item) || m4.destructively_aliases(item);} - - }; - -// ---------------------------------------------------------------------------------------- - -#define DLIB_DEFINE_OP_M(op_name, function, extra_cost) \ - template <typename M> \ - struct op_name \ - { \ - op_name( \ - const M& m_ \ - ) : m(m_){} \ - \ - const M& m; \ - \ - const static long cost = M::cost+(extra_cost); \ - const static long NR = M::NR; \ - const static long NC = M::NC; \ - typedef typename M::type type; \ - typedef const typename M::type const_ret_type; \ - typedef typename M::mem_manager_type mem_manager_type; \ - typedef typename M::layout_type layout_type; \ - \ - const_ret_type apply (long r, long c) const { return function(m(r,c)); } \ - \ - long nr () const { return m.nr(); } \ - long nc () const { return m.nc(); } \ - \ - template <typename U> bool aliases ( const matrix_exp<U>& item) const \ - { return m.aliases(item); } \ - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const \ - { return m.destructively_aliases(item); } \ - \ - } - -#define DLIB_DEFINE_FUNCTION_M(op_name, name, function, extra_cost) \ - DLIB_DEFINE_OP_M(op_name, function, extra_cost); \ - template < typename M > \ - const matrix_op<op_name<M> > name ( const matrix_exp<M>& m) \ - { \ - typedef op_name<M> op; \ - return matrix_op<op>(op(m.ref())); \ - } - -// ---------------------------------------------------------------------------------------- - -#define DLIB_DEFINE_OP_MS(op_name, function, extra_cost) \ - template <typename M, typename S> \ - struct op_name \ - { \ - op_name( \ - const M& m_, \ - const S& s_ \ - ) : m(m_), s(s_){} \ - \ - const M& m; \ - const S s; \ - \ - const static long cost = M::cost+(extra_cost); \ - const static long NR = M::NR; \ - const static long NC = M::NC; \ - typedef typename M::type type; \ - typedef const typename M::type const_ret_type; \ - typedef typename M::mem_manager_type mem_manager_type; \ - typedef typename M::layout_type layout_type; \ - \ - const_ret_type apply (long r, long c) const { return function(m(r,c), s); } \ - \ - long nr () const { return m.nr(); } \ - long nc () const { return m.nc(); } \ - \ - template <typename U> bool aliases ( const matrix_exp<U>& item) const \ - { return m.aliases(item); } \ - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const \ - { return m.destructively_aliases(item); } \ - \ - } - -#define DLIB_DEFINE_FUNCTION_MS(op_name, name, function, extra_cost) \ - DLIB_DEFINE_OP_MS(op_name, function, extra_cost); \ - template < typename M, typename S > \ - const matrix_op<op_name<M, S> > name ( const matrix_exp<M>& m, const S& s) \ - { \ - typedef op_name<M, S> op; \ - return matrix_op<op>(op(m.ref(), s)); \ - } - -// ---------------------------------------------------------------------------------------- - -#define DLIB_DEFINE_OP_SM(op_name, function, extra_cost) \ - template <typename S, typename M> \ - struct op_name \ - { \ - op_name( \ - const S& s_, \ - const M& m_ \ - ) : m(m_), s(s_){} \ - \ - const M& m; \ - const S s; \ - \ - const static long cost = M::cost+(extra_cost); \ - const static long NR = M::NR; \ - const static long NC = M::NC; \ - typedef typename M::type type; \ - typedef const typename M::type const_ret_type; \ - typedef typename M::mem_manager_type mem_manager_type; \ - typedef typename M::layout_type layout_type; \ - \ - const_ret_type apply (long r, long c) const { return function(s, m(r,c)); } \ - \ - long nr () const { return m.nr(); } \ - long nc () const { return m.nc(); } \ - \ - template <typename U> bool aliases ( const matrix_exp<U>& item) const \ - { return m.aliases(item); } \ - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const \ - { return m.destructively_aliases(item); } \ - \ - } - -#define DLIB_DEFINE_FUNCTION_SM(op_name, name, function, extra_cost) \ - DLIB_DEFINE_OP_SM(op_name, function, extra_cost); \ - template < typename S, typename M > \ - const matrix_op<op_name<S, M> > name (const S& s, const matrix_exp<M>& m) \ - { \ - typedef op_name<S, M> op; \ - return matrix_op<op>(op(s, m.ref())); \ - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_OP_H_ - diff --git a/ml/dlib/dlib/matrix/matrix_qr.h b/ml/dlib/dlib/matrix/matrix_qr.h deleted file mode 100644 index 086d481f1..000000000 --- a/ml/dlib/dlib/matrix/matrix_qr.h +++ /dev/null @@ -1,466 +0,0 @@ -// Copyright (C) 2009 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -// This code was adapted from code from the JAMA part of NIST's TNT library. -// See: http://math.nist.gov/tnt/ -#ifndef DLIB_MATRIX_QR_DECOMPOSITION_H -#define DLIB_MATRIX_QR_DECOMPOSITION_H - -#include "matrix.h" -#include "matrix_utilities.h" -#include "matrix_subexp.h" - -#ifdef DLIB_USE_LAPACK -#include "lapack/geqrf.h" -#include "lapack/ormqr.h" -#endif - -#include "matrix_trsm.h" - -namespace dlib -{ - - template < - typename matrix_exp_type - > - class qr_decomposition - { - - public: - - const static long NR = matrix_exp_type::NR; - const static long NC = matrix_exp_type::NC; - typedef typename matrix_exp_type::type type; - typedef typename matrix_exp_type::mem_manager_type mem_manager_type; - typedef typename matrix_exp_type::layout_type layout_type; - - typedef matrix<type,0,0,mem_manager_type,layout_type> matrix_type; - - // You have supplied an invalid type of matrix_exp_type. You have - // to use this object with matrices that contain float or double type data. - COMPILE_TIME_ASSERT((is_same_type<float, type>::value || - is_same_type<double, type>::value )); - - - - template <typename EXP> - qr_decomposition( - const matrix_exp<EXP>& A - ); - - bool is_full_rank( - ) const; - - long nr( - ) const; - - long nc( - ) const; - - const matrix_type get_r ( - ) const; - - const matrix_type get_q ( - ) const; - - template <typename T, long R, long C, typename MM, typename L> - void get_q ( - matrix<T,R,C,MM,L>& Q - ) const; - - template <typename EXP> - const matrix_type solve ( - const matrix_exp<EXP>& B - ) const; - - private: - -#ifndef DLIB_USE_LAPACK - template <typename EXP> - const matrix_type solve_mat ( - const matrix_exp<EXP>& B - ) const; - - template <typename EXP> - const matrix_type solve_vect ( - const matrix_exp<EXP>& B - ) const; -#endif - - - /** Array for internal storage of decomposition. - @serial internal array storage. - */ - matrix<type,0,0,mem_manager_type,column_major_layout> QR_; - - /** Row and column dimensions. - @serial column dimension. - @serial row dimension. - */ - long m, n; - - /** Array for internal storage of diagonal of R. - @serial diagonal of R. - */ - typedef matrix<type,0,1,mem_manager_type,column_major_layout> column_vector_type; - column_vector_type tau; - column_vector_type Rdiag; - - - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Member functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - template <typename EXP> - qr_decomposition<matrix_exp_type>:: - qr_decomposition( - const matrix_exp<EXP>& A - ) - { - COMPILE_TIME_ASSERT((is_same_type<type, typename EXP::type>::value)); - - // make sure requires clause is not broken - DLIB_ASSERT(A.nr() >= A.nc() && A.size() > 0, - "\tqr_decomposition::qr_decomposition(A)" - << "\n\tInvalid inputs were given to this function" - << "\n\tA.nr(): " << A.nr() - << "\n\tA.nc(): " << A.nc() - << "\n\tA.size(): " << A.size() - << "\n\tthis: " << this - ); - - - QR_ = A; - m = A.nr(); - n = A.nc(); - -#ifdef DLIB_USE_LAPACK - - lapack::geqrf(QR_, tau); - Rdiag = diag(QR_); - -#else - Rdiag.set_size(n); - long i=0, j=0, k=0; - - // Main loop. - for (k = 0; k < n; k++) - { - // Compute 2-norm of k-th column without under/overflow. - type nrm = 0; - for (i = k; i < m; i++) - { - nrm = hypot(nrm,QR_(i,k)); - } - - if (nrm != 0.0) - { - // Form k-th Householder vector. - if (QR_(k,k) < 0) - { - nrm = -nrm; - } - for (i = k; i < m; i++) - { - QR_(i,k) /= nrm; - } - QR_(k,k) += 1.0; - - // Apply transformation to remaining columns. - for (j = k+1; j < n; j++) - { - type s = 0.0; - for (i = k; i < m; i++) - { - s += QR_(i,k)*QR_(i,j); - } - s = -s/QR_(k,k); - for (i = k; i < m; i++) - { - QR_(i,j) += s*QR_(i,k); - } - } - } - Rdiag(k) = -nrm; - } -#endif - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - long qr_decomposition<matrix_exp_type>:: - nr ( - ) const - { - return m; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - long qr_decomposition<matrix_exp_type>:: - nc ( - ) const - { - return n; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - bool qr_decomposition<matrix_exp_type>:: - is_full_rank( - ) const - { - type eps = max(abs(Rdiag)); - if (eps != 0) - eps *= std::sqrt(std::numeric_limits<type>::epsilon())/100; - else - eps = 1; // there is no max so just use 1 - - // check if any of the elements of Rdiag are effectively 0 - return min(abs(Rdiag)) > eps; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename qr_decomposition<matrix_exp_type>::matrix_type qr_decomposition<matrix_exp_type>:: - get_r( - ) const - { - matrix_type R(n,n); - for (long i = 0; i < n; i++) - { - for (long j = 0; j < n; j++) - { - if (i < j) - { - R(i,j) = QR_(i,j); - } - else if (i == j) - { - R(i,j) = Rdiag(i); - } - else - { - R(i,j) = 0.0; - } - } - } - return R; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - const typename qr_decomposition<matrix_exp_type>::matrix_type qr_decomposition<matrix_exp_type>:: - get_q( - ) const - { - matrix_type Q; - get_q(Q); - return Q; - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - template <typename T, long R, long C, typename MM, typename L> - void qr_decomposition<matrix_exp_type>:: - get_q( - matrix<T,R,C,MM,L>& X - ) const - { -#ifdef DLIB_USE_LAPACK - // Take only the first n columns of an identity matrix. This way - // X ends up being an m by n matrix. - X = colm(identity_matrix<type>(m), range(0,n-1)); - - // Compute Y = Q*X - lapack::ormqr('L','N', QR_, tau, X); - -#else - long i=0, j=0, k=0; - - X.set_size(m,n); - for (k = n-1; k >= 0; k--) - { - for (i = 0; i < m; i++) - { - X(i,k) = 0.0; - } - X(k,k) = 1.0; - for (j = k; j < n; j++) - { - if (QR_(k,k) != 0) - { - type s = 0.0; - for (i = k; i < m; i++) - { - s += QR_(i,k)*X(i,j); - } - s = -s/QR_(k,k); - for (i = k; i < m; i++) - { - X(i,j) += s*QR_(i,k); - } - } - } - } -#endif - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - template <typename EXP> - const typename qr_decomposition<matrix_exp_type>::matrix_type qr_decomposition<matrix_exp_type>:: - solve( - const matrix_exp<EXP>& B - ) const - { - COMPILE_TIME_ASSERT((is_same_type<type, typename EXP::type>::value)); - - // make sure requires clause is not broken - DLIB_ASSERT(B.nr() == nr(), - "\tconst matrix_type qr_decomposition::solve(B)" - << "\n\tInvalid inputs were given to this function" - << "\n\tB.nr(): " << B.nr() - << "\n\tnr(): " << nr() - << "\n\tthis: " << this - ); - -#ifdef DLIB_USE_LAPACK - - using namespace blas_bindings; - matrix<type,0,0,mem_manager_type,column_major_layout> X(B); - // Compute Y = transpose(Q)*B - lapack::ormqr('L','T',QR_, tau, X); - // Solve R*X = Y; - triangular_solver(CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, QR_, X, n); - - /* return n x nx portion of X */ - return subm(X,0,0,n,B.nc()); - -#else - // just call the right version of the solve function - if (B.nc() == 1) - return solve_vect(B); - else - return solve_mat(B); -#endif - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Private member functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - -#ifndef DLIB_USE_LAPACK - - template <typename matrix_exp_type> - template <typename EXP> - const typename qr_decomposition<matrix_exp_type>::matrix_type qr_decomposition<matrix_exp_type>:: - solve_vect( - const matrix_exp<EXP>& B - ) const - { - - column_vector_type x(B); - - // Compute Y = transpose(Q)*B - for (long k = 0; k < n; k++) - { - type s = 0.0; - for (long i = k; i < m; i++) - { - s += QR_(i,k)*x(i); - } - s = -s/QR_(k,k); - for (long i = k; i < m; i++) - { - x(i) += s*QR_(i,k); - } - } - // Solve R*X = Y; - for (long k = n-1; k >= 0; k--) - { - x(k) /= Rdiag(k); - for (long i = 0; i < k; i++) - { - x(i) -= x(k)*QR_(i,k); - } - } - - - /* return n x 1 portion of x */ - return colm(x,0,n); - } - -// ---------------------------------------------------------------------------------------- - - template <typename matrix_exp_type> - template <typename EXP> - const typename qr_decomposition<matrix_exp_type>::matrix_type qr_decomposition<matrix_exp_type>:: - solve_mat( - const matrix_exp<EXP>& B - ) const - { - const long nx = B.nc(); - matrix_type X(B); - long i=0, j=0, k=0; - - // Compute Y = transpose(Q)*B - for (k = 0; k < n; k++) - { - for (j = 0; j < nx; j++) - { - type s = 0.0; - for (i = k; i < m; i++) - { - s += QR_(i,k)*X(i,j); - } - s = -s/QR_(k,k); - for (i = k; i < m; i++) - { - X(i,j) += s*QR_(i,k); - } - } - } - // Solve R*X = Y; - for (k = n-1; k >= 0; k--) - { - for (j = 0; j < nx; j++) - { - X(k,j) /= Rdiag(k); - } - for (i = 0; i < k; i++) - { - for (j = 0; j < nx; j++) - { - X(i,j) -= X(k,j)*QR_(i,k); - } - } - } - - /* return n x nx portion of X */ - return subm(X,0,0,n,nx); - } - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_USE_LAPACK not defined - -} - -#endif // DLIB_MATRIX_QR_DECOMPOSITION_H - - - diff --git a/ml/dlib/dlib/matrix/matrix_read_from_istream.h b/ml/dlib/dlib/matrix/matrix_read_from_istream.h deleted file mode 100644 index 3aced3584..000000000 --- a/ml/dlib/dlib/matrix/matrix_read_from_istream.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (C) 2013 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_READ_FROM_ISTREAM_H_h_ -#define DLIB_MATRIx_READ_FROM_ISTREAM_H_h_ - -#include "matrix.h" -#include <vector> -#include <iostream> - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - inline bool next_is_whitespace ( - std::istream& in - ) - { - return in.peek() == '\n' || - in.peek() == ' ' || - in.peek() == ',' || - in.peek() == '\t' || - in.peek() == '\r'; - } - } - - template <typename T, long NR, long NC, typename MM, typename L> - std::istream& operator>> ( - std::istream& in, - matrix<T,NR,NC,MM,L>& m - ) - { - using namespace dlib::impl; - long num_rows = 0; - std::vector<T> buf; - buf.reserve(100); - - // eat any leading whitespace - while (next_is_whitespace(in)) - in.get(); - - bool at_start_of_line = true; - bool stop = false; - while(!stop && in.peek() != EOF) - { - T temp; - in >> temp; - if (!in) - return in; - - buf.push_back(temp); - if (at_start_of_line) - { - at_start_of_line = false; - ++num_rows; - } - - // Eat next block of whitespace but also note if we hit the start of the next - // line. - while (next_is_whitespace(in)) - { - if (at_start_of_line && in.peek() == '\n') - { - stop = true; - break; - } - - if (in.get() == '\n') - at_start_of_line = true; - } - } - - // It's an error for there to not be any matrix data in the input stream - if (num_rows == 0) - { - in.clear(in.rdstate() | std::ios::failbit); - return in; - } - - const long num_cols = buf.size()/num_rows; - // It's also an error if the sizes don't make sense. - if (num_rows*num_cols != (long)buf.size() || - (NR != 0 && NR != num_rows) || - (NC != 0 && NC != num_cols)) - { - in.clear(in.rdstate() | std::ios::failbit); - return in; - } - - - m = reshape(mat(buf),num_rows, buf.size()/num_rows); - - if (in.eof()) - { - // Clear the eof and fail bits since this is caused by peeking at the EOF. - // But in the current case, we have successfully read the matrix. - in.clear(in.rdstate() & (~(std::ios::eofbit | std::ios::failbit))); - } - return in; - } -} - -// ---------------------------------------------------------------------------------------- - -#endif // DLIB_MATRIx_READ_FROM_ISTREAM_H_h_ - diff --git a/ml/dlib/dlib/matrix/matrix_subexp.h b/ml/dlib/dlib/matrix/matrix_subexp.h deleted file mode 100644 index 668e57496..000000000 --- a/ml/dlib/dlib/matrix/matrix_subexp.h +++ /dev/null @@ -1,1566 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_SUBEXP_ -#define DLIB_MATRIx_SUBEXP_ - -#include "matrix_subexp_abstract.h" -#include "matrix_op.h" -#include "matrix.h" -#include "../geometry/rectangle.h" -#include "matrix_expressions.h" -#include "matrix_mat.h" - - - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <long start, long inc, long end> - const matrix_range_static_exp<start,inc,end> range ( - ) - { - COMPILE_TIME_ASSERT(inc > 0); - return matrix_range_static_exp<start,inc,end>(); - } - - template <long start, long end> - const matrix_range_static_exp<start,1,end> range ( - ) - { - return matrix_range_static_exp<start,1,end>(); - } - - inline const matrix_range_exp<long> range ( - long start, - long end - ) - { - return matrix_range_exp<long>(start,end); - } - - inline const matrix_range_exp<long> range ( - long start, - long inc, - long end - ) - { - DLIB_ASSERT(inc > 0, - "\tconst matrix_exp range(start, inc, end)" - << "\n\tInvalid inputs to this function" - << "\n\tstart: " << start - << "\n\tinc: " << inc - << "\n\tend: " << end - ); - - return matrix_range_exp<long>(start,inc,end); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_subm - { - op_subm ( - const M& m_x, - const long& r_x, - const long& c_x, - const long& nr_x, - const long& nc_x - ) : m(m_x), r_(r_x), c_(c_x), nr_(nr_x), nc_(nc_x) { } - - const M& m; - const long r_; - const long c_; - const long nr_; - const long nc_; - - const static long cost = M::cost+1; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const static long NR = 0; - const static long NC = 0; - - const_ret_type apply ( long r, long c) const { return m(r+r_,c+c_); } - - long nr () const { return nr_; } - long nc () const { return nc_; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_op<op_subm<EXP> > subm ( - const matrix_exp<EXP>& m, - long r, - long c, - long nr, - long nc - ) - { - DLIB_ASSERT(r >= 0 && c >= 0 && nr >= 0 && nc >= 0 && r+nr <= m.nr() && c+nc <= m.nc(), - "\tconst matrix_exp subm(const matrix_exp& m, r, c, nr, nc)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tr: " << r - << "\n\tc: " << c - << "\n\tnr: " << nr - << "\n\tnc: " << nc - ); - - typedef op_subm<EXP> op; - return matrix_op<op>(op(m.ref(),r,c,nr,nc)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const matrix_op<op_subm<EXP> > subm_clipped ( - const matrix_exp<EXP>& m, - long r, - long c, - long nr, - long nc - ) - { - rectangle box(c,r,c+nc-1,r+nr-1); - box = box.intersect(get_rect(m)); - typedef op_subm<EXP> op; - return matrix_op<op>(op(m.ref(),box.top(),box.left(),box.height(),box.width())); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const matrix_op<op_subm<EXP> > subm ( - const matrix_exp<EXP>& m, - const rectangle& rect - ) - { - DLIB_ASSERT(get_rect(m).contains(rect) == true, - "\tconst matrix_exp subm(const matrix_exp& m, const rectangle& rect)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\trect.left(): " << rect.left() - << "\n\trect.top(): " << rect.top() - << "\n\trect.right(): " << rect.right() - << "\n\trect.bottom(): " << rect.bottom() - ); - - typedef op_subm<EXP> op; - return matrix_op<op>(op(m.ref(),rect.top(),rect.left(),rect.height(),rect.width())); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const matrix_op<op_subm<EXP> > subm_clipped ( - const matrix_exp<EXP>& m, - rectangle rect - ) - { - rect = rect.intersect(get_rect(m)); - - typedef op_subm<EXP> op; - return matrix_op<op>(op(m.ref(),rect.top(),rect.left(),rect.height(),rect.width())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2, typename M3> - struct op_subm_range - { - op_subm_range( const M1& m1_, const M2& rows_, const M3& cols_) : - m1(m1_), rows(rows_), cols(cols_) {} - const M1& m1; - const M2& rows; - const M3& cols; - - const static long cost = M1::cost+M2::cost+M3::cost; - typedef typename M1::type type; - typedef typename M1::const_ret_type const_ret_type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - const static long NR = M2::NC*M2::NR; - const static long NC = M3::NC*M3::NR; - - const_ret_type apply ( long r, long c) const { return m1(rows(r),cols(c)); } - - long nr () const { return rows.size(); } - long nc () const { return cols.size(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || rows.aliases(item) || cols.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || rows.aliases(item) || cols.aliases(item); } - }; - - template < - typename EXP, - typename EXPr, - typename EXPc - > - const matrix_op<op_subm_range<EXP,EXPr,EXPc> > subm ( - const matrix_exp<EXP>& m, - const matrix_exp<EXPr>& rows, - const matrix_exp<EXPc>& cols - ) - { - // the rows and cols matrices must contain integer elements - COMPILE_TIME_ASSERT(std::numeric_limits<typename EXPr::type>::is_integer); - COMPILE_TIME_ASSERT(std::numeric_limits<typename EXPc::type>::is_integer); - - DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && 0 <= min(cols) && max(cols) < m.nc() && - (rows.nr() == 1 || rows.nc() == 1) && (cols.nr() == 1 || cols.nc() == 1), - "\tconst matrix_exp subm(const matrix_exp& m, const matrix_exp& rows, const matrix_exp& cols)" - << "\n\tYou have given invalid arguments to this function" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tmin(rows): " << min(rows) - << "\n\tmax(rows): " << max(rows) - << "\n\tmin(cols): " << min(cols) - << "\n\tmax(cols): " << max(cols) - << "\n\trows.nr(): " << rows.nr() - << "\n\trows.nc(): " << rows.nc() - << "\n\tcols.nr(): " << cols.nr() - << "\n\tcols.nc(): " << cols.nc() - ); - - typedef op_subm_range<EXP,EXPr,EXPc> op; - return matrix_op<op>(op(m.ref(),rows.ref(),cols.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_rowm - { - op_rowm(const M& m_, const long& row_) : m(m_), row(row_) {} - const M& m; - const long row; - - const static long cost = M::cost; - const static long NR = 1; - const static long NC = M::NC; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long, long c) const { return m(row,c); } - - long nr () const { return 1; } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_op<op_rowm<EXP> > rowm ( - const matrix_exp<EXP>& m, - long row - ) - { - DLIB_ASSERT(row >= 0 && row < m.nr(), - "\tconst matrix_exp rowm(const matrix_exp& m, row)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\trow: " << row - ); - - typedef op_rowm<EXP> op; - return matrix_op<op>(op(m.ref(),row)); - } - - template <typename EXP> - struct rowm_exp - { - typedef matrix_op<op_rowm<EXP> > type; - }; - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_rowm2 - { - op_rowm2(const M& m_, const long& row_, const long& len) : m(m_), row(row_), length(len) {} - const M& m; - const long row; - const long length; - - const static long cost = M::cost; - const static long NR = 1; - const static long NC = 0; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long , long c) const { return m(row,c); } - - long nr () const { return 1; } - long nc () const { return length; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_op<op_rowm2<EXP> > rowm ( - const matrix_exp<EXP>& m, - long row, - long length - ) - { - DLIB_ASSERT(row >= 0 && row < m.nr() && - length >= 0 && length <= m.nc(), - "\tconst matrix_exp rowm(const matrix_exp& m, row, length)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\trow: " << row - << "\n\tlength: " << length - ); - - typedef op_rowm2<EXP> op; - return matrix_op<op>(op(m.ref(), row, length)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_rowm_range - { - op_rowm_range( const M1& m1_, const M2& rows_) : m1(m1_), rows(rows_) {} - const M1& m1; - const M2& rows; - - const static long cost = M1::cost+M2::cost; - typedef typename M1::type type; - typedef typename M1::const_ret_type const_ret_type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - const static long NR = M2::NC*M2::NR; - const static long NC = M1::NC; - - const_ret_type apply ( long r, long c) const { return m1(rows(r),c); } - - long nr () const { return rows.size(); } - long nc () const { return m1.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || rows.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || rows.aliases(item); } - }; - - template < - typename EXP1, - typename EXP2 - > - const matrix_op<op_rowm_range<EXP1,EXP2> > rowm ( - const matrix_exp<EXP1>& m, - const matrix_exp<EXP2>& rows - ) - { - // the rows matrix must contain integer elements - COMPILE_TIME_ASSERT(std::numeric_limits<typename EXP2::type>::is_integer); - - DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && (rows.nr() == 1 || rows.nc() == 1), - "\tconst matrix_exp rowm(const matrix_exp& m, const matrix_exp& rows)" - << "\n\tYou have given invalid arguments to this function" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tmin(rows): " << min(rows) - << "\n\tmax(rows): " << max(rows) - << "\n\trows.nr(): " << rows.nr() - << "\n\trows.nc(): " << rows.nc() - ); - - typedef op_rowm_range<EXP1,EXP2> op; - return matrix_op<op>(op(m.ref(),rows.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_colm - { - op_colm(const M& m_, const long& col_) : m(m_), col(col_) {} - const M& m; - const long col; - - const static long cost = M::cost; - const static long NR = M::NR; - const static long NC = 1; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long) const { return m(r,col); } - - long nr () const { return m.nr(); } - long nc () const { return 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_op<op_colm<EXP> > colm ( - const matrix_exp<EXP>& m, - long col - ) - { - DLIB_ASSERT(col >= 0 && col < m.nc(), - "\tconst matrix_exp colm(const matrix_exp& m, row)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tcol: " << col - ); - - typedef op_colm<EXP> op; - return matrix_op<op>(op(m.ref(),col)); - } - - template <typename EXP> - struct colm_exp - { - typedef matrix_op<op_colm<EXP> > type; - }; - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_colm2 - { - op_colm2(const M& m_, const long& col_, const long& len) : m(m_), col(col_), length(len) {} - const M& m; - const long col; - const long length; - - const static long cost = M::cost; - const static long NR = 0; - const static long NC = 1; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long ) const { return m(r,col); } - - long nr () const { return length; } - long nc () const { return 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_op<op_colm2<EXP> > colm ( - const matrix_exp<EXP>& m, - long col, - long length - ) - { - DLIB_ASSERT(col >= 0 && col < m.nc() && - length >= 0 && length <= m.nr(), - "\tconst matrix_exp colm(const matrix_exp& m, col, length)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tcol: " << col - << "\n\tlength: " << length - ); - - typedef op_colm2<EXP> op; - return matrix_op<op>(op(m.ref(),col, length)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_colm_range - { - op_colm_range( const M1& m1_, const M2& cols_) : m1(m1_), cols(cols_) {} - const M1& m1; - const M2& cols; - - typedef typename M1::type type; - typedef typename M1::const_ret_type const_ret_type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - const static long NR = M1::NR; - const static long NC = M2::NC*M2::NR; - const static long cost = M1::cost+M2::cost; - - const_ret_type apply (long r, long c) const { return m1(r,cols(c)); } - - long nr () const { return m1.nr(); } - long nc () const { return cols.size(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || cols.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || cols.aliases(item); } - }; - - template < - typename EXP1, - typename EXP2 - > - const matrix_op<op_colm_range<EXP1,EXP2> > colm ( - const matrix_exp<EXP1>& m, - const matrix_exp<EXP2>& cols - ) - { - // the rows matrix must contain integer elements - COMPILE_TIME_ASSERT(std::numeric_limits<typename EXP2::type>::is_integer); - - DLIB_ASSERT(0 <= min(cols) && max(cols) < m.nc() && (cols.nr() == 1 || cols.nc() == 1), - "\tconst matrix_exp colm(const matrix_exp& m, const matrix_exp& cols)" - << "\n\tYou have given invalid arguments to this function" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tmin(cols): " << min(cols) - << "\n\tmax(cols): " << max(cols) - << "\n\tcols.nr(): " << cols.nr() - << "\n\tcols.nc(): " << cols.nc() - ); - - typedef op_colm_range<EXP1,EXP2> op; - return matrix_op<op>(op(m.ref(),cols.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename T> - class assignable_ptr_matrix - { - public: - typedef T type; - typedef row_major_layout layout_type; - typedef matrix<T,0,0,default_memory_manager,layout_type> matrix_type; - - assignable_ptr_matrix( - T* ptr_, - long nr_, - long nc_ - ) : ptr(ptr_), height(nr_), width(nc_){} - - T& operator() ( - long r, - long c - ) - { - return ptr[r*width + c]; - } - - const T& operator() ( - long r, - long c - ) const - { - return ptr[r*width + c]; - } - - long nr() const { return height; } - long nc() const { return width; } - - template <typename EXP> - assignable_ptr_matrix& operator= ( - const matrix_exp<EXP>& exp - ) - { - // You can only assign to a set_ptrm() expression with a source matrix that - // contains the same type of elements as the target (i.e. you can't mix double - // and float types). - COMPILE_TIME_ASSERT((is_same_type<T, typename EXP::type>::value == true)); - - DLIB_ASSERT( exp.nr() == height && exp.nc() == width, - "\tassignable_matrix_expression set_ptrm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\twidth (target matrix): " << width - << "\n\theight (target matrix): " << height - ); - - if (exp.destructively_aliases(mat(ptr,height,width)) == false) - { - matrix_assign(*this, exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to ptr to - // avoid aliasing issues during the copy - this->operator=(tmp(exp)); - } - - return *this; - } - - template <typename EXP> - assignable_ptr_matrix& operator+= ( - const matrix_exp<EXP>& exp - ) - { - // You can only assign to a set_ptrm() expression with a source matrix that - // contains the same type of elements as the target (i.e. you can't mix double - // and float types). - COMPILE_TIME_ASSERT((is_same_type<T, typename EXP::type>::value == true)); - - DLIB_ASSERT( exp.nr() == height && exp.nc() == width, - "\tassignable_matrix_expression set_ptrm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\twidth (target matrix): " << width - << "\n\theight (target matrix): " << height - ); - - if (exp.destructively_aliases(mat(ptr,height,width)) == false) - { - matrix_assign(*this, mat(ptr,height,width)+exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to ptr to - // avoid aliasing issues during the copy - this->operator+=(tmp(exp)); - } - - return *this; - } - - template <typename EXP> - assignable_ptr_matrix& operator-= ( - const matrix_exp<EXP>& exp - ) - { - // You can only assign to a set_ptrm() expression with a source matrix that - // contains the same type of elements as the target (i.e. you can't mix double - // and float types). - COMPILE_TIME_ASSERT((is_same_type<T, typename EXP::type>::value == true)); - - DLIB_ASSERT( exp.nr() == height && exp.nc() == width, - "\tassignable_matrix_expression set_ptrm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\twidth (target matrix): " << width - << "\n\theight (target matrix): " << height - ); - - if (exp.destructively_aliases(mat(ptr,height,width)) == false) - { - matrix_assign(*this, mat(ptr,height,width)-exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to ptr to - // avoid aliasing issues during the copy - this->operator-=(tmp(exp)); - } - - return *this; - } - - assignable_ptr_matrix& operator= ( - const T& value - ) - { - const long size = width*height; - for (long i = 0; i < size; ++i) - ptr[i] = value; - - return *this; - } - - assignable_ptr_matrix& operator+= ( - const T& value - ) - { - const long size = width*height; - for (long i = 0; i < size; ++i) - ptr[i] += value; - - return *this; - } - - assignable_ptr_matrix& operator-= ( - const T& value - ) - { - const long size = width*height; - for (long i = 0; i < size; ++i) - ptr[i] -= value; - - return *this; - } - - - T* ptr; - const long height; - const long width; - }; - - - template <typename T> - assignable_ptr_matrix<T> set_ptrm ( - T* ptr, - long nr, - long nc = 1 - ) - { - DLIB_ASSERT(nr >= 0 && nc >= 0, - "\t assignable_matrix_expression set_ptrm(T* ptr, long nr, long nc)" - << "\n\t The dimensions can't be negative." - << "\n\t nr: " << nr - << "\n\t nc: " << nc - ); - - - return assignable_ptr_matrix<T>(ptr,nr,nc); - } - -// ---------------------------------------------------------------------------------------- - - template <typename T, long NR, long NC, typename mm, typename l> - class assignable_sub_matrix - { - public: - typedef T type; - typedef l layout_type; - typedef matrix<T,NR,NC,mm,l> matrix_type; - - assignable_sub_matrix( - matrix<T,NR,NC,mm,l>& m_, - long top_, - long left_, - long height_, - long width_ - ) : m(m_), left(left_), top(top_), width(width_), height(height_) {} - - T& operator() ( - long r, - long c - ) - { - return m(r+top,c+left); - } - - const T& operator() ( - long r, - long c - ) const - { - return m(r+top,c+left); - } - - long nr() const { return height; } - long nc() const { return width; } - - template <typename EXP> - assignable_sub_matrix& operator= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nr() == height && exp.nc() == width, - "\tassignable_matrix_expression set_subm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\twidth (target matrix): " << width - << "\n\theight (target matrix): " << height - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator=(tmp(exp)); - } - - return *this; - } - - template <typename EXP> - assignable_sub_matrix& operator+= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nr() == height && exp.nc() == width, - "\tassignable_matrix_expression set_subm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\twidth (target matrix): " << width - << "\n\theight (target matrix): " << height - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, subm(m,top,left,height,width)+exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator+=(tmp(exp)); - } - - return *this; - } - - template <typename EXP> - assignable_sub_matrix& operator-= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nr() == height && exp.nc() == width, - "\tassignable_matrix_expression set_subm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\twidth (target matrix): " << width - << "\n\theight (target matrix): " << height - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, subm(m,top,left,height,width)-exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator-=(tmp(exp)); - } - - return *this; - } - - assignable_sub_matrix& operator= ( - const T& value - ) - { - const long bottom = top+height-1; - const long right = left+width-1; - for (long r = top; r <= bottom; ++r) - { - for (long c = left; c <= right; ++c) - { - m(r,c) = value; - } - } - - return *this; - } - - assignable_sub_matrix& operator+= ( - const T& value - ) - { - const long bottom = top+height-1; - const long right = left+width-1; - for (long r = top; r <= bottom; ++r) - { - for (long c = left; c <= right; ++c) - { - m(r,c) += value; - } - } - - return *this; - } - - assignable_sub_matrix& operator-= ( - const T& value - ) - { - const long bottom = top+height-1; - const long right = left+width-1; - for (long r = top; r <= bottom; ++r) - { - for (long c = left; c <= right; ++c) - { - m(r,c) -= value; - } - } - - return *this; - } - - - matrix<T,NR,NC,mm,l>& m; - const long left, top, width, height; - }; - - - template <typename T, long NR, long NC, typename mm, typename l> - assignable_sub_matrix<T,NR,NC,mm,l> set_subm ( - matrix<T,NR,NC,mm,l>& m, - const rectangle& rect - ) - { - DLIB_ASSERT(get_rect(m).contains(rect) == true, - "\tassignable_matrix_expression set_subm(matrix& m, const rectangle& rect)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\trect.left(): " << rect.left() - << "\n\trect.top(): " << rect.top() - << "\n\trect.right(): " << rect.right() - << "\n\trect.bottom(): " << rect.bottom() - ); - - - return assignable_sub_matrix<T,NR,NC,mm,l>(m,rect.top(), rect.left(), rect.height(), rect.width()); - } - - - template <typename T, long NR, long NC, typename mm, typename l> - assignable_sub_matrix<T,NR,NC,mm,l> set_subm ( - matrix<T,NR,NC,mm,l>& m, - long r, - long c, - long nr, - long nc - ) - { - DLIB_ASSERT(r >= 0 && c >= 0 && nr >= 0 && nc >= 0 && r+nr <= m.nr() && c+nc <= m.nc(), - "\tassignable_matrix_expression set_subm(matrix& m, r, c, nr, nc)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tr: " << r - << "\n\tc: " << c - << "\n\tnr: " << nr - << "\n\tnc: " << nc - ); - - return assignable_sub_matrix<T,NR,NC,mm,l>(m,r,c, nr, nc); - } - -// ---------------------------------------------------------------------------------------- - - template <typename T, long NR, long NC, typename mm, typename l, typename EXPr, typename EXPc> - class assignable_sub_range_matrix - { - public: - typedef T type; - typedef l layout_type; - typedef matrix<T,NR,NC,mm,l> matrix_type; - - assignable_sub_range_matrix( - matrix<T,NR,NC,mm,l>& m_, - const EXPr& rows_, - const EXPc& cols_ - ) : m(m_), rows(rows_), cols(cols_) {} - - T& operator() ( - long r, - long c - ) - { - return m(rows(r),cols(c)); - } - - long nr() const { return rows.size(); } - long nc() const { return cols.size(); } - - - template <typename EXP> - assignable_sub_range_matrix& operator= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nr() == rows.size() && exp.nc() == cols.size(), - "\tassignable_matrix_expression set_subm(matrix& m, const matrix_exp rows, const matrix_exp cols)" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\trows.size() (target matrix): " << rows.size() - << "\n\tcols.size() (target matrix): " << cols.size() - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator=(tmp(exp)); - } - - return *this; - } - - template <typename EXP> - assignable_sub_range_matrix& operator+= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nr() == rows.size() && exp.nc() == cols.size(), - "\tassignable_matrix_expression set_subm(matrix& m, const matrix_exp rows, const matrix_exp cols)" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\trows.size() (target matrix): " << rows.size() - << "\n\tcols.size() (target matrix): " << cols.size() - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, subm(m,rows,cols)+exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator+=(tmp(exp)); - } - - return *this; - } - - template <typename EXP> - assignable_sub_range_matrix& operator-= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nr() == rows.size() && exp.nc() == cols.size(), - "\tassignable_matrix_expression set_subm(matrix& m, const matrix_exp rows, const matrix_exp cols)" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\trows.size() (target matrix): " << rows.size() - << "\n\tcols.size() (target matrix): " << cols.size() - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, subm(m,rows,cols)-exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator-=(tmp(exp)); - } - - return *this; - } - - assignable_sub_range_matrix& operator= ( - const T& value - ) - { - for (long r = 0; r < rows.size(); ++r) - { - for (long c = 0; c < cols.size(); ++c) - { - m(rows(r),cols(c)) = value; - } - } - - return *this; - } - - assignable_sub_range_matrix& operator+= ( - const T& value - ) - { - for (long r = 0; r < rows.size(); ++r) - { - for (long c = 0; c < cols.size(); ++c) - { - m(rows(r),cols(c)) += value; - } - } - - return *this; - } - - assignable_sub_range_matrix& operator-= ( - const T& value - ) - { - for (long r = 0; r < rows.size(); ++r) - { - for (long c = 0; c < cols.size(); ++c) - { - m(rows(r),cols(c)) -= value; - } - } - - return *this; - } - - private: - - matrix<T,NR,NC,mm,l>& m; - const EXPr rows; - const EXPc cols; - }; - - template <typename T, long NR, long NC, typename mm, typename l, typename EXPr, typename EXPc> - assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,EXPc > set_subm ( - matrix<T,NR,NC,mm,l>& m, - const matrix_exp<EXPr>& rows, - const matrix_exp<EXPc>& cols - ) - { - DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && 0 <= min(cols) && max(cols) < m.nc() && - (rows.nr() == 1 || rows.nc() == 1) && (cols.nr() == 1 || cols.nc() == 1), - "\tassignable_matrix_expression set_subm(matrix& m, const matrix_exp& rows, const matrix_exp& cols)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tmin(rows): " << min(rows) - << "\n\tmax(rows): " << max(rows) - << "\n\tmin(cols): " << min(cols) - << "\n\tmax(cols): " << max(cols) - << "\n\trows.nr(): " << rows.nr() - << "\n\trows.nc(): " << rows.nc() - << "\n\tcols.nr(): " << cols.nr() - << "\n\tcols.nc(): " << cols.nc() - ); - - return assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,EXPc >(m,rows.ref(),cols.ref()); - } - -// ---------------------------------------------------------------------------------------- - - template <typename T, long NR, long NC, typename mm, typename l, typename EXPr> - assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,matrix_range_exp<long> > set_rowm ( - matrix<T,NR,NC,mm,l>& m, - const matrix_exp<EXPr>& rows - ) - { - DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && (rows.nr() == 1 || rows.nc() == 1), - "\tassignable_matrix_expression set_rowm(matrix& m, const matrix_exp& rows)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tmin(rows): " << min(rows) - << "\n\tmax(rows): " << max(rows) - << "\n\trows.nr(): " << rows.nr() - << "\n\trows.nc(): " << rows.nc() - ); - - return assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,matrix_range_exp<long> >(m,rows.ref(),range(0,m.nc()-1)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename T, long NR, long NC, typename mm, typename l, typename EXPc> - assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_range_exp<long>,EXPc > set_colm ( - matrix<T,NR,NC,mm,l>& m, - const matrix_exp<EXPc>& cols - ) - { - DLIB_ASSERT(0 <= min(cols) && max(cols) < m.nc() && (cols.nr() == 1 || cols.nc() == 1), - "\tassignable_matrix_expression set_colm(matrix& m, const matrix_exp& cols)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tmin(cols): " << min(cols) - << "\n\tmax(cols): " << max(cols) - << "\n\tcols.nr(): " << cols.nr() - << "\n\tcols.nc(): " << cols.nc() - ); - - return assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_range_exp<long>,EXPc >(m,range(0,m.nr()-1),cols.ref()); - } - -// ---------------------------------------------------------------------------------------- - - template <typename T, long NR, long NC, typename mm, typename l> - class assignable_col_matrix - { - public: - typedef T type; - typedef l layout_type; - typedef matrix<T,NR,NC,mm,l> matrix_type; - - assignable_col_matrix( - matrix<T,NR,NC,mm,l>& m_, - const long col_ - ) : m(m_), col(col_) {} - - T& operator() ( - long r, - long - ) - { - return m(r,col); - } - - const T& operator() ( - long r, - long - ) const - { - return m(r,col); - } - - long nr() const { return m.nr(); } - long nc() const { return 1; } - - template <typename EXP> - assignable_col_matrix& operator= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nc() == 1 && exp.nr() == m.nr(), - "\tassignable_matrix_expression set_colm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\tm.nr() (target matrix): " << m.nr() - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator=(tmp(exp)); - } - - return *this; - } - - template <typename EXP> - assignable_col_matrix& operator+= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nc() == 1 && exp.nr() == m.nr(), - "\tassignable_matrix_expression set_colm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\tm.nr() (target matrix): " << m.nr() - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, colm(m,col)+exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator+=(tmp(exp)); - } - - return *this; - } - - template <typename EXP> - assignable_col_matrix& operator-= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nc() == 1 && exp.nr() == m.nr(), - "\tassignable_matrix_expression set_colm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\tm.nr() (target matrix): " << m.nr() - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, colm(m,col)-exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator-=(tmp(exp)); - } - - return *this; - } - - assignable_col_matrix& operator= ( - const T& value - ) - { - for (long i = 0; i < m.nr(); ++i) - { - m(i,col) = value; - } - - return *this; - } - - assignable_col_matrix& operator+= ( - const T& value - ) - { - for (long i = 0; i < m.nr(); ++i) - { - m(i,col) += value; - } - - return *this; - } - - assignable_col_matrix& operator-= ( - const T& value - ) - { - for (long i = 0; i < m.nr(); ++i) - { - m(i,col) -= value; - } - - return *this; - } - - - matrix<T,NR,NC,mm,l>& m; - const long col; - }; - - - template <typename T, long NR, long NC, typename mm, typename l> - assignable_col_matrix<T,NR,NC,mm,l> set_colm ( - matrix<T,NR,NC,mm,l>& m, - const long col - ) - { - DLIB_ASSERT(col >= 0 && col < m.nc(), - "\tassignable_matrix_expression set_colm(matrix& m, col)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tcol: " << col - ); - - - return assignable_col_matrix<T,NR,NC,mm,l>(m,col); - } - -// ---------------------------------------------------------------------------------------- - - - template <typename T, long NR, long NC, typename mm, typename l> - class assignable_row_matrix - { - public: - typedef T type; - typedef l layout_type; - typedef matrix<T,NR,NC,mm,l> matrix_type; - - assignable_row_matrix( - matrix<T,NR,NC,mm,l>& m_, - const long row_ - ) : m(m_), row(row_) {} - - - T& operator() ( - long , - long c - ) - { - return m(row,c); - } - - const T& operator() ( - long , - long c - ) const - { - return m(row,c); - } - - long nr() const { return 1; } - long nc() const { return m.nc(); } - - - template <typename EXP> - assignable_row_matrix& operator= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nr() == 1 && exp.nc() == m.nc(), - "\tassignable_matrix_expression set_rowm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\tm.nc() (target matrix): " << m.nc() - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator=(tmp(exp)); - } - - return *this; - } - - template <typename EXP> - assignable_row_matrix& operator+= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nr() == 1 && exp.nc() == m.nc(), - "\tassignable_matrix_expression set_rowm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\tm.nc() (target matrix): " << m.nc() - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, rowm(m,row)+exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator+=(tmp(exp)); - } - - return *this; - } - - template <typename EXP> - assignable_row_matrix& operator-= ( - const matrix_exp<EXP>& exp - ) - { - DLIB_ASSERT( exp.nr() == 1 && exp.nc() == m.nc(), - "\tassignable_matrix_expression set_rowm()" - << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" - << "\n\texp.nr() (source matrix): " << exp.nr() - << "\n\texp.nc() (source matrix): " << exp.nc() - << "\n\tm.nc() (target matrix): " << m.nc() - ); - - if (exp.destructively_aliases(m) == false) - { - matrix_assign(*this, rowm(m,row)-exp); - } - else - { - // make a temporary copy of the matrix we are going to assign to m to - // avoid aliasing issues during the copy - this->operator-=(tmp(exp)); - } - - return *this; - } - - assignable_row_matrix& operator= ( - const T& value - ) - { - for (long i = 0; i < m.nc(); ++i) - { - m(row,i) = value; - } - - return *this; - } - - assignable_row_matrix& operator+= ( - const T& value - ) - { - for (long i = 0; i < m.nc(); ++i) - { - m(row,i) += value; - } - - return *this; - } - - assignable_row_matrix& operator-= ( - const T& value - ) - { - for (long i = 0; i < m.nc(); ++i) - { - m(row,i) -= value; - } - - return *this; - } - - - matrix<T,NR,NC,mm,l>& m; - const long row; - }; - - - template <typename T, long NR, long NC, typename mm, typename l> - assignable_row_matrix<T,NR,NC,mm,l> set_rowm ( - matrix<T,NR,NC,mm,l>& m, - const long row - ) - { - DLIB_ASSERT(row >= 0 && row < m.nr(), - "\tassignable_matrix_expression set_rowm(matrix& m, row)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\trow: " << row - ); - - - return assignable_row_matrix<T,NR,NC,mm,l>(m,row); - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_SUBEXP_ - diff --git a/ml/dlib/dlib/matrix/matrix_subexp_abstract.h b/ml/dlib/dlib/matrix/matrix_subexp_abstract.h deleted file mode 100644 index 2665d1b99..000000000 --- a/ml/dlib/dlib/matrix/matrix_subexp_abstract.h +++ /dev/null @@ -1,570 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_MATRIx_SUBEXP_ABSTRACT_ -#ifdef DLIB_MATRIx_SUBEXP_ABSTRACT_ - -#include "matrix_abstract.h" -#include "../geometry/rectangle.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - template <long start, long inc, long end> - const matrix_exp range ( - ); - /*! - requires - - inc > 0 - ensures - - returns a matrix R such that: - - R::type == long - - R.nr() == 1 - - R.nc() == abs(end - start)/inc + 1 - - if (start <= end) then - - R(i) == start + i*inc - - else - - R(i) == start - i*inc - !*/ - - template <long start, long end> - const matrix_exp range ( - ) { return range<start,1,end>(); } - - const matrix_exp range ( - long start, - long inc, - long end - ); - /*! - requires - - inc > 0 - ensures - - returns a matrix R such that: - - R::type == long - - R.nr() == 1 - - R.nc() == abs(end - start)/inc + 1 - - if (start <= end) then - - R(i) == start + i*inc - - else - - R(i) == start - i*inc - !*/ - - const matrix_exp range ( - long start, - long end - ) { return range(start,1,end); } - -// ---------------------------------------------------------------------------------------- - - const matrix_exp subm ( - const matrix_exp& m, - const matrix_exp& rows, - const matrix_exp& cols, - ); - /*! - requires - - rows and cols contain integral elements (e.g. int, long) - - 0 <= min(rows) && max(rows) < m.nr() - - 0 <= min(cols) && max(cols) < m.nc() - - rows.nr() == 1 || rows.nc() == 1 - - cols.nr() == 1 || cols.nc() == 1 - (i.e. rows and cols must be vectors) - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R.nr() == rows.size() - - R.nc() == cols.size() - - for all valid r and c: - R(r,c) == m(rows(r),cols(c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp subm ( - const matrix_exp& m, - long row, - long col, - long nr, - long nc - ); - /*! - requires - - row >= 0 - - col >= 0 - - nr >= 0 - - nc >= 0 - - row + nr <= m.nr() - - col + nc <= m.nc() - ensures - - returns a matrix R such that: - - R.nr() == nr - - R.nc() == nc - - for all valid r and c: - R(r, c) == m(r+row,c+col) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp subm ( - const matrix_exp& m, - const rectangle& rect - ); - /*! - requires - - get_rect(m).contains(rect) == true - (i.e. rect is a region inside the matrix m) - ensures - - returns a matrix R such that: - - R.nr() == rect.height() - - R.nc() == rect.width() - - for all valid r and c: - R(r, c) == m(r+rect.top(), c+rect.left()) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp subm_clipped ( - const matrix_exp& m, - long row, - long col, - long nr, - long nc - ); - /*! - ensures - - This function is just like subm() except that it will automatically clip the - indicated sub matrix window so that it does not extend outside m. - In particular: - - Let box = rectangle(col,row,col+nc-1,row+nr-1) - (i.e. the box that contains the indicated sub matrix) - - Let box_clipped = box.intersect(get_rect(m)) - - Then this function returns a matrix R such that: - - R.nr() == box_clipped.height() - - R.nc() == box_clipped.width() - - for all valid r and c: - R(r, c) == m(r+box_clipped.top(),c+box_clipped.left()) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp subm_clipped ( - const matrix_exp& m, - const rectangle& rect - ); - /*! - ensures - - Let box_clipped == rect.intersect(get_rect(m)) - - returns a matrix R such that: - - R.nr() == box_clipped.height() - - R.nc() == box_clipped.width() - - for all valid r and c: - R(r, c) == m(r+box_clipped.top(), c+box_clipped.left()) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp rowm ( - const matrix_exp& m, - long row - ); - /*! - requires - - 0 <= row < m.nr() - ensures - - returns a matrix R such that: - - R.nr() == 1 - - R.nc() == m.nc() - - for all valid i: - R(i) == m(row,i) - !*/ - - template <typename EXP> - struct rowm_exp - { - /*! - WHAT THIS OBJECT REPRESENTS - This struct allows you to determine the type of matrix expression - object returned from the rowm(m,row) function. An example makes its - use clear: - - template <typename EXP> - void do_something( const matrix_exp<EXP>& mat) - { - // r is a matrix expression that aliases mat. - typename rowm_exp<EXP>::type r = rowm(mat,0); - - // Print the first row of mat. So we see that by using - // rowm_exp we can save the object returned by rowm() in - // a local variable. - cout << r << endl; - - // Note that you can only save the return value of rowm() to - // a local variable if the argument to rowm() has a lifetime - // beyond the rowm() expression. The example shown above is - // OK but the following would result in undefined behavior: - typename rowm_exp<EXP>::type bad = rowm(mat + mat,0); - } - !*/ - typedef type_of_expression_returned_by_rowm type; - }; - -// ---------------------------------------------------------------------------------------- - - const matrix_exp rowm ( - const matrix_exp& m, - long row, - long length - ); - /*! - requires - - 0 <= row < m.nr() - - 0 <= length <= m.nc() - ensures - - returns a matrix R such that: - - R.nr() == 1 - - R.nc() == length - - for all valid i: - R(i) == m(row,i) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp rowm ( - const matrix_exp& m, - const matrix_exp& rows - ); - /*! - requires - - rows contains integral elements (e.g. int, long) - - 0 <= min(rows) && max(rows) < m.nr() - - rows.nr() == 1 || rows.nc() == 1 - (i.e. rows must be a vector) - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R.nr() == rows.size() - - R.nc() == m.nc() - - for all valid r and c: - R(r,c) == m(rows(r),c) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp colm ( - const matrix_exp& m, - long col - ); - /*! - requires - - 0 <= col < m.nc() - ensures - - returns a matrix R such that: - - R.nr() == m.nr() - - R.nc() == 1 - - for all valid i: - R(i) == m(i,col) - !*/ - - template <typename EXP> - struct colm_exp - { - /*! - WHAT THIS OBJECT REPRESENTS - This struct allows you to determine the type of matrix expression - object returned from the colm(m,col) function. An example makes its - use clear: - - template <typename EXP> - void do_something( const matrix_exp<EXP>& mat) - { - // c is a matrix expression that aliases mat. - typename colm_exp<EXP>::type c = colm(mat,0); - - // Print the first column of mat. So we see that by using - // colm_exp we can save the object returned by colm() in - // a local variable. - cout << c << endl; - - // Note that you can only save the return value of colm() to - // a local variable if the argument to colm() has a lifetime - // beyond the colm() expression. The example shown above is - // OK but the following would result in undefined behavior: - typename colm_exp<EXP>::type bad = colm(mat + mat,0); - } - !*/ - typedef type_of_expression_returned_by_colm type; - }; - -// ---------------------------------------------------------------------------------------- - - const matrix_exp colm ( - const matrix_exp& m, - long col, - long length - ); - /*! - requires - - 0 <= col < m.nc() - - 0 <= length <= m.nr() - ensures - - returns a matrix R such that: - - R.nr() == length - - R.nc() == 1 - - for all valid i: - R(i) == m(i,col) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp colm ( - const matrix_exp& m, - const matrix_exp& cols - ); - /*! - requires - - cols contains integral elements (e.g. int, long) - - 0 <= min(cols) && max(cols) < m.nc() - - cols.nr() == 1 || cols.nc() == 1 - (i.e. cols must be a vector) - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R.nr() == m.nr() - - R.nc() == cols.size() - - for all valid r and c: - R(r,c) == m(r,cols(c)) - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename T> - assignable_matrix_expression set_ptrm ( - T* ptr, - long nr, - long nc = 1 - ); - /*! - requires - - ptr == a pointer to nr*nc elements of type T - - nr >= 0 - - nc >= 0 - ensures - - statements of the following form: - - set_ptrm(ptr,nr,nc) = some_matrix; - result in it being the case that: - - mat(ptr,nr,nc) == some_matrix. - - - statements of the following form: - - set_ptrm(ptr,nr,nc) = scalar_value; - result in it being the case that: - - mat(ptr,nr,nc) == uniform_matrix<matrix::type>(nr,nc,scalar_value). - - - In addition to the normal assignment statements using the = symbol, you may - also use the usual += and -= versions of the assignment operator. In these - cases, they have their usual effect. - !*/ - -// ---------------------------------------------------------------------------------------- - - assignable_matrix_expression set_subm ( - matrix& m, - long row, - long col, - long nr, - long nc - ); - /*! - requires - - row >= 0 - - col >= 0 - - nr >= 0 - - nc >= 0 - - row + nr <= m.nr() - - col + nc <= m.nc() - ensures - - statements of the following form: - - set_subm(m,row,col,nr,nc) = some_matrix; - result in it being the case that: - - subm(m,row,col,nr,nc) == some_matrix. - - - statements of the following form: - - set_subm(m,row,col,nr,nc) = scalar_value; - result in it being the case that: - - subm(m,row,col,nr,nc) == uniform_matrix<matrix::type>(nr,nc,scalar_value). - - - In addition to the normal assignment statements using the = symbol, you may - also use the usual += and -= versions of the assignment operator. In these - cases, they have their usual effect. - !*/ - -// ---------------------------------------------------------------------------------------- - - assignable_matrix_expression set_subm ( - matrix& m, - const rectangle& rect - ); - /*! - requires - - get_rect(m).contains(rect) == true - (i.e. rect is a region inside the matrix m) - ensures - - statements of the following form: - - set_subm(m,rect) = some_matrix; - result in it being the case that: - - subm(m,rect) == some_matrix. - - - statements of the following form: - - set_subm(m,rect) = scalar_value; - result in it being the case that: - - subm(m,rect) == uniform_matrix<matrix::type>(nr,nc,scalar_value). - - - In addition to the normal assignment statements using the = symbol, you may - also use the usual += and -= versions of the assignment operator. In these - cases, they have their usual effect. - !*/ - -// ---------------------------------------------------------------------------------------- - - assignable_matrix_expression set_subm ( - matrix& m, - const matrix_exp& rows, - const matrix_exp& cols - ); - /*! - requires - - rows and cols contain integral elements (e.g. int, long) - - 0 <= min(rows) && max(rows) < m.nr() - - 0 <= min(cols) && max(cols) < m.nc() - - rows.nr() == 1 || rows.nc() == 1 - - cols.nr() == 1 || cols.nc() == 1 - (i.e. rows and cols must be vectors) - ensures - - statements of the following form: - - set_subm(m,rows,cols) = some_matrix; - result in it being the case that: - - subm(m,rows,cols) == some_matrix. - - - statements of the following form: - - set_subm(m,rows,cols) = scalar_value; - result in it being the case that: - - subm(m,rows,cols) == uniform_matrix<matrix::type>(nr,nc,scalar_value). - - - In addition to the normal assignment statements using the = symbol, you may - also use the usual += and -= versions of the assignment operator. In these - cases, they have their usual effect. - !*/ - -// ---------------------------------------------------------------------------------------- - - assignable_matrix_expression set_rowm ( - matrix& m, - long row - ); - /*! - requires - - 0 <= row < m.nr() - ensures - - statements of the following form: - - set_rowm(m,row) = some_matrix; - result in it being the case that: - - rowm(m,row) == some_matrix. - - - statements of the following form: - - set_rowm(m,row) = scalar_value; - result in it being the case that: - - rowm(m,row) == uniform_matrix<matrix::type>(1,nc,scalar_value). - - - In addition to the normal assignment statements using the = symbol, you may - also use the usual += and -= versions of the assignment operator. In these - cases, they have their usual effect. - !*/ - -// ---------------------------------------------------------------------------------------- - - assignable_matrix_expression set_rowm ( - matrix& m, - const matrix_exp& rows - ); - /*! - requires - - rows contains integral elements (e.g. int, long) - - 0 <= min(rows) && max(rows) < m.nr() - - rows.nr() == 1 || rows.nc() == 1 - (i.e. rows must be a vector) - ensures - - statements of the following form: - - set_rowm(m,rows) = some_matrix; - result in it being the case that: - - rowm(m,rows) == some_matrix. - - - statements of the following form: - - set_rowm(m,rows) = scalar_value; - result in it being the case that: - - rowm(m,rows) == uniform_matrix<matrix::type>(nr,nc,scalar_value). - - - In addition to the normal assignment statements using the = symbol, you may - also use the usual += and -= versions of the assignment operator. In these - cases, they have their usual effect. - !*/ - -// ---------------------------------------------------------------------------------------- - - assignable_matrix_expression set_colm ( - matrix& m, - long col - ); - /*! - requires - - 0 <= col < m.nr() - ensures - - statements of the following form: - - set_colm(m,col) = some_matrix; - result in it being the case that: - - colm(m,col) == some_matrix. - - - statements of the following form: - - set_colm(m,col) = scalar_value; - result in it being the case that: - - colm(m,col) == uniform_matrix<matrix::type>(nr,1,scalar_value). - - - In addition to the normal assignment statements using the = symbol, you may - also use the usual += and -= versions of the assignment operator. In these - cases, they have their usual effect. - !*/ - -// ---------------------------------------------------------------------------------------- - - assignable_matrix_expression set_colm ( - matrix& m, - const matrix_exp& cols - ); - /*! - requires - - cols contains integral elements (e.g. int, long) - - 0 <= min(cols) && max(cols) < m.nc() - - cols.nr() == 1 || cols.nc() == 1 - (i.e. cols must be a vector) - ensures - - statements of the following form: - - set_colm(m,cols) = some_matrix; - result in it being the case that: - - colm(m,cols) == some_matrix. - - - statements of the following form: - - set_colm(m,cols) = scalar_value; - result in it being the case that: - - colm(m,cols) == uniform_matrix<matrix::type>(nr,nc,scalar_value). - - - In addition to the normal assignment statements using the = symbol, you may - also use the usual += and -= versions of the assignment operator. In these - cases, they have their usual effect. - !*/ - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_SUBEXP_ABSTRACT_ - diff --git a/ml/dlib/dlib/matrix/matrix_trsm.h b/ml/dlib/dlib/matrix/matrix_trsm.h deleted file mode 100644 index ef5ec5ed9..000000000 --- a/ml/dlib/dlib/matrix/matrix_trsm.h +++ /dev/null @@ -1,654 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRiX_TRSM_Hh_ -#define DLIB_MATRiX_TRSM_Hh_ -#include "lapack/fortran_id.h" -#include "cblas_constants.h" - -namespace dlib -{ - namespace blas_bindings - { -#ifdef DLIB_USE_BLAS -#ifndef CBLAS_H - extern "C" - { - void cblas_strsm(const CBLAS_ORDER Order, const CBLAS_SIDE Side, - const CBLAS_UPLO Uplo, const CBLAS_TRANSPOSE TransA, - const CBLAS_DIAG Diag, const int M, const int N, - const float alpha, const float *A, const int lda, - float *B, const int ldb); - - void cblas_dtrsm(const CBLAS_ORDER Order, const CBLAS_SIDE Side, - const CBLAS_UPLO Uplo, const CBLAS_TRANSPOSE TransA, - const CBLAS_DIAG Diag, const int M, const int N, - const double alpha, const double *A, const int lda, - double *B, const int ldb); - } -#endif // if not CBLAS_H -#endif // if DLIB_USE_BLAS - - // ------------------------------------------------------------------------------------ - -/* Purpose */ -/* ======= */ - -/* DTRSM solves one of the matrix equations */ - -/* op( A )*X = alpha*B, or X*op( A ) = alpha*B, */ - -/* where alpha is a scalar, X and B are m by n matrices, A is a unit, or */ -/* non-unit, upper or lower triangular matrix and op( A ) is one of */ - -/* op( A ) = A or op( A ) = A'. */ - -/* The matrix X is overwritten on B. */ - -/* Arguments */ -/* ========== */ - -/* SIDE - CHARACTER*1. */ -/* On entry, SIDE specifies whether op( A ) appears on the left */ -/* or right of X as follows: */ - -/* SIDE = 'L' or 'l' op( A )*X = alpha*B. */ - -/* SIDE = 'R' or 'r' X*op( A ) = alpha*B. */ - -/* Unchanged on exit. */ - -/* UPLO - CHARACTER*1. */ -/* On entry, UPLO specifies whether the matrix A is an upper or */ -/* lower triangular matrix as follows: */ - -/* UPLO = 'U' or 'u' A is an upper triangular matrix. */ - -/* UPLO = 'L' or 'l' A is a lower triangular matrix. */ - -/* Unchanged on exit. */ - -/* TRANSA - CHARACTER*1. */ -/* On entry, TRANSA specifies the form of op( A ) to be used in */ -/* the matrix multiplication as follows: */ - -/* TRANSA = 'N' or 'n' op( A ) = A. */ - -/* TRANSA = 'T' or 't' op( A ) = A'. */ - -/* TRANSA = 'C' or 'c' op( A ) = A'. */ - -/* Unchanged on exit. */ - -/* DIAG - CHARACTER*1. */ -/* On entry, DIAG specifies whether or not A is unit triangular */ -/* as follows: */ - -/* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ - -/* DIAG = 'N' or 'n' A is not assumed to be unit */ -/* triangular. */ - -/* Unchanged on exit. */ - -/* M - INTEGER. */ -/* On entry, M specifies the number of rows of B. M must be at */ -/* least zero. */ -/* Unchanged on exit. */ - -/* N - INTEGER. */ -/* On entry, N specifies the number of columns of B. N must be */ -/* at least zero. */ -/* Unchanged on exit. */ - -/* ALPHA - DOUBLE PRECISION. */ -/* On entry, ALPHA specifies the scalar alpha. When alpha is */ -/* zero then A is not referenced and B need not be set before */ -/* entry. */ -/* Unchanged on exit. */ - -/* A - DOUBLE PRECISION array of DIMENSION ( LDA, k ), where k is m */ -/* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. */ -/* Before entry with UPLO = 'U' or 'u', the leading k by k */ -/* upper triangular part of the array A must contain the upper */ -/* triangular matrix and the strictly lower triangular part of */ -/* A is not referenced. */ -/* Before entry with UPLO = 'L' or 'l', the leading k by k */ -/* lower triangular part of the array A must contain the lower */ -/* triangular matrix and the strictly upper triangular part of */ -/* A is not referenced. */ -/* Note that when DIAG = 'U' or 'u', the diagonal elements of */ -/* A are not referenced either, but are assumed to be unity. */ -/* Unchanged on exit. */ - -/* LDA - INTEGER. */ -/* On entry, LDA specifies the first dimension of A as declared */ -/* in the calling (sub) program. When SIDE = 'L' or 'l' then */ -/* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' */ -/* then LDA must be at least max( 1, n ). */ -/* Unchanged on exit. */ - -/* B - DOUBLE PRECISION array of DIMENSION ( LDB, n ). */ -/* Before entry, the leading m by n part of the array B must */ -/* contain the right-hand side matrix B, and on exit is */ -/* overwritten by the solution matrix X. */ - -/* LDB - INTEGER. */ -/* On entry, LDB specifies the first dimension of B as declared */ -/* in the calling (sub) program. LDB must be at least */ -/* max( 1, m ). */ -/* Unchanged on exit. */ - - -/* Level 3 Blas routine. */ - - -/* -- Written on 8-February-1989. */ -/* Jack Dongarra, Argonne National Laboratory. */ -/* Iain Duff, AERE Harwell. */ -/* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ -/* Sven Hammarling, Numerical Algorithms Group Ltd. */ - - template <typename T> - void local_trsm( - const CBLAS_ORDER Order, - CBLAS_SIDE Side, - CBLAS_UPLO Uplo, - const CBLAS_TRANSPOSE TransA, - const CBLAS_DIAG Diag, - long m, - long n, - T alpha, - const T *a, - long lda, - T *b, - long ldb - ) - /*! - This is a copy of the dtrsm routine from the netlib.org BLAS which was run though - f2c and converted into this form for use when a BLAS library is not available. - !*/ - { - if (Order == CblasRowMajor) - { - // since row major ordering looks like transposition to FORTRAN we need to flip a - // few things. - if (Side == CblasLeft) - Side = CblasRight; - else - Side = CblasLeft; - - if (Uplo == CblasUpper) - Uplo = CblasLower; - else - Uplo = CblasUpper; - - std::swap(m,n); - } - - /* System generated locals */ - long a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3; - - /* Local variables */ - long i__, j, k, info; - T temp; - bool lside; - long nrowa; - bool upper; - bool nounit; - - /* Parameter adjustments */ - a_dim1 = lda; - a_offset = 1 + a_dim1; - a -= a_offset; - b_dim1 = ldb; - b_offset = 1 + b_dim1; - b -= b_offset; - - /* Function Body */ - lside = (Side == CblasLeft); - if (lside) - { - nrowa = m; - } else - { - nrowa = n; - } - nounit = (Diag == CblasNonUnit); - upper = (Uplo == CblasUpper); - - info = 0; - if (! lside && ! (Side == CblasRight)) { - info = 1; - } else if (! upper && !(Uplo == CblasLower) ) { - info = 2; - } else if (!(TransA == CblasNoTrans) && - !(TransA == CblasTrans) && - !(TransA == CblasConjTrans)) { - info = 3; - } else if (!(Diag == CblasUnit) && - !(Diag == CblasNonUnit) ) { - info = 4; - } else if (m < 0) { - info = 5; - } else if (n < 0) { - info = 6; - } else if (lda < std::max<long>(1,nrowa)) { - info = 9; - } else if (ldb < std::max<long>(1,m)) { - info = 11; - } - DLIB_CASSERT( info == 0, "Invalid inputs given to local_trsm"); - - /* Quick return if possible. */ - - if (m == 0 || n == 0) { - return; - } - - /* And when alpha.eq.zero. */ - - if (alpha == 0.) { - i__1 = n; - for (j = 1; j <= i__1; ++j) { - i__2 = m; - for (i__ = 1; i__ <= i__2; ++i__) { - b[i__ + j * b_dim1] = 0.; - /* L10: */ - } - /* L20: */ - } - return; - } - - /* Start the operations. */ - - if (lside) { - if (TransA == CblasNoTrans) { - - /* Form B := alpha*inv( A )*B. */ - - if (upper) { - i__1 = n; - for (j = 1; j <= i__1; ++j) { - if (alpha != 1.) { - i__2 = m; - for (i__ = 1; i__ <= i__2; ++i__) { - b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] - ; - /* L30: */ - } - } - for (k = m; k >= 1; --k) { - if (b[k + j * b_dim1] != 0.) { - if (nounit) { - b[k + j * b_dim1] /= a[k + k * a_dim1]; - } - i__2 = k - 1; - for (i__ = 1; i__ <= i__2; ++i__) { - b[i__ + j * b_dim1] -= b[k + j * b_dim1] * a[ - i__ + k * a_dim1]; - /* L40: */ - } - } - /* L50: */ - } - /* L60: */ - } - } else { - i__1 = n; - for (j = 1; j <= i__1; ++j) { - if (alpha != 1.) { - i__2 = m; - for (i__ = 1; i__ <= i__2; ++i__) { - b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] - ; - /* L70: */ - } - } - i__2 = m; - for (k = 1; k <= i__2; ++k) { - if (b[k + j * b_dim1] != 0.) { - if (nounit) { - b[k + j * b_dim1] /= a[k + k * a_dim1]; - } - i__3 = m; - for (i__ = k + 1; i__ <= i__3; ++i__) { - b[i__ + j * b_dim1] -= b[k + j * b_dim1] * a[ - i__ + k * a_dim1]; - /* L80: */ - } - } - /* L90: */ - } - /* L100: */ - } - } - } else { - - /* Form B := alpha*inv( A' )*B. */ - - if (upper) { - i__1 = n; - for (j = 1; j <= i__1; ++j) { - i__2 = m; - for (i__ = 1; i__ <= i__2; ++i__) { - temp = alpha * b[i__ + j * b_dim1]; - i__3 = i__ - 1; - for (k = 1; k <= i__3; ++k) { - temp -= a[k + i__ * a_dim1] * b[k + j * b_dim1]; - /* L110: */ - } - if (nounit) { - temp /= a[i__ + i__ * a_dim1]; - } - b[i__ + j * b_dim1] = temp; - /* L120: */ - } - /* L130: */ - } - } else { - i__1 = n; - for (j = 1; j <= i__1; ++j) { - for (i__ = m; i__ >= 1; --i__) { - temp = alpha * b[i__ + j * b_dim1]; - i__2 = m; - for (k = i__ + 1; k <= i__2; ++k) { - temp -= a[k + i__ * a_dim1] * b[k + j * b_dim1]; - /* L140: */ - } - if (nounit) { - temp /= a[i__ + i__ * a_dim1]; - } - b[i__ + j * b_dim1] = temp; - /* L150: */ - } - /* L160: */ - } - } - } - } else { - if (TransA == CblasNoTrans) { - - /* Form B := alpha*B*inv( A ). */ - - if (upper) { - i__1 = n; - for (j = 1; j <= i__1; ++j) { - if (alpha != 1.) { - i__2 = m; - for (i__ = 1; i__ <= i__2; ++i__) { - b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] - ; - /* L170: */ - } - } - i__2 = j - 1; - for (k = 1; k <= i__2; ++k) { - if (a[k + j * a_dim1] != 0.) { - i__3 = m; - for (i__ = 1; i__ <= i__3; ++i__) { - b[i__ + j * b_dim1] -= a[k + j * a_dim1] * b[ - i__ + k * b_dim1]; - /* L180: */ - } - } - /* L190: */ - } - if (nounit) { - temp = 1. / a[j + j * a_dim1]; - i__2 = m; - for (i__ = 1; i__ <= i__2; ++i__) { - b[i__ + j * b_dim1] = temp * b[i__ + j * b_dim1]; - /* L200: */ - } - } - /* L210: */ - } - } else { - for (j = n; j >= 1; --j) { - if (alpha != 1.) { - i__1 = m; - for (i__ = 1; i__ <= i__1; ++i__) { - b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] - ; - /* L220: */ - } - } - i__1 = n; - for (k = j + 1; k <= i__1; ++k) { - if (a[k + j * a_dim1] != 0.) { - i__2 = m; - for (i__ = 1; i__ <= i__2; ++i__) { - b[i__ + j * b_dim1] -= a[k + j * a_dim1] * b[ - i__ + k * b_dim1]; - /* L230: */ - } - } - /* L240: */ - } - if (nounit) { - temp = 1. / a[j + j * a_dim1]; - i__1 = m; - for (i__ = 1; i__ <= i__1; ++i__) { - b[i__ + j * b_dim1] = temp * b[i__ + j * b_dim1]; - /* L250: */ - } - } - /* L260: */ - } - } - } else { - - /* Form B := alpha*B*inv( A' ). */ - - if (upper) { - for (k = n; k >= 1; --k) { - if (nounit) { - temp = 1. / a[k + k * a_dim1]; - i__1 = m; - for (i__ = 1; i__ <= i__1; ++i__) { - b[i__ + k * b_dim1] = temp * b[i__ + k * b_dim1]; - /* L270: */ - } - } - i__1 = k - 1; - for (j = 1; j <= i__1; ++j) { - if (a[j + k * a_dim1] != 0.) { - temp = a[j + k * a_dim1]; - i__2 = m; - for (i__ = 1; i__ <= i__2; ++i__) { - b[i__ + j * b_dim1] -= temp * b[i__ + k * - b_dim1]; - /* L280: */ - } - } - /* L290: */ - } - if (alpha != 1.) { - i__1 = m; - for (i__ = 1; i__ <= i__1; ++i__) { - b[i__ + k * b_dim1] = alpha * b[i__ + k * b_dim1] - ; - /* L300: */ - } - } - /* L310: */ - } - } else { - i__1 = n; - for (k = 1; k <= i__1; ++k) { - if (nounit) { - temp = 1. / a[k + k * a_dim1]; - i__2 = m; - for (i__ = 1; i__ <= i__2; ++i__) { - b[i__ + k * b_dim1] = temp * b[i__ + k * b_dim1]; - /* L320: */ - } - } - i__2 = n; - for (j = k + 1; j <= i__2; ++j) { - if (a[j + k * a_dim1] != 0.) { - temp = a[j + k * a_dim1]; - i__3 = m; - for (i__ = 1; i__ <= i__3; ++i__) { - b[i__ + j * b_dim1] -= temp * b[i__ + k * - b_dim1]; - /* L330: */ - } - } - /* L340: */ - } - if (alpha != 1.) { - i__2 = m; - for (i__ = 1; i__ <= i__2; ++i__) { - b[i__ + k * b_dim1] = alpha * b[i__ + k * b_dim1] - ; - /* L350: */ - } - } - /* L360: */ - } - } - } - } - } - - // ------------------------------------------------------------------------------------ - - inline void cblas_trsm(const CBLAS_ORDER Order, const CBLAS_SIDE Side, - const CBLAS_UPLO Uplo, const CBLAS_TRANSPOSE TransA, - const CBLAS_DIAG Diag, const int M, const int N, - const float alpha, const float *A, const int lda, - float *B, const int ldb) - { -#ifdef DLIB_USE_BLAS - if (M > 4) - { - cblas_strsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); - return; - } -#endif - local_trsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); - } - - inline void cblas_trsm(const CBLAS_ORDER Order, const CBLAS_SIDE Side, - const CBLAS_UPLO Uplo, const CBLAS_TRANSPOSE TransA, - const CBLAS_DIAG Diag, const int M, const int N, - const double alpha, const double *A, const int lda, - double *B, const int ldb) - { -#ifdef DLIB_USE_BLAS - if (M > 4) - { - cblas_dtrsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); - return; - } -#endif - local_trsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); - } - - inline void cblas_trsm(const CBLAS_ORDER Order, const CBLAS_SIDE Side, - const CBLAS_UPLO Uplo, const CBLAS_TRANSPOSE TransA, - const CBLAS_DIAG Diag, const int M, const int N, - const long double alpha, const long double *A, const int lda, - long double *B, const int ldb) - { - local_trsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, - long NC1, long NC2, - typename MM - > - inline void triangular_solver ( - const CBLAS_SIDE Side, - const CBLAS_UPLO Uplo, - const CBLAS_TRANSPOSE TransA, - const CBLAS_DIAG Diag, - const matrix<T,NR1,NC1,MM,row_major_layout>& A, - const T alpha, - matrix<T,NR2,NC2,MM,row_major_layout>& B - ) - { - cblas_trsm(CblasRowMajor, Side, Uplo, TransA, Diag, B.nr(), B.nc(), - alpha, &A(0,0), A.nc(), &B(0,0), B.nc()); - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, - long NC1, long NC2, - typename MM - > - inline void triangular_solver ( - const CBLAS_SIDE Side, - const CBLAS_UPLO Uplo, - const CBLAS_TRANSPOSE TransA, - const CBLAS_DIAG Diag, - const matrix<T,NR1,NC1,MM,column_major_layout>& A, - const T alpha, - matrix<T,NR2,NC2,MM,column_major_layout>& B - ) - { - cblas_trsm(CblasColMajor, Side, Uplo, TransA, Diag, B.nr(), B.nc(), - alpha, &A(0,0), A.nr(), &B(0,0), B.nr()); - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, - long NC1, long NC2, - typename MM - > - inline void triangular_solver ( - const CBLAS_SIDE Side, - const CBLAS_UPLO Uplo, - const CBLAS_TRANSPOSE TransA, - const CBLAS_DIAG Diag, - const matrix<T,NR1,NC1,MM,column_major_layout>& A, - matrix<T,NR2,NC2,MM,column_major_layout>& B, - long rows_of_B - ) - { - const T alpha = 1; - cblas_trsm(CblasColMajor, Side, Uplo, TransA, Diag, rows_of_B, B.nc(), - alpha, &A(0,0), A.nr(), &B(0,0), B.nr()); - } - - // ------------------------------------------------------------------------------------ - - template < - typename T, - long NR1, long NR2, - long NC1, long NC2, - typename MM, - typename layout - > - inline void triangular_solver ( - const CBLAS_SIDE Side, - const CBLAS_UPLO Uplo, - const CBLAS_TRANSPOSE TransA, - const CBLAS_DIAG Diag, - const matrix<T,NR1,NC1,MM,layout>& A, - matrix<T,NR2,NC2,MM,layout>& B - ) - { - const T alpha = 1; - triangular_solver(Side, Uplo, TransA, Diag, A, alpha, B); - } - - // ------------------------------------------------------------------------------------ - - } -} - -#endif // DLIB_MATRiX_TRSM_Hh_ - diff --git a/ml/dlib/dlib/matrix/matrix_utilities.h b/ml/dlib/dlib/matrix/matrix_utilities.h deleted file mode 100644 index 0c5091a4b..000000000 --- a/ml/dlib/dlib/matrix/matrix_utilities.h +++ /dev/null @@ -1,4544 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_MATRIx_UTILITIES_ -#define DLIB_MATRIx_UTILITIES_ - -#include "matrix_utilities_abstract.h" -#include "matrix.h" -#include <cmath> -#include <complex> -#include <limits> -#include "../pixel.h" -#include "../stl_checked.h" -#include <vector> -#include <algorithm> -#include "../std_allocator.h" -#include "matrix_expressions.h" -#include "matrix_math_functions.h" -#include "matrix_op.h" -#include "../general_hash/random_hashing.h" -#include "matrix_mat.h" - - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - /*!A is_complex - This is a template that can be used to determine if a type is a specialization - of the std::complex template class. - - For example: - is_complex<float>::value == false - is_complex<std::complex<float> >::value == true - !*/ - - template <typename T> - struct is_complex { static const bool value = false; }; - - template <typename T> - struct is_complex<std::complex<T> > { static const bool value = true; }; - template <typename T> - struct is_complex<std::complex<T>& > { static const bool value = true; }; - template <typename T> - struct is_complex<const std::complex<T>& > { static const bool value = true; }; - template <typename T> - struct is_complex<const std::complex<T> > { static const bool value = true; }; - -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - inline bool is_row_vector ( - const matrix_exp<EXP>& m - ) { return m.nr() == 1; } - - template <typename EXP> - inline bool is_col_vector ( - const matrix_exp<EXP>& m - ) { return m.nc() == 1; } - - template <typename EXP> - inline bool is_vector ( - const matrix_exp<EXP>& m - ) { return is_row_vector(m) || is_col_vector(m); } - -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - inline bool is_finite ( - const matrix_exp<EXP>& m - ) - { - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - if (!is_finite(m(r,c))) - return false; - } - } - return true; - } - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - template <typename T> - const T& magnitude (const T& item) { return item; } - template <typename T> - T magnitude (const std::complex<T>& item) { return std::norm(item); } - } - - template < - typename EXP - > - void find_min_and_max ( - const matrix_exp<EXP>& m, - typename EXP::type& min_val, - typename EXP::type& max_val - ) - { - DLIB_ASSERT(m.size() > 0, - "\ttype find_min_and_max(const matrix_exp& m, min_val, max_val)" - << "\n\tYou can't ask for the min and max of an empty matrix" - << "\n\tm.size(): " << m.size() - ); - typedef typename matrix_exp<EXP>::type type; - - min_val = m(0,0); - max_val = min_val; - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - type temp = m(r,c); - if (dlib::impl::magnitude(temp) > dlib::impl::magnitude(max_val)) - max_val = temp; - if (dlib::impl::magnitude(temp) < dlib::impl::magnitude(min_val)) - min_val = temp; - } - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - point max_point ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(m.size() > 0, - "\tpoint max_point(const matrix_exp& m)" - << "\n\tm can't be empty" - << "\n\tm.size(): " << m.size() - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - typedef typename matrix_exp<EXP>::type type; - - point best_point(0,0); - type val = m(0,0); - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - type temp = m(r,c); - if (dlib::impl::magnitude(temp) > dlib::impl::magnitude(val)) - { - val = temp; - best_point = point(c,r); - } - } - } - return best_point; - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - point min_point ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(m.size() > 0, - "\tpoint min_point(const matrix_exp& m)" - << "\n\tm can't be empty" - << "\n\tm.size(): " << m.size() - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - typedef typename matrix_exp<EXP>::type type; - - point best_point(0,0); - type val = m(0,0); - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - type temp = m(r,c); - if (dlib::impl::magnitude(temp) < dlib::impl::magnitude(val)) - { - val = temp; - best_point = point(c,r); - } - } - } - return best_point; - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - long index_of_max ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(m.size() > 0 && is_vector(m) == true, - "\tlong index_of_max(const matrix_exp& m)" - << "\n\tm must be a row or column matrix" - << "\n\tm.size(): " << m.size() - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - typedef typename matrix_exp<EXP>::type type; - - type val = m(0); - long best_idx = 0; - for (long i = 1; i < m.size(); ++i) - { - type temp = m(i); - if (dlib::impl::magnitude(temp) > dlib::impl::magnitude(val)) - { - val = temp; - best_idx = i; - } - } - return best_idx; - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - long index_of_min ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(m.size() > 0 && is_vector(m), - "\tlong index_of_min(const matrix_exp& m)" - << "\n\tm must be a row or column matrix" - << "\n\tm.size(): " << m.size() - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - typedef typename matrix_exp<EXP>::type type; - - type val = m(0); - long best_idx = 0; - for (long i = 1; i < m.size(); ++i) - { - type temp = m(i); - if (dlib::impl::magnitude(temp) < dlib::impl::magnitude(val)) - { - val = temp; - best_idx = i; - } - } - return best_idx; - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const typename matrix_exp<EXP>::type max ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(m.size() > 0, - "\ttype max(const matrix_exp& m)" - << "\n\tYou can't ask for the max() of an empty matrix" - << "\n\tm.size(): " << m.size() - ); - typedef typename matrix_exp<EXP>::type type; - - type val = m(0,0); - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - type temp = m(r,c); - if (dlib::impl::magnitude(temp) > dlib::impl::magnitude(val)) - val = temp; - } - } - return val; - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const typename matrix_exp<EXP>::type min ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(m.size() > 0, - "\ttype min(const matrix_exp& m)" - << "\n\tYou can't ask for the min() of an empty matrix" - << "\n\tm.size(): " << m.size() - ); - typedef typename matrix_exp<EXP>::type type; - - type val = m(0,0); - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - type temp = m(r,c); - if (dlib::impl::magnitude(temp) < dlib::impl::magnitude(val)) - val = temp; - } - } - return val; - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_binary_min : basic_op_mm<M1,M2> - { - op_binary_min( const M1& m1_, const M2& m2_) : basic_op_mm<M1,M2>(m1_,m2_){} - - typedef typename M1::type type; - typedef const type const_ret_type; - const static long cost = M1::cost + M2::cost + 1; - - const_ret_type apply ( long r, long c) const - { return std::min(this->m1(r,c),this->m2(r,c)); } - }; - - template < - typename EXP1, - typename EXP2 - > - inline const matrix_op<op_binary_min<EXP1,EXP2> > min_pointwise ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); - COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0); - DLIB_ASSERT(a.nr() == b.nr() && - a.nc() == b.nc(), - "\t const matrix_exp min_pointwise(const matrix_exp& a, const matrix_exp& b)" - << "\n\ta.nr(): " << a.nr() - << "\n\ta.nc(): " << a.nc() - << "\n\tb.nr(): " << b.nr() - << "\n\tb.nc(): " << b.nc() - ); - typedef op_binary_min<EXP1,EXP2> op; - return matrix_op<op>(op(a.ref(),b.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2, typename M3> - struct op_min_pointwise3 : basic_op_mmm<M1,M2,M3> - { - op_min_pointwise3( const M1& m1_, const M2& m2_, const M3& m3_) : - basic_op_mmm<M1,M2,M3>(m1_,m2_,m3_){} - - typedef typename M1::type type; - typedef const typename M1::type const_ret_type; - const static long cost = M1::cost + M2::cost + M3::cost + 2; - - const_ret_type apply (long r, long c) const - { return std::min(this->m1(r,c),std::min(this->m2(r,c),this->m3(r,c))); } - }; - - template < - typename EXP1, - typename EXP2, - typename EXP3 - > - inline const matrix_op<op_min_pointwise3<EXP1,EXP2,EXP3> > - min_pointwise ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b, - const matrix_exp<EXP3>& c - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - COMPILE_TIME_ASSERT((is_same_type<typename EXP2::type,typename EXP3::type>::value == true)); - COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); - COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NR == 0 || EXP2::NC == 0); - COMPILE_TIME_ASSERT(EXP2::NR == EXP3::NR || EXP2::NR == 0 || EXP3::NR == 0); - COMPILE_TIME_ASSERT(EXP2::NC == EXP3::NC || EXP2::NC == 0 || EXP3::NC == 0); - DLIB_ASSERT(a.nr() == b.nr() && - a.nc() == b.nc() && - b.nr() == c.nr() && - b.nc() == c.nc(), - "\tconst matrix_exp min_pointwise(a,b,c)" - << "\n\tYou can only make a do a pointwise min between equally sized matrices" - << "\n\ta.nr(): " << a.nr() - << "\n\ta.nc(): " << a.nc() - << "\n\tb.nr(): " << b.nr() - << "\n\tb.nc(): " << b.nc() - << "\n\tc.nr(): " << c.nr() - << "\n\tc.nc(): " << c.nc() - ); - - typedef op_min_pointwise3<EXP1,EXP2,EXP3> op; - return matrix_op<op>(op(a.ref(),b.ref(),c.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_binary_max : basic_op_mm<M1,M2> - { - op_binary_max( const M1& m1_, const M2& m2_) : basic_op_mm<M1,M2>(m1_,m2_){} - - typedef typename M1::type type; - typedef const type const_ret_type; - const static long cost = M1::cost + M2::cost + 1; - - const_ret_type apply ( long r, long c) const - { return std::max(this->m1(r,c),this->m2(r,c)); } - }; - - template < - typename EXP1, - typename EXP2 - > - inline const matrix_op<op_binary_max<EXP1,EXP2> > max_pointwise ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); - COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0); - DLIB_ASSERT(a.nr() == b.nr() && - a.nc() == b.nc(), - "\t const matrix_exp max_pointwise(const matrix_exp& a, const matrix_exp& b)" - << "\n\ta.nr(): " << a.nr() - << "\n\ta.nc(): " << a.nc() - << "\n\tb.nr(): " << b.nr() - << "\n\tb.nc(): " << b.nc() - ); - typedef op_binary_max<EXP1,EXP2> op; - return matrix_op<op>(op(a.ref(),b.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2, typename M3> - struct op_max_pointwise3 : basic_op_mmm<M1,M2,M3> - { - op_max_pointwise3( const M1& m1_, const M2& m2_, const M3& m3_) : - basic_op_mmm<M1,M2,M3>(m1_,m2_,m3_){} - - typedef typename M1::type type; - typedef const typename M1::type const_ret_type; - const static long cost = M1::cost + M2::cost + M3::cost + 2; - - const_ret_type apply (long r, long c) const - { return std::max(this->m1(r,c),std::max(this->m2(r,c),this->m3(r,c))); } - }; - - template < - typename EXP1, - typename EXP2, - typename EXP3 - > - inline const matrix_op<op_max_pointwise3<EXP1,EXP2,EXP3> > - max_pointwise ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b, - const matrix_exp<EXP3>& c - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - COMPILE_TIME_ASSERT((is_same_type<typename EXP2::type,typename EXP3::type>::value == true)); - COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); - COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NR == 0 || EXP2::NC == 0); - COMPILE_TIME_ASSERT(EXP2::NR == EXP3::NR || EXP2::NR == 0 || EXP3::NR == 0); - COMPILE_TIME_ASSERT(EXP2::NC == EXP3::NC || EXP2::NC == 0 || EXP3::NC == 0); - DLIB_ASSERT(a.nr() == b.nr() && - a.nc() == b.nc() && - b.nr() == c.nr() && - b.nc() == c.nc(), - "\tconst matrix_exp max_pointwise(a,b,c)" - << "\n\tYou can only make a do a pointwise max between equally sized matrices" - << "\n\ta.nr(): " << a.nr() - << "\n\ta.nc(): " << a.nc() - << "\n\tb.nr(): " << b.nr() - << "\n\tb.nc(): " << b.nc() - << "\n\tc.nr(): " << c.nr() - << "\n\tc.nc(): " << c.nc() - ); - - typedef op_max_pointwise3<EXP1,EXP2,EXP3> op; - return matrix_op<op>(op(a.ref(),b.ref(),c.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - typename enable_if_c<std::numeric_limits<typename EXP::type>::is_integer, double>::type length ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(is_vector(m) == true, - "\ttype length(const matrix_exp& m)" - << "\n\tm must be a row or column vector" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - - return std::sqrt(static_cast<double>(sum(squared(m)))); - } - - template < - typename EXP - > - typename disable_if_c<std::numeric_limits<typename EXP::type>::is_integer, const typename EXP::type>::type length ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(is_vector(m) == true, - "\ttype length(const matrix_exp& m)" - << "\n\tm must be a row or column vector" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - return std::sqrt(sum(squared(m))); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const typename matrix_exp<EXP>::type length_squared ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(is_vector(m) == true, - "\ttype length_squared(const matrix_exp& m)" - << "\n\tm must be a row or column vector" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - return sum(squared(m)); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_trans - { - op_trans( const M& m_) : m(m_){} - - const M& m; - - const static long cost = M::cost; - const static long NR = M::NC; - const static long NC = M::NR; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - - const_ret_type apply (long r, long c) const { return m(c,r); } - - long nr () const { return m.nc(); } - long nc () const { return m.nr(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - - }; - - template < - typename M - > - const matrix_op<op_trans<M> > trans ( - const matrix_exp<M>& m - ) - { - typedef op_trans<M> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - -// don't to anything at all for diagonal matrices - template < - typename M - > - const matrix_diag_exp<M>& trans ( - const matrix_diag_exp<M>& m - ) - { - return m; - } - -// ---------------------------------------------------------------------------------------- - -// I introduced this struct because it avoids an inane compiler warning from gcc - template <typename EXP> - struct is_not_ct_vector{ static const bool value = (EXP::NR != 1 && EXP::NC != 1); }; - - template < - typename EXP1, - typename EXP2 - > - typename enable_if_c<(is_not_ct_vector<EXP1>::value) || (is_not_ct_vector<EXP2>::value), - typename EXP1::type>::type - dot ( - const matrix_exp<EXP1>& m1, - const matrix_exp<EXP2>& m2 - ) - { - // You are getting an error on this line because you are trying to - // compute the dot product between two matrices that aren't both vectors (i.e. - // they aren't column or row matrices). - COMPILE_TIME_ASSERT(EXP1::NR*EXP1::NC == 0 || - EXP2::NR*EXP2::NC == 0); - - DLIB_ASSERT(is_vector(m1) && is_vector(m2) && m1.size() == m2.size() && - m1.size() > 0, - "\t type dot(const matrix_exp& m1, const matrix_exp& m2)" - << "\n\t You can only compute the dot product between non-empty vectors of equal length." - << "\n\t is_vector(m1): " << is_vector(m1) - << "\n\t is_vector(m2): " << is_vector(m2) - << "\n\t m1.size(): " << m1.size() - << "\n\t m2.size(): " << m2.size() - ); - - if (is_col_vector(m1) && is_col_vector(m2)) return (trans(m1)*m2)(0); - if (is_col_vector(m1) && is_row_vector(m2)) return (m2*m1)(0); - if (is_row_vector(m1) && is_col_vector(m2)) return (m1*m2)(0); - - //if (is_row_vector(m1) && is_row_vector(m2)) - return (m1*trans(m2))(0); - } - - template < typename EXP1, typename EXP2 > - typename enable_if_c<EXP1::NR == 1 && EXP2::NR == 1 && EXP1::NC != 1 && EXP2::NC != 1, typename EXP1::type>::type - dot ( const matrix_exp<EXP1>& m1, const matrix_exp<EXP2>& m2) - { - DLIB_ASSERT(m1.size() == m2.size(), - "\t type dot(const matrix_exp& m1, const matrix_exp& m2)" - << "\n\t You can only compute the dot product between vectors of equal length" - << "\n\t m1.size(): " << m1.size() - << "\n\t m2.size(): " << m2.size() - ); - - return m1*trans(m2); - } - - template < typename EXP1, typename EXP2 > - typename enable_if_c<EXP1::NR == 1 && EXP2::NC == 1 && EXP1::NC != 1 && EXP2::NR != 1, typename EXP1::type>::type - dot ( const matrix_exp<EXP1>& m1, const matrix_exp<EXP2>& m2) - { - DLIB_ASSERT(m1.size() == m2.size(), - "\t type dot(const matrix_exp& m1, const matrix_exp& m2)" - << "\n\t You can only compute the dot product between vectors of equal length" - << "\n\t m1.size(): " << m1.size() - << "\n\t m2.size(): " << m2.size() - ); - - return m1*m2; - } - - template < typename EXP1, typename EXP2 > - typename enable_if_c<EXP1::NC == 1 && EXP2::NR == 1 && EXP1::NR != 1 && EXP2::NC != 1, typename EXP1::type>::type - dot ( const matrix_exp<EXP1>& m1, const matrix_exp<EXP2>& m2) - { - DLIB_ASSERT(m1.size() == m2.size(), - "\t type dot(const matrix_exp& m1, const matrix_exp& m2)" - << "\n\t You can only compute the dot product between vectors of equal length" - << "\n\t m1.size(): " << m1.size() - << "\n\t m2.size(): " << m2.size() - ); - - return m2*m1; - } - - template < typename EXP1, typename EXP2 > - typename enable_if_c<EXP1::NC == 1 && EXP2::NC == 1 && EXP1::NR != 1 && EXP2::NR != 1, typename EXP1::type>::type - dot ( const matrix_exp<EXP1>& m1, const matrix_exp<EXP2>& m2) - { - DLIB_ASSERT(m1.size() == m2.size(), - "\t type dot(const matrix_exp& m1, const matrix_exp& m2)" - << "\n\t You can only compute the dot product between vectors of equal length" - << "\n\t m1.size(): " << m1.size() - << "\n\t m2.size(): " << m2.size() - ); - - return trans(m1)*m2; - } - - template < typename EXP1, typename EXP2 > - typename enable_if_c<(EXP1::NC*EXP1::NR == 1) || (EXP2::NC*EXP2::NR == 1), typename EXP1::type>::type - dot ( const matrix_exp<EXP1>& m1, const matrix_exp<EXP2>& m2) - { - DLIB_ASSERT(m1.size() == m2.size(), - "\t type dot(const matrix_exp& m1, const matrix_exp& m2)" - << "\n\t You can only compute the dot product between vectors of equal length" - << "\n\t m1.size(): " << m1.size() - << "\n\t m2.size(): " << m2.size() - ); - - return m1(0)*m2(0); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M, long R, long C> - struct op_removerc - { - op_removerc( const M& m_) : m(m_){} - - const M& m; - - const static long cost = M::cost+2; - const static long NR = (M::NR==0) ? 0 : (M::NR - 1); - const static long NC = (M::NC==0) ? 0 : (M::NC - 1); - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply (long r, long c) const - { - if (r < R) - { - if (c < C) - return m(r,c); - else - return m(r,c+1); - } - else - { - if (c < C) - return m(r+1,c); - else - return m(r+1,c+1); - } - } - - long nr () const { return m.nr() - 1; } - long nc () const { return m.nc() - 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template <typename M> - struct op_removerc2 - { - op_removerc2( const M& m_, const long R_, const long C_) : m(m_), R(R_), C(C_){} - const M& m; - const long R; - const long C; - - const static long cost = M::cost+2; - const static long NR = (M::NR==0) ? 0 : (M::NR - 1); - const static long NC = (M::NC==0) ? 0 : (M::NC - 1); - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply (long r, long c) const - { - if (r < R) - { - if (c < C) - return m(r,c); - else - return m(r,c+1); - } - else - { - if (c < C) - return m(r+1,c); - else - return m(r+1,c+1); - } - } - - long nr () const { return m.nr() - 1; } - long nc () const { return m.nc() - 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - long R, - long C, - typename EXP - > - const matrix_op<op_removerc<EXP,R,C> > removerc ( - const matrix_exp<EXP>& m - ) - { - // you can't remove a row from a matrix with only one row - COMPILE_TIME_ASSERT((EXP::NR > R && R >= 0) || EXP::NR == 0); - // you can't remove a column from a matrix with only one column - COMPILE_TIME_ASSERT((EXP::NC > C && C >= 0) || EXP::NR == 0); - DLIB_ASSERT(m.nr() > R && R >= 0 && m.nc() > C && C >= 0, - "\tconst matrix_exp removerc<R,C>(const matrix_exp& m)" - << "\n\tYou can't remove a row/column from a matrix if it doesn't have that row/column" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tR: " << R - << "\n\tC: " << C - ); - typedef op_removerc<EXP,R,C> op; - return matrix_op<op>(op(m.ref())); - } - - template < - typename EXP - > - const matrix_op<op_removerc2<EXP> > removerc ( - const matrix_exp<EXP>& m, - long R, - long C - ) - { - DLIB_ASSERT(m.nr() > R && R >= 0 && m.nc() > C && C >= 0, - "\tconst matrix_exp removerc(const matrix_exp& m,R,C)" - << "\n\tYou can't remove a row/column from a matrix if it doesn't have that row/column" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tR: " << R - << "\n\tC: " << C - ); - typedef op_removerc2<EXP> op; - return matrix_op<op>(op(m.ref(),R,C)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M, long C> - struct op_remove_col - { - op_remove_col( const M& m_) : m(m_){} - const M& m; - - const static long cost = M::cost+2; - const static long NR = M::NR; - const static long NC = (M::NC==0) ? 0 : (M::NC - 1); - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long c) const - { - if (c < C) - { - return m(r,c); - } - else - { - return m(r,c+1); - } - } - - long nr () const { return m.nr(); } - long nc () const { return m.nc() - 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template <typename M> - struct op_remove_col2 - { - op_remove_col2( const M& m_, const long C_) : m(m_), C(C_){} - const M& m; - const long C; - - const static long cost = M::cost+2; - const static long NR = M::NR; - const static long NC = (M::NC==0) ? 0 : (M::NC - 1); - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long c) const - { - if (c < C) - { - return m(r,c); - } - else - { - return m(r,c+1); - } - } - - long nr () const { return m.nr(); } - long nc () const { return m.nc() - 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - long C, - typename EXP - > - const matrix_op<op_remove_col<EXP, C> > remove_col ( - const matrix_exp<EXP>& m - ) - { - // You can't remove the given column from the matrix because the matrix doesn't - // have a column with that index. - COMPILE_TIME_ASSERT((EXP::NC > C && C >= 0) || EXP::NC == 0); - DLIB_ASSERT(m.nc() > C && C >= 0 , - "\tconst matrix_exp remove_col<C>(const matrix_exp& m)" - << "\n\tYou can't remove a col from a matrix if it doesn't have it" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tC: " << C - ); - typedef op_remove_col<EXP,C> op; - return matrix_op<op>(op(m.ref())); - } - - template < - typename EXP - > - const matrix_op<op_remove_col2<EXP> > remove_col ( - const matrix_exp<EXP>& m, - long C - ) - { - DLIB_ASSERT(m.nc() > C && C >= 0 , - "\tconst matrix_exp remove_col(const matrix_exp& m,C)" - << "\n\tYou can't remove a col from a matrix if it doesn't have it" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tC: " << C - ); - typedef op_remove_col2<EXP> op; - return matrix_op<op>(op(m.ref(),C)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M, long R> - struct op_remove_row - { - op_remove_row( const M& m_) : m(m_){} - const M& m; - - const static long cost = M::cost+2; - const static long NR = (M::NR==0) ? 0 : (M::NR - 1); - const static long NC = M::NC; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long c) const - { - if (r < R) - { - return m(r,c); - } - else - { - return m(r+1,c); - } - } - - long nr () const { return m.nr() - 1; } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template <typename M> - struct op_remove_row2 - { - op_remove_row2( const M& m_, const long R_) : m(m_), R(R_){} - const M& m; - const long R; - - const static long cost = M::cost+2; - const static long NR = (M::NR==0) ? 0 : (M::NR - 1); - const static long NC = M::NC; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long c) const - { - if (r < R) - { - return m(r,c); - } - else - { - return m(r+1,c); - } - } - - long nr () const { return m.nr() - 1; } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - long R, - typename EXP - > - const matrix_op<op_remove_row<EXP,R> > remove_row ( - const matrix_exp<EXP>& m - ) - { - // You can't remove the given row from the matrix because the matrix doesn't - // have a row with that index. - COMPILE_TIME_ASSERT((EXP::NR > R && R >= 0) || EXP::NR == 0); - DLIB_ASSERT(m.nr() > R && R >= 0, - "\tconst matrix_exp remove_row<R>(const matrix_exp& m)" - << "\n\tYou can't remove a row from a matrix if it doesn't have it" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tR: " << R - ); - typedef op_remove_row<EXP,R> op; - return matrix_op<op>(op(m.ref())); - } - - template < - typename EXP - > - const matrix_op<op_remove_row2<EXP> > remove_row ( - const matrix_exp<EXP>& m, - long R - ) - { - DLIB_ASSERT(m.nr() > R && R >= 0, - "\tconst matrix_exp remove_row(const matrix_exp& m, long R)" - << "\n\tYou can't remove a row from a matrix if it doesn't have it" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tR: " << R - ); - typedef op_remove_row2<EXP> op; - return matrix_op<op>(op(m.ref(),R)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_diagm - { - op_diagm( const M& m_) : m(m_){} - const M& m; - - const static long cost = M::cost+2; - const static long N = M::NC*M::NR; - const static long NR = N; - const static long NC = N; - typedef typename M::type type; - typedef const typename M::type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long c) const - { - if (r==c) - return m(r); - else - return 0; - } - - long nr () const { return (m.nr()>m.nc())? m.nr():m.nc(); } - long nc () const { return (m.nr()>m.nc())? m.nr():m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_diag_op<op_diagm<EXP> > diagm ( - const matrix_exp<EXP>& m - ) - { - // You can only make a diagonal matrix out of a row or column vector - COMPILE_TIME_ASSERT(EXP::NR == 0 || EXP::NR == 1 || EXP::NC == 1 || EXP::NC == 0); - DLIB_ASSERT(is_vector(m), - "\tconst matrix_exp diagm(const matrix_exp& m)" - << "\n\tYou can only apply diagm() to a row or column matrix" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - typedef op_diagm<EXP> op; - return matrix_diag_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_diagm_mult : basic_op_mm<M1,M2> - { - op_diagm_mult( const M1& m1_, const M2& m2_) : basic_op_mm<M1,M2>(m1_,m2_){} - - typedef typename M1::type type; - typedef const type const_ret_type; - const static long cost = M1::cost + M2::cost + 1; - - const_ret_type apply ( long r, long c) const - { - if (r == c) - return this->m1(r,c)*this->m2(r,c); - else - return 0; - } - }; - - template < - typename EXP1, - typename EXP2 - > - inline const matrix_diag_op<op_diagm_mult<EXP1,EXP2> > operator* ( - const matrix_diag_exp<EXP1>& a, - const matrix_diag_exp<EXP2>& b - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type, typename EXP2::type>::value)); - COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); - COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0); - DLIB_ASSERT(a.nr() == b.nr() && - a.nc() == b.nc(), - "\tconst matrix_exp operator(const matrix_diag_exp& a, const matrix_diag_exp& b)" - << "\n\tYou can only multiply diagonal matrices together if they are the same size" - << "\n\ta.nr(): " << a.nr() - << "\n\ta.nc(): " << a.nc() - << "\n\tb.nr(): " << b.nr() - << "\n\tb.nc(): " << b.nc() - ); - typedef op_diagm_mult<EXP1,EXP2> op; - return matrix_diag_op<op>(op(a.ref(),b.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_diag - { - op_diag( const M& m_) : m(m_){} - const M& m; - - const static long cost = M::cost; - const static long NR = tmin<M::NR,M::NC>::value; - const static long NC = 1; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long ) const { return m(r,r); } - - long nr () const { return std::min(m.nc(),m.nr()); } - long nc () const { return 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_op<op_diag<EXP> > diag ( - const matrix_exp<EXP>& m - ) - { - typedef op_diag<EXP> op; - return matrix_op<op>(op(m.ref())); - } - - template <typename EXP> - struct diag_exp - { - typedef matrix_op<op_diag<EXP> > type; - }; - -// ---------------------------------------------------------------------------------------- - - template <typename M, typename target_type> - struct op_cast - { - op_cast( const M& m_) : m(m_){} - const M& m; - - const static long cost = M::cost+2; - const static long NR = M::NR; - const static long NC = M::NC; - typedef target_type type; - typedef const target_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long c) const { return static_cast<target_type>(m(r,c)); } - - long nr () const { return m.nr(); } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.destructively_aliases(item); } - }; - - template < - typename target_type, - typename EXP - > - const matrix_op<op_cast<EXP, target_type> > matrix_cast ( - const matrix_exp<EXP>& m - ) - { - typedef op_cast<EXP, target_type> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - namespace impl - { - template <typename type, typename S> - inline type lessthan(const type& val, const S& s) - { - if (val < s) - return 1; - else - return 0; - } - - } - DLIB_DEFINE_OP_MS(op_lessthan, impl::lessthan, 1); - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_lessthan<EXP,S> > >::type operator< ( - const matrix_exp<EXP>& m, - const S& s - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_lessthan<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_lessthan<EXP,S> > >::type operator> ( - const S& s, - const matrix_exp<EXP>& m - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_lessthan<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - template <typename type, typename S> - inline type lessthan_eq(const type& val, const S& s) - { - if (val <= s) - return 1; - else - return 0; - } - - } - DLIB_DEFINE_OP_MS(op_lessthan_eq, impl::lessthan_eq, 1); - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_lessthan_eq<EXP,S> > >::type operator<= ( - const matrix_exp<EXP>& m, - const S& s - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_lessthan_eq<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_lessthan_eq<EXP,S> > >::type operator>= ( - const S& s, - const matrix_exp<EXP>& m - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_lessthan_eq<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - template <typename type, typename S> - inline type greaterthan(const type& val, const S& s) - { - if (val > s) - return 1; - else - return 0; - } - - } - DLIB_DEFINE_OP_MS(op_greaterthan, impl::greaterthan, 1); - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_greaterthan<EXP,S> > >::type operator> ( - const matrix_exp<EXP>& m, - const S& s - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_greaterthan<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_greaterthan<EXP,S> > >::type operator< ( - const S& s, - const matrix_exp<EXP>& m - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_greaterthan<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - template <typename type, typename S> - inline type greaterthan_eq(const type& val, const S& s) - { - if (val >= s) - return 1; - else - return 0; - } - - } - DLIB_DEFINE_OP_MS(op_greaterthan_eq, impl::greaterthan_eq, 1); - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_greaterthan_eq<EXP,S> > >::type operator>= ( - const matrix_exp<EXP>& m, - const S& s - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_greaterthan_eq<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_greaterthan_eq<EXP,S> > >::type operator<= ( - const S& s, - const matrix_exp<EXP>& m - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_greaterthan_eq<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - template <typename type, typename S> - inline type equal_to(const type& val, const S& s) - { - if (val == s) - return 1; - else - return 0; - } - - } - DLIB_DEFINE_OP_MS(op_equal_to, impl::equal_to, 1); - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_equal_to<EXP,S> > >::type operator== ( - const matrix_exp<EXP>& m, - const S& s - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT( is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_equal_to<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_equal_to<EXP,S> > >::type operator== ( - const S& s, - const matrix_exp<EXP>& m - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT( is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_equal_to<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - template <typename type, typename S> - inline type not_equal_to(const type& val, const S& s) - { - if (val != s) - return 1; - else - return 0; - } - - } - DLIB_DEFINE_OP_MS(op_not_equal_to, impl::not_equal_to, 1); - - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_not_equal_to<EXP,S> > >::type operator!= ( - const matrix_exp<EXP>& m, - const S& s - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_not_equal_to<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - - template < - typename EXP, - typename S - > - const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_not_equal_to<EXP,S> > >::type operator!= ( - const S& s, - const matrix_exp<EXP>& m - ) - { - // you can only use this relational operator with the built in scalar types like - // long, float, etc. - COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); - - typedef op_not_equal_to<EXP,S> op; - return matrix_op<op>(op(m.ref(),s)); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - typename MM, - typename U, - typename L - > - typename disable_if<is_matrix<U>,void>::type set_all_elements ( - matrix<T,NR,NC,MM,L>& m, - const U& value - ) - { - // The value you are trying to assign to each element of the m matrix - // doesn't have the appropriate type. - COMPILE_TIME_ASSERT(is_matrix<T>::value == is_matrix<U>::value); - - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - m(r,c) = static_cast<T>(value); - } - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - typename MM, - typename U, - typename L - > - typename enable_if<is_matrix<U>,void>::type set_all_elements ( - matrix<T,NR,NC,MM,L>& m, - const U& value - ) - { - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - m(r,c) = value; - } - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - inline const typename matrix_exp<EXP>::matrix_type tmp ( - const matrix_exp<EXP>& m - ) - { - return typename matrix_exp<EXP>::matrix_type (m); - } - -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - constexpr bool is_row_major ( - const matrix_exp<EXP>& - ) - { - return is_same_type<typename EXP::layout_type,row_major_layout>::value; - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const typename lazy_disable_if<is_matrix<typename EXP::type>, EXP>::type sum ( - const matrix_exp<EXP>& m - ) - { - typedef typename matrix_exp<EXP>::type type; - - type val = 0; - if (is_row_major(m)) - { - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - val += m(r,c); - } - } - } - else - { - for (long c = 0; c < m.nc(); ++c) - { - for (long r = 0; r < m.nr(); ++r) - { - val += m(r,c); - } - } - } - return val; - } - - template < - typename EXP - > - const typename lazy_enable_if<is_matrix<typename EXP::type>, EXP>::type sum ( - const matrix_exp<EXP>& m - ) - { - typedef typename matrix_exp<EXP>::type type; - - type val; - if (m.size() > 0) - val.set_size(m(0,0).nr(),m(0,0).nc()); - set_all_elements(val,0); - - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - val += m(r,c); - } - } - return val; - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_sumr - { - op_sumr(const M& m_) : m(m_) {} - const M& m; - - const static long cost = M::cost+10; - const static long NR = 1; - const static long NC = M::NC; - typedef typename M::type type; - typedef const typename M::type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long , long c) const - { - type temp = m(0,c); - for (long r = 1; r < m.nr(); ++r) - temp += m(r,c); - return temp; - } - - long nr () const { return 1; } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_op<op_sumr<EXP> > sum_rows ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(m.size() > 0 , - "\tconst matrix_exp sum_rows(m)" - << "\n\t The matrix can't be empty" - << "\n\t m.size(): " << m.size() - ); - typedef op_sumr<EXP> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_sumc - { - op_sumc(const M& m_) : m(m_) {} - const M& m; - - const static long cost = M::cost + 10; - const static long NR = M::NR; - const static long NC = 1; - typedef typename M::type type; - typedef const typename M::type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long ) const - { - type temp = m(r,0); - for (long c = 1; c < m.nc(); ++c) - temp += m(r,c); - return temp; - } - - long nr () const { return m.nr(); } - long nc () const { return 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_op<op_sumc<EXP> > sum_cols ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(m.size() > 0 , - "\tconst matrix_exp sum_cols(m)" - << "\n\t The matrix can't be empty" - << "\n\t m.size(): " << m.size() - ); - typedef op_sumc<EXP> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - inline const typename disable_if<is_complex<typename EXP::type>, typename matrix_exp<EXP>::type>::type mean ( - const matrix_exp<EXP>& m - ) - { - return sum(m)/(m.nr()*m.nc()); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - inline const typename enable_if<is_complex<typename EXP::type>, typename matrix_exp<EXP>::type>::type mean ( - const matrix_exp<EXP>& m - ) - { - typedef typename EXP::type::value_type type; - return sum(m)/(type)(m.nr()*m.nc()); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const typename matrix_exp<EXP>::type variance ( - const matrix_exp<EXP>& m - ) - { - using std::pow; - using dlib::pow; - const typename matrix_exp<EXP>::type avg = mean(m); - - typedef typename matrix_exp<EXP>::type type; - - type val; - val = 0; - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - val += pow(m(r,c) - avg,2); - } - } - - if (m.nr() * m.nc() <= 1) - { - return val; - } - else - { - // Note, for some reason, in gcc 4.1 performing this division using a - // double instead of a long value avoids a segmentation fault. That is, - // using 1.0 instead of 1 does the trick. - return val/(m.nr()*m.nc() - 1.0); - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const typename matrix_exp<EXP>::type stddev ( - const matrix_exp<EXP>& m - ) - { - using std::sqrt; - using dlib::sqrt; - return sqrt(variance(m)); - } - -// ---------------------------------------------------------------------------------------- - -// this is a workaround for a bug in visual studio 7.1 - template <typename EXP> - struct visual_studio_sucks_cov_helper - { - typedef typename EXP::type inner_type; - typedef matrix<typename inner_type::type, inner_type::NR, inner_type::NR, typename EXP::mem_manager_type> type; - }; - - template < - typename EXP - > - const typename visual_studio_sucks_cov_helper<EXP>::type covariance ( - const matrix_exp<EXP>& m - ) - { - // perform static checks to make sure m is a column vector - COMPILE_TIME_ASSERT(EXP::NR == 0 || EXP::NR > 1); - COMPILE_TIME_ASSERT(EXP::NC == 1 || EXP::NC == 0); - - // perform static checks to make sure the matrices contained in m are column vectors - COMPILE_TIME_ASSERT(EXP::type::NC == 1 || EXP::type::NC == 0 ); - - DLIB_ASSERT(m.size() > 1 && is_col_vector(m), - "\tconst matrix covariance(const matrix_exp& m)" - << "\n\tYou can only apply covariance() to a column matrix" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); -#ifdef ENABLE_ASSERTS - for (long i = 0; i < m.nr(); ++i) - { - DLIB_ASSERT(m(0).size() == m(i).size() && m(i).size() > 0 && is_col_vector(m(i)), - "\tconst matrix covariance(const matrix_exp& m)" - << "\n\tYou can only apply covariance() to a column matrix of column matrices" - << "\n\tm(0).size(): " << m(0).size() - << "\n\tm(i).size(): " << m(i).size() - << "\n\tis_col_vector(m(i)): " << (is_col_vector(m(i)) ? "true" : "false") - << "\n\ti: " << i - ); - } -#endif - - // now perform the actual calculation of the covariance matrix. - typename visual_studio_sucks_cov_helper<EXP>::type cov(m(0).nr(),m(0).nr()); - set_all_elements(cov,0); - - const typename EXP::type avg = mean(m); - - for (long r = 0; r < m.nr(); ++r) - { - cov += (m(r) - avg)*trans(m(r) - avg); - } - - cov *= 1.0 / (m.nr() - 1.0); - return cov; - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const typename matrix_exp<EXP>::type prod ( - const matrix_exp<EXP>& m - ) - { - typedef typename matrix_exp<EXP>::type type; - - type val = 1; - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - val *= m(r,c); - } - } - return val; - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - struct op_uniform_matrix_3 : does_not_alias - { - op_uniform_matrix_3(const long& rows_, const long& cols_, const T& val_ ) : - rows(rows_), cols(cols_), val(val_) {} - - const long rows; - const long cols; - const T val; - - const static long cost = 1; - const static long NR = 0; - const static long NC = 0; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - typedef T type; - typedef const T& const_ret_type; - const_ret_type apply (long, long ) const { return val; } - - long nr() const { return rows; } - long nc() const { return cols; } - }; - - template < - typename T - > - const matrix_op<op_uniform_matrix_3<T> > uniform_matrix ( - long nr, - long nc, - const T& val - ) - { - DLIB_ASSERT(nr >= 0 && nc >= 0, - "\tconst matrix_exp uniform_matrix<T>(nr, nc, val)" - << "\n\tnr and nc have to be bigger than 0" - << "\n\tnr: " << nr - << "\n\tnc: " << nc - ); - typedef op_uniform_matrix_3<T> op; - return matrix_op<op>(op(nr, nc, val)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_op<op_uniform_matrix_3<T> > zeros_matrix ( - long nr, - long nc - ) - { - DLIB_ASSERT(nr >= 0 && nc >= 0, - "\tconst matrix_exp zeros_matrix<T>(nr, nc)" - << "\n\tnr and nc have to be >= 0" - << "\n\tnr: " << nr - << "\n\tnc: " << nc - ); - typedef op_uniform_matrix_3<T> op; - return matrix_op<op>(op(nr, nc, 0)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const matrix_op<op_uniform_matrix_3<typename EXP::type> > zeros_matrix ( - const matrix_exp<EXP>& mat - ) - { - DLIB_ASSERT(mat.nr() >= 0 && mat.nc() >= 0, - "\tconst matrix_exp zeros_matrix(mat)" - << "\n\t nr and nc have to be >= 0" - << "\n\t mat.nr(): " << mat.nr() - << "\n\t mat.nc(): " << mat.nc() - ); - typedef typename EXP::type T; - typedef op_uniform_matrix_3<T> op; - return matrix_op<op>(op(mat.nr(), mat.nc(), 0)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_op<op_uniform_matrix_3<T> > ones_matrix ( - long nr, - long nc - ) - { - DLIB_ASSERT(nr >= 0 && nc >= 0, - "\tconst matrix_exp ones_matrix<T>(nr, nc)" - << "\n\tnr and nc have to be >= 0" - << "\n\tnr: " << nr - << "\n\tnc: " << nc - ); - typedef op_uniform_matrix_3<T> op; - return matrix_op<op>(op(nr, nc, 1)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP - > - const matrix_op<op_uniform_matrix_3<typename EXP::type> > ones_matrix ( - const matrix_exp<EXP>& mat - ) - { - DLIB_ASSERT(mat.nr() >= 0 && mat.nc() >= 0, - "\tconst matrix_exp ones_matrix(mat)" - << "\n\t nr and nc have to be >= 0" - << "\n\t mat.nr(): " << mat.nr() - << "\n\t mat.nc(): " << mat.nc() - ); - typedef typename EXP::type T; - typedef op_uniform_matrix_3<T> op; - return matrix_op<op>(op(mat.nr(), mat.nc(), 1)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR_, - long NC_ - > - struct op_uniform_matrix_2 : does_not_alias - { - op_uniform_matrix_2( const T& val_ ) : val(val_) {} - const T val; - - const static long cost = 1; - const static long NR = NR_; - const static long NC = NC_; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - typedef T type; - typedef const T& const_ret_type; - - const_ret_type apply (long , long ) const { return val; } - - long nr() const { return NR; } - long nc() const { return NC; } - }; - - template < - typename T, - long NR, - long NC - > - const matrix_op<op_uniform_matrix_2<T,NR,NC> > uniform_matrix ( - const T& val - ) - { - COMPILE_TIME_ASSERT(NR > 0 && NC > 0); - - typedef op_uniform_matrix_2<T,NR,NC> op; - return matrix_op<op>(op(val)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR_, - long NC_, - T val - > - struct op_uniform_matrix : does_not_alias - { - const static long cost = 1; - const static long NR = NR_; - const static long NC = NC_; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - typedef T type; - typedef const T const_ret_type; - const_ret_type apply ( long , long ) const { return val; } - - long nr() const { return NR; } - long nc() const { return NC; } - }; - - template < - typename T, - long NR, - long NC, - T val - > - const matrix_op<op_uniform_matrix<T,NR,NC,val> > uniform_matrix ( - ) - { - COMPILE_TIME_ASSERT(NR > 0 && NC > 0); - typedef op_uniform_matrix<T,NR,NC,val> op; - return matrix_op<op>(op()); - } - -// ---------------------------------------------------------------------------------------- - - struct op_gaussian_randm : does_not_alias - { - op_gaussian_randm ( - long nr_, - long nc_, - unsigned long seed_ - ) :_nr(nr_), _nc(nc_), seed(seed_){} - - const long _nr; - const long _nc; - const unsigned long seed; - - const static long cost = 100; - const static long NR = 0; - const static long NC = 0; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - typedef double type; - typedef double const_ret_type; - const_ret_type apply ( long r, long c) const { return gaussian_random_hash(r,c,seed); } - - long nr() const { return _nr; } - long nc() const { return _nc; } - }; - - inline const matrix_op<op_gaussian_randm> gaussian_randm ( - long nr, - long nc, - unsigned long seed = 0 - ) - { - DLIB_ASSERT(nr >= 0 && nc >= 0, - "\tmatrix_exp gaussian_randm(nr, nc, seed)" - << "\n\tInvalid inputs to this function" - << "\n\tnr: " << nr - << "\n\tnc: " << nc - ); - - typedef op_gaussian_randm op; - return matrix_op<op>(op(nr,nc,seed)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_add_diag - { - op_add_diag( const M& m_, const typename M::type& value_) : m(m_), value(value_){} - const M& m; - const typename M::type value; - - const static long cost = M::cost+1; - const static long NR = M::NR; - const static long NC = M::NC; - typedef typename M::type type; - typedef const typename M::type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long c) const - { - if (r==c) - return m(r,c)+value; - else - return m(r,c); - } - - long nr () const { return m.nr(); } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.destructively_aliases(item); } - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - struct op_identity_matrix_2 : does_not_alias - { - op_identity_matrix_2(const long& size_) : size(size_) {} - - const long size; - - const static long cost = 1; - const static long NR = 0; - const static long NC = 0; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - typedef T type; - typedef const T const_ret_type; - const_ret_type apply (long r, long c) const { return static_cast<type>(r == c); } - - long nr() const { return size; } - long nc() const { return size; } - }; - - template < - typename T, - typename U - > - const matrix_diag_op<op_identity_matrix_2<T> > identity_matrix ( - const U& size - ) - { - // the size argument must be some scalar value, not a matrix! - COMPILE_TIME_ASSERT(is_matrix<U>::value == false); - - DLIB_ASSERT(size > 0, - "\tconst matrix_exp identity_matrix<T>(size)" - << "\n\tsize must be bigger than 0" - << "\n\tsize: " << size - ); - typedef op_identity_matrix_2<T> op; - return matrix_diag_op<op>(op(size)); - } - - template < - typename EXP - > - const matrix_diag_op<op_identity_matrix_2<typename EXP::type> > identity_matrix ( - const matrix_exp<EXP>& mat - ) - { - DLIB_ASSERT(mat.nr() == mat.nc(), - "\tconst matrix_exp identity_matrix(mat)" - << "\n\t mat must be a square matrix." - << "\n\t mat.nr(): " << mat.nr() - << "\n\t mat.nc(): " << mat.nc() - ); - typedef typename EXP::type T; - typedef op_identity_matrix_2<T> op; - return matrix_diag_op<op>(op(mat.nr())); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP, - typename T - > - const matrix_op<op_add_diag<EXP> > operator+ ( - const matrix_exp<EXP>& lhs, - const matrix_exp<matrix_diag_op<op_identity_matrix_2<T> > >& DLIB_IF_ASSERT(rhs) - ) - { - // both matrices must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<T,typename EXP::type>::value == true)); - - // You can only add matrices together if they both have the same number of rows and columns. - DLIB_ASSERT(lhs.nc() == rhs.nc() && - lhs.nr() == rhs.nr(), - "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" - << "\n\tYou are trying to add two incompatible matrices together" - << "\n\tlhs.nr(): " << lhs.nr() - << "\n\tlhs.nc(): " << lhs.nc() - << "\n\trhs.nr(): " << rhs.nr() - << "\n\trhs.nc(): " << rhs.nc() - << "\n\t&lhs: " << &lhs - << "\n\t&rhs: " << &rhs - ); - - - typedef op_add_diag<EXP> op; - return matrix_op<op>(op(lhs.ref(),1)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP, - typename T - > - const matrix_op<op_add_diag<EXP> > operator+ ( - const matrix_exp<matrix_diag_op<op_identity_matrix_2<T> > >& DLIB_IF_ASSERT(lhs), - const matrix_exp<EXP>& rhs - ) - { - // both matrices must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<T,typename EXP::type>::value == true)); - - // You can only add matrices together if they both have the same number of rows and columns. - DLIB_ASSERT(lhs.nc() == rhs.nc() && - lhs.nr() == rhs.nr(), - "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" - << "\n\tYou are trying to add two incompatible matrices together" - << "\n\tlhs.nr(): " << lhs.nr() - << "\n\tlhs.nc(): " << lhs.nc() - << "\n\trhs.nr(): " << rhs.nr() - << "\n\trhs.nc(): " << rhs.nc() - << "\n\t&lhs: " << &lhs - << "\n\t&rhs: " << &rhs - ); - - - typedef op_add_diag<EXP> op; - return matrix_op<op>(op(rhs.ref(),1)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long N - > - struct op_const_diag_matrix : does_not_alias - { - op_const_diag_matrix(const long& size_, const T& value_) : size(size_),value(value_) {} - - const long size; - const T value; - - const static long cost = 1; - const static long NR = N; - const static long NC = N; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - typedef T type; - typedef const T const_ret_type; - const_ret_type apply (long r, long c) const - { - if (r == c) - return value; - else - return 0; - } - - long nr() const { return size; } - long nc() const { return size; } - }; - - template < - typename T, - typename U - > - const typename disable_if<is_matrix<U>, matrix_diag_op<op_const_diag_matrix<T,0> > >::type operator* ( - const matrix_exp<matrix_diag_op<op_identity_matrix_2<T> > >& m, - const U& value - ) - { - typedef op_const_diag_matrix<T,0> op; - return matrix_diag_op<op>(op(m.nr(), value)); - } - - template < - typename T, - typename U - > - const typename disable_if<is_matrix<U>, matrix_diag_op<op_const_diag_matrix<T,0> > >::type operator* ( - const U& value, - const matrix_exp<matrix_diag_op<op_identity_matrix_2<T> > >& m - ) - { - typedef op_const_diag_matrix<T,0> op; - return matrix_diag_op<op>(op(m.nr(), value)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP, - typename T, - long N - > - const matrix_op<op_add_diag<EXP> > operator+ ( - const matrix_exp<EXP>& lhs, - const matrix_exp<matrix_diag_op<op_const_diag_matrix<T,N> > >& rhs - ) - { - // both matrices must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<T,typename EXP::type>::value == true)); - - // You can only add matrices together if they both have the same number of rows and columns. - DLIB_ASSERT(lhs.nc() == rhs.nc() && - lhs.nr() == rhs.nr(), - "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" - << "\n\tYou are trying to add two incompatible matrices together" - << "\n\tlhs.nr(): " << lhs.nr() - << "\n\tlhs.nc(): " << lhs.nc() - << "\n\trhs.nr(): " << rhs.nr() - << "\n\trhs.nc(): " << rhs.nc() - << "\n\t&lhs: " << &lhs - << "\n\t&rhs: " << &rhs - ); - - - typedef op_add_diag<EXP> op; - return matrix_op<op>(op(lhs.ref(),rhs.ref().op.value)); - } - - template < - typename EXP, - typename T, - long N - > - const matrix_op<op_add_diag<EXP> > operator+ ( - const matrix_exp<matrix_diag_op<op_const_diag_matrix<T,N> > >& lhs, - const matrix_exp<EXP>& rhs - ) - { - // both matrices must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<T,typename EXP::type>::value == true)); - - // You can only add matrices together if they both have the same number of rows and columns. - DLIB_ASSERT(lhs.nc() == rhs.nc() && - lhs.nr() == rhs.nr(), - "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" - << "\n\tYou are trying to add two incompatible matrices together" - << "\n\tlhs.nr(): " << lhs.nr() - << "\n\tlhs.nc(): " << lhs.nc() - << "\n\trhs.nr(): " << rhs.nr() - << "\n\trhs.nc(): " << rhs.nc() - << "\n\t&lhs: " << &lhs - << "\n\t&rhs: " << &rhs - ); - - - typedef op_add_diag<EXP> op; - return matrix_op<op>(op(rhs.ref(),lhs.ref().op.value)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long N - > - struct op_identity_matrix : does_not_alias - { - const static long cost = 1; - const static long NR = N; - const static long NC = N; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - typedef T type; - typedef const T const_ret_type; - const_ret_type apply ( long r, long c) const { return static_cast<type>(r == c); } - - long nr () const { return NR; } - long nc () const { return NC; } - }; - - template < - typename T, - long N - > - const matrix_diag_op<op_identity_matrix<T,N> > identity_matrix ( - ) - { - COMPILE_TIME_ASSERT(N > 0); - - typedef op_identity_matrix<T,N> op; - return matrix_diag_op<op>(op()); - } - - template < - typename T, - typename U, - long N - > - const typename disable_if<is_matrix<U>, matrix_diag_op<op_const_diag_matrix<T,N> > >::type operator* ( - const matrix_exp<matrix_diag_op<op_identity_matrix<T,N> > >& m, - const U& value - ) - { - typedef op_const_diag_matrix<T,N> op; - return matrix_diag_op<op>(op(m.nr(), value)); - } - - template < - typename T, - typename U, - long N - > - const typename disable_if<is_matrix<U>, matrix_diag_op<op_const_diag_matrix<T,N> > >::type operator* ( - const U& value, - const matrix_exp<matrix_diag_op<op_identity_matrix<T,N> > >& m - ) - { - typedef op_const_diag_matrix<T,N> op; - return matrix_diag_op<op>(op(m.nr(), value)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP, - typename T, - long N - > - const matrix_op<op_add_diag<EXP> > operator+ ( - const matrix_exp<matrix_diag_op<op_identity_matrix<T,N> > >& DLIB_IF_ASSERT(lhs), - const matrix_exp<EXP>& rhs - ) - { - // both matrices must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<T,typename EXP::type>::value == true)); - - // You can only add matrices together if they both have the same number of rows and columns. - DLIB_ASSERT(lhs.nc() == rhs.nc() && - lhs.nr() == rhs.nr(), - "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" - << "\n\tYou are trying to add two incompatible matrices together" - << "\n\tlhs.nr(): " << lhs.nr() - << "\n\tlhs.nc(): " << lhs.nc() - << "\n\trhs.nr(): " << rhs.nr() - << "\n\trhs.nc(): " << rhs.nc() - << "\n\t&lhs: " << &lhs - << "\n\t&rhs: " << &rhs - ); - - - typedef op_add_diag<EXP> op; - return matrix_op<op>(op(rhs.ref(),1)); - } - - template < - typename EXP, - typename T, - long N - > - const matrix_op<op_add_diag<EXP> > operator+ ( - const matrix_exp<EXP>& lhs, - const matrix_exp<matrix_diag_op<op_identity_matrix<T,N> > >& DLIB_IF_ASSERT(rhs) - ) - { - // both matrices must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<T,typename EXP::type>::value == true)); - - // You can only add matrices together if they both have the same number of rows and columns. - DLIB_ASSERT(lhs.nc() == rhs.nc() && - lhs.nr() == rhs.nr(), - "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" - << "\n\tYou are trying to add two incompatible matrices together" - << "\n\tlhs.nr(): " << lhs.nr() - << "\n\tlhs.nc(): " << lhs.nc() - << "\n\trhs.nr(): " << rhs.nr() - << "\n\trhs.nc(): " << rhs.nc() - << "\n\t&lhs: " << &lhs - << "\n\t&rhs: " << &rhs - ); - - - typedef op_add_diag<EXP> op; - return matrix_op<op>(op(lhs.ref(),1)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M, long R, long C> - struct op_rotate - { - op_rotate(const M& m_) : m(m_) {} - const M& m; - - const static long cost = M::cost + 2; - const static long NR = M::NR; - const static long NC = M::NC; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - const_ret_type apply ( long r, long c) const { return m((r+R)%m.nr(),(c+C)%m.nc()); } - - long nr () const { return m.nr(); } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - long R, - long C, - typename EXP - > - const matrix_op<op_rotate<EXP,R,C> > rotate ( - const matrix_exp<EXP>& m - ) - { - typedef op_rotate<EXP,R,C> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - // A template to tell me if two types can be multiplied together in a sensible way. Here - // I'm saying it is ok if they are both the same type or one is the complex version of the other. - template <typename T, typename U> struct compatible { static const bool value = false; typedef T type; }; - template <typename T> struct compatible<T,T> { static const bool value = true; typedef T type; }; - template <typename T> struct compatible<std::complex<T>,T> { static const bool value = true; typedef std::complex<T> type; }; - template <typename T> struct compatible<T,std::complex<T> > { static const bool value = true; typedef std::complex<T> type; }; - } - - - template <typename M1, typename M2> - struct op_pointwise_multiply : basic_op_mm<M1,M2> - { - op_pointwise_multiply( const M1& m1_, const M2& m2_) : basic_op_mm<M1,M2>(m1_,m2_){} - - typedef typename impl::compatible<typename M1::type, typename M2::type>::type type; - typedef const type const_ret_type; - const static long cost = M1::cost + M2::cost + 1; - - const_ret_type apply ( long r, long c) const - { return this->m1(r,c)*this->m2(r,c); } - }; - - template < - typename EXP1, - typename EXP2 - > - inline const matrix_op<op_pointwise_multiply<EXP1,EXP2> > pointwise_multiply ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b - ) - { - COMPILE_TIME_ASSERT((impl::compatible<typename EXP1::type,typename EXP2::type>::value == true)); - COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); - COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0); - DLIB_ASSERT(a.nr() == b.nr() && - a.nc() == b.nc(), - "\tconst matrix_exp pointwise_multiply(const matrix_exp& a, const matrix_exp& b)" - << "\n\tYou can only make a do a pointwise multiply with two equally sized matrices" - << "\n\ta.nr(): " << a.nr() - << "\n\ta.nc(): " << a.nc() - << "\n\tb.nr(): " << b.nr() - << "\n\tb.nc(): " << b.nc() - ); - typedef op_pointwise_multiply<EXP1,EXP2> op; - return matrix_op<op>(op(a.ref(),b.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2, typename M3> - struct op_pointwise_multiply3 : basic_op_mmm<M1,M2,M3> - { - op_pointwise_multiply3( const M1& m1_, const M2& m2_, const M3& m3_) : - basic_op_mmm<M1,M2,M3>(m1_,m2_,m3_){} - - typedef typename M1::type type; - typedef const typename M1::type const_ret_type; - const static long cost = M1::cost + M2::cost + M3::cost + 2; - - const_ret_type apply (long r, long c) const - { return this->m1(r,c)*this->m2(r,c)*this->m3(r,c); } - }; - - template < - typename EXP1, - typename EXP2, - typename EXP3 - > - inline const matrix_op<op_pointwise_multiply3<EXP1,EXP2,EXP3> > - pointwise_multiply ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b, - const matrix_exp<EXP3>& c - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - COMPILE_TIME_ASSERT((is_same_type<typename EXP2::type,typename EXP3::type>::value == true)); - COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); - COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NR == 0 || EXP2::NC == 0); - COMPILE_TIME_ASSERT(EXP2::NR == EXP3::NR || EXP2::NR == 0 || EXP3::NR == 0); - COMPILE_TIME_ASSERT(EXP2::NC == EXP3::NC || EXP2::NC == 0 || EXP3::NC == 0); - DLIB_ASSERT(a.nr() == b.nr() && - a.nc() == b.nc() && - b.nr() == c.nr() && - b.nc() == c.nc(), - "\tconst matrix_exp pointwise_multiply(a,b,c)" - << "\n\tYou can only make a do a pointwise multiply between equally sized matrices" - << "\n\ta.nr(): " << a.nr() - << "\n\ta.nc(): " << a.nc() - << "\n\tb.nr(): " << b.nr() - << "\n\tb.nc(): " << b.nc() - << "\n\tc.nr(): " << c.nr() - << "\n\tc.nc(): " << c.nc() - ); - - typedef op_pointwise_multiply3<EXP1,EXP2,EXP3> op; - return matrix_op<op>(op(a.ref(),b.ref(),c.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2, typename M3, typename M4> - struct op_pointwise_multiply4 : basic_op_mmmm<M1,M2,M3,M4> - { - op_pointwise_multiply4( const M1& m1_, const M2& m2_, const M3& m3_, const M4& m4_) : - basic_op_mmmm<M1,M2,M3,M4>(m1_,m2_,m3_,m4_){} - - typedef typename M1::type type; - typedef const typename M1::type const_ret_type; - const static long cost = M1::cost + M2::cost + M3::cost + M4::cost + 3; - - const_ret_type apply (long r, long c) const - { return this->m1(r,c)*this->m2(r,c)*this->m3(r,c)*this->m4(r,c); } - }; - - - template < - typename EXP1, - typename EXP2, - typename EXP3, - typename EXP4 - > - inline const matrix_op<op_pointwise_multiply4<EXP1,EXP2,EXP3,EXP4> > pointwise_multiply ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b, - const matrix_exp<EXP3>& c, - const matrix_exp<EXP4>& d - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - COMPILE_TIME_ASSERT((is_same_type<typename EXP2::type,typename EXP3::type>::value == true)); - COMPILE_TIME_ASSERT((is_same_type<typename EXP3::type,typename EXP4::type>::value == true)); - COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); - COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0 ); - COMPILE_TIME_ASSERT(EXP2::NR == EXP3::NR || EXP2::NR == 0 || EXP3::NR == 0); - COMPILE_TIME_ASSERT(EXP2::NC == EXP3::NC || EXP2::NC == 0 || EXP3::NC == 0); - COMPILE_TIME_ASSERT(EXP3::NR == EXP4::NR || EXP3::NR == 0 || EXP4::NR == 0); - COMPILE_TIME_ASSERT(EXP3::NC == EXP4::NC || EXP3::NC == 0 || EXP4::NC == 0); - DLIB_ASSERT(a.nr() == b.nr() && - a.nc() == b.nc() && - b.nr() == c.nr() && - b.nc() == c.nc() && - c.nr() == d.nr() && - c.nc() == d.nc(), - "\tconst matrix_exp pointwise_multiply(a,b,c,d)" - << "\n\tYou can only make a do a pointwise multiply between equally sized matrices" - << "\n\ta.nr(): " << a.nr() - << "\n\ta.nc(): " << a.nc() - << "\n\tb.nr(): " << b.nr() - << "\n\tb.nc(): " << b.nc() - << "\n\tc.nr(): " << c.nr() - << "\n\tc.nc(): " << c.nc() - << "\n\td.nr(): " << d.nr() - << "\n\td.nc(): " << d.nc() - ); - - typedef op_pointwise_multiply4<EXP1,EXP2,EXP3,EXP4> op; - return matrix_op<op>(op(a.ref(),b.ref(),c.ref(),d.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename P, - int type = static_switch< - pixel_traits<P>::grayscale, - pixel_traits<P>::rgb, - pixel_traits<P>::hsi, - pixel_traits<P>::rgb_alpha, - pixel_traits<P>::lab - >::value - > - struct pixel_to_vector_helper; - - template <typename P> - struct pixel_to_vector_helper<P,1> - { - template <typename M> - static void assign ( - M& m, - const P& pixel - ) - { - m(0) = static_cast<typename M::type>(pixel); - } - }; - - template <typename P> - struct pixel_to_vector_helper<P,2> - { - template <typename M> - static void assign ( - M& m, - const P& pixel - ) - { - m(0) = static_cast<typename M::type>(pixel.red); - m(1) = static_cast<typename M::type>(pixel.green); - m(2) = static_cast<typename M::type>(pixel.blue); - } - }; - - template <typename P> - struct pixel_to_vector_helper<P,3> - { - template <typename M> - static void assign ( - M& m, - const P& pixel - ) - { - m(0) = static_cast<typename M::type>(pixel.h); - m(1) = static_cast<typename M::type>(pixel.s); - m(2) = static_cast<typename M::type>(pixel.i); - } - }; - - template <typename P> - struct pixel_to_vector_helper<P,4> - { - template <typename M> - static void assign ( - M& m, - const P& pixel - ) - { - m(0) = static_cast<typename M::type>(pixel.red); - m(1) = static_cast<typename M::type>(pixel.green); - m(2) = static_cast<typename M::type>(pixel.blue); - m(3) = static_cast<typename M::type>(pixel.alpha); - } - }; - - template <typename P> - struct pixel_to_vector_helper<P,5> - { - template <typename M> - static void assign ( - M& m, - const P& pixel - ) - { - m(0) = static_cast<typename M::type>(pixel.l); - m(1) = static_cast<typename M::type>(pixel.a); - m(2) = static_cast<typename M::type>(pixel.b); - } - }; - - - template < - typename T, - typename P - > - inline const matrix<T,pixel_traits<P>::num,1> pixel_to_vector ( - const P& pixel - ) - { - COMPILE_TIME_ASSERT(pixel_traits<P>::num > 0); - matrix<T,pixel_traits<P>::num,1> m; - pixel_to_vector_helper<P>::assign(m,pixel); - return m; - } - -// ---------------------------------------------------------------------------------------- - - template < - typename P, - int type = static_switch< - pixel_traits<P>::grayscale, - pixel_traits<P>::rgb, - pixel_traits<P>::hsi, - pixel_traits<P>::rgb_alpha, - pixel_traits<P>::lab - >::value - > - struct vector_to_pixel_helper; - - template <typename P> - struct vector_to_pixel_helper<P,1> - { - template <typename M> - static void assign ( - P& pixel, - const M& m - ) - { - pixel = static_cast<unsigned char>(m(0)); - } - }; - - template <typename P> - struct vector_to_pixel_helper<P,2> - { - template <typename M> - static void assign ( - P& pixel, - const M& m - ) - { - pixel.red = static_cast<unsigned char>(m(0)); - pixel.green = static_cast<unsigned char>(m(1)); - pixel.blue = static_cast<unsigned char>(m(2)); - } - }; - - template <typename P> - struct vector_to_pixel_helper<P,3> - { - template <typename M> - static void assign ( - P& pixel, - const M& m - ) - { - pixel.h = static_cast<unsigned char>(m(0)); - pixel.s = static_cast<unsigned char>(m(1)); - pixel.i = static_cast<unsigned char>(m(2)); - } - }; - - template <typename P> - struct vector_to_pixel_helper<P,4> - { - template <typename M> - static void assign ( - P& pixel, - const M& m - ) - { - pixel.red = static_cast<unsigned char>(m(0)); - pixel.green = static_cast<unsigned char>(m(1)); - pixel.blue = static_cast<unsigned char>(m(2)); - pixel.alpha = static_cast<unsigned char>(m(3)); - } - }; - - template <typename P> - struct vector_to_pixel_helper<P,5> - { - template <typename M> - static void assign ( - P& pixel, - const M& m - ) - { - pixel.l = static_cast<unsigned char>(m(0)); - pixel.a = static_cast<unsigned char>(m(1)); - pixel.b = static_cast<unsigned char>(m(2)); - } - }; - - template < - typename P, - typename EXP - > - inline void vector_to_pixel ( - P& pixel, - const matrix_exp<EXP>& vector - ) - { - COMPILE_TIME_ASSERT(pixel_traits<P>::num == matrix_exp<EXP>::NR); - COMPILE_TIME_ASSERT(matrix_exp<EXP>::NC == 1); - vector_to_pixel_helper<P>::assign(pixel,vector); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M, long lower, long upper> - struct op_clamp : basic_op_m<M> - { - op_clamp( const M& m_) : basic_op_m<M>(m_){} - - typedef typename M::type type; - typedef const typename M::type const_ret_type; - const static long cost = M::cost + 2; - - const_ret_type apply ( long r, long c) const - { - const type temp = this->m(r,c); - if (temp > static_cast<type>(upper)) - return static_cast<type>(upper); - else if (temp < static_cast<type>(lower)) - return static_cast<type>(lower); - else - return temp; - } - }; - - template < - long l, - long u, - typename EXP - > - const matrix_op<op_clamp<EXP,l,u> > clamp ( - const matrix_exp<EXP>& m - ) - { - typedef op_clamp<EXP,l,u> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_clamp2 : basic_op_m<M> - { - typedef typename M::type type; - - op_clamp2( const M& m_, const type& l, const type& u) : - basic_op_m<M>(m_), lower(l), upper(u){} - - const type& lower; - const type& upper; - - typedef const typename M::type const_ret_type; - const static long cost = M::cost + 2; - - const_ret_type apply ( long r, long c) const - { - const type temp = this->m(r,c); - if (temp > upper) - return upper; - else if (temp < lower) - return lower; - else - return temp; - } - }; - - template < - typename EXP - > - const matrix_op<op_clamp2<EXP> > clamp ( - const matrix_exp<EXP>& m, - const typename EXP::type& lower, - const typename EXP::type& upper - ) - { - typedef op_clamp2<EXP> op; - return matrix_op<op>(op(m.ref(),lower, upper)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2, typename M3> - struct op_clamp_m : basic_op_mmm<M1,M2,M3> - { - op_clamp_m( const M1& m1_, const M2& m2_, const M3& m3_) : - basic_op_mmm<M1,M2,M3>(m1_,m2_,m3_){} - - typedef typename M1::type type; - typedef const typename M1::type const_ret_type; - const static long cost = M1::cost + M2::cost + M3::cost + 2; - - const_ret_type apply (long r, long c) const - { - const type val = this->m1(r,c); - const type lower = this->m2(r,c); - const type upper = this->m3(r,c); - if (val <= upper) - { - if (lower <= val) - return val; - else - return lower; - } - else - { - return upper; - } - } - }; - - template < - typename EXP1, - typename EXP2, - typename EXP3 - > - const matrix_op<op_clamp_m<EXP1,EXP2,EXP3> > - clamp ( - const matrix_exp<EXP1>& m, - const matrix_exp<EXP2>& lower, - const matrix_exp<EXP3>& upper - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - COMPILE_TIME_ASSERT((is_same_type<typename EXP2::type,typename EXP3::type>::value == true)); - COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); - COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NR == 0 || EXP2::NC == 0); - COMPILE_TIME_ASSERT(EXP2::NR == EXP3::NR || EXP2::NR == 0 || EXP3::NR == 0); - COMPILE_TIME_ASSERT(EXP2::NC == EXP3::NC || EXP2::NC == 0 || EXP3::NC == 0); - DLIB_ASSERT(m.nr() == lower.nr() && - m.nc() == lower.nc() && - m.nr() == upper.nr() && - m.nc() == upper.nc(), - "\tconst matrix_exp clamp(m,lower,upper)" - << "\n\t Invalid inputs were given to this function." - << "\n\t m.nr(): " << m.nr() - << "\n\t m.nc(): " << m.nc() - << "\n\t lower.nr(): " << lower.nr() - << "\n\t lower.nc(): " << lower.nc() - << "\n\t upper.nr(): " << upper.nr() - << "\n\t upper.nc(): " << upper.nc() - ); - - typedef op_clamp_m<EXP1,EXP2,EXP3> op; - return matrix_op<op>(op(m.ref(),lower.ref(),upper.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_lowerbound : basic_op_m<M> - { - typedef typename M::type type; - - op_lowerbound( const M& m_, const type& thresh_) : - basic_op_m<M>(m_), thresh(thresh_){} - - const type& thresh; - - typedef const typename M::type const_ret_type; - const static long cost = M::cost + 2; - - const_ret_type apply ( long r, long c) const - { - const type temp = this->m(r,c); - if (temp >= thresh) - return temp; - else - return thresh; - } - }; - - template < - typename EXP - > - const matrix_op<op_lowerbound<EXP> > lowerbound ( - const matrix_exp<EXP>& m, - const typename EXP::type& thresh - ) - { - typedef op_lowerbound<EXP> op; - return matrix_op<op>(op(m.ref(), thresh)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_upperbound : basic_op_m<M> - { - typedef typename M::type type; - - op_upperbound( const M& m_, const type& thresh_) : - basic_op_m<M>(m_), thresh(thresh_){} - - const type& thresh; - - typedef const typename M::type const_ret_type; - const static long cost = M::cost + 2; - - const_ret_type apply ( long r, long c) const - { - const type temp = this->m(r,c); - if (temp <= thresh) - return temp; - else - return thresh; - } - }; - - template < - typename EXP - > - const matrix_op<op_upperbound<EXP> > upperbound ( - const matrix_exp<EXP>& m, - const typename EXP::type& thresh - ) - { - typedef op_upperbound<EXP> op; - return matrix_op<op>(op(m.ref(), thresh)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_reshape - { - op_reshape(const M& m_, const long& rows_, const long& cols_) : m(m_),rows(rows_),cols(cols_) {} - const M& m; - const long rows; - const long cols; - - const static long cost = M::cost+2; - const static long NR = 0; - const static long NC = 0; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - - const_ret_type apply ( long r, long c) const - { - const long idx = r*cols + c; - return m(idx/m.nc(), idx%m.nc()); - } - - long nr () const { return rows; } - long nc () const { return cols; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_op<op_reshape<EXP> > reshape ( - const matrix_exp<EXP>& m, - const long& rows, - const long& cols - ) - { - DLIB_ASSERT(m.size() == rows*cols && rows > 0 && cols > 0, - "\tconst matrix_exp reshape(m, rows, cols)" - << "\n\t The size of m must match the dimensions you want to reshape it into." - << "\n\t m.size(): " << m.size() - << "\n\t rows*cols: " << rows*cols - << "\n\t rows: " << rows - << "\n\t cols: " << cols - ); - - typedef op_reshape<EXP> op; - return matrix_op<op>(op(m.ref(), rows, cols)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP1, - typename EXP2 - > - typename disable_if<is_complex<typename EXP1::type>,bool>::type equal ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b, - const typename EXP1::type eps = 100*std::numeric_limits<typename EXP1::type>::epsilon() - ) - { - // check if the dimensions don't match - if (a.nr() != b.nr() || a.nc() != b.nc()) - return false; - - for (long r = 0; r < a.nr(); ++r) - { - for (long c = 0; c < a.nc(); ++c) - { - if (std::abs(a(r,c)-b(r,c)) > eps) - return false; - } - } - - // no non-equal points found so we return true - return true; - } - - template < - typename EXP1, - typename EXP2 - > - typename enable_if<is_complex<typename EXP1::type>,bool>::type equal ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b, - const typename EXP1::type::value_type eps = 100*std::numeric_limits<typename EXP1::type::value_type>::epsilon() - ) - { - // check if the dimensions don't match - if (a.nr() != b.nr() || a.nc() != b.nc()) - return false; - - for (long r = 0; r < a.nr(); ++r) - { - for (long c = 0; c < a.nc(); ++c) - { - if (std::abs(real(a(r,c)-b(r,c))) > eps || - std::abs(imag(a(r,c)-b(r,c))) > eps) - return false; - } - } - - // no non-equal points found so we return true - return true; - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_scale_columns - { - op_scale_columns(const M1& m1_, const M2& m2_) : m1(m1_), m2(m2_) {} - const M1& m1; - const M2& m2; - - const static long cost = M1::cost + M2::cost + 1; - typedef typename M1::type type; - typedef const typename M1::type const_ret_type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - const static long NR = M1::NR; - const static long NC = M1::NC; - - const_ret_type apply ( long r, long c) const { return m1(r,c)*m2(c); } - - long nr () const { return m1.nr(); } - long nc () const { return m1.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item) ; } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.destructively_aliases(item) || m2.aliases(item); } - }; - - template < - typename EXP1, - typename EXP2 - > - const matrix_op<op_scale_columns<EXP1,EXP2> > scale_columns ( - const matrix_exp<EXP1>& m, - const matrix_exp<EXP2>& v - ) - { - // Both arguments to this function must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - // The v argument must be a row or column vector. - COMPILE_TIME_ASSERT((EXP2::NC == 1 || EXP2::NC == 0) || (EXP2::NR == 1 || EXP2::NR == 0)); - - // figure out the compile time known length of v - const long v_len = ((EXP2::NR)*(EXP2::NC) == 0)? 0 : (tmax<EXP2::NR,EXP2::NC>::value); - - // the length of v must match the number of columns in m - COMPILE_TIME_ASSERT(EXP1::NC == v_len || EXP1::NC == 0 || v_len == 0); - - DLIB_ASSERT(is_vector(v) == true && v.size() == m.nc(), - "\tconst matrix_exp scale_columns(m, v)" - << "\n\tv must be a row or column vector and its length must match the number of columns in m" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tv.nr(): " << v.nr() - << "\n\tv.nc(): " << v.nc() - ); - typedef op_scale_columns<EXP1,EXP2> op; - return matrix_op<op>(op(m.ref(),v.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_scale_columns_diag - { - op_scale_columns_diag(const M1& m1_, const M2& m2_) : m1(m1_), m2(m2_) {} - const M1& m1; - const M2& m2; - - const static long cost = M1::cost + M2::cost + 1; - typedef typename M1::type type; - typedef const typename M1::type const_ret_type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - const static long NR = M1::NR; - const static long NC = M1::NC; - - const_ret_type apply ( long r, long c) const { return m1(r,c)*m2(c,c); } - - long nr () const { return m1.nr(); } - long nc () const { return m1.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item) ; } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.destructively_aliases(item) || m2.aliases(item); } - }; - -// turn expressions of the form mat*diagonal_matrix into scale_columns(mat, d) - template < - typename EXP1, - typename EXP2 - > - const matrix_op<op_scale_columns_diag<EXP1,EXP2> > operator* ( - const matrix_exp<EXP1>& m, - const matrix_diag_exp<EXP2>& d - ) - { - // Both arguments to this function must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - - // figure out the compile time known length of d - const long v_len = ((EXP2::NR)*(EXP2::NC) == 0)? 0 : (tmax<EXP2::NR,EXP2::NC>::value); - - // the length of d must match the number of columns in m - COMPILE_TIME_ASSERT(EXP1::NC == v_len || EXP1::NC == 0 || v_len == 0); - - DLIB_ASSERT(m.nc() == d.nr(), - "\tconst matrix_exp operator*(m, d)" - << "\n\tmatrix dimensions don't match" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\td.nr(): " << d.nr() - << "\n\td.nc(): " << d.nc() - ); - typedef op_scale_columns_diag<EXP1,EXP2> op; - return matrix_op<op>(op(m.ref(),d.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_scale_rows - { - op_scale_rows(const M1& m1_, const M2& m2_) : m1(m1_), m2(m2_) {} - const M1& m1; - const M2& m2; - - const static long cost = M1::cost + M2::cost + 1; - typedef typename M1::type type; - typedef const typename M1::type const_ret_type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - const static long NR = M1::NR; - const static long NC = M1::NC; - - const_ret_type apply ( long r, long c) const { return m1(r,c)*m2(r); } - - long nr () const { return m1.nr(); } - long nc () const { return m1.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item) ; } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.destructively_aliases(item) || m2.aliases(item); } - }; - - template < - typename EXP1, - typename EXP2 - > - const matrix_op<op_scale_rows<EXP1,EXP2> > scale_rows ( - const matrix_exp<EXP1>& m, - const matrix_exp<EXP2>& v - ) - { - // Both arguments to this function must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - // The v argument must be a row or column vector. - COMPILE_TIME_ASSERT((EXP2::NC == 1 || EXP2::NC == 0) || (EXP2::NR == 1 || EXP2::NR == 0)); - - // figure out the compile time known length of v - const long v_len = ((EXP2::NR)*(EXP2::NC) == 0)? 0 : (tmax<EXP2::NR,EXP2::NC>::value); - - // the length of v must match the number of rows in m - COMPILE_TIME_ASSERT(EXP1::NR == v_len || EXP1::NR == 0 || v_len == 0); - - DLIB_ASSERT(is_vector(v) == true && v.size() == m.nr(), - "\tconst matrix_exp scale_rows(m, v)" - << "\n\tv must be a row or column vector and its length must match the number of rows in m" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tv.nr(): " << v.nr() - << "\n\tv.nc(): " << v.nc() - ); - typedef op_scale_rows<EXP1,EXP2> op; - return matrix_op<op>(op(m.ref(),v.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_scale_rows_diag - { - op_scale_rows_diag(const M1& m1_, const M2& m2_) : m1(m1_), m2(m2_) {} - const M1& m1; - const M2& m2; - - const static long cost = M1::cost + M2::cost + 1; - typedef typename M1::type type; - typedef const typename M1::type const_ret_type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - const static long NR = M1::NR; - const static long NC = M1::NC; - - const_ret_type apply ( long r, long c) const { return m1(r,c)*m2(r,r); } - - long nr () const { return m1.nr(); } - long nc () const { return m1.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item) ; } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.destructively_aliases(item) || m2.aliases(item); } - }; - -// turn expressions of the form diagonal_matrix*mat into scale_rows(mat, d) - template < - typename EXP1, - typename EXP2 - > - const matrix_op<op_scale_rows_diag<EXP1,EXP2> > operator* ( - const matrix_diag_exp<EXP2>& d, - const matrix_exp<EXP1>& m - ) - { - // Both arguments to this function must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - - // figure out the compile time known length of d - const long v_len = ((EXP2::NR)*(EXP2::NC) == 0)? 0 : (tmax<EXP2::NR,EXP2::NC>::value); - - // the length of d must match the number of rows in m - COMPILE_TIME_ASSERT(EXP1::NR == v_len || EXP1::NR == 0 || v_len == 0); - - DLIB_ASSERT(d.nc() == m.nr(), - "\tconst matrix_exp operator*(d, m)" - << "\n\tThe dimensions of the d and m matrices don't match." - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\td.nr(): " << d.nr() - << "\n\td.nc(): " << d.nc() - ); - typedef op_scale_rows_diag<EXP1,EXP2> op; - return matrix_op<op>(op(m.ref(),d.ref())); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - /* - The idea here is to catch expressions of the form d*M*d where d is diagonal and M - is some square matrix and turn them into something equivalent to - pointwise_multiply(diag(d)*trans(diag(d)), M). - - The reason for this is that doing it this way is more numerically stable. In particular, - doing 2 matrix multiplies as suggested by d*M*d could result in an asymmetric matrix even - if M is symmetric to begin with. - */ - - template <typename M1, typename M2, typename M3> - struct op_diag_m_diag - { - // This operator represents M1*M2*M3 where M1 and M3 are diagonal - - op_diag_m_diag(const M1& m1_, const M2& m2_, const M3& m3_) : m1(m1_), m2(m2_), m3(m3_) {} - const M1& m1; - const M2& m2; - const M3& m3; - - const static long cost = M1::cost + M2::cost + M3::cost + 1; - typedef typename M2::type type; - typedef const typename M2::type const_ret_type; - typedef typename M2::mem_manager_type mem_manager_type; - typedef typename M2::layout_type layout_type; - const static long NR = M2::NR; - const static long NC = M2::NC; - - const_ret_type apply ( long r, long c) const { return (m1(r,r)*m3(c,c))*m2(r,c); } - - long nr () const { return m2.nr(); } - long nc () const { return m2.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item) ; } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m2.destructively_aliases(item) || m1.aliases(item) || m3.aliases(item) ; } - }; - - // catch d*(M*d) = EXP1*EXP2*EXP3 - template < - typename EXP1, - typename EXP2, - typename EXP3 - > - const matrix_op<op_diag_m_diag<EXP1,EXP2,EXP3> > operator* ( - const matrix_diag_exp<EXP1>& d, - const matrix_exp<matrix_op<op_scale_columns_diag<EXP2,EXP3> > >& m - ) - { - // Both arguments to this function must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - - // figure out the compile time known length of d - const long v_len = ((EXP1::NR)*(EXP1::NC) == 0)? 0 : (tmax<EXP1::NR,EXP1::NC>::value); - - // the length of d must match the number of rows in m - COMPILE_TIME_ASSERT(EXP2::NR == v_len || EXP2::NR == 0 || v_len == 0); - - DLIB_ASSERT(d.nc() == m.nr(), - "\tconst matrix_exp operator*(d, m)" - << "\n\tmatrix dimensions don't match" - << "\n\td.nr(): " << d.nr() - << "\n\td.nc(): " << d.nc() - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - ); - typedef op_diag_m_diag<EXP1,EXP2,EXP3> op; - return matrix_op<op>(op(d.ref(), m.ref().op.m1, m.ref().op.m2)); - } - - // catch (d*M)*d = EXP1*EXP2*EXP3 - template < - typename EXP1, - typename EXP2, - typename EXP3 - > - const matrix_op<op_diag_m_diag<EXP1,EXP2,EXP3> > operator* ( - const matrix_exp<matrix_op<op_scale_rows_diag<EXP2,EXP1> > >& m, - const matrix_diag_exp<EXP3>& d - ) - { - // Both arguments to this function must contain the same type of element - COMPILE_TIME_ASSERT((is_same_type<typename EXP3::type,typename EXP2::type>::value == true)); - - // figure out the compile time known length of d - const long v_len = ((EXP3::NR)*(EXP3::NC) == 0)? 0 : (tmax<EXP3::NR,EXP3::NC>::value); - - // the length of d must match the number of columns in m - COMPILE_TIME_ASSERT(EXP2::NC == v_len || EXP2::NC == 0 || v_len == 0); - - DLIB_ASSERT(m.nc() == d.nr(), - "\tconst matrix_exp operator*(m, d)" - << "\n\tmatrix dimensions don't match" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\td.nr(): " << d.nr() - << "\n\td.nc(): " << d.nc() - ); - typedef op_diag_m_diag<EXP1,EXP2,EXP3> op; - return matrix_op<op>(op(m.ref().op.m2, m.ref().op.m1, d.ref())); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - struct sort_columns_sort_helper - { - template <typename T> - bool operator() ( - const T& item1, - const T& item2 - ) const - { - return item1.first < item2.first; - } - }; - - template < - typename T, long NR, long NC, typename mm, typename l1, - long NR2, long NC2, typename mm2, typename l2 - > - void sort_columns ( - matrix<T,NR,NC,mm,l1>& m, - matrix<T,NR2,NC2,mm2,l2>& v - ) - { - COMPILE_TIME_ASSERT(NC2 == 1 || NC2 == 0); - COMPILE_TIME_ASSERT(NC == NR2 || NC == 0 || NR2 == 0); - - DLIB_ASSERT(is_col_vector(v) == true && v.size() == m.nc(), - "\tconst matrix_exp sort_columns(m, v)" - << "\n\tv must be a column vector and its length must match the number of columns in m" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tv.nr(): " << v.nr() - << "\n\tv.nc(): " << v.nc() - ); - - - - // Now we have to sort the given vectors in the m matrix according - // to how big their corresponding v(column index) values are. - typedef std::pair<T, matrix<T,0,1,mm> > col_pair; - typedef std_allocator<col_pair, mm> alloc; - std::vector<col_pair,alloc> colvalues; - col_pair p; - for (long r = 0; r < v.nr(); ++r) - { - p.first = v(r); - p.second = colm(m,r); - colvalues.push_back(p); - } - std::sort(colvalues.begin(), colvalues.end(), sort_columns_sort_helper()); - - for (long i = 0; i < v.nr(); ++i) - { - v(i) = colvalues[i].first; - set_colm(m,i) = colvalues[i].second; - } - - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, long NR, long NC, typename mm, typename l1, - long NR2, long NC2, typename mm2, typename l2 - > - void rsort_columns ( - matrix<T,NR,NC,mm,l1>& m, - matrix<T,NR2,NC2,mm2,l2>& v - ) - { - COMPILE_TIME_ASSERT(NC2 == 1 || NC2 == 0); - COMPILE_TIME_ASSERT(NC == NR2 || NC == 0 || NR2 == 0); - - DLIB_ASSERT(is_col_vector(v) == true && v.size() == m.nc(), - "\tconst matrix_exp rsort_columns(m, v)" - << "\n\tv must be a column vector and its length must match the number of columns in m" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tv.nr(): " << v.nr() - << "\n\tv.nc(): " << v.nc() - ); - - - - // Now we have to sort the given vectors in the m matrix according - // to how big their corresponding v(column index) values are. - typedef std::pair<T, matrix<T,0,1,mm> > col_pair; - typedef std_allocator<col_pair, mm> alloc; - std::vector<col_pair,alloc> colvalues; - col_pair p; - for (long r = 0; r < v.nr(); ++r) - { - p.first = v(r); - p.second = colm(m,r); - colvalues.push_back(p); - } - std::sort(colvalues.rbegin(), colvalues.rend(), sort_columns_sort_helper()); - - for (long i = 0; i < v.nr(); ++i) - { - v(i) = colvalues[i].first; - set_colm(m,i) = colvalues[i].second; - } - - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_tensor_product - { - op_tensor_product(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {} - const M1& m1; - const M2& m2; - - const static long cost = M1::cost + M2::cost + 1; - const static long NR = M1::NR*M2::NR; - const static long NC = M1::NC*M2::NC; - typedef typename M1::type type; - typedef const typename M1::type const_ret_type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - - const_ret_type apply ( long r, long c) const - { - return m1(r/m2.nr(),c/m2.nc())*m2(r%m2.nr(),c%m2.nc()); - } - - long nr () const { return m1.nr()*m2.nr(); } - long nc () const { return m1.nc()*m2.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item); } - }; - - template < - typename EXP1, - typename EXP2 - > - inline const matrix_op<op_tensor_product<EXP1,EXP2> > tensor_product ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - typedef op_tensor_product<EXP1,EXP2> op; - return matrix_op<op>(op(a.ref(),b.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_make_symmetric : basic_op_m<M> - { - op_make_symmetric ( const M& m_) : basic_op_m<M>(m_){} - - const static long cost = M::cost+1; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - const_ret_type apply ( long r, long c) const - { - if (r >= c) - return this->m(r,c); - else - return this->m(c,r); - } - }; - - template < - typename EXP - > - const matrix_op<op_make_symmetric<EXP> > make_symmetric ( - const matrix_exp<EXP>& m - ) - { - DLIB_ASSERT(m.nr() == m.nc(), - "\tconst matrix make_symmetric(m)" - << "\n\t m must be a square matrix" - << "\n\t m.nr(): " << m.nr() - << "\n\t m.nc(): " << m.nc() - ); - - typedef op_make_symmetric<EXP> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_lowerm : basic_op_m<M> - { - op_lowerm( const M& m_) : basic_op_m<M>(m_){} - - const static long cost = M::cost+2; - typedef typename M::type type; - typedef const typename M::type const_ret_type; - const_ret_type apply ( long r, long c) const - { - if (r >= c) - return this->m(r,c); - else - return 0; - } - }; - - template <typename M> - struct op_lowerm_s : basic_op_m<M> - { - typedef typename M::type type; - op_lowerm_s( const M& m_, const type& s_) : basic_op_m<M>(m_), s(s_){} - - const type s; - - const static long cost = M::cost+2; - typedef const typename M::type const_ret_type; - const_ret_type apply ( long r, long c) const - { - if (r > c) - return this->m(r,c); - else if (r==c) - return s; - else - return 0; - } - }; - - template < - typename EXP - > - const matrix_op<op_lowerm<EXP> > lowerm ( - const matrix_exp<EXP>& m - ) - { - typedef op_lowerm<EXP> op; - return matrix_op<op>(op(m.ref())); - } - - template < - typename EXP - > - const matrix_op<op_lowerm_s<EXP> > lowerm ( - const matrix_exp<EXP>& m, - typename EXP::type s - ) - { - typedef op_lowerm_s<EXP> op; - return matrix_op<op>(op(m.ref(),s)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_upperm : basic_op_m<M> - { - op_upperm( const M& m_) : basic_op_m<M>(m_){} - - const static long cost = M::cost+2; - typedef typename M::type type; - typedef const typename M::type const_ret_type; - const_ret_type apply ( long r, long c) const - { - if (r <= c) - return this->m(r,c); - else - return 0; - } - }; - - template <typename M> - struct op_upperm_s : basic_op_m<M> - { - typedef typename M::type type; - op_upperm_s( const M& m_, const type& s_) : basic_op_m<M>(m_), s(s_){} - - const type s; - - const static long cost = M::cost+2; - typedef const typename M::type const_ret_type; - const_ret_type apply ( long r, long c) const - { - if (r < c) - return this->m(r,c); - else if (r==c) - return s; - else - return 0; - } - }; - - template < - typename EXP - > - const matrix_op<op_upperm<EXP> > upperm ( - const matrix_exp<EXP>& m - ) - { - typedef op_upperm<EXP> op; - return matrix_op<op>(op(m.ref())); - } - - template < - typename EXP - > - const matrix_op<op_upperm_s<EXP> > upperm ( - const matrix_exp<EXP>& m, - typename EXP::type s - ) - { - typedef op_upperm_s<EXP> op; - return matrix_op<op>(op(m.ref(),s)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename rand_gen> - inline const matrix<double> randm( - long nr, - long nc, - rand_gen& rnd - ) - { - DLIB_ASSERT(nr >= 0 && nc >= 0, - "\tconst matrix randm(nr, nc, rnd)" - << "\n\tInvalid inputs to this function" - << "\n\tnr: " << nr - << "\n\tnc: " << nc - ); - - matrix<double> m(nr,nc); - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - m(r,c) = rnd.get_random_double(); - } - } - - return m; - } - -// ---------------------------------------------------------------------------------------- - - inline const matrix<double> randm( - long nr, - long nc - ) - { - DLIB_ASSERT(nr >= 0 && nc >= 0, - "\tconst matrix randm(nr, nc)" - << "\n\tInvalid inputs to this function" - << "\n\tnr: " << nr - << "\n\tnc: " << nc - ); - - matrix<double> m(nr,nc); - // make a double that contains RAND_MAX + the smallest number that still - // makes the resulting double slightly bigger than static_cast<double>(RAND_MAX) - double max_val = RAND_MAX; - max_val += std::numeric_limits<double>::epsilon()*RAND_MAX; - - for (long r = 0; r < m.nr(); ++r) - { - for (long c = 0; c < m.nc(); ++c) - { - m(r,c) = std::rand()/max_val; - } - } - - return m; - } - -// ---------------------------------------------------------------------------------------- - - inline const matrix_range_exp<double> linspace ( - double start, - double end, - long num - ) - { - DLIB_ASSERT(num >= 0, - "\tconst matrix_exp linspace(start, end, num)" - << "\n\tInvalid inputs to this function" - << "\n\tstart: " << start - << "\n\tend: " << end - << "\n\tnum: " << num - ); - - return matrix_range_exp<double>(start,end,num,false); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_linpiece - { - op_linpiece(const double val_, const M& joints_) : joints(joints_), val(val_){} - - const M& joints; - const double val; - - const static long cost = 10; - - const static long NR = (M::NR*M::NC==0) ? (0) : (M::NR*M::NC-1); - const static long NC = 1; - typedef typename M::type type; - typedef default_memory_manager mem_manager_type; - typedef row_major_layout layout_type; - - typedef type const_ret_type; - const_ret_type apply (long i, long ) const - { - if (joints(i) < val) - return std::min<type>(val,joints(i+1)) - joints(i); - else - return 0; - } - - long nr () const { return joints.size()-1; } - long nc () const { return 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return joints.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return joints.aliases(item); } - }; - - template < typename EXP > - const matrix_op<op_linpiece<EXP> > linpiece ( - const double val, - const matrix_exp<EXP>& joints - ) - { - // make sure requires clause is not broken - DLIB_ASSERT(is_vector(joints) && joints.size() >= 2, - "\t matrix_exp linpiece()" - << "\n\t Invalid inputs were given to this function " - << "\n\t is_vector(joints): " << is_vector(joints) - << "\n\t joints.size(): " << joints.size() - ); -#ifdef ENABLE_ASSERTS - for (long i = 1; i < joints.size(); ++i) - { - DLIB_ASSERT(joints(i-1) < joints(i), - "\t matrix_exp linpiece()" - << "\n\t Invalid inputs were given to this function " - << "\n\t joints("<<i-1<<"): " << joints(i-1) - << "\n\t joints("<<i<<"): " << joints(i) - ); - } -#endif - - typedef op_linpiece<EXP> op; - return matrix_op<op>(op(val,joints.ref())); - } - -// ---------------------------------------------------------------------------------------- - - inline const matrix_log_range_exp<double> logspace ( - double start, - double end, - long num - ) - { - DLIB_ASSERT(num >= 0, - "\tconst matrix_exp logspace(start, end, num)" - << "\n\tInvalid inputs to this function" - << "\n\tstart: " << start - << "\n\tend: " << end - << "\n\tnum: " << num - ); - - return matrix_log_range_exp<double>(start,end,num); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_cart_prod - { - op_cart_prod(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {} - const M1& m1; - const M2& m2; - - const static long cost = M1::cost+M2::cost+1; - typedef typename M1::type type; - typedef const typename M1::const_ret_type const_ret_type; - - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - const static long NR = M1::NR+M2::NR; - const static long NC = M1::NC*M2::NC; - - const_ret_type apply ( long r, long c) const - { - if (r < m1.nr()) - return m1(r, c/m2.nc()); - else - return m2(r-m1.nr(), c%m2.nc()); - } - - long nr () const { return m1.nr() + m2.nr(); } - long nc () const { return m1.nc() * m2.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item); } - }; - - template < - typename EXP1, - typename EXP2 - > - const matrix_op<op_cart_prod<EXP1,EXP2> > cartesian_product ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - - typedef op_cart_prod<EXP1,EXP2> op; - return matrix_op<op>(op(a.ref(),b.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_mat_to_vect - { - op_mat_to_vect(const M& m_) : m(m_) {} - const M& m; - - const static long cost = M::cost+2; - const static long NR = M::NC*M::NR; - const static long NC = 1; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - - const_ret_type apply ( long r, long ) const { return m(r/m.nc(), r%m.nc()); } - - long nr () const { return m.size(); } - long nc () const { return 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP - > - const matrix_op<op_mat_to_vect<EXP> > reshape_to_column_vector ( - const matrix_exp<EXP>& m - ) - { - typedef op_mat_to_vect<EXP> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR_, - long NC_, - typename MM - > - struct op_mat_to_vect2 - { - typedef matrix<T,NR_,NC_,MM,row_major_layout> M; - op_mat_to_vect2(const M& m_) : m(m_) {} - const M& m; - - const static long cost = M::cost+2; - const static long NR = M::NC*M::NR; - const static long NC = 1; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - - const_ret_type apply ( long r, long ) const { return (&m(0,0))[r]; } - - long nr () const { return m.size(); } - long nc () const { return 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename T, - long NR, - long NC, - typename MM - > - const matrix_op<op_mat_to_vect2<T,NR,NC,MM> > reshape_to_column_vector ( - const matrix<T,NR,NC,MM,row_major_layout>& m - ) - { - typedef op_mat_to_vect2<T,NR,NC,MM> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_join_rows - { - op_join_rows(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_),_nr(std::max(m1.nr(),m2.nr())) {} - const M1& m1; - const M2& m2; - const long _nr; - - template <typename T, typename U, bool selection> - struct type_selector; - template <typename T, typename U> - struct type_selector<T,U,true> { typedef T type; }; - template <typename T, typename U> - struct type_selector<T,U,false> { typedef U type; }; - - // If both const_ret_types are references then we should use them as the const_ret_type type - // but otherwise we should use the normal type. - typedef typename M1::const_ret_type T1; - typedef typename M1::type T2; - typedef typename M2::const_ret_type T3; - typedef typename type_selector<T1, T2, is_reference_type<T1>::value && is_reference_type<T3>::value>::type const_ret_type; - - const static long cost = M1::cost + M2::cost + 1; - const static long NR = tmax<M1::NR, M2::NR>::value; - const static long NC = (M1::NC*M2::NC != 0)? (M1::NC+M2::NC) : (0); - typedef typename M1::type type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - - const_ret_type apply (long r, long c) const - { - if (c < m1.nc()) - return m1(r,c); - else - return m2(r,c-m1.nc()); - } - - long nr () const { return _nr; } - long nc () const { return m1.nc()+m2.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item); } - }; - - template < - typename EXP1, - typename EXP2 - > - inline const matrix_op<op_join_rows<EXP1,EXP2> > join_rows ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - // You are getting an error on this line because you are trying to join two matrices that - // don't have the same number of rows - COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || (EXP1::NR*EXP2::NR == 0)); - - DLIB_ASSERT(a.nr() == b.nr() || a.size() == 0 || b.size() == 0, - "\tconst matrix_exp join_rows(const matrix_exp& a, const matrix_exp& b)" - << "\n\tYou can only use join_rows() if both matrices have the same number of rows" - << "\n\ta.nr(): " << a.nr() - << "\n\tb.nr(): " << b.nr() - << "\n\ta.nc(): " << a.nc() - << "\n\tb.nc(): " << b.nc() - ); - - typedef op_join_rows<EXP1,EXP2> op; - return matrix_op<op>(op(a.ref(),b.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M1, typename M2> - struct op_join_cols - { - op_join_cols(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_),_nc(std::max(m1.nc(),m2.nc())) {} - const M1& m1; - const M2& m2; - const long _nc; - - template <typename T, typename U, bool selection> - struct type_selector; - template <typename T, typename U> - struct type_selector<T,U,true> { typedef T type; }; - template <typename T, typename U> - struct type_selector<T,U,false> { typedef U type; }; - - // If both const_ret_types are references then we should use them as the const_ret_type type - // but otherwise we should use the normal type. - typedef typename M1::const_ret_type T1; - typedef typename M1::type T2; - typedef typename M2::const_ret_type T3; - typedef typename type_selector<T1, T2, is_reference_type<T1>::value && is_reference_type<T3>::value>::type const_ret_type; - - - - const static long cost = M1::cost + M2::cost + 1; - const static long NC = tmax<M1::NC, M2::NC>::value; - const static long NR = (M1::NR*M2::NR != 0)? (M1::NR+M2::NR) : (0); - typedef typename M1::type type; - typedef typename M1::mem_manager_type mem_manager_type; - typedef typename M1::layout_type layout_type; - - const_ret_type apply ( long r, long c) const - { - if (r < m1.nr()) - return m1(r,c); - else - return m2(r-m1.nr(),c); - } - - long nr () const { return m1.nr()+m2.nr(); } - long nc () const { return _nc; } - - - template <typename U> bool aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const - { return m1.aliases(item) || m2.aliases(item); } - }; - - template < - typename EXP1, - typename EXP2 - > - inline const matrix_op<op_join_cols<EXP1,EXP2> > join_cols ( - const matrix_exp<EXP1>& a, - const matrix_exp<EXP2>& b - ) - { - COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); - // You are getting an error on this line because you are trying to join two matrices that - // don't have the same number of columns - COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || (EXP1::NC*EXP2::NC == 0)); - - DLIB_ASSERT(a.nc() == b.nc() || a.size() == 0 || b.size() == 0, - "\tconst matrix_exp join_cols(const matrix_exp& a, const matrix_exp& b)" - << "\n\tYou can only use join_cols() if both matrices have the same number of columns" - << "\n\ta.nr(): " << a.nr() - << "\n\tb.nr(): " << b.nr() - << "\n\ta.nc(): " << a.nc() - << "\n\tb.nc(): " << b.nc() - ); - - typedef op_join_cols<EXP1,EXP2> op; - return matrix_op<op>(op(a.ref(),b.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_fliplr - { - op_fliplr( const M& m_) : m(m_){} - - const M& m; - - const static long cost = M::cost; - const static long NR = M::NR; - const static long NC = M::NC; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - - const_ret_type apply (long r, long c) const { return m(r,m.nc()-c-1); } - - long nr () const { return m.nr(); } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - - }; - - template < - typename M - > - const matrix_op<op_fliplr<M> > fliplr ( - const matrix_exp<M>& m - ) - { - typedef op_fliplr<M> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_flipud - { - op_flipud( const M& m_) : m(m_){} - - const M& m; - - const static long cost = M::cost; - const static long NR = M::NR; - const static long NC = M::NC; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - - const_ret_type apply (long r, long c) const { return m(m.nr()-r-1,c); } - - long nr () const { return m.nr(); } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - - }; - - template < - typename M - > - const matrix_op<op_flipud<M> > flipud ( - const matrix_exp<M>& m - ) - { - typedef op_flipud<M> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M> - struct op_flip - { - op_flip( const M& m_) : m(m_){} - - const M& m; - - const static long cost = M::cost; - const static long NR = M::NR; - const static long NC = M::NC; - typedef typename M::type type; - typedef typename M::const_ret_type const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - - const_ret_type apply (long r, long c) const { return m(m.nr()-r-1, m.nc()-c-1); } - - long nr () const { return m.nr(); } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - - }; - - template < - typename M - > - const matrix_op<op_flip<M> > flip ( - const matrix_exp<M>& m - ) - { - typedef op_flip<M> op; - return matrix_op<op>(op(m.ref())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename T, long NR, long NC, typename MM, typename L> - uint32 hash ( - const matrix<T,NR,NC,MM,L>& item, - uint32 seed = 0 - ) - { - DLIB_ASSERT_HAS_STANDARD_LAYOUT(T); - - if (item.size() == 0) - return 0; - else - return murmur_hash3(&item(0,0), sizeof(T)*item.size(), seed); - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_UTILITIES_ - diff --git a/ml/dlib/dlib/matrix/matrix_utilities_abstract.h b/ml/dlib/dlib/matrix/matrix_utilities_abstract.h deleted file mode 100644 index ad4c91167..000000000 --- a/ml/dlib/dlib/matrix/matrix_utilities_abstract.h +++ /dev/null @@ -1,1874 +0,0 @@ -// Copyright (C) 2006 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_MATRIx_UTILITIES_ABSTRACT_ -#ifdef DLIB_MATRIx_UTILITIES_ABSTRACT_ - -#include "matrix_abstract.h" -#include <complex> -#include "../pixel.h" -#include "../geometry/rectangle.h" -#inclue <vector> - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Simple matrix utilities -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename EXP> - constexpr bool is_row_major ( - const matrix_exp<EXP>& - ); - /*! - ensures - - returns true if and only if the given matrix expression uses the row_major_layout. - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp diag ( - const matrix_exp& m - ); - /*! - ensures - - returns a column vector R that contains the elements from the diagonal - of m in the order R(0)==m(0,0), R(1)==m(1,1), R(2)==m(2,2) and so on. - !*/ - - template <typename EXP> - struct diag_exp - { - /*! - WHAT THIS OBJECT REPRESENTS - This struct allows you to determine the type of matrix expression - object returned from the diag() function. An example makes its - use clear: - - template <typename EXP> - void do_something( const matrix_exp<EXP>& mat) - { - // d is a matrix expression that aliases mat. - typename diag_exp<EXP>::type d = diag(mat); - - // Print the diagonal of mat. So we see that by using - // diag_exp we can save the object returned by diag() in - // a local variable. - cout << d << endl; - - // Note that you can only save the return value of diag() to - // a local variable if the argument to diag() has a lifetime - // beyond the diag() expression. The example shown above is - // OK but the following would result in undefined behavior: - typename diag_exp<EXP>::type bad = diag(mat + mat); - } - !*/ - typedef type_of_expression_returned_by_diag type; - }; - -// ---------------------------------------------------------------------------------------- - - const matrix_exp diagm ( - const matrix_exp& m - ); - /*! - requires - - is_vector(m) == true - (i.e. m is a row or column matrix) - ensures - - returns a square matrix M such that: - - diag(M) == m - - non diagonal elements of M are 0 - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp trans ( - const matrix_exp& m - ); - /*! - ensures - - returns the transpose of the matrix m - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_type::type dot ( - const matrix_exp& m1, - const matrix_exp& m2 - ); - /*! - requires - - is_vector(m1) == true - - is_vector(m2) == true - - m1.size() == m2.size() - - m1.size() > 0 - ensures - - returns the dot product between m1 and m2. That is, this function - computes and returns the sum, for all i, of m1(i)*m2(i). - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp lowerm ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix M such that: - - M::type == the same type that was in m - - M has the same dimensions as m - - M is the lower triangular part of m. That is: - - if (r >= c) then - - M(r,c) == m(r,c) - - else - - M(r,c) == 0 - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp lowerm ( - const matrix_exp& m, - const matrix_exp::type scalar_value - ); - /*! - ensures - - returns a matrix M such that: - - M::type == the same type that was in m - - M has the same dimensions as m - - M is the lower triangular part of m except that the diagonal has - been set to scalar_value. That is: - - if (r > c) then - - M(r,c) == m(r,c) - - else if (r == c) then - - M(r,c) == scalar_value - - else - - M(r,c) == 0 - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp upperm ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix M such that: - - M::type == the same type that was in m - - M has the same dimensions as m - - M is the upper triangular part of m. That is: - - if (r <= c) then - - M(r,c) == m(r,c) - - else - - M(r,c) == 0 - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp upperm ( - const matrix_exp& m, - const matrix_exp::type scalar_value - ); - /*! - ensures - - returns a matrix M such that: - - M::type == the same type that was in m - - M has the same dimensions as m - - M is the upper triangular part of m except that the diagonal has - been set to scalar_value. That is: - - if (r < c) then - - M(r,c) == m(r,c) - - else if (r == c) then - - M(r,c) == scalar_value - - else - - M(r,c) == 0 - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp make_symmetric ( - const matrix_exp& m - ); - /*! - requires - - m.nr() == m.nc() - (i.e. m must be a square matrix) - ensures - - returns a matrix M such that: - - M::type == the same type that was in m - - M has the same dimensions as m - - M is a symmetric matrix, that is, M == trans(M) and - it is constructed from the lower triangular part of m. Specifically, - we have: - - lowerm(M) == lowerm(m) - - upperm(M) == trans(lowerm(m)) - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - T val - > - const matrix_exp uniform_matrix ( - ); - /*! - requires - - NR > 0 && NC > 0 - ensures - - returns an NR by NC matrix with elements of type T and all set to val. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC - > - const matrix_exp uniform_matrix ( - const T& val - ); - /*! - requires - - NR > 0 && NC > 0 - ensures - - returns an NR by NC matrix with elements of type T and all set to val. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_exp uniform_matrix ( - long nr, - long nc, - const T& val - ); - /*! - requires - - nr >= 0 && nc >= 0 - ensures - - returns an nr by nc matrix with elements of type T and all set to val. - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp ones_matrix ( - const matrix_exp& mat - ); - /*! - requires - - mat.nr() >= 0 && mat.nc() >= 0 - ensures - - Let T denote the type of element in mat. Then this function - returns uniform_matrix<T>(mat.nr(), mat.nc(), 1) - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_exp ones_matrix ( - long nr, - long nc - ); - /*! - requires - - nr >= 0 && nc >= 0 - ensures - - returns uniform_matrix<T>(nr, nc, 1) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp zeros_matrix ( - const matrix_exp& mat - ); - /*! - requires - - mat.nr() >= 0 && mat.nc() >= 0 - ensures - - Let T denote the type of element in mat. Then this function - returns uniform_matrix<T>(mat.nr(), mat.nc(), 0) - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_exp zeros_matrix ( - long nr, - long nc - ); - /*! - requires - - nr >= 0 && nc >= 0 - ensures - - returns uniform_matrix<T>(nr, nc, 0) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp identity_matrix ( - const matrix_exp& mat - ); - /*! - requires - - mat.nr() == mat.nc() - ensures - - returns an identity matrix with the same dimensions as mat and - containing the same type of elements as mat. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - const matrix_exp identity_matrix ( - long N - ); - /*! - requires - - N > 0 - ensures - - returns an N by N identity matrix with elements of type T. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long N - > - const matrix_exp identity_matrix ( - ); - /*! - requires - - N > 0 - ensures - - returns an N by N identity matrix with elements of type T. - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp linspace ( - double start, - double end, - long num - ); - /*! - requires - - num >= 0 - ensures - - returns a matrix M such that: - - M::type == double - - is_row_vector(M) == true - - M.size() == num - - M == a row vector with num linearly spaced values beginning with start - and stopping with end. - - M(num-1) == end - - if (num > 1) then - - M(0) == start - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp logspace ( - double start, - double end, - long num - ); - /*! - requires - - num >= 0 - ensures - - returns a matrix M such that: - - M::type == double - - is_row_vector(M) == true - - M.size() == num - - M == a row vector with num logarithmically spaced values beginning with - 10^start and stopping with 10^end. - (i.e. M == pow(10, linspace(start, end, num))) - - M(num-1) == 10^end - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp linpiece ( - const double val, - const matrix_exp& joints - ); - /*! - requires - - is_vector(joints) == true - - joints.size() >= 2 - - for all valid i < j: - - joints(i) < joints(j) - ensures - - linpiece() is useful for creating piecewise linear functions of val. For - example, if w is a parameter vector then you can represent a piecewise linear - function of val as: f(val) = dot(w, linpiece(val, linspace(0,100,5))). In - this case, f(val) is piecewise linear on the intervals [0,25], [25,50], - [50,75], [75,100]. Moreover, w(i) defines the derivative of f(val) in the - i-th interval. Finally, outside the interval [0,100] f(val) has a derivative - of zero and f(0) == 0. - - To be precise, this function returns a column vector L such that: - - L.size() == joints.size()-1 - - is_col_vector(L) == true - - L contains the same type of elements as joints. - - for all valid i: - - if (joints(i) < val) - - L(i) == min(val,joints(i+1)) - joints(i) - - else - - L(i) == 0 - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - long R, - long C - > - const matrix_exp rotate ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - R( (r+R)%m.nr() , (c+C)%m.nc() ) == m(r,c) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp fliplr ( - const matrix_exp& m - ); - /*! - ensures - - flips the matrix m from left to right and returns the result. - I.e. reverses the order of the columns. - - returns a matrix M such that: - - M::type == the same type that was in m - - M has the same dimensions as m - - for all valid r and c: - M(r,c) == m(r, m.nc()-c-1) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp flipud ( - const matrix_exp& m - ); - /*! - ensures - - flips the matrix m from up to down and returns the result. - I.e. reverses the order of the rows. - - returns a matrix M such that: - - M::type == the same type that was in m - - M has the same dimensions as m - - for all valid r and c: - M(r,c) == m(m.nr()-r-1, c) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp flip ( - const matrix_exp& m - ); - /*! - ensures - - flips the matrix m from up to down and left to right and returns the - result. I.e. returns flipud(fliplr(m)). - - returns a matrix M such that: - - M::type == the same type that was in m - - M has the same dimensions as m - - for all valid r and c: - M(r,c) == m(m.nr()-r-1, m.nc()-c-1) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp reshape ( - const matrix_exp& m, - long rows, - long cols - ); - /*! - requires - - m.size() == rows*cols - - rows > 0 - - cols > 0 - ensures - - returns a matrix M such that: - - M.nr() == rows - - M.nc() == cols - - M.size() == m.size() - - for all valid r and c: - - let IDX = r*cols + c - - M(r,c) == m(IDX/m.nc(), IDX%m.nc()) - - - i.e. The matrix m is reshaped into a new matrix of rows by cols - dimension. Additionally, the elements of m are laid into M in row major - order. - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp reshape_to_column_vector ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix M such that: - - is_col_vector(M) == true - - M.size() == m.size() - - for all valid r and c: - - m(r,c) == M(r*m.nc() + c) - - - i.e. The matrix m is reshaped into a column vector. Note that - the elements are pulled out in row major order. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - long R, - long C - > - const matrix_exp removerc ( - const matrix_exp& m - ); - /*! - requires - - m.nr() > R >= 0 - - m.nc() > C >= 0 - ensures - - returns a matrix M such that: - - M.nr() == m.nr() - 1 - - M.nc() == m.nc() - 1 - - M == m with its R row and C column removed - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp removerc ( - const matrix_exp& m, - long R, - long C - ); - /*! - requires - - m.nr() > R >= 0 - - m.nc() > C >= 0 - ensures - - returns a matrix M such that: - - M.nr() == m.nr() - 1 - - M.nc() == m.nc() - 1 - - M == m with its R row and C column removed - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - long R - > - const matrix_exp remove_row ( - const matrix_exp& m - ); - /*! - requires - - m.nr() > R >= 0 - ensures - - returns a matrix M such that: - - M.nr() == m.nr() - 1 - - M.nc() == m.nc() - - M == m with its R row removed - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp remove_row ( - const matrix_exp& m, - long R - ); - /*! - requires - - m.nr() > R >= 0 - ensures - - returns a matrix M such that: - - M.nr() == m.nr() - 1 - - M.nc() == m.nc() - - M == m with its R row removed - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - long C - > - const matrix_exp remove_col ( - const matrix_exp& m - ); - /*! - requires - - m.nc() > C >= 0 - ensures - - returns a matrix M such that: - - M.nr() == m.nr() - - M.nc() == m.nc() - 1 - - M == m with its C column removed - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp remove_col ( - const matrix_exp& m, - long C - ); - /*! - requires - - m.nc() > C >= 0 - ensures - - returns a matrix M such that: - - M.nr() == m.nr() - - M.nc() == m.nc() - 1 - - M == m with its C column removed - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename target_type - > - const matrix_exp matrix_cast ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R where for all valid r and c: - R(r,c) == static_cast<target_type>(m(r,c)) - also, R has the same dimensions as m. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - typename MM, - typename U, - typename L - > - void set_all_elements ( - matrix<T,NR,NC,MM,L>& m, - U value - ); - /*! - ensures - - for all valid r and c: - m(r,c) == value - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::matrix_type tmp ( - const matrix_exp& m - ); - /*! - ensures - - returns a temporary matrix object that is a copy of m. - (This allows you to easily force a matrix_exp to fully evaluate) - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - typename MM, - typename L - > - uint32 hash ( - const matrix<T,NR,NC,MM,L>& item, - uint32 seed = 0 - ); - /*! - requires - - T is a standard layout type (e.g. a POD type like int, float, - or a simple struct). - ensures - - returns a 32bit hash of the data stored in item. - - Each value of seed results in a different hash function being used. - (e.g. hash(item,0) should generally not be equal to hash(item,1)) - - uses the murmur_hash3() routine to compute the actual hash. - - Note that if the memory layout of the elements in item change between - hardware platforms then hash() will give different outputs. If you want - hash() to always give the same output for the same input then you must - ensure that elements of item always have the same layout in memory. - Typically this means using fixed width types and performing byte swapping - to account for endianness before passing item to hash(). - !*/ - -// ---------------------------------------------------------------------------------------- - - // if matrix_exp contains non-complex types (e.g. float, double) - bool equal ( - const matrix_exp& a, - const matrix_exp& b, - const matrix_exp::type epsilon = 100*std::numeric_limits<matrix_exp::type>::epsilon() - ); - /*! - ensures - - if (a and b don't have the same dimensions) then - - returns false - - else if (there exists an r and c such that abs(a(r,c)-b(r,c)) > epsilon) then - - returns false - - else - - returns true - !*/ - -// ---------------------------------------------------------------------------------------- - - // if matrix_exp contains std::complex types - bool equal ( - const matrix_exp& a, - const matrix_exp& b, - const matrix_exp::type::value_type epsilon = 100*std::numeric_limits<matrix_exp::type::value_type>::epsilon() - ); - /*! - ensures - - if (a and b don't have the same dimensions) then - - returns false - - else if (there exists an r and c such that abs(real(a(r,c)-b(r,c))) > epsilon - or abs(imag(a(r,c)-b(r,c))) > epsilon) then - - returns false - - else - - returns true - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp pointwise_multiply ( - const matrix_exp& a, - const matrix_exp& b - ); - /*! - requires - - a.nr() == b.nr() - - a.nc() == b.nc() - - a and b both contain the same type of element (one or both - can also be of type std::complex so long as the underlying type - in them is the same) - ensures - - returns a matrix R such that: - - R::type == the same type that was in a and b. - - R has the same dimensions as a and b. - - for all valid r and c: - R(r,c) == a(r,c) * b(r,c) - !*/ - - const matrix_exp pointwise_multiply ( - const matrix_exp& a, - const matrix_exp& b, - const matrix_exp& c - ); - /*! - performs pointwise_multiply(a,pointwise_multiply(b,c)); - !*/ - - const matrix_exp pointwise_multiply ( - const matrix_exp& a, - const matrix_exp& b, - const matrix_exp& c, - const matrix_exp& d - ); - /*! - performs pointwise_multiply(pointwise_multiply(a,b),pointwise_multiply(c,d)); - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp join_rows ( - const matrix_exp& a, - const matrix_exp& b - ); - /*! - requires - - a.nr() == b.nr() || a.size() == 0 || b.size() == 0 - - a and b both contain the same type of element - ensures - - This function joins two matrices together by concatenating their rows. - - returns a matrix R such that: - - R::type == the same type that was in a and b. - - R.nr() == a.nr() == b.nr() - - R.nc() == a.nc() + b.nc() - - for all valid r and c: - - if (c < a.nc()) then - - R(r,c) == a(r,c) - - else - - R(r,c) == b(r, c-a.nc()) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp join_cols ( - const matrix_exp& a, - const matrix_exp& b - ); - /*! - requires - - a.nc() == b.nc() || a.size() == 0 || b.size() == 0 - - a and b both contain the same type of element - ensures - - This function joins two matrices together by concatenating their columns. - - returns a matrix R such that: - - R::type == the same type that was in a and b. - - R.nr() == a.nr() + b.nr() - - R.nc() == a.nc() == b.nc() - - for all valid r and c: - - if (r < a.nr()) then - - R(r,c) == a(r,c) - - else - - R(r,c) == b(r-a.nr(), c) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp tensor_product ( - const matrix_exp& a, - const matrix_exp& b - ); - /*! - requires - - a and b both contain the same type of element - ensures - - returns a matrix R such that: - - R::type == the same type that was in a and b. - - R.nr() == a.nr() * b.nr() - - R.nc() == a.nc() * b.nc() - - for all valid r and c: - R(r,c) == a(r/b.nr(), c/b.nc()) * b(r%b.nr(), c%b.nc()) - - I.e. R is the tensor product of matrix a with matrix b - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp cartesian_product ( - const matrix_exp& A, - const matrix_exp& B - ); - /*! - requires - - A and B both contain the same type of element - ensures - - Think of A and B as sets of column vectors. Then this function - returns a matrix that contains a set of column vectors that is - the Cartesian product of the sets A and B. That is, the resulting - matrix contains every possible combination of vectors from both A and - B. - - returns a matrix R such that: - - R::type == the same type that was in A and B. - - R.nr() == A.nr() + B.nr() - - R.nc() == A.nc() * B.nc() - - Each column of R is the concatenation of a column vector - from A with a column vector from B. - - for all valid r and c: - - if (r < A.nr()) then - - R(r,c) == A(r, c/B.nc()) - - else - - R(r,c) == B(r-A.nr(), c%B.nc()) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp scale_columns ( - const matrix_exp& m, - const matrix_exp& v - ); - /*! - requires - - is_vector(v) == true - - v.size() == m.nc() - - m and v both contain the same type of element - ensures - - returns a matrix R such that: - - R::type == the same type that was in m and v. - - R has the same dimensions as m. - - for all valid r and c: - R(r,c) == m(r,c) * v(c) - - i.e. R is the result of multiplying each of m's columns by - the corresponding scalar in v. - - - Note that this function is identical to the expression m*diagm(v). - That is, the * operator is overloaded for this case and will invoke - scale_columns() automatically as appropriate. - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp scale_rows ( - const matrix_exp& m, - const matrix_exp& v - ); - /*! - requires - - is_vector(v) == true - - v.size() == m.nr() - - m and v both contain the same type of element - ensures - - returns a matrix R such that: - - R::type == the same type that was in m and v. - - R has the same dimensions as m. - - for all valid r and c: - R(r,c) == m(r,c) * v(r) - - i.e. R is the result of multiplying each of m's rows by - the corresponding scalar in v. - - - Note that this function is identical to the expression diagm(v)*m. - That is, the * operator is overloaded for this case and will invoke - scale_rows() automatically as appropriate. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename T> - void sort_columns ( - matrix<T>& m, - matrix<T>& v - ); - /*! - requires - - is_col_vector(v) == true - - v.size() == m.nc() - - m and v both contain the same type of element - ensures - - the dimensions for m and v are not changed - - sorts the columns of m according to the values in v. - i.e. - - #v == the contents of v but in sorted order according to - operator<. So smaller elements come first. - - Let #v(new(i)) == v(i) (i.e. new(i) is the index element i moved to) - - colm(#m,new(i)) == colm(m,i) - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename T> - void rsort_columns ( - matrix<T>& m, - matrix<T>& v - ); - /*! - requires - - is_col_vector(v) == true - - v.size() == m.nc() - - m and v both contain the same type of element - ensures - - the dimensions for m and v are not changed - - sorts the columns of m according to the values in v. - i.e. - - #v == the contents of v but in sorted order according to - operator>. So larger elements come first. - - Let #v(new(i)) == v(i) (i.e. new(i) is the index element i moved to) - - colm(#m,new(i)) == colm(m,i) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::type length_squared ( - const matrix_exp& m - ); - /*! - requires - - is_vector(m) == true - ensures - - returns sum(squared(m)) - (i.e. returns the square of the length of the vector m) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::type length ( - const matrix_exp& m - ); - /*! - requires - - is_vector(m) == true - ensures - - returns sqrt(sum(squared(m))) - (i.e. returns the length of the vector m) - - if (m contains integer valued elements) then - - The return type is a double that represents the length. Therefore, the - return value of length() is always represented using a floating point - type. - !*/ - -// ---------------------------------------------------------------------------------------- - - bool is_row_vector ( - const matrix_exp& m - ); - /*! - ensures - - if (m.nr() == 1) then - - return true - - else - - returns false - !*/ - - bool is_col_vector ( - const matrix_exp& m - ); - /*! - ensures - - if (m.nc() == 1) then - - return true - - else - - returns false - !*/ - - bool is_vector ( - const matrix_exp& m - ); - /*! - ensures - - if (is_row_vector(m) || is_col_vector(m)) then - - return true - - else - - returns false - !*/ - -// ---------------------------------------------------------------------------------------- - - bool is_finite ( - const matrix_exp& m - ); - /*! - ensures - - returns true if all the values in m are finite values and also not any kind - of NaN value. - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Thresholding relational operators -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator< ( - const matrix_exp& m, - const S& s - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (m(r,c) < s) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator< ( - const S& s, - const matrix_exp& m - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (s < m(r,c)) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator<= ( - const matrix_exp& m, - const S& s - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (m(r,c) <= s) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator<= ( - const S& s, - const matrix_exp& m - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (s <= m(r,c)) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator> ( - const matrix_exp& m, - const S& s - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (m(r,c) > s) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator> ( - const S& s, - const matrix_exp& m - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (s > m(r,c)) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator>= ( - const matrix_exp& m, - const S& s - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (m(r,c) >= s) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator>= ( - const S& s, - const matrix_exp& m - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (s >= m(r,c)) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator== ( - const matrix_exp& m, - const S& s - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (m(r,c) == s) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator== ( - const S& s, - const matrix_exp& m - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (s == m(r,c)) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator!= ( - const matrix_exp& m, - const S& s - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (m(r,c) != s) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const matrix_exp operator!= ( - const S& s, - const matrix_exp& m - ); - /*! - requires - - is_built_in_scalar_type<S>::value == true - - is_built_in_scalar_type<matrix_exp::type>::value == true - ensures - - returns a matrix R such that: - - R::type == the same type that was in m. - - R has the same dimensions as m. - - for all valid r and c: - - if (s != m(r,c)) then - - R(r,c) == 1 - - else - - R(r,c) == 0 - - i.e. R is a binary matrix of all 1s or 0s. - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Statistics -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - const matrix_exp::type min ( - const matrix_exp& m - ); - /*! - requires - - m.size() > 0 - ensures - - returns the value of the smallest element of m. If m contains complex - elements then the element returned is the one with the smallest norm - according to std::norm(). - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp min_pointwise ( - const matrix_exp& a, - const matrix_exp& b - ); - /*! - requires - - a.nr() == b.nr() - - a.nc() == b.nc() - - a and b both contain the same type of element - ensures - - returns a matrix R such that: - - R::type == the same type that was in a and b. - - R has the same dimensions as a and b. - - for all valid r and c: - R(r,c) == std::min(a(r,c), b(r,c)) - !*/ - - const matrix_exp min_pointwise ( - const matrix_exp& a, - const matrix_exp& b, - const matrix_exp& c - ); - /*! - performs min_pointwise(a,min_pointwise(b,c)); - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::type max ( - const matrix_exp& m - ); - /*! - requires - - m.size() > 0 - ensures - - returns the value of the biggest element of m. If m contains complex - elements then the element returned is the one with the largest norm - according to std::norm(). - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp max_pointwise ( - const matrix_exp& a, - const matrix_exp& b - ); - /*! - requires - - a.nr() == b.nr() - - a.nc() == b.nc() - - a and b both contain the same type of element - ensures - - returns a matrix R such that: - - R::type == the same type that was in a and b. - - R has the same dimensions as a and b. - - for all valid r and c: - R(r,c) == std::max(a(r,c), b(r,c)) - !*/ - - const matrix_exp max_pointwise ( - const matrix_exp& a, - const matrix_exp& b, - const matrix_exp& c - ); - /*! - performs max_pointwise(a,max_pointwise(b,c)); - !*/ - -// ---------------------------------------------------------------------------------------- - - void find_min_and_max ( - const matrix_exp& m, - matrix_exp::type& min_val, - matrix_exp::type& max_val - ); - /*! - requires - - m.size() > 0 - ensures - - #min_val == min(m) - - #max_val == max(m) - - This function computes both the min and max in just one pass - over the elements of the matrix m. - !*/ - -// ---------------------------------------------------------------------------------------- - - long index_of_max ( - const matrix_exp& m - ); - /*! - requires - - is_vector(m) == true - - m.size() > 0 - ensures - - returns the index of the largest element in m. - (i.e. m(index_of_max(m)) == max(m)) - !*/ - -// ---------------------------------------------------------------------------------------- - - long index_of_min ( - const matrix_exp& m - ); - /*! - requires - - is_vector(m) == true - - m.size() > 0 - ensures - - returns the index of the smallest element in m. - (i.e. m(index_of_min(m)) == min(m)) - !*/ - -// ---------------------------------------------------------------------------------------- - - point max_point ( - const matrix_exp& m - ); - /*! - requires - - m.size() > 0 - ensures - - returns the location of the maximum element of the array, that is, if the - returned point is P then it will be the case that: m(P.y(),P.x()) == max(m). - !*/ - -// ---------------------------------------------------------------------------------------- - - dlib::vector<double,2> max_point_interpolated ( - const matrix_exp& m - ); - /*! - requires - - m.size() > 0 - ensures - - Like max_point(), this function finds the location in m with the largest - value. However, we additionally use some quadratic interpolation to find the - location of the maximum point with sub-pixel accuracy. Therefore, the - returned point is equal to max_point(m) + some small sub-pixel delta. - !*/ - -// ---------------------------------------------------------------------------------------- - - point min_point ( - const matrix_exp& m - ); - /*! - requires - - m.size() > 0 - ensures - - returns the location of the minimum element of the array, that is, if the - returned point is P then it will be the case that: m(P.y(),P.x()) == min(m). - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::type sum ( - const matrix_exp& m - ); - /*! - ensures - - returns the sum of all elements in m - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp sum_rows ( - const matrix_exp& m - ); - /*! - requires - - m.size() > 0 - ensures - - returns a row matrix that contains the sum of all the rows in m. - - returns a matrix M such that - - M::type == the same type that was in m - - M.nr() == 1 - - M.nc() == m.nc() - - for all valid i: - - M(i) == sum(colm(m,i)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp sum_cols ( - const matrix_exp& m - ); - /*! - requires - - m.size() > 0 - ensures - - returns a column matrix that contains the sum of all the columns in m. - - returns a matrix M such that - - M::type == the same type that was in m - - M.nr() == m.nr() - - M.nc() == 1 - - for all valid i: - - M(i) == sum(rowm(m,i)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::type prod ( - const matrix_exp& m - ); - /*! - ensures - - returns the results of multiplying all elements of m together. - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::type mean ( - const matrix_exp& m - ); - /*! - ensures - - returns the mean of all elements in m. - (i.e. returns sum(m)/(m.nr()*m.nc())) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::type variance ( - const matrix_exp& m - ); - /*! - ensures - - returns the unbiased sample variance of all elements in m - (i.e. 1.0/(m.nr()*m.nc() - 1)*(sum of all pow(m(i,j) - mean(m),2))) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp::type stddev ( - const matrix_exp& m - ); - /*! - ensures - - returns sqrt(variance(m)) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix covariance ( - const matrix_exp& m - ); - /*! - requires - - matrix_exp::type == a dlib::matrix object - - is_col_vector(m) == true - - m.size() > 1 - - for all valid i, j: - - is_col_vector(m(i)) == true - - m(i).size() > 0 - - m(i).size() == m(j).size() - - i.e. m contains only column vectors and all the column vectors - have the same non-zero length - ensures - - returns the unbiased sample covariance matrix for the set of samples - in m. - (i.e. 1.0/(m.nr()-1)*(sum of all (m(i) - mean(m))*trans(m(i) - mean(m)))) - - the returned matrix will contain elements of type matrix_exp::type::type. - - the returned matrix will have m(0).nr() rows and columns. - !*/ - -// ---------------------------------------------------------------------------------------- - - template <typename rand_gen> - const matrix<double> randm( - long nr, - long nc, - rand_gen& rnd - ); - /*! - requires - - nr >= 0 - - nc >= 0 - - rand_gen == an object that implements the rand/rand_float_abstract.h interface - ensures - - generates a random matrix using the given rnd random number generator - - returns a matrix M such that - - M::type == double - - M.nr() == nr - - M.nc() == nc - - for all valid i, j: - - M(i,j) == a random number such that 0 <= M(i,j) < 1 - !*/ - -// ---------------------------------------------------------------------------------------- - - inline const matrix<double> randm( - long nr, - long nc - ); - /*! - requires - - nr >= 0 - - nc >= 0 - ensures - - generates a random matrix using std::rand() - - returns a matrix M such that - - M::type == double - - M.nr() == nr - - M.nc() == nc - - for all valid i, j: - - M(i,j) == a random number such that 0 <= M(i,j) < 1 - !*/ - -// ---------------------------------------------------------------------------------------- - - inline const matrix_exp gaussian_randm ( - long nr, - long nc, - unsigned long seed = 0 - ); - /*! - requires - - nr >= 0 - - nc >= 0 - ensures - - returns a matrix with its values filled with 0 mean unit variance Gaussian - random numbers. - - Each setting of the seed results in a different random matrix. - - The returned matrix is lazily evaluated using the expression templates - technique. This means that the returned matrix doesn't take up any memory - and is only an expression template. The values themselves are computed on - demand using the gaussian_random_hash() routine. - - returns a matrix M such that - - M::type == double - - M.nr() == nr - - M.nc() == nc - - for all valid i, j: - - M(i,j) == gaussian_random_hash(i,j,seed) - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// Pixel and Image Utilities -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template < - typename T, - typename P - > - const matrix<T,pixel_traits<P>::num,1> pixel_to_vector ( - const P& pixel - ); - /*! - requires - - pixel_traits<P> must be defined - ensures - - returns a matrix M such that: - - M::type == T - - M::NC == 1 - - M::NR == pixel_traits<P>::num - - if (pixel_traits<P>::grayscale) then - - M(0) == pixel - - if (pixel_traits<P>::rgb) then - - M(0) == pixel.red - - M(1) == pixel.green - - M(2) == pixel.blue - - if (pixel_traits<P>::hsi) then - - M(0) == pixel.h - - M(1) == pixel.s - - M(2) == pixel.i - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename P - > - void vector_to_pixel ( - P& pixel, - const matrix_exp& vector - ); - /*! - requires - - vector::NR == pixel_traits<P>::num - - vector::NC == 1 - (i.e. you have to use a statically dimensioned vector) - ensures - - if (pixel_traits<P>::grayscale) then - - pixel == M(0) - - if (pixel_traits<P>::rgb) then - - pixel.red == M(0) - - pixel.green == M(1) - - pixel.blue == M(2) - - if (pixel_traits<P>::hsi) then - - pixel.h == M(0) - - pixel.s == M(1) - - pixel.i == M(2) - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - long lower, - long upper - > - const matrix_exp clamp ( - const matrix_exp& m - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - - if (m(r,c) > upper) then - - R(r,c) == upper - - else if (m(r,c) < lower) then - - R(r,c) == lower - - else - - R(r,c) == m(r,c) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp clamp ( - const matrix_exp& m, - const matrix_exp::type& lower, - const matrix_exp::type& upper - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - - if (m(r,c) > upper) then - - R(r,c) == upper - - else if (m(r,c) < lower) then - - R(r,c) == lower - - else - - R(r,c) == m(r,c) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp clamp ( - const matrix_exp& m, - const matrix_exp& lower, - const matrix_exp& upper - ); - /*! - requires - - m.nr() == lower.nr() - - m.nc() == lower.nc() - - m.nr() == upper.nr() - - m.nc() == upper.nc() - - m, lower, and upper all contain the same type of elements. - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - - if (m(r,c) > upper(r,c)) then - - R(r,c) == upper(r,c) - - else if (m(r,c) < lower(r,c)) then - - R(r,c) == lower(r,c) - - else - - R(r,c) == m(r,c) - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp lowerbound ( - const matrix_exp& m, - const matrix_exp::type& thresh - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - - if (m(r,c) >= thresh) then - - R(r,c) == m(r,c) - - else - - R(r,c) == thresh - !*/ - -// ---------------------------------------------------------------------------------------- - - const matrix_exp upperbound ( - const matrix_exp& m, - const matrix_exp::type& thresh - ); - /*! - ensures - - returns a matrix R such that: - - R::type == the same type that was in m - - R has the same dimensions as m - - for all valid r and c: - - if (m(r,c) <= thresh) then - - R(r,c) == m(r,c) - - else - - R(r,c) == thresh - !*/ - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_MATRIx_UTILITIES_ABSTRACT_ - diff --git a/ml/dlib/dlib/matrix/symmetric_matrix_cache.h b/ml/dlib/dlib/matrix/symmetric_matrix_cache.h deleted file mode 100644 index bff268aef..000000000 --- a/ml/dlib/dlib/matrix/symmetric_matrix_cache.h +++ /dev/null @@ -1,464 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_SYMMETRIC_MATRIX_CAcHE_Hh_ -#define DLIB_SYMMETRIC_MATRIX_CAcHE_Hh_ - -#include "symmetric_matrix_cache_abstract.h" -#include <vector> -#include "../matrix.h" -#include "../algs.h" -#include "../array.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - template <typename M, typename cache_element_type> - struct op_symm_cache : basic_op_m<M> - { - inline op_symm_cache( - const M& m_, - long max_size_megabytes_ - ) : - basic_op_m<M>(m_), - max_size_megabytes(max_size_megabytes_), - is_initialized(false) - { - lookup.assign(this->m.nr(), -1); - - diag_cache = matrix_cast<cache_element_type>(dlib::diag(m_)); - } - - op_symm_cache ( - const op_symm_cache& item - ) : - basic_op_m<M>(item.m), - diag_cache(item.diag_cache), - max_size_megabytes(item.max_size_megabytes), - is_initialized(false) - { - lookup.assign(this->m.nr(), -1); - } - - typedef cache_element_type type; - typedef const cache_element_type& const_ret_type; - const static long cost = M::cost + 3; - - inline const_ret_type apply ( long r, long c) const - { - if (lookup[c] != -1) - { - return cache[lookup[c]](r); - } - else if (r == c) - { - return diag_cache(r); - } - else if (lookup[r] != -1) - { - // the matrix is symmetric so this is legit - return cache[lookup[r]](c); - } - else - { - add_col_to_cache(c); - return cache[lookup[c]](r); - } - } - - inline std::pair<const type*,long*> col(long i) const - /*! - requires - - 0 <= i < nc() - ensures - - returns a pair P such that: - - P.first == a pointer to the first element of the ith column - - P.second == a pointer to the integer used to count the number of - outstanding references to the ith column. - !*/ - { - if (is_cached(i) == false) - add_col_to_cache(i); - - // find where this column is in the cache - long idx = lookup[i]; - if (idx == next) - { - // if this column was the next to be replaced - // then make sure that doesn't happen - next = (next + 1)%cache.size(); - } - - return std::make_pair(&cache[idx](0), &references[idx]); - } - - const type* diag() const { init(); return &diag_cache(0); } - - long* diag_ref_count() const - { - return &diag_reference_count; - } - - private: - inline bool is_cached ( - long r - ) const - { - return (lookup[r] != -1); - } - - inline void init() const - { - if (is_initialized == false) - { - // figure out how many columns of the matrix we can have - // with the given amount of memory. - long max_size = (max_size_megabytes*1024*1024)/(this->m.nr()*sizeof(type)); - // don't let it be 0 or 1 - if (max_size <= 1) - max_size = 2; - - const long size = std::min(max_size,this->m.nr()); - - diag_reference_count = 0; - - references.set_max_size(this->m.nr()); - references.set_size(size); - for (unsigned long i = 0; i < references.size(); ++i) - references[i] = 0; - - cache.set_max_size(this->m.nr()); - cache.set_size(size); - - rlookup.assign(size,-1); - next = 0; - - is_initialized = true; - } - } - - void make_sure_next_is_unreferenced ( - ) const - { - if (references[next] != 0) - { - // find an unreferenced element of the cache - unsigned long i; - for (i = 1; i < references.size(); ++i) - { - const unsigned long idx = (next+i)%references.size(); - if (references[idx] == 0) - { - next = idx; - break; - } - } - - // if all elements of the cache are referenced then make the cache bigger - // and use the new element. - if (references[next] != 0) - { - cache.resize(cache.size()+1); - - next = references.size(); - references.resize(references.size()+1); - references[next] = 0; - - rlookup.push_back(-1); - } - } - } - - inline void add_col_to_cache( - long c - ) const - { - init(); - make_sure_next_is_unreferenced(); - - // if the lookup table is pointing to cache[next] then clear lookup[next] - if (rlookup[next] != -1) - lookup[rlookup[next]] = -1; - - // make the lookup table so that it says c is now cached at the spot indicated by next - lookup[c] = next; - rlookup[next] = c; - - // compute this column in the matrix and store it in the cache - cache[next] = matrix_cast<cache_element_type>(colm(this->m,c)); - - next = (next + 1)%cache.size(); - } - - /*! - INITIAL VALUE - - for all valid x: - - lookup(x) == -1 - - - diag_cache == the diagonal of the original matrix - - is_initialized == false - - max_size_megabytes == the max_size_megabytes from symmetric_matrix_cache() - - CONVENTION - - diag_cache == the diagonal of the original matrix - - lookup.size() == diag_cache.size() - - - if (is_initialized) then - - if (lookup[c] != -1) then - - cache[lookup[c]] == the cached column c of the matrix - - rlookup[lookup[c]] == c - - - if (rlookup[x] != -1) then - - lookup[rlookup[x]] == x - - cache[x] == the cached column rlookup[x] of the matrix - - - next == the next element in the cache table to use to cache something - - references[i] == the number of outstanding references to cache element cache[i] - - - diag_reference_count == the number of outstanding references to diag_cache. - (this isn't really needed. It's just here so that we can reuse the matrix - expression from colm() to implement diag()) - !*/ - - - mutable array<matrix<type,0,1,typename M::mem_manager_type> > cache; - mutable array<long> references; - matrix<type,0,1,typename M::mem_manager_type> diag_cache; - mutable std::vector<long> lookup; - mutable std::vector<long> rlookup; - mutable long next; - - const long max_size_megabytes; - mutable bool is_initialized; - mutable long diag_reference_count; - - }; - - template < - typename cache_element_type, - typename EXP - > - const matrix_op<op_symm_cache<EXP,cache_element_type> > symmetric_matrix_cache ( - const matrix_exp<EXP>& m, - long max_size_megabytes - ) - { - // Don't check that m is symmetric since doing so would be extremely onerous for the - // kinds of matrices intended for use with the symmetric_matrix_cache. Check everything - // else though. - DLIB_ASSERT(m.size() > 0 && m.nr() == m.nc() && max_size_megabytes >= 0, - "\tconst matrix_exp symmetric_matrix_cache(const matrix_exp& m, max_size_megabytes)" - << "\n\t You have given invalid arguments to this function" - << "\n\t m.nr(): " << m.nr() - << "\n\t m.nc(): " << m.nc() - << "\n\t m.size(): " << m.size() - << "\n\t max_size_megabytes: " << max_size_megabytes - ); - - typedef op_symm_cache<EXP,cache_element_type> op; - return matrix_op<op>(op(m.ref(), max_size_megabytes)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M, typename cache_element_type> - struct op_colm_symm_cache - { - typedef cache_element_type type; - - op_colm_symm_cache( - const M& m_, - const type* data_, - long* ref_count_ - ) : - m(m_), - data(data_), - ref_count(ref_count_) - { - *ref_count += 1; - } - - op_colm_symm_cache ( - const op_colm_symm_cache& item - ) : - m(item.m), - data(item.data), - ref_count(item.ref_count) - { - *ref_count += 1; - } - - ~op_colm_symm_cache( - ) - { - *ref_count -= 1; - } - - const M& m; - - const type* const data; - long* const ref_count; - - const static long cost = M::cost; - const static long NR = M::NR; - const static long NC = 1; - typedef const type& const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - inline const_ret_type apply ( long r, long) const { return data[r]; } - - long nr () const { return m.nr(); } - long nc () const { return 1; } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP, - typename cache_element_type - > - inline const matrix_op<op_colm_symm_cache<EXP,cache_element_type> > colm ( - const matrix_exp<matrix_op<op_symm_cache<EXP,cache_element_type> > >& m, - long col - ) - { - DLIB_ASSERT(col >= 0 && col < m.nc(), - "\tconst matrix_exp colm(const matrix_exp& m, row)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\tcol: " << col - ); - - std::pair<const cache_element_type*,long*> p = m.ref().op.col(col); - - typedef op_colm_symm_cache<EXP,cache_element_type> op; - return matrix_op<op>(op(m.ref().op.m, - p.first, - p.second)); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename EXP, - typename cache_element_type - > - inline const matrix_op<op_colm_symm_cache<EXP,cache_element_type> > diag ( - const matrix_exp<matrix_op<op_symm_cache<EXP,cache_element_type> > >& m - ) - { - typedef op_colm_symm_cache<EXP,cache_element_type> op; - return matrix_op<op>(op(m.ref().op.m, - m.ref().op.diag(), - m.ref().op.diag_ref_count())); - } - -// ---------------------------------------------------------------------------------------- - - template <typename M, typename cache_element_type> - struct op_rowm_symm_cache - { - typedef cache_element_type type; - - op_rowm_symm_cache( - const M& m_, - const type* data_, - long* ref_count_ - ) : - m(m_), - data(data_), - ref_count(ref_count_) - { - *ref_count += 1; - } - - op_rowm_symm_cache ( - const op_rowm_symm_cache& item - ) : - m(item.m), - data(item.data), - ref_count(item.ref_count) - { - *ref_count += 1; - } - - ~op_rowm_symm_cache( - ) - { - *ref_count -= 1; - } - - const M& m; - - const type* const data; - long* const ref_count; - - const static long cost = M::cost; - const static long NR = 1; - const static long NC = M::NC; - typedef const type& const_ret_type; - typedef typename M::mem_manager_type mem_manager_type; - typedef typename M::layout_type layout_type; - inline const_ret_type apply ( long , long c) const { return data[c]; } - - long nr () const { return 1; } - long nc () const { return m.nc(); } - - template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } - }; - - template < - typename EXP, - typename cache_element_type - > - inline const matrix_op<op_rowm_symm_cache<EXP,cache_element_type> > rowm ( - const matrix_exp<matrix_op<op_symm_cache<EXP,cache_element_type> > >& m, - long row - ) - { - DLIB_ASSERT(row >= 0 && row < m.nr(), - "\tconst matrix_exp rowm(const matrix_exp& m, row)" - << "\n\tYou have specified invalid sub matrix dimensions" - << "\n\tm.nr(): " << m.nr() - << "\n\tm.nc(): " << m.nc() - << "\n\trow: " << row - ); - - std::pair<const cache_element_type*,long*> p = m.ref().op.col(row); - - typedef op_rowm_symm_cache<EXP,cache_element_type> op; - return matrix_op<op>(op(m.ref().op.m, - p.first, - p.second)); - } - -// ---------------------------------------------------------------------------------------- - - template <typename EXP, typename cache_element_type> - struct colm_exp<matrix_op<op_symm_cache<EXP, cache_element_type> > > - { - typedef matrix_op<op_colm_symm_cache<EXP, cache_element_type> > type; - }; - - template <typename EXP, typename cache_element_type> - struct rowm_exp<matrix_op<op_symm_cache<EXP, cache_element_type> > > - { - typedef matrix_op<op_rowm_symm_cache<EXP, cache_element_type> > type; - }; - - template <typename EXP, typename cache_element_type> - struct diag_exp<matrix_op<op_symm_cache<EXP, cache_element_type> > > - { - typedef matrix_op<op_colm_symm_cache<EXP, cache_element_type> > type; - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_SYMMETRIC_MATRIX_CAcHE_Hh_ - diff --git a/ml/dlib/dlib/matrix/symmetric_matrix_cache_abstract.h b/ml/dlib/dlib/matrix/symmetric_matrix_cache_abstract.h deleted file mode 100644 index 6a41ad282..000000000 --- a/ml/dlib/dlib/matrix/symmetric_matrix_cache_abstract.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2010 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#define DLIB_SYMMETRIC_MATRIX_CAcHE_ABSTRACT_Hh_ -#ifndef DLIB_SYMMETRIC_MATRIX_CAcHE_ABSTRACT_Hh_ - -#include "matrix_abstract.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - template < - typename cache_element_type - > - const matrix_exp symmetric_matrix_cache ( - const matrix_exp& m, - long max_size_megabytes - ); - /*! - requires - - m.size() > 0 - - m.nr() == m.nc() - - max_size_megabytes >= 0 - ensures - - This function assumes that m is symmetric. If m is not symmetric then it won't - crash but you will get incorrect results. - - This method creates a matrix expression which internally caches the elements - of m so that they can be accessed quickly. It is useful if m is some kind of - complex matrix expression which is both very large and expensive to evaluate. - An example would be a kernel_matrix() expression with an expensive kernel and - a large number of samples. Such an expression would result in a huge matrix, - potentially too big to store in memory. The symmetric_matrix_cache() then makes - it easy to store just the parts of a matrix expression which are accessed most - often in memory. The specific details are defined below. - - returns a matrix M such that - - M == m - (i.e. M represents the same matrix as m) - - M will cache elements of m and hold them internally so they can be quickly - accessed. In particular, M will attempt to allocate no more than - max_size_megabytes megabytes of memory for the purposes of caching - elements of m. When an element of the matrix is accessed it is either - retrieved from the cache, or if this is not possible, then an entire - column of m is loaded into a part of the cache which hasn't been used - recently and the needed element returned. - - diag(m) is always loaded into the cache and is stored separately from - the cached columns. That means accesses to the diagonal elements of m - are always fast. - - M will store the cached elements of m as cache_element_type objects. - Typically, cache_element_type will be float or double. - - To avoid repeated cache lookups, the following operations are optimized for - use with the symmetric_matrix_cache(): - - diag(M), rowm(M,row_idx), colm(M,col_idx) - These methods will perform only one cache lookup operation for an - entire row/column/diagonal worth of data. - !*/ - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_SYMMETRIC_MATRIX_CAcHE_ABSTRACT_Hh_ - |