Scythe-1.0.3
|
00001 /* 00002 * Scythe Statistical Library Copyright (C) 2000-2002 Andrew D. Martin 00003 * and Kevin M. Quinn; 2002-present Andrew D. Martin, Kevin M. Quinn, 00004 * and Daniel Pemstein. All Rights Reserved. 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify under the terms of the GNU General Public License as 00008 * published by Free Software Foundation; either version 2 of the 00009 * License, or (at your option) any later version. See the text files 00010 * COPYING and LICENSE, distributed with this source code, for further 00011 * information. 00012 * -------------------------------------------------------------------- 00013 * scythestat/smath.h 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 /* Almost every function in this file follows one of the two patterns 00056 * described by these macros. The first macro handles single-argument 00057 * functions. The second handles two-matrix-argument functions (or 00058 * scalar-matrix, matrix-scalar. The second macro also permits 00059 * cross-type operations (these are limited only by the capabilities 00060 * of the underlying functions). 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 /* calc the inverse cosine of each element of a Matrix */ 00154 00176 SCYTHE_MATH_OP(acos, ::acos) 00177 00178 /* calc the inverse hyperbolic cosine of each element of a Matrix */ 00201 SCYTHE_MATH_OP(acosh, ::acosh) 00202 00203 /* calc the inverse sine of each element of a Matrix */ 00204 00227 SCYTHE_MATH_OP(asin, ::asin) 00228 00229 /* calc the inverse hyperbolic sine of each element of a Matrix */ 00230 00253 SCYTHE_MATH_OP(asinh, ::asinh) 00254 00255 /* calc the inverse tangent of each element of a Matrix */ 00256 00279 SCYTHE_MATH_OP(atan, ::atan) 00280 00281 /* calc the inverse hyperbolic tangent of each element of a Matrix */ 00304 SCYTHE_MATH_OP(atanh, ::atanh) 00305 00306 /* calc the angle whose tangent is y/x */ 00307 00332 SCYTHE_MATH_OP_2ARG(atan2, std::ptr_fun(::atan2)) 00333 00334 /* calc the cube root of each element of a Matrix */ 00346 SCYTHE_MATH_OP(cbrt, ::cbrt) 00347 00348 /* calc the ceil of each element of a Matrix */ 00360 SCYTHE_MATH_OP(ceil, ::ceil) 00361 00362 /* create a matrix containing the absval of the first input and the 00363 * sign of the second 00364 */ 00376 SCYTHE_MATH_OP_2ARG(copysign, std::ptr_fun(::copysign)) 00377 00378 /* calc the cosine of each element of a Matrix */ 00379 00401 SCYTHE_MATH_OP(cos, ::cos) 00402 00403 /* calc the hyperbolic cosine of each element of a Matrix */ 00425 SCYTHE_MATH_OP(cosh, ::cosh) 00426 00427 /* calc the error function of each element of a Matrix */ 00438 SCYTHE_MATH_OP(erf, ::erf) 00439 00440 /* calc the complementary error function of each element of a Matrix */ 00452 SCYTHE_MATH_OP(erfc, ::erfc) 00453 00454 /* calc the vaue e^x of each element of a Matrix */ 00466 SCYTHE_MATH_OP(exp, ::exp) 00467 00468 /* calc the exponent - 1 of each element of a Matrix */ 00480 SCYTHE_MATH_OP(expm1, ::expm1) 00481 00482 /* calc the absval of each element of a Matrix */ 00491 SCYTHE_MATH_OP(fabs, ::fabs) 00492 00493 /* calc the floor of each element of a Matrix */ 00505 SCYTHE_MATH_OP(floor, ::floor) 00506 00507 /* calc the remainder of the division of each matrix element */ 00518 SCYTHE_MATH_OP_2ARG(fmod, std::ptr_fun(::fmod)) 00519 00520 /* calc the fractional val of input and return exponents in int 00521 * matrix reference 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 /* calc the euclidean distance between the two inputs */ 00568 SCYTHE_MATH_OP_2ARG(hypot, std::ptr_fun(::hypot)) 00569 00570 /* return (int) logb */ 00571 SCYTHE_MATH_OP(ilogb, ::ilogb) 00572 00573 /* compute the bessel func of the first kind of the order 0 */ 00589 SCYTHE_MATH_OP(j0, ::j0) 00590 00591 /* compute the bessel func of the first kind of the order 1 */ 00607 SCYTHE_MATH_OP(j1, ::j1) 00608 00609 /* compute the bessel func of the first kind of the order n 00610 * TODO: This definition causes the compiler to issue some warnings. 00611 * Fix 00612 */ 00629 SCYTHE_MATH_OP_2ARG(jn, std::ptr_fun(::jn)) 00630 00631 /* calc x * 2 ^ex */ 00641 SCYTHE_MATH_OP_2ARG(ldexp, std::ptr_fun(::ldexp)) 00642 00643 /* compute the natural log of the absval of gamma function */ 00644 00656 SCYTHE_MATH_OP(lgamma, ::lgamma) 00657 00658 /* calc the natural log of each element of a Matrix */ 00671 SCYTHE_MATH_OP(log, ::log) 00672 00673 /* calc the base-10 log of each element of a Matrix */ 00686 SCYTHE_MATH_OP(log10, ::log10) 00687 00688 /* calc the natural log of 1 + each element of a Matrix */ 00701 SCYTHE_MATH_OP(log1p, ::log1p) 00702 00703 /* calc the logb of each element of a Matrix */ 00716 SCYTHE_MATH_OP(logb, ::logb) 00717 00718 /* x = frac + i, return matrix of frac and place i in 2nd matrix 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 /* calc x^ex of each element of a Matrix */ 00752 00762 SCYTHE_MATH_OP_2ARG(pow, std::ptr_fun(::pow)) 00763 00764 /* calc rem == x - n * y */ 00765 SCYTHE_MATH_OP_2ARG(remainder, std::ptr_fun(::remainder)) 00766 00767 /* return x rounded to nearest int */ 00768 00778 SCYTHE_MATH_OP(rint, ::rint) 00779 00780 /* returns x * FLT_RADIX^ex */ 00781 SCYTHE_MATH_OP_2ARG(scalbn, std::ptr_fun(::scalbn)) 00782 00783 /* calc the sine of x */ 00784 00806 SCYTHE_MATH_OP(sin, ::sin) 00807 00808 /* calc the hyperbolic sine of x */ 00830 SCYTHE_MATH_OP(sinh, ::sinh) 00831 00832 /* calc the sqrt of x */ 00844 SCYTHE_MATH_OP(sqrt, ::sqrt) 00845 00846 /* calc the tangent of x */ 00847 00869 SCYTHE_MATH_OP(tan, ::tan) 00870 00871 /* calc the hyperbolic tangent of x */ 00893 SCYTHE_MATH_OP(tanh, ::tanh) 00894 00895 /* bessel function of the second kind of order 0*/ 00911 SCYTHE_MATH_OP(y0, ::y0) 00912 00913 /* bessel function of the second kind of order 1*/ 00929 SCYTHE_MATH_OP(y1, ::y1) 00930 00931 /* bessel function of the second kind of order n 00932 * TODO: This definition causes the compiler to issue some warnings. 00933 * Fix 00934 */ 00951 SCYTHE_MATH_OP_2ARG(yn, std::ptr_fun(::yn)) 00952 00953 } // end namespace scythe 00954 00955 #endif /* SCYTHE_MATH_H */