00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00032 #ifndef SCYTHE_MATH_H
00033 #define SCYTHE_MATH_H
00034
00035 #ifdef SCYTHE_COMPILE_DIRECT
00036 #include "matrix.h"
00037 #include "algorithm.h"
00038 #include "error.h"
00039 #else
00040 #include "scythestat/matrix.h"
00041 #include "scythestat/algorithm.h"
00042 #include "scythestat/error.h"
00043 #endif
00044
00045 #include <cmath>
00046 #include <numeric>
00047 #include <set>
00048
00049 namespace scythe {
00050
00051 namespace {
00052 typedef unsigned int uint;
00053 }
00054
00055
00056
00057
00058
00059
00060
00061
00062 #define SCYTHE_MATH_OP(NAME, OP) \
00063 template <matrix_order RO, matrix_style RS, typename T, \
00064 matrix_order PO, matrix_style PS> \
00065 Matrix<T,RO,RS> \
00066 NAME (const Matrix<T,PO,PS>& A) \
00067 { \
00068 Matrix<T,RO,RS> res(A.rows(), A.cols(), false); \
00069 std::transform(A.begin_f(), A.end_f(), res.begin_f(), OP); \
00070 return res; \
00071 } \
00072 \
00073 template <typename T, matrix_order O, matrix_style S> \
00074 Matrix<T,O,Concrete> \
00075 NAME (const Matrix<T,O,S>& A) \
00076 { \
00077 return NAME<O,Concrete>(A); \
00078 }
00079
00080 #define SCYTHE_MATH_OP_2ARG(NAME, OP) \
00081 template <matrix_order RO, matrix_style RS, typename T, \
00082 matrix_order PO1, matrix_style PS1, \
00083 matrix_order PO2, matrix_style PS2, typename S> \
00084 Matrix<T,RO,RS> \
00085 NAME (const Matrix<T,PO1,PS1>& A, const Matrix<S,PO2,PS2>& B) \
00086 { \
00087 SCYTHE_CHECK_10 (A.size() != 1 && B.size() != 1 && \
00088 A.size() != B.size(), scythe_conformation_error, \
00089 "Matrices with dimensions (" << A.rows() \
00090 << ", " << A.cols() \
00091 << ") and (" << B.rows() << ", " << B.cols() \
00092 << ") are not conformable"); \
00093 \
00094 Matrix<T,RO,RS> res; \
00095 \
00096 if (A.size() == 1) { \
00097 res.resize2Match(B); \
00098 std::transform(B.template begin_f<RO>(), B.template end_f<RO>(),\
00099 res.begin_f(), std::bind1st(OP, A(0))); \
00100 } else if (B.size() == 1) { \
00101 res.resize2Match(A); \
00102 std::transform(A.template begin_f<RO>(), A.template end_f<RO>(),\
00103 res.begin_f(), std::bind2nd(OP, B(0))); \
00104 } else { \
00105 res.resize2Match(A); \
00106 std::transform(A.template begin_f<RO>(), A.template end_f<RO>(),\
00107 B.template begin_f<RO>(), res.begin_f(), OP); \
00108 } \
00109 \
00110 return res; \
00111 } \
00112 \
00113 template <typename T, matrix_order PO1, matrix_style PS1, \
00114 matrix_order PO2, matrix_style PS2, \
00115 typename S> \
00116 Matrix<T,PO1,Concrete> \
00117 NAME (const Matrix<T,PO1,PS1>& A, const Matrix<S,PO2,PS2>& B) \
00118 { \
00119 return NAME<PO1,Concrete>(A, B); \
00120 } \
00121 \
00122 template<matrix_order RO, matrix_style RS, typename T, \
00123 matrix_order PO, matrix_style PS, typename S> \
00124 Matrix<T,RO,RS> \
00125 NAME (const Matrix<T,PO,PS>& A, S b) \
00126 { \
00127 return NAME<RO,RS>(A, Matrix<S,RO,Concrete>(b)); \
00128 } \
00129 \
00130 template <typename T, typename S, matrix_order PO, matrix_style PS> \
00131 Matrix<T,PO,Concrete> \
00132 NAME (const Matrix<T,PO,PS>& A, S b) \
00133 { \
00134 return NAME<PO,Concrete>(A, Matrix<S,PO,Concrete>(b)); \
00135 } \
00136 \
00137 template<matrix_order RO, matrix_style RS, typename T, \
00138 matrix_order PO, matrix_style PS, typename S> \
00139 Matrix<T,RO,RS> \
00140 NAME (T a, const Matrix<S,PO,PS>& B) \
00141 { \
00142 return NAME<RO,RS>(Matrix<S, RO,Concrete>(a), B); \
00143 } \
00144 \
00145 template <typename T, typename S, matrix_order PO, matrix_style PS> \
00146 Matrix<T,PO,Concrete> \
00147 NAME (T a, const Matrix<S,PO,PS>& B) \
00148 { \
00149 return NAME<PO,Concrete>(Matrix<S,PO,Concrete>(a), B); \
00150 }
00151
00152
00153
00154
00176 SCYTHE_MATH_OP(acos, ::acos)
00177
00178
00201 SCYTHE_MATH_OP(acosh, ::acosh)
00202
00203
00204
00227 SCYTHE_MATH_OP(asin, ::asin)
00228
00229
00230
00253 SCYTHE_MATH_OP(asinh, ::asinh)
00254
00255
00256
00279 SCYTHE_MATH_OP(atan, ::atan)
00280
00281
00304 SCYTHE_MATH_OP(atanh, ::atanh)
00305
00306
00307
00332 SCYTHE_MATH_OP_2ARG(atan2, std::ptr_fun(::atan2))
00333
00334
00346 SCYTHE_MATH_OP(cbrt, ::cbrt)
00347
00348
00360 SCYTHE_MATH_OP(ceil, ::ceil)
00361
00362
00363
00364
00376 SCYTHE_MATH_OP_2ARG(copysign, std::ptr_fun(::copysign))
00377
00378
00379
00401 SCYTHE_MATH_OP(cos, ::cos)
00402
00403
00425 SCYTHE_MATH_OP(cosh, ::cosh)
00426
00427
00438 SCYTHE_MATH_OP(erf, ::erf)
00439
00440
00452 SCYTHE_MATH_OP(erfc, ::erfc)
00453
00454
00466 SCYTHE_MATH_OP(exp, ::exp)
00467
00468
00480 SCYTHE_MATH_OP(expm1, ::expm1)
00481
00482
00491 SCYTHE_MATH_OP(fabs, ::fabs)
00492
00493
00505 SCYTHE_MATH_OP(floor, ::floor)
00506
00507
00518 SCYTHE_MATH_OP_2ARG(fmod, std::ptr_fun(::fmod))
00519
00520
00521
00522
00523
00526 template <matrix_order RO, matrix_style RS, typename T,
00527 matrix_order PO1, matrix_style PS1,
00528 matrix_order PO2, matrix_style PS2>
00529 Matrix<T,RO,RS>
00530 frexp (const Matrix<T,PO1,PS1>& A, Matrix<int,PO2,PS2>& ex)
00531 {
00532 SCYTHE_CHECK_10(A.size() != ex.size(), scythe_conformation_error,
00533 "The input matrix sizes do not match");
00534 Matrix<T,PO1,Concrete> res(A.rows(), A.cols());
00535
00536 typename Matrix<T,PO1,PS1>::const_forward_iterator it;
00537 typename Matrix<T,PO1,Concrete>::forward_iterator rit
00538 = res.begin_f();
00539 typename Matrix<int,PO2,PS2>::const_forward_iterator it2
00540 = ex.begin_f();
00541 for (it = A.begin_f(); it != A.end_f(); ++it) {
00542 *rit = ::frexp(*it, &(*it2));
00543 ++it2; ++rit;
00544 }
00545
00546 return res;
00547 }
00548
00549 template <typename T, matrix_order PO1, matrix_style PS1,
00550 matrix_order PO2, matrix_style PS2>
00551 Matrix<T,PO1,Concrete>
00552 frexp (Matrix<T,PO1,PS1>& A, Matrix<int,PO2,PS2>& ex)
00553 {
00554 return frexp<PO1,Concrete>(A,ex);
00555 }
00556
00557
00568 SCYTHE_MATH_OP_2ARG(hypot, std::ptr_fun(::hypot))
00569
00570
00571 SCYTHE_MATH_OP(ilogb, ::ilogb)
00572
00573
00589 SCYTHE_MATH_OP(j0, ::j0)
00590
00591
00607 SCYTHE_MATH_OP(j1, ::j1)
00608
00609
00610
00611
00612
00629 SCYTHE_MATH_OP_2ARG(jn, std::ptr_fun(::jn))
00630
00631
00641 SCYTHE_MATH_OP_2ARG(ldexp, std::ptr_fun(::ldexp))
00642
00643
00644
00656 SCYTHE_MATH_OP(lgamma, ::lgamma)
00657
00658
00671 SCYTHE_MATH_OP(log, ::log)
00672
00673
00686 SCYTHE_MATH_OP(log10, ::log10)
00687
00688
00701 SCYTHE_MATH_OP(log1p, ::log1p)
00702
00703
00716 SCYTHE_MATH_OP(logb, ::logb)
00717
00718
00719
00720 template <matrix_order RO, matrix_style RS, typename T,
00721 matrix_order PO1, matrix_style PS1,
00722 matrix_order PO2, matrix_style PS2>
00723 Matrix<T,RO,RS>
00724 modf (const Matrix<T,PO1,PS1>& A, Matrix<double,PO2,PS2>& ipart)
00725 {
00726 SCYTHE_CHECK_10(A.size() != ipart.size(), scythe_conformation_error,
00727 "The input matrix sizes do not match");
00728 Matrix<T,PO1,Concrete> res(A.rows(), A.cols());
00729
00730 typename Matrix<T,PO1,PS1>::const_forward_iterator it;
00731 typename Matrix<T,PO1,Concrete>::forward_iterator rit
00732 = res.begin_f();
00733 typename Matrix<double,PO2,PS2>::const_forward_iterator it2
00734 = ipart.begin_f();
00735 for (it = A.begin_f(); it != A.end_f(); ++it) {
00736 *rit = ::modf(*it, &(*it2));
00737 ++it2; ++rit;
00738 }
00739
00740 return res;
00741 }
00742
00743 template <typename T, matrix_order PO1, matrix_style PS1,
00744 matrix_order PO2, matrix_style PS2>
00745 Matrix<T,PO1,Concrete>
00746 modf (Matrix<T,PO1,PS1>& A, Matrix<double,PO2,PS2>& ipart)
00747 {
00748 return modf<PO1,Concrete>(A,ipart);
00749 }
00750
00751
00752
00762 SCYTHE_MATH_OP_2ARG(pow, std::ptr_fun(::pow))
00763
00764
00765 SCYTHE_MATH_OP_2ARG(remainder, std::ptr_fun(::remainder))
00766
00767
00768
00769
00778 SCYTHE_MATH_OP(rint, ::rint)
00779
00780
00781 SCYTHE_MATH_OP_2ARG(scalbn, std::ptr_fun(::scalbn))
00782
00783
00784
00806 SCYTHE_MATH_OP(sin, ::sin)
00807
00808
00830 SCYTHE_MATH_OP(sinh, ::sinh)
00831
00832
00844 SCYTHE_MATH_OP(sqrt, ::sqrt)
00845
00846
00847
00869 SCYTHE_MATH_OP(tan, ::tan)
00870
00871
00893 SCYTHE_MATH_OP(tanh, ::tanh)
00894
00895
00911 SCYTHE_MATH_OP(y0, ::y0)
00912
00913
00929 SCYTHE_MATH_OP(y1, ::y1)
00930
00931
00932
00933
00934
00951 SCYTHE_MATH_OP_2ARG(yn, std::ptr_fun(::yn))
00952
00953 }
00954
00955 #endif