summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/matrix/matrix_utilities_abstract.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:19:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:20:02 +0000
commit58daab21cd043e1dc37024a7f99b396788372918 (patch)
tree96771e43bb69f7c1c2b0b4f7374cb74d7866d0cb /ml/dlib/dlib/matrix/matrix_utilities_abstract.h
parentReleasing debian version 1.43.2-1. (diff)
downloadnetdata-58daab21cd043e1dc37024a7f99b396788372918.tar.xz
netdata-58daab21cd043e1dc37024a7f99b396788372918.zip
Merging upstream version 1.44.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ml/dlib/dlib/matrix/matrix_utilities_abstract.h')
-rw-r--r--ml/dlib/dlib/matrix/matrix_utilities_abstract.h1874
1 files changed, 1874 insertions, 0 deletions
diff --git a/ml/dlib/dlib/matrix/matrix_utilities_abstract.h b/ml/dlib/dlib/matrix/matrix_utilities_abstract.h
new file mode 100644
index 000000000..ad4c91167
--- /dev/null
+++ b/ml/dlib/dlib/matrix/matrix_utilities_abstract.h
@@ -0,0 +1,1874 @@
+// 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_
+