// 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 #include #include 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 inline type sigmoid (const type& val) { return static_cast(1/(1 + std::exp(-val))); } template 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::value); if (val >= eps || val <= -eps) return val; else return 0; } template 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::value); const type eps = 10*std::numeric_limits::epsilon(); if (val >= eps || val <= -eps) return val; else return 0; } template inline type squared (const type& val) { return val*val; } template inline type sign (const type& val) { if (val >= 0) return +1; else return -1; } template type cubed (const type& val) { return val*val*val; } template 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::value == true || is_same_type::value == true || is_same_type::value == true )); return std::pow(val,static_cast(s)); } template 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::value == true || is_same_type::value == true || is_same_type::value == true )); return std::pow(static_cast(s),val); } template 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::value == true || is_same_type::value == true || is_same_type::value == true || is_same_type >::value == true || is_same_type >::value == true || is_same_type >::value == true )); if (val != static_cast(0)) return static_cast((type)1.0/val); else return 0; } template 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::value == true || is_same_type::value == true || is_same_type::value == true )); if (val != static_cast(0)) return static_cast((type)1.0/val); else return std::numeric_limits::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 struct op_round : basic_op_m { op_round( const M& m_) : basic_op_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(std::floor(this->m(r,c)+0.5)); } }; template struct op_round::is_integer>::type > : basic_op_m { op_round( const M& m_) : basic_op_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 > round ( const matrix_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::value); typedef op_round op; return matrix_op(op(m.ref())); } // ---------------------------------------------------------------------------------------- template struct op_normalize : basic_op_m { typedef typename M::type type; op_normalize( const M& m_, const type& s_) : basic_op_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 > normalize ( const matrix_exp& m ) { // you can only compute normalized matrices that contain floats, doubles or long doubles. COMPILE_TIME_ASSERT(( is_same_type::value == true || is_same_type::value == true || is_same_type::value == true )); typedef op_normalize op; typename EXP::type temp = std::sqrt(sum(squared(m))); if (temp != 0.0) temp = 1.0/temp; return matrix_op(op(m.ref(),temp)); } // ---------------------------------------------------------------------------------------- template struct op_abs : basic_op_m { op_abs( const M& m_) : basic_op_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(std::abs(this->m(r,c))); } }; template struct op_abs > : basic_op_m { op_abs( const M& m_) : basic_op_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(std::abs(this->m(r,c))); } }; template < typename EXP > const matrix_op > abs ( const matrix_exp& m ) { typedef op_abs op; return matrix_op(op(m.ref())); } // ---------------------------------------------------------------------------------------- template struct op_complex_matrix : basic_op_m { op_complex_matrix( const M& m_) : basic_op_m(m_){} const static long cost = M::cost+1; typedef std::complex type; typedef const std::complex const_ret_type; const_ret_type apply ( long r, long c) const { return type(this->m(r,c)); } }; template < typename EXP > const matrix_op > complex_matrix ( const matrix_exp& m ) { typedef op_complex_matrix op; return matrix_op(op(m.ref())); } // ---------------------------------------------------------------------------------------- template struct op_complex_matrix2 : basic_op_mm { op_complex_matrix2( const M1& m1_, const M2& m2_) : basic_op_mm(m1_,m2_){} const static long cost = M1::cost+M2::cost+1; typedef std::complex type; typedef const std::complex 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 > complex_matrix ( const matrix_exp& real_part, const matrix_exp& imag_part ) { COMPILE_TIME_ASSERT((is_same_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 op; return matrix_op(op(real_part.ref(),imag_part.ref())); } // ---------------------------------------------------------------------------------------- template struct op_norm : basic_op_m { op_norm( const M& m_) : basic_op_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 > norm ( const matrix_exp& m ) { typedef op_norm op; return matrix_op(op(m.ref())); } // ---------------------------------------------------------------------------------------- template struct op_real : basic_op_m { op_real( const M& m_) : basic_op_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 > real ( const matrix_exp& m ) { typedef op_real op; return matrix_op(op(m.ref())); } // ---------------------------------------------------------------------------------------- template struct op_imag : basic_op_m { op_imag( const M& m_) : basic_op_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 > imag ( const matrix_exp& m ) { typedef op_imag op; return matrix_op(op(m.ref())); } // ---------------------------------------------------------------------------------------- } #endif // DLIB_MATRIx_MATH_FUNCTIONS