blob: 0416ec5d2d83885ec44ffc489de95bcd5adde1c2 [file] [log] [blame]
Gael Guennebaud8cef5412008-06-21 17:28:07 +00001// This file is part of Eigen, a lightweight C++ template library
Benoit Jacob6347b1d2009-05-22 20:25:33 +02002// for linear algebra.
Gael Guennebaud8cef5412008-06-21 17:28:07 +00003//
Gael Guennebaud28e64b02010-06-24 23:21:58 +02004// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
Gael Guennebaud8cef5412008-06-21 17:28:07 +00005//
Benoit Jacob69124cf2012-07-13 14:42:47 -04006// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
Gael Guennebaud19bc4182013-02-25 01:17:44 +01009
Gael Guennebaud8cef5412008-06-21 17:28:07 +000010#include "main.h"
Gael Guennebaud8cef5412008-06-21 17:28:07 +000011
Benoit Jacobe2775862010-04-28 18:51:38 -040012template<typename ArrayType> void array(const ArrayType& m)
Gael Guennebaud8cef5412008-06-21 17:28:07 +000013{
Hauke Heibelf1679c72010-06-20 17:37:56 +020014 typedef typename ArrayType::Index Index;
Benoit Jacobe2775862010-04-28 18:51:38 -040015 typedef typename ArrayType::Scalar Scalar;
Benoit Jacobe2775862010-04-28 18:51:38 -040016 typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
17 typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;
Gael Guennebaud8cef5412008-06-21 17:28:07 +000018
Hauke Heibelf1679c72010-06-20 17:37:56 +020019 Index rows = m.rows();
Hauke Heibelf578dc72010-12-16 17:34:13 +010020 Index cols = m.cols();
Gael Guennebaud8cef5412008-06-21 17:28:07 +000021
Benoit Jacobe2775862010-04-28 18:51:38 -040022 ArrayType m1 = ArrayType::Random(rows, cols),
23 m2 = ArrayType::Random(rows, cols),
Gael Guennebaud8cef5412008-06-21 17:28:07 +000024 m3(rows, cols);
Christoph Hertzberg3be9f5c2015-04-16 13:25:20 +020025 ArrayType m4 = m1; // copy constructor
26 VERIFY_IS_APPROX(m1, m4);
Gael Guennebaud8cef5412008-06-21 17:28:07 +000027
Gael Guennebaud627595a2009-06-10 11:20:30 +020028 ColVectorType cv1 = ColVectorType::Random(rows);
29 RowVectorType rv1 = RowVectorType::Random(cols);
30
Benoit Jacob47160402010-10-25 10:15:22 -040031 Scalar s1 = internal::random<Scalar>(),
Hauke Heibel8cb3e362012-03-02 16:27:27 +010032 s2 = internal::random<Scalar>();
33
Gael Guennebaud59dc1da2008-09-03 17:16:28 +000034 // scalar addition
Gael Guennebaudc70d5422010-01-18 22:54:20 +010035 VERIFY_IS_APPROX(m1 + s1, s1 + m1);
Benoit Jacobe2775862010-04-28 18:51:38 -040036 VERIFY_IS_APPROX(m1 + s1, ArrayType::Constant(rows,cols,s1) + m1);
Gael Guennebaudc70d5422010-01-18 22:54:20 +010037 VERIFY_IS_APPROX(s1 - m1, (-m1)+s1 );
Benoit Jacobe2775862010-04-28 18:51:38 -040038 VERIFY_IS_APPROX(m1 - s1, m1 - ArrayType::Constant(rows,cols,s1));
39 VERIFY_IS_APPROX(s1 - m1, ArrayType::Constant(rows,cols,s1) - m1);
40 VERIFY_IS_APPROX((m1*Scalar(2)) - s2, (m1+m1) - ArrayType::Constant(rows,cols,s2) );
Gael Guennebaud8cef5412008-06-21 17:28:07 +000041 m3 = m1;
Gael Guennebaudc70d5422010-01-18 22:54:20 +010042 m3 += s2;
43 VERIFY_IS_APPROX(m3, m1 + s2);
Gael Guennebaud8cef5412008-06-21 17:28:07 +000044 m3 = m1;
Gael Guennebaudc70d5422010-01-18 22:54:20 +010045 m3 -= s1;
Hauke Heibelf578dc72010-12-16 17:34:13 +010046 VERIFY_IS_APPROX(m3, m1 - s1);
47
48 // scalar operators via Maps
49 m3 = m1;
50 ArrayType::Map(m1.data(), m1.rows(), m1.cols()) -= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
51 VERIFY_IS_APPROX(m1, m3 - m2);
52
53 m3 = m1;
54 ArrayType::Map(m1.data(), m1.rows(), m1.cols()) += ArrayType::Map(m2.data(), m2.rows(), m2.cols());
55 VERIFY_IS_APPROX(m1, m3 + m2);
56
57 m3 = m1;
58 ArrayType::Map(m1.data(), m1.rows(), m1.cols()) *= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
59 VERIFY_IS_APPROX(m1, m3 * m2);
60
61 m3 = m1;
62 m2 = ArrayType::Random(rows,cols);
63 m2 = (m2==0).select(1,m2);
64 ArrayType::Map(m1.data(), m1.rows(), m1.cols()) /= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
65 VERIFY_IS_APPROX(m1, m3 / m2);
Gael Guennebaud05ad0832008-07-19 13:03:23 +000066
Gael Guennebaud59dc1da2008-09-03 17:16:28 +000067 // reductions
Gael Guennebaud42af5872013-02-23 22:58:14 +010068 VERIFY_IS_APPROX(m1.abs().colwise().sum().sum(), m1.abs().sum());
69 VERIFY_IS_APPROX(m1.abs().rowwise().sum().sum(), m1.abs().sum());
70 using std::abs;
71 VERIFY_IS_MUCH_SMALLER_THAN(abs(m1.colwise().sum().sum() - m1.sum()), m1.abs().sum());
72 VERIFY_IS_MUCH_SMALLER_THAN(abs(m1.rowwise().sum().sum() - m1.sum()), m1.abs().sum());
Gael Guennebaud28e139a2013-02-23 23:06:45 +010073 if (!internal::isMuchSmallerThan(abs(m1.sum() - (m1+m2).sum()), m1.abs().sum(), test_precision<Scalar>()))
Hauke Heibel83e3c452010-12-16 18:53:02 +010074 VERIFY_IS_NOT_APPROX(((m1+m2).rowwise().sum()).sum(), m1.sum());
Gael Guennebaud66e99ab2016-06-06 15:11:41 +020075 VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar,Scalar>()));
Gael Guennebaud627595a2009-06-10 11:20:30 +020076
77 // vector-wise ops
78 m3 = m1;
79 VERIFY_IS_APPROX(m3.colwise() += cv1, m1.colwise() + cv1);
80 m3 = m1;
81 VERIFY_IS_APPROX(m3.colwise() -= cv1, m1.colwise() - cv1);
82 m3 = m1;
83 VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1);
84 m3 = m1;
85 VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1);
Gael Guennebaud0a18eec2014-09-19 13:25:28 +020086
87 // Conversion from scalar
88 VERIFY_IS_APPROX((m3 = s1), ArrayType::Constant(rows,cols,s1));
89 VERIFY_IS_APPROX((m3 = 1), ArrayType::Constant(rows,cols,1));
90 VERIFY_IS_APPROX((m3.topLeftCorner(rows,cols) = 1), ArrayType::Constant(rows,cols,1));
91 typedef Array<Scalar,
92 ArrayType::RowsAtCompileTime==Dynamic?2:ArrayType::RowsAtCompileTime,
93 ArrayType::ColsAtCompileTime==Dynamic?2:ArrayType::ColsAtCompileTime,
94 ArrayType::Options> FixedArrayType;
95 FixedArrayType f1(s1);
96 VERIFY_IS_APPROX(f1, FixedArrayType::Constant(s1));
97 FixedArrayType f2(numext::real(s1));
98 VERIFY_IS_APPROX(f2, FixedArrayType::Constant(numext::real(s1)));
99 FixedArrayType f3((int)100*numext::real(s1));
100 VERIFY_IS_APPROX(f3, FixedArrayType::Constant((int)100*numext::real(s1)));
101 f1.setRandom();
102 FixedArrayType f4(f1.data());
103 VERIFY_IS_APPROX(f4, f1);
104
105 // Check possible conflicts with 1D ctor
106 typedef Array<Scalar, Dynamic, 1> OneDArrayType;
107 OneDArrayType o1(rows);
108 VERIFY(o1.size()==rows);
109 OneDArrayType o4((int)rows);
110 VERIFY(o4.size()==rows);
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000111}
112
Benoit Jacobe2775862010-04-28 18:51:38 -0400113template<typename ArrayType> void comparisons(const ArrayType& m)
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000114{
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100115 using std::abs;
Hauke Heibelf1679c72010-06-20 17:37:56 +0200116 typedef typename ArrayType::Index Index;
Benoit Jacobe2775862010-04-28 18:51:38 -0400117 typedef typename ArrayType::Scalar Scalar;
Benoit Jacob874ff5a2009-01-26 17:56:04 +0000118 typedef typename NumTraits<Scalar>::Real RealScalar;
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000119
Hauke Heibelf1679c72010-06-20 17:37:56 +0200120 Index rows = m.rows();
121 Index cols = m.cols();
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000122
Benoit Jacob47160402010-10-25 10:15:22 -0400123 Index r = internal::random<Index>(0, rows-1),
124 c = internal::random<Index>(0, cols-1);
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000125
Benoit Jacobe2775862010-04-28 18:51:38 -0400126 ArrayType m1 = ArrayType::Random(rows, cols),
Gael Guennebaud9fc1c922015-06-22 16:48:27 +0200127 m2 = ArrayType::Random(rows, cols),
128 m3(rows, cols),
129 m4 = m1;
130
131 m4 = (m4.abs()==Scalar(0)).select(1,m4);
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000132
Gael Guennebaudc70d5422010-01-18 22:54:20 +0100133 VERIFY(((m1 + Scalar(1)) > m1).all());
134 VERIFY(((m1 - Scalar(1)) < m1).all());
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000135 if (rows*cols>1)
136 {
137 m3 = m1;
138 m3(r,c) += 1;
Gael Guennebaudc70d5422010-01-18 22:54:20 +0100139 VERIFY(! (m1 < m3).all() );
140 VERIFY(! (m1 > m3).all() );
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000141 }
Christoph Hertzberg494fa992015-05-07 17:28:40 +0200142 VERIFY(!(m1 > m2 && m1 < m2).any());
143 VERIFY((m1 <= m2 || m1 >= m2).all());
Gael Guennebaud627595a2009-06-10 11:20:30 +0200144
Christoph Hertzberg36052c42013-10-17 15:37:29 +0200145 // comparisons array to scalar
Gael Guennebaudc70d5422010-01-18 22:54:20 +0100146 VERIFY( (m1 != (m1(r,c)+1) ).any() );
Christoph Hertzberg36052c42013-10-17 15:37:29 +0200147 VERIFY( (m1 > (m1(r,c)-1) ).any() );
148 VERIFY( (m1 < (m1(r,c)+1) ).any() );
149 VERIFY( (m1 == m1(r,c) ).any() );
150
151 // comparisons scalar to array
152 VERIFY( ( (m1(r,c)+1) != m1).any() );
153 VERIFY( ( (m1(r,c)-1) < m1).any() );
154 VERIFY( ( (m1(r,c)+1) > m1).any() );
155 VERIFY( ( m1(r,c) == m1).any() );
Gael Guennebaud627595a2009-06-10 11:20:30 +0200156
Gael Guennebaud59dc1da2008-09-03 17:16:28 +0000157 // test Select
Gael Guennebaudc70d5422010-01-18 22:54:20 +0100158 VERIFY_IS_APPROX( (m1<m2).select(m1,m2), m1.cwiseMin(m2) );
159 VERIFY_IS_APPROX( (m1>m2).select(m1,m2), m1.cwiseMax(m2) );
Gael Guennebaud9f795582009-12-16 19:18:40 +0100160 Scalar mid = (m1.cwiseAbs().minCoeff() + m1.cwiseAbs().maxCoeff())/Scalar(2);
Gael Guennebaud59dc1da2008-09-03 17:16:28 +0000161 for (int j=0; j<cols; ++j)
162 for (int i=0; i<rows; ++i)
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100163 m3(i,j) = abs(m1(i,j))<mid ? 0 : m1(i,j);
Benoit Jacobe2775862010-04-28 18:51:38 -0400164 VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
165 .select(ArrayType::Zero(rows,cols),m1), m3);
Gael Guennebaude14aa8c2008-09-03 17:56:06 +0000166 // shorter versions:
Benoit Jacobe2775862010-04-28 18:51:38 -0400167 VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
Gael Guennebaud59dc1da2008-09-03 17:16:28 +0000168 .select(0,m1), m3);
Benoit Jacobe2775862010-04-28 18:51:38 -0400169 VERIFY_IS_APPROX( (m1.abs()>=ArrayType::Constant(rows,cols,mid))
Gael Guennebaud59dc1da2008-09-03 17:16:28 +0000170 .select(m1,0), m3);
Gael Guennebaude14aa8c2008-09-03 17:56:06 +0000171 // even shorter version:
Gael Guennebaudc70d5422010-01-18 22:54:20 +0100172 VERIFY_IS_APPROX( (m1.abs()<mid).select(0,m1), m3);
Gael Guennebaud627595a2009-06-10 11:20:30 +0200173
Gael Guennebaud56c7e162009-01-24 15:22:44 +0000174 // count
Gael Guennebaudc70d5422010-01-18 22:54:20 +0100175 VERIFY(((m1.abs()+1)>RealScalar(0.1)).count() == rows*cols);
Benoit Jacobaaaade42010-05-30 16:00:58 -0400176
Gael Guennebaud35c11582011-05-31 22:17:34 +0200177 // and/or
178 VERIFY( (m1<RealScalar(0) && m1>RealScalar(0)).count() == 0);
179 VERIFY( (m1<RealScalar(0) || m1>=RealScalar(0)).count() == rows*cols);
180 RealScalar a = m1.abs().mean();
181 VERIFY( (m1<-a || m1>a).count() == (m1.abs()>a).count());
182
Benoit Jacobaaaade42010-05-30 16:00:58 -0400183 typedef Array<typename ArrayType::Index, Dynamic, 1> ArrayOfIndices;
Gael Guennebaud4ebb8042010-06-02 09:45:57 +0200184
Gael Guennebaud9f795582009-12-16 19:18:40 +0100185 // TODO allows colwise/rowwise for array
Benoit Jacobaaaade42010-05-30 16:00:58 -0400186 VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).colwise().count(), ArrayOfIndices::Constant(cols,rows).transpose());
187 VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).rowwise().count(), ArrayOfIndices::Constant(rows, cols));
Benoit Jacobe8009992008-11-03 22:47:00 +0000188}
189
Benoit Jacobe2775862010-04-28 18:51:38 -0400190template<typename ArrayType> void array_real(const ArrayType& m)
Gael Guennebaud0ce5bc02010-01-27 23:23:59 +0100191{
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100192 using std::abs;
Gael Guennebaud9b9177f2013-07-05 13:35:34 +0200193 using std::sqrt;
Hauke Heibelf1679c72010-06-20 17:37:56 +0200194 typedef typename ArrayType::Index Index;
Benoit Jacobe2775862010-04-28 18:51:38 -0400195 typedef typename ArrayType::Scalar Scalar;
Gael Guennebaud0ce5bc02010-01-27 23:23:59 +0100196 typedef typename NumTraits<Scalar>::Real RealScalar;
197
Hauke Heibelf1679c72010-06-20 17:37:56 +0200198 Index rows = m.rows();
199 Index cols = m.cols();
Gael Guennebaud0ce5bc02010-01-27 23:23:59 +0100200
Benoit Jacobe2775862010-04-28 18:51:38 -0400201 ArrayType m1 = ArrayType::Random(rows, cols),
Gael Guennebaudc695cbf2013-06-24 13:33:44 +0200202 m2 = ArrayType::Random(rows, cols),
Gael Guennebaud9fc1c922015-06-22 16:48:27 +0200203 m3(rows, cols),
204 m4 = m1;
Benoit Steiner83149622015-12-10 13:13:45 -0800205
Gael Guennebaud9fc1c922015-06-22 16:48:27 +0200206 m4 = (m4.abs()==Scalar(0)).select(1,m4);
Gael Guennebaud0ce5bc02010-01-27 23:23:59 +0100207
Gael Guennebaud9b1ad5e2012-03-09 12:08:06 +0100208 Scalar s1 = internal::random<Scalar>();
209
Deanna Hood41b717d2015-03-18 03:11:03 +1000210 // these tests are mostly to check possible compilation issues with free-functions.
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100211 VERIFY_IS_APPROX(m1.sin(), sin(m1));
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100212 VERIFY_IS_APPROX(m1.cos(), cos(m1));
Deanna Hoodf89fcef2015-03-11 13:13:30 +1000213 VERIFY_IS_APPROX(m1.tan(), tan(m1));
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100214 VERIFY_IS_APPROX(m1.asin(), asin(m1));
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100215 VERIFY_IS_APPROX(m1.acos(), acos(m1));
Jitse Niesende150b12014-06-19 15:12:33 +0100216 VERIFY_IS_APPROX(m1.atan(), atan(m1));
Deanna Hoodf89fcef2015-03-11 13:13:30 +1000217 VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
218 VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
219 VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
Gael Guennebaud13950562016-05-20 14:58:19 +0200220#if EIGEN_HAS_C99_MATH
Eugene Brevdofa4f9332015-12-07 15:24:49 -0800221 VERIFY_IS_APPROX(m1.lgamma(), lgamma(m1));
Eugene Brevdof7362772015-12-24 21:15:38 -0800222 VERIFY_IS_APPROX(m1.digamma(), digamma(m1));
Eugene Brevdofa4f9332015-12-07 15:24:49 -0800223 VERIFY_IS_APPROX(m1.erf(), erf(m1));
224 VERIFY_IS_APPROX(m1.erfc(), erfc(m1));
Benoit Steiner83149622015-12-10 13:13:45 -0800225#endif // EIGEN_HAS_C99_MATH
Deanna Hooda5e49972015-03-11 08:56:42 +1000226 VERIFY_IS_APPROX(m1.arg(), arg(m1));
Deanna Hood31fdd672015-03-11 06:39:23 +1000227 VERIFY_IS_APPROX(m1.round(), round(m1));
228 VERIFY_IS_APPROX(m1.floor(), floor(m1));
229 VERIFY_IS_APPROX(m1.ceil(), ceil(m1));
Christoph Hertzberg61e09772015-08-14 17:32:34 +0200230 VERIFY((m1.isNaN() == (Eigen::isnan)(m1)).all());
231 VERIFY((m1.isInf() == (Eigen::isinf)(m1)).all());
232 VERIFY((m1.isFinite() == (Eigen::isfinite)(m1)).all());
Deanna Hood41b717d2015-03-18 03:11:03 +1000233 VERIFY_IS_APPROX(m1.inverse(), inverse(m1));
234 VERIFY_IS_APPROX(m1.abs(), abs(m1));
235 VERIFY_IS_APPROX(m1.abs2(), abs2(m1));
236 VERIFY_IS_APPROX(m1.square(), square(m1));
237 VERIFY_IS_APPROX(m1.cube(), cube(m1));
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100238 VERIFY_IS_APPROX(cos(m1+RealScalar(3)*m2), cos((m1+RealScalar(3)*m2).eval()));
Gael Guennebaud3f32f5e2015-11-27 16:27:53 +0100239 VERIFY_IS_APPROX(m1.sign(), sign(m1));
Gael Guennebaud4ebb8042010-06-02 09:45:57 +0200240
Deanna Hood41b717d2015-03-18 03:11:03 +1000241
242 // avoid NaNs with abs() so verification doesn't fail
243 m3 = m1.abs();
244 VERIFY_IS_APPROX(m3.sqrt(), sqrt(abs(m1)));
Benoit Steinere25e3a02015-12-03 18:16:35 -0800245 VERIFY_IS_APPROX(m3.rsqrt(), Scalar(1)/sqrt(abs(m1)));
Deanna Hood41b717d2015-03-18 03:11:03 +1000246 VERIFY_IS_APPROX(m3.log(), log(m3));
Gael Guennebaud89099b02016-06-01 17:00:08 +0200247 VERIFY_IS_APPROX(m3.log1p(), log1p(m3));
Deanna Hood41b717d2015-03-18 03:11:03 +1000248 VERIFY_IS_APPROX(m3.log10(), log10(m3));
249
250
251 VERIFY((!(m1>m2) == (m1<=m2)).all());
252
253 VERIFY_IS_APPROX(sin(m1.asin()), m1);
254 VERIFY_IS_APPROX(cos(m1.acos()), m1);
255 VERIFY_IS_APPROX(tan(m1.atan()), m1);
256 VERIFY_IS_APPROX(sinh(m1), 0.5*(exp(m1)-exp(-m1)));
257 VERIFY_IS_APPROX(cosh(m1), 0.5*(exp(m1)+exp(-m1)));
258 VERIFY_IS_APPROX(tanh(m1), (0.5*(exp(m1)-exp(-m1)))/(0.5*(exp(m1)+exp(-m1))));
Gael Guennebaud2e0ece72015-10-06 17:22:12 +0200259 VERIFY_IS_APPROX(arg(m1), ((m1<0).template cast<Scalar>())*std::acos(-1.0));
Deanna Hood41b717d2015-03-18 03:11:03 +1000260 VERIFY((round(m1) <= ceil(m1) && round(m1) >= floor(m1)).all());
Christoph Hertzberg61e09772015-08-14 17:32:34 +0200261 VERIFY((Eigen::isnan)((m1*0.0)/0.0).all());
262 VERIFY((Eigen::isinf)(m4/0.0).all());
263 VERIFY(((Eigen::isfinite)(m1) && (!(Eigen::isfinite)(m1*0.0/0.0)) && (!(Eigen::isfinite)(m4/0.0))).all());
Deanna Hood41b717d2015-03-18 03:11:03 +1000264 VERIFY_IS_APPROX(inverse(inverse(m1)),m1);
265 VERIFY((abs(m1) == m1 || abs(m1) == -m1).all());
266 VERIFY_IS_APPROX(m3, sqrt(abs2(m1)));
Gael Guennebaud3f32f5e2015-11-27 16:27:53 +0100267 VERIFY_IS_APPROX( m1.sign(), -(-m1).sign() );
268 VERIFY_IS_APPROX( m1*m1.sign(),m1.abs());
269 VERIFY_IS_APPROX(m1.sign() * m1.abs(), m1);
Benoit Jacob5d63d2c2010-04-28 22:42:34 -0400270
Gael Guennebaud62670c82013-06-10 23:40:56 +0200271 VERIFY_IS_APPROX(numext::abs2(numext::real(m1)) + numext::abs2(numext::imag(m1)), numext::abs2(m1));
272 VERIFY_IS_APPROX(numext::abs2(real(m1)) + numext::abs2(imag(m1)), numext::abs2(m1));
Benoit Jacob5d63d2c2010-04-28 22:42:34 -0400273 if(!NumTraits<Scalar>::IsComplex)
Gael Guennebaud62670c82013-06-10 23:40:56 +0200274 VERIFY_IS_APPROX(numext::real(m1), m1);
Gael Guennebaud4ebb8042010-06-02 09:45:57 +0200275
Jitse Niesen6fecb6f2014-02-24 14:10:17 +0000276 // shift argument of logarithm so that it is not zero
277 Scalar smallNumber = NumTraits<Scalar>::dummy_precision();
Deanna Hood41b717d2015-03-18 03:11:03 +1000278 VERIFY_IS_APPROX((m3 + smallNumber).log() , log(abs(m1) + smallNumber));
Gael Guennebaud89099b02016-06-01 17:00:08 +0200279 VERIFY_IS_APPROX((m3 + smallNumber + 1).log() , log1p(abs(m1) + smallNumber));
Gael Guennebaud4ebb8042010-06-02 09:45:57 +0200280
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100281 VERIFY_IS_APPROX(m1.exp() * m2.exp(), exp(m1+m2));
282 VERIFY_IS_APPROX(m1.exp(), exp(m1));
283 VERIFY_IS_APPROX(m1.exp() / m2.exp(),(m1-m2).exp());
Gael Guennebaud575ac542010-06-19 23:17:07 +0200284
285 VERIFY_IS_APPROX(m1.pow(2), m1.square());
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100286 VERIFY_IS_APPROX(pow(m1,2), m1.square());
Deanna Hood41b717d2015-03-18 03:11:03 +1000287 VERIFY_IS_APPROX(m1.pow(3), m1.cube());
288 VERIFY_IS_APPROX(pow(m1,3), m1.cube());
Gael Guennebaud6544b492015-07-20 13:57:55 +0200289 VERIFY_IS_APPROX((-m1).pow(3), -m1.cube());
290 VERIFY_IS_APPROX(pow(2*m1,3), 8*m1.cube());
Hauke Heibel81c13362012-03-07 08:58:42 +0100291
292 ArrayType exponents = ArrayType::Constant(rows, cols, RealScalar(2));
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100293 VERIFY_IS_APPROX(Eigen::pow(m1,exponents), m1.square());
Gael Guennebaud6544b492015-07-20 13:57:55 +0200294 VERIFY_IS_APPROX(m1.pow(exponents), m1.square());
295 VERIFY_IS_APPROX(Eigen::pow(2*m1,exponents), 4*m1.square());
296 VERIFY_IS_APPROX((2*m1).pow(exponents), 4*m1.square());
297 VERIFY_IS_APPROX(Eigen::pow(m1,2*exponents), m1.square().square());
298 VERIFY_IS_APPROX(m1.pow(2*exponents), m1.square().square());
299 VERIFY_IS_APPROX(pow(m1(0,0), exponents), ArrayType::Constant(rows,cols,m1(0,0)*m1(0,0)));
Hauke Heibel81c13362012-03-07 08:58:42 +0100300
Gael Guennebaud575ac542010-06-19 23:17:07 +0200301 VERIFY_IS_APPROX(m3.pow(RealScalar(0.5)), m3.sqrt());
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100302 VERIFY_IS_APPROX(pow(m3,RealScalar(0.5)), m3.sqrt());
Benoit Steinere25e3a02015-12-03 18:16:35 -0800303
304 VERIFY_IS_APPROX(m3.pow(RealScalar(-0.5)), m3.rsqrt());
305 VERIFY_IS_APPROX(pow(m3,RealScalar(-0.5)), m3.rsqrt());
306
Deanna Hood41b717d2015-03-18 03:11:03 +1000307 VERIFY_IS_APPROX(log10(m3), log(m3)/log(10));
Hauke Heibel81c13362012-03-07 08:58:42 +0100308
309 // scalar by array division
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100310 const RealScalar tiny = sqrt(std::numeric_limits<RealScalar>::epsilon());
Hauke Heibeldd9365e2012-03-09 14:04:13 +0100311 s1 += Scalar(tiny);
312 m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
Hauke Heibel81c13362012-03-07 08:58:42 +0100313 VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
Eugene Brevdof7362772015-12-24 21:15:38 -0800314
Gael Guennebaudccb408e2016-05-19 18:34:41 +0200315
316
Gael Guennebaud13950562016-05-20 14:58:19 +0200317#if EIGEN_HAS_C99_MATH
Eugene Brevdob1a9afe2016-03-13 15:45:34 -0700318 // check special functions (comparing against numpy implementation)
Gael Guennebaudccb408e2016-05-19 18:34:41 +0200319 if (!NumTraits<Scalar>::IsComplex)
320 {
Eugene Brevdo7ea35bf2016-03-03 19:39:41 -0800321
Eugene Brevdob1a9afe2016-03-13 15:45:34 -0700322 {
323 // Test various propreties of igamma & igammac. These are normalized
324 // gamma integrals where
325 // igammac(a, x) = Gamma(a, x) / Gamma(a)
326 // igamma(a, x) = gamma(a, x) / Gamma(a)
327 // where Gamma and gamma are considered the standard unnormalized
328 // upper and lower incomplete gamma functions, respectively.
329 ArrayType a = m1.abs() + 2;
330 ArrayType x = m2.abs() + 2;
331 ArrayType zero = ArrayType::Zero(rows, cols);
332 ArrayType one = ArrayType::Constant(rows, cols, Scalar(1.0));
333 ArrayType a_m1 = a - one;
334 ArrayType Gamma_a_x = Eigen::igammac(a, x) * a.lgamma().exp();
335 ArrayType Gamma_a_m1_x = Eigen::igammac(a_m1, x) * a_m1.lgamma().exp();
336 ArrayType gamma_a_x = Eigen::igamma(a, x) * a.lgamma().exp();
337 ArrayType gamma_a_m1_x = Eigen::igamma(a_m1, x) * a_m1.lgamma().exp();
338
339 // Gamma(a, 0) == Gamma(a)
340 VERIFY_IS_APPROX(Eigen::igammac(a, zero), one);
341
342 // Gamma(a, x) + gamma(a, x) == Gamma(a)
343 VERIFY_IS_APPROX(Gamma_a_x + gamma_a_x, a.lgamma().exp());
344
345 // Gamma(a, x) == (a - 1) * Gamma(a-1, x) + x^(a-1) * exp(-x)
346 VERIFY_IS_APPROX(Gamma_a_x, (a - 1) * Gamma_a_m1_x + x.pow(a-1) * (-x).exp());
347
348 // gamma(a, x) == (a - 1) * gamma(a-1, x) - x^(a-1) * exp(-x)
349 VERIFY_IS_APPROX(gamma_a_x, (a - 1) * gamma_a_m1_x - x.pow(a-1) * (-x).exp());
350 }
351
352 // Check exact values of igamma and igammac against a third party calculation.
Eugene Brevdo0b9e0ab2016-03-04 21:12:10 -0800353 Scalar a_s[] = {Scalar(0), Scalar(1), Scalar(1.5), Scalar(4), Scalar(0.0001), Scalar(1000.5)};
354 Scalar x_s[] = {Scalar(0), Scalar(1), Scalar(1.5), Scalar(4), Scalar(0.0001), Scalar(1000.5)};
Eugene Brevdo7ea35bf2016-03-03 19:39:41 -0800355
356 // location i*6+j corresponds to a_s[i], x_s[j].
357 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
Eugene Brevdo0b9e0ab2016-03-04 21:12:10 -0800358 Scalar igamma_s[][6] = {{0.0, nan, nan, nan, nan, nan},
359 {0.0, 0.6321205588285578, 0.7768698398515702,
360 0.9816843611112658, 9.999500016666262e-05, 1.0},
361 {0.0, 0.4275932955291202, 0.608374823728911,
362 0.9539882943107686, 7.522076445089201e-07, 1.0},
363 {0.0, 0.01898815687615381, 0.06564245437845008,
364 0.5665298796332909, 4.166333347221828e-18, 1.0},
365 {0.0, 0.9999780593618628, 0.9999899967080838,
366 0.9999996219837988, 0.9991370418689945, 1.0},
367 {0.0, 0.0, 0.0, 0.0, 0.0, 0.5042041932513908}};
368 Scalar igammac_s[][6] = {{nan, nan, nan, nan, nan, nan},
369 {1.0, 0.36787944117144233, 0.22313016014842982,
370 0.018315638888734182, 0.9999000049998333, 0.0},
371 {1.0, 0.5724067044708798, 0.3916251762710878,
372 0.04601170568923136, 0.9999992477923555, 0.0},
373 {1.0, 0.9810118431238462, 0.9343575456215499,
374 0.4334701203667089, 1.0, 0.0},
375 {1.0, 2.1940638138146658e-05, 1.0003291916285e-05,
376 3.7801620118431334e-07, 0.0008629581310054535,
377 0.0},
378 {1.0, 1.0, 1.0, 1.0, 1.0, 0.49579580674813944}};
Eugene Brevdo7ea35bf2016-03-03 19:39:41 -0800379 for (int i = 0; i < 6; ++i) {
380 for (int j = 0; j < 6; ++j) {
Eugene Brevdo0b9e0ab2016-03-04 21:12:10 -0800381 if ((std::isnan)(igamma_s[i][j])) {
382 VERIFY((std::isnan)(numext::igamma(a_s[i], x_s[j])));
383 } else {
384 VERIFY_IS_APPROX(numext::igamma(a_s[i], x_s[j]), igamma_s[i][j]);
385 }
386
387 if ((std::isnan)(igammac_s[i][j])) {
388 VERIFY((std::isnan)(numext::igammac(a_s[i], x_s[j])));
389 } else {
390 VERIFY_IS_APPROX(numext::igammac(a_s[i], x_s[j]), igammac_s[i][j]);
391 }
Eugene Brevdo7ea35bf2016-03-03 19:39:41 -0800392 }
393 }
Eugene Brevdof7362772015-12-24 21:15:38 -0800394 }
Eugene Brevdo14897602015-12-24 21:28:18 -0800395#endif // EIGEN_HAS_C99_MATH
Eugene Brevdof7362772015-12-24 21:15:38 -0800396
Gael Guennebaudc695cbf2013-06-24 13:33:44 +0200397 // check inplace transpose
398 m3 = m1;
399 m3.transposeInPlace();
Deanna Hood41b717d2015-03-18 03:11:03 +1000400 VERIFY_IS_APPROX(m3, m1.transpose());
Gael Guennebaudc695cbf2013-06-24 13:33:44 +0200401 m3.transposeInPlace();
Deanna Hood41b717d2015-03-18 03:11:03 +1000402 VERIFY_IS_APPROX(m3, m1);
Gael Guennebaud0ce5bc02010-01-27 23:23:59 +0100403}
404
Jitse Niesen837db082011-05-09 10:17:41 +0100405template<typename ArrayType> void array_complex(const ArrayType& m)
406{
407 typedef typename ArrayType::Index Index;
Deanna Hood41b717d2015-03-18 03:11:03 +1000408 typedef typename ArrayType::Scalar Scalar;
409 typedef typename NumTraits<Scalar>::Real RealScalar;
Jitse Niesen837db082011-05-09 10:17:41 +0100410
411 Index rows = m.rows();
412 Index cols = m.cols();
413
414 ArrayType m1 = ArrayType::Random(rows, cols),
Gael Guennebaud9fc1c922015-06-22 16:48:27 +0200415 m2(rows, cols),
416 m4 = m1;
417
418 m4.real() = (m4.real().abs()==RealScalar(0)).select(RealScalar(1),m4.real());
419 m4.imag() = (m4.imag().abs()==RealScalar(0)).select(RealScalar(1),m4.imag());
Jitse Niesen837db082011-05-09 10:17:41 +0100420
Deanna Hood41b717d2015-03-18 03:11:03 +1000421 Array<RealScalar, -1, -1> m3(rows, cols);
422
Jitse Niesen837db082011-05-09 10:17:41 +0100423 for (Index i = 0; i < m.rows(); ++i)
424 for (Index j = 0; j < m.cols(); ++j)
Gael Guennebauda76fbbf2012-11-06 15:25:50 +0100425 m2(i,j) = sqrt(m1(i,j));
Jitse Niesen837db082011-05-09 10:17:41 +0100426
Deanna Hood41b717d2015-03-18 03:11:03 +1000427 // these tests are mostly to check possible compilation issues with free-functions.
Deanna Hoodf89fcef2015-03-11 13:13:30 +1000428 VERIFY_IS_APPROX(m1.sin(), sin(m1));
429 VERIFY_IS_APPROX(m1.cos(), cos(m1));
430 VERIFY_IS_APPROX(m1.tan(), tan(m1));
431 VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
432 VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
433 VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
Deanna Hood41b717d2015-03-18 03:11:03 +1000434 VERIFY_IS_APPROX(m1.arg(), arg(m1));
Christoph Hertzberg61e09772015-08-14 17:32:34 +0200435 VERIFY((m1.isNaN() == (Eigen::isnan)(m1)).all());
436 VERIFY((m1.isInf() == (Eigen::isinf)(m1)).all());
437 VERIFY((m1.isFinite() == (Eigen::isfinite)(m1)).all());
Deanna Hood41b717d2015-03-18 03:11:03 +1000438 VERIFY_IS_APPROX(m1.inverse(), inverse(m1));
439 VERIFY_IS_APPROX(m1.log(), log(m1));
440 VERIFY_IS_APPROX(m1.log10(), log10(m1));
441 VERIFY_IS_APPROX(m1.abs(), abs(m1));
442 VERIFY_IS_APPROX(m1.abs2(), abs2(m1));
443 VERIFY_IS_APPROX(m1.sqrt(), sqrt(m1));
444 VERIFY_IS_APPROX(m1.square(), square(m1));
445 VERIFY_IS_APPROX(m1.cube(), cube(m1));
446 VERIFY_IS_APPROX(cos(m1+RealScalar(3)*m2), cos((m1+RealScalar(3)*m2).eval()));
Gael Guennebaud3f32f5e2015-11-27 16:27:53 +0100447 VERIFY_IS_APPROX(m1.sign(), sign(m1));
Deanna Hood41b717d2015-03-18 03:11:03 +1000448
449
450 VERIFY_IS_APPROX(m1.exp() * m2.exp(), exp(m1+m2));
451 VERIFY_IS_APPROX(m1.exp(), exp(m1));
452 VERIFY_IS_APPROX(m1.exp() / m2.exp(),(m1-m2).exp());
453
454 VERIFY_IS_APPROX(sinh(m1), 0.5*(exp(m1)-exp(-m1)));
455 VERIFY_IS_APPROX(cosh(m1), 0.5*(exp(m1)+exp(-m1)));
456 VERIFY_IS_APPROX(tanh(m1), (0.5*(exp(m1)-exp(-m1)))/(0.5*(exp(m1)+exp(-m1))));
457
458 for (Index i = 0; i < m.rows(); ++i)
459 for (Index j = 0; j < m.cols(); ++j)
460 m3(i,j) = std::atan2(imag(m1(i,j)), real(m1(i,j)));
461 VERIFY_IS_APPROX(arg(m1), m3);
462
463 std::complex<RealScalar> zero(0.0,0.0);
Christoph Hertzberg61e09772015-08-14 17:32:34 +0200464 VERIFY((Eigen::isnan)(m1*zero/zero).all());
Gael Guennebaud4a985e72015-11-20 14:52:08 +0100465#if EIGEN_COMP_MSVC
466 // msvc complex division is not robust
467 VERIFY((Eigen::isinf)(m4/RealScalar(0)).all());
468#else
Gael Guennebaud40f326e2015-06-17 15:33:09 +0200469#if EIGEN_COMP_CLANG
Gael Guennebaud4a985e72015-11-20 14:52:08 +0100470 // clang's complex division is notoriously broken too
Christoph Hertzberg61e09772015-08-14 17:32:34 +0200471 if((numext::isinf)(m4(0,0)/RealScalar(0))) {
Gael Guennebaud40f326e2015-06-17 15:33:09 +0200472#endif
Gael Guennebaud4a985e72015-11-20 14:52:08 +0100473 VERIFY((Eigen::isinf)(m4/zero).all());
Gael Guennebaud40f326e2015-06-17 15:33:09 +0200474#if EIGEN_COMP_CLANG
475 }
476 else
477 {
Christoph Hertzberg61e09772015-08-14 17:32:34 +0200478 VERIFY((Eigen::isinf)(m4.real()/zero.real()).all());
Gael Guennebaud40f326e2015-06-17 15:33:09 +0200479 }
480#endif
Gael Guennebaud4a985e72015-11-20 14:52:08 +0100481#endif // MSVC
482
Christoph Hertzberg61e09772015-08-14 17:32:34 +0200483 VERIFY(((Eigen::isfinite)(m1) && (!(Eigen::isfinite)(m1*zero/zero)) && (!(Eigen::isfinite)(m1/zero))).all());
Deanna Hood41b717d2015-03-18 03:11:03 +1000484
485 VERIFY_IS_APPROX(inverse(inverse(m1)),m1);
486 VERIFY_IS_APPROX(conj(m1.conjugate()), m1);
487 VERIFY_IS_APPROX(abs(m1), sqrt(square(real(m1))+square(imag(m1))));
488 VERIFY_IS_APPROX(abs(m1), sqrt(abs2(m1)));
489 VERIFY_IS_APPROX(log10(m1), log(m1)/log(10));
490
Gael Guennebaud3f32f5e2015-11-27 16:27:53 +0100491 VERIFY_IS_APPROX( m1.sign(), -(-m1).sign() );
492 VERIFY_IS_APPROX( m1.sign() * m1.abs(), m1);
493
Deanna Hood41b717d2015-03-18 03:11:03 +1000494 // scalar by array division
Eugene Brevdof7362772015-12-24 21:15:38 -0800495 Scalar s1 = internal::random<Scalar>();
Benoit Steiner2d74ef92016-05-17 07:20:11 -0700496 const RealScalar tiny = std::sqrt(std::numeric_limits<RealScalar>::epsilon());
Deanna Hood41b717d2015-03-18 03:11:03 +1000497 s1 += Scalar(tiny);
498 m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
499 VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
500
501 // check inplace transpose
502 m2 = m1;
503 m2.transposeInPlace();
504 VERIFY_IS_APPROX(m2, m1.transpose());
505 m2.transposeInPlace();
506 VERIFY_IS_APPROX(m2, m1);
Deanna Hood31fdd672015-03-11 06:39:23 +1000507
Jitse Niesen837db082011-05-09 10:17:41 +0100508}
509
Abraham Bachrach039408c2012-01-11 11:00:30 -0500510template<typename ArrayType> void min_max(const ArrayType& m)
511{
512 typedef typename ArrayType::Index Index;
513 typedef typename ArrayType::Scalar Scalar;
514
515 Index rows = m.rows();
516 Index cols = m.cols();
517
518 ArrayType m1 = ArrayType::Random(rows, cols);
519
520 // min/max with array
521 Scalar maxM1 = m1.maxCoeff();
522 Scalar minM1 = m1.minCoeff();
523
524 VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, minM1), (m1.min)(ArrayType::Constant(rows,cols, minM1)));
525 VERIFY_IS_APPROX(m1, (m1.min)(ArrayType::Constant(rows,cols, maxM1)));
526
527 VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, maxM1), (m1.max)(ArrayType::Constant(rows,cols, maxM1)));
528 VERIFY_IS_APPROX(m1, (m1.max)(ArrayType::Constant(rows,cols, minM1)));
529
530 // min/max with scalar input
531 VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, minM1), (m1.min)( minM1));
532 VERIFY_IS_APPROX(m1, (m1.min)( maxM1));
533
534 VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, maxM1), (m1.max)( maxM1));
535 VERIFY_IS_APPROX(m1, (m1.max)( minM1));
536
537}
538
Gael Guennebaudccb408e2016-05-19 18:34:41 +0200539template<typename X, typename Y>
540void verify_component_wise(const X& x, const Y& y)
541{
542 for(Index i=0; i<x.size(); ++i)
543 {
544 if((numext::isfinite)(y(i)))
545 VERIFY_IS_APPROX( x(i), y(i) );
546 else if((numext::isnan)(y(i)))
547 VERIFY((numext::isnan)(x(i)));
548 else
549 VERIFY_IS_EQUAL( x(i), y(i) );
550 }
551}
552
553// check special functions (comparing against numpy implementation)
554template<typename ArrayType> void array_special_functions()
555{
556 using std::abs;
557 using std::sqrt;
558 typedef typename ArrayType::Scalar Scalar;
559 typedef typename NumTraits<Scalar>::Real RealScalar;
560
561 Scalar plusinf = std::numeric_limits<Scalar>::infinity();
562 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
563
564 // Check the zeta function against scipy.special.zeta
565 {
566 ArrayType x(7), q(7), res(7), ref(7);
567 x << 1.5, 4, 10.5, 10000.5, 3, 1, 0.9;
568 q << 2, 1.5, 3, 1.0001, -2.5, 1.2345, 1.2345;
569 ref << 1.61237534869, 0.234848505667, 1.03086757337e-5, 0.367879440865, 0.054102025820864097, plusinf, nan;
570 CALL_SUBTEST( verify_component_wise(ref, ref); );
571 CALL_SUBTEST( res = x.zeta(q); verify_component_wise(res, ref); );
572 CALL_SUBTEST( res = zeta(x,q); verify_component_wise(res, ref); );
573 }
574
575 // digamma
576 {
577 ArrayType x(7), res(7), ref(7);
578 x << 1, 1.5, 4, -10.5, 10000.5, 0, -1;
579 ref << -0.5772156649015329, 0.03648997397857645, 1.2561176684318, 2.398239129535781, 9.210340372392849, plusinf, plusinf;
580 CALL_SUBTEST( verify_component_wise(ref, ref); );
581
582 CALL_SUBTEST( res = x.digamma(); verify_component_wise(res, ref); );
583 CALL_SUBTEST( res = digamma(x); verify_component_wise(res, ref); );
584 }
585
586
Gael Guennebaud13950562016-05-20 14:58:19 +0200587#if EIGEN_HAS_C99_MATH
Gael Guennebaudccb408e2016-05-19 18:34:41 +0200588 {
589 ArrayType n(11), x(11), res(11), ref(11);
590 n << 1, 1, 1, 1.5, 17, 31, 28, 8, 42, 147, 170;
591 x << 2, 3, 25.5, 1.5, 4.7, 11.8, 17.7, 30.2, 15.8, 54.1, 64;
592 ref << 0.644934066848, 0.394934066848, 0.0399946696496, nan, 293.334565435, 0.445487887616, -2.47810300902e-07, -8.29668781082e-09, -0.434562276666, 0.567742190178, -0.0108615497927;
593 CALL_SUBTEST( verify_component_wise(ref, ref); );
594
Eugene Brevdo39baff82016-06-02 17:04:19 -0700595 if(sizeof(RealScalar)>=8) { // double
596 // Reason for commented line: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1232
597 // CALL_SUBTEST( res = x.polygamma(n); verify_component_wise(res, ref); );
Gael Guennebaudccb408e2016-05-19 18:34:41 +0200598 CALL_SUBTEST( res = polygamma(n,x); verify_component_wise(res, ref); );
599 }
600 else {
Eugene Brevdo39baff82016-06-02 17:04:19 -0700601 // CALL_SUBTEST( res = x.polygamma(n); verify_component_wise(res.head(8), ref.head(8)); );
Gael Guennebaudccb408e2016-05-19 18:34:41 +0200602 CALL_SUBTEST( res = polygamma(n,x); verify_component_wise(res.head(8), ref.head(8)); );
603 }
Gael Guennebaudccb408e2016-05-19 18:34:41 +0200604 }
Benoit Steiner7aa5bc92016-05-23 14:39:51 -0700605#endif
Eugene Brevdo39baff82016-06-02 17:04:19 -0700606
607#if EIGEN_HAS_C99_MATH
608 {
609 // Inputs and ground truth generated with scipy via:
610 // a = np.logspace(-3, 3, 5) - 1e-3
611 // b = np.logspace(-3, 3, 5) - 1e-3
612 // x = np.linspace(-0.1, 1.1, 5)
613 // (full_a, full_b, full_x) = np.vectorize(lambda a, b, x: (a, b, x))(*np.ix_(a, b, x))
614 // full_a = full_a.flatten().tolist() # same for full_b, full_x
615 // v = scipy.special.betainc(full_a, full_b, full_x).flatten().tolist()
616 //
617 // Note in Eigen, we call betainc with arguments in the order (x, a, b).
618 ArrayType a(125);
619 ArrayType b(125);
620 ArrayType x(125);
621 ArrayType v(125);
622 ArrayType res(125);
623
624 a << 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
625 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
626 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
627 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
628 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
629 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
630 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
631 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
632 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
633 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
634 0.03062277660168379, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999,
635 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999,
636 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999,
637 31.62177660168379, 31.62177660168379, 31.62177660168379,
638 31.62177660168379, 31.62177660168379, 31.62177660168379,
639 31.62177660168379, 31.62177660168379, 31.62177660168379,
640 31.62177660168379, 31.62177660168379, 31.62177660168379,
641 31.62177660168379, 31.62177660168379, 31.62177660168379,
642 31.62177660168379, 31.62177660168379, 31.62177660168379,
643 31.62177660168379, 31.62177660168379, 31.62177660168379,
644 31.62177660168379, 31.62177660168379, 31.62177660168379,
645 31.62177660168379, 999.999, 999.999, 999.999, 999.999, 999.999, 999.999,
646 999.999, 999.999, 999.999, 999.999, 999.999, 999.999, 999.999, 999.999,
647 999.999, 999.999, 999.999, 999.999, 999.999, 999.999, 999.999, 999.999,
648 999.999, 999.999, 999.999;
649
650 b << 0.0, 0.0, 0.0, 0.0, 0.0, 0.03062277660168379, 0.03062277660168379,
651 0.03062277660168379, 0.03062277660168379, 0.03062277660168379, 0.999,
652 0.999, 0.999, 0.999, 0.999, 31.62177660168379, 31.62177660168379,
653 31.62177660168379, 31.62177660168379, 31.62177660168379, 999.999,
654 999.999, 999.999, 999.999, 999.999, 0.0, 0.0, 0.0, 0.0, 0.0,
655 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
656 0.03062277660168379, 0.03062277660168379, 0.999, 0.999, 0.999, 0.999,
657 0.999, 31.62177660168379, 31.62177660168379, 31.62177660168379,
658 31.62177660168379, 31.62177660168379, 999.999, 999.999, 999.999,
659 999.999, 999.999, 0.0, 0.0, 0.0, 0.0, 0.0, 0.03062277660168379,
660 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
661 0.03062277660168379, 0.999, 0.999, 0.999, 0.999, 0.999,
662 31.62177660168379, 31.62177660168379, 31.62177660168379,
663 31.62177660168379, 31.62177660168379, 999.999, 999.999, 999.999,
664 999.999, 999.999, 0.0, 0.0, 0.0, 0.0, 0.0, 0.03062277660168379,
665 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
666 0.03062277660168379, 0.999, 0.999, 0.999, 0.999, 0.999,
667 31.62177660168379, 31.62177660168379, 31.62177660168379,
668 31.62177660168379, 31.62177660168379, 999.999, 999.999, 999.999,
669 999.999, 999.999, 0.0, 0.0, 0.0, 0.0, 0.0, 0.03062277660168379,
670 0.03062277660168379, 0.03062277660168379, 0.03062277660168379,
671 0.03062277660168379, 0.999, 0.999, 0.999, 0.999, 0.999,
672 31.62177660168379, 31.62177660168379, 31.62177660168379,
673 31.62177660168379, 31.62177660168379, 999.999, 999.999, 999.999,
674 999.999, 999.999;
675
676 x << -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5,
677 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2,
678 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1,
679 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1,
680 -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8,
681 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5,
682 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2,
683 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1,
684 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5, 0.8, 1.1, -0.1, 0.2, 0.5,
685 0.8, 1.1;
686
687 v << nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
688 nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
689 nan, nan, nan, 0.47972119876364683, 0.5, 0.5202788012363533, nan, nan,
690 0.9518683957740043, 0.9789663010413743, 0.9931729188073435, nan, nan,
691 0.999995949033062, 0.9999999999993698, 0.9999999999999999, nan, nan,
692 0.9999999999999999, 0.9999999999999999, 0.9999999999999999, nan, nan,
693 nan, nan, nan, nan, nan, 0.006827081192655869, 0.0210336989586256,
694 0.04813160422599567, nan, nan, 0.20014344256217678, 0.5000000000000001,
695 0.7998565574378232, nan, nan, 0.9991401428435834, 0.999999999698403,
696 0.9999999999999999, nan, nan, 0.9999999999999999, 0.9999999999999999,
697 0.9999999999999999, nan, nan, nan, nan, nan, nan, nan,
698 1.0646600232370887e-25, 6.301722877826246e-13, 4.050966937974938e-06,
699 nan, nan, 7.864342668429763e-23, 3.015969667594166e-10,
700 0.0008598571564165444, nan, nan, 6.031987710123844e-08,
701 0.5000000000000007, 0.9999999396801229, nan, nan, 0.9999999999999999,
702 0.9999999999999999, 0.9999999999999999, nan, nan, nan, nan, nan, nan,
703 nan, 0.0, 7.029920380986636e-306, 2.2450728208591345e-101, nan, nan,
704 0.0, 9.275871147869727e-302, 1.2232913026152827e-97, nan, nan, 0.0,
705 3.0891393081932924e-252, 2.9303043666183996e-60, nan, nan,
706 2.248913486879199e-196, 0.5000000000004947, 0.9999999999999999, nan;
707
708 CALL_SUBTEST(res = betainc(a, b, x);
709 verify_component_wise(res, v););
710 }
Eugene Brevdoc53687d2016-06-05 11:10:30 -0700711
712 // Test various properties of betainc
713 {
714 ArrayType m1 = ArrayType::Random(32);
715 ArrayType m2 = ArrayType::Random(32);
716 ArrayType m3 = ArrayType::Random(32);
717 ArrayType one = ArrayType::Constant(32, Scalar(1.0));
718 const Scalar eps = std::numeric_limits<Scalar>::epsilon();
719 ArrayType a = (m1 * 4.0).exp();
720 ArrayType b = (m2 * 4.0).exp();
721 ArrayType x = m3.abs();
722
723 // betainc(a, 1, x) == x**a
724 CALL_SUBTEST(
725 ArrayType test = betainc(a, one, x);
726 ArrayType expected = x.pow(a);
727 verify_component_wise(test, expected););
728
729 // betainc(1, b, x) == 1 - (1 - x)**b
730 CALL_SUBTEST(
731 ArrayType test = betainc(one, b, x);
732 ArrayType expected = one - (one - x).pow(b);
733 verify_component_wise(test, expected););
734
735 // betainc(a, b, x) == 1 - betainc(b, a, 1-x)
736 CALL_SUBTEST(
737 ArrayType test = betainc(a, b, x) + betainc(b, a, one - x);
738 ArrayType expected = one;
739 verify_component_wise(test, expected););
740
741 // betainc(a+1, b, x) = betainc(a, b, x) - x**a * (1 - x)**b / (a * beta(a, b))
742 CALL_SUBTEST(
743 ArrayType num = x.pow(a) * (one - x).pow(b);
744 ArrayType denom = a * (a.lgamma() + b.lgamma() - (a + b).lgamma()).exp();
745 // Add eps to rhs and lhs so that component-wise test doesn't result in
746 // nans when both outputs are zeros.
747 ArrayType expected = betainc(a, b, x) - num / denom + eps;
748 ArrayType test = betainc(a + one, b, x) + eps;
749 if (sizeof(Scalar) >= 8) { // double
750 verify_component_wise(test, expected);
751 } else {
752 // Reason for limited test: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1232
753 verify_component_wise(test.head(8), expected.head(8));
754 });
755
756 // betainc(a, b+1, x) = betainc(a, b, x) + x**a * (1 - x)**b / (b * beta(a, b))
757 CALL_SUBTEST(
758 // Add eps to rhs and lhs so that component-wise test doesn't result in
759 // nans when both outputs are zeros.
760 ArrayType num = x.pow(a) * (one - x).pow(b);
761 ArrayType denom = b * (a.lgamma() + b.lgamma() - (a + b).lgamma()).exp();
762 ArrayType expected = betainc(a, b, x) + num / denom + eps;
763 ArrayType test = betainc(a, b + one, x) + eps;
764 verify_component_wise(test, expected););
765 }
Eugene Brevdo39baff82016-06-02 17:04:19 -0700766#endif
Gael Guennebaudccb408e2016-05-19 18:34:41 +0200767}
768
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000769void test_array()
770{
Gael Guennebaud8d6bd562016-05-20 14:45:33 +0200771#ifndef EIGEN_HAS_C99_MATH
772 std::cerr << "WARNING: testing of special math functions disabled" << std::endl;
773#endif
774
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000775 for(int i = 0; i < g_repeat; i++) {
Hauke Heibel2d0dfe52010-12-16 17:36:10 +0100776 CALL_SUBTEST_1( array(Array<float, 1, 1>()) );
Hauke Heibelb31e1242010-12-16 19:07:23 +0100777 CALL_SUBTEST_2( array(Array22f()) );
778 CALL_SUBTEST_3( array(Array44d()) );
Gael Guennebauda8f66fe2011-07-12 14:41:00 +0200779 CALL_SUBTEST_4( array(ArrayXXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
780 CALL_SUBTEST_5( array(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
781 CALL_SUBTEST_6( array(ArrayXXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000782 }
Hauke Heibel2d0dfe52010-12-16 17:36:10 +0100783 for(int i = 0; i < g_repeat; i++) {
784 CALL_SUBTEST_1( comparisons(Array<float, 1, 1>()) );
Hauke Heibelb31e1242010-12-16 19:07:23 +0100785 CALL_SUBTEST_2( comparisons(Array22f()) );
786 CALL_SUBTEST_3( comparisons(Array44d()) );
Gael Guennebauda8f66fe2011-07-12 14:41:00 +0200787 CALL_SUBTEST_5( comparisons(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
788 CALL_SUBTEST_6( comparisons(ArrayXXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
Hauke Heibel2d0dfe52010-12-16 17:36:10 +0100789 }
790 for(int i = 0; i < g_repeat; i++) {
Abraham Bachrach039408c2012-01-11 11:00:30 -0500791 CALL_SUBTEST_1( min_max(Array<float, 1, 1>()) );
792 CALL_SUBTEST_2( min_max(Array22f()) );
793 CALL_SUBTEST_3( min_max(Array44d()) );
794 CALL_SUBTEST_5( min_max(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
795 CALL_SUBTEST_6( min_max(ArrayXXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
796 }
797 for(int i = 0; i < g_repeat; i++) {
Hauke Heibel2d0dfe52010-12-16 17:36:10 +0100798 CALL_SUBTEST_1( array_real(Array<float, 1, 1>()) );
Hauke Heibelb31e1242010-12-16 19:07:23 +0100799 CALL_SUBTEST_2( array_real(Array22f()) );
800 CALL_SUBTEST_3( array_real(Array44d()) );
Gael Guennebauda8f66fe2011-07-12 14:41:00 +0200801 CALL_SUBTEST_5( array_real(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
Hauke Heibel2d0dfe52010-12-16 17:36:10 +0100802 }
Jitse Niesen837db082011-05-09 10:17:41 +0100803 for(int i = 0; i < g_repeat; i++) {
Gael Guennebauda8f66fe2011-07-12 14:41:00 +0200804 CALL_SUBTEST_4( array_complex(ArrayXXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
Jitse Niesen837db082011-05-09 10:17:41 +0100805 }
Benoit Jacob5d63d2c2010-04-28 22:42:34 -0400806
Hauke Heibel2d0dfe52010-12-16 17:36:10 +0100807 VERIFY((internal::is_same< internal::global_math_functions_filtering_base<int>::type, int >::value));
808 VERIFY((internal::is_same< internal::global_math_functions_filtering_base<float>::type, float >::value));
809 VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Array2i>::type, ArrayBase<Array2i> >::value));
Gael Guennebaud64fcfd32016-06-14 11:26:57 +0200810 typedef CwiseUnaryOp<internal::scalar_abs_op<double>, ArrayXd > Xpr;
Hauke Heibel2d0dfe52010-12-16 17:36:10 +0100811 VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Xpr>::type,
812 ArrayBase<Xpr>
813 >::value));
Gael Guennebaudccb408e2016-05-19 18:34:41 +0200814
815 CALL_SUBTEST_7(array_special_functions<ArrayXf>());
816 CALL_SUBTEST_7(array_special_functions<ArrayXd>());
Gael Guennebaud8cef5412008-06-21 17:28:07 +0000817}