You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

497 lines
19 KiB

  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
  5. //
  6. // 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/.
  9. #include "main.h"
  10. template<typename ArrayType> void array(const ArrayType& m)
  11. {
  12. typedef typename ArrayType::Index Index;
  13. typedef typename ArrayType::Scalar Scalar;
  14. typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
  15. typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;
  16. Index rows = m.rows();
  17. Index cols = m.cols();
  18. ArrayType m1 = ArrayType::Random(rows, cols),
  19. m2 = ArrayType::Random(rows, cols),
  20. m3(rows, cols);
  21. ArrayType m4 = m1; // copy constructor
  22. VERIFY_IS_APPROX(m1, m4);
  23. ColVectorType cv1 = ColVectorType::Random(rows);
  24. RowVectorType rv1 = RowVectorType::Random(cols);
  25. Scalar s1 = internal::random<Scalar>(),
  26. s2 = internal::random<Scalar>();
  27. // scalar addition
  28. VERIFY_IS_APPROX(m1 + s1, s1 + m1);
  29. VERIFY_IS_APPROX(m1 + s1, ArrayType::Constant(rows,cols,s1) + m1);
  30. VERIFY_IS_APPROX(s1 - m1, (-m1)+s1 );
  31. VERIFY_IS_APPROX(m1 - s1, m1 - ArrayType::Constant(rows,cols,s1));
  32. VERIFY_IS_APPROX(s1 - m1, ArrayType::Constant(rows,cols,s1) - m1);
  33. VERIFY_IS_APPROX((m1*Scalar(2)) - s2, (m1+m1) - ArrayType::Constant(rows,cols,s2) );
  34. m3 = m1;
  35. m3 += s2;
  36. VERIFY_IS_APPROX(m3, m1 + s2);
  37. m3 = m1;
  38. m3 -= s1;
  39. VERIFY_IS_APPROX(m3, m1 - s1);
  40. // scalar operators via Maps
  41. m3 = m1;
  42. ArrayType::Map(m1.data(), m1.rows(), m1.cols()) -= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  43. VERIFY_IS_APPROX(m1, m3 - m2);
  44. m3 = m1;
  45. ArrayType::Map(m1.data(), m1.rows(), m1.cols()) += ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  46. VERIFY_IS_APPROX(m1, m3 + m2);
  47. m3 = m1;
  48. ArrayType::Map(m1.data(), m1.rows(), m1.cols()) *= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  49. VERIFY_IS_APPROX(m1, m3 * m2);
  50. m3 = m1;
  51. m2 = ArrayType::Random(rows,cols);
  52. m2 = (m2==0).select(1,m2);
  53. ArrayType::Map(m1.data(), m1.rows(), m1.cols()) /= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  54. VERIFY_IS_APPROX(m1, m3 / m2);
  55. // reductions
  56. VERIFY_IS_APPROX(m1.abs().colwise().sum().sum(), m1.abs().sum());
  57. VERIFY_IS_APPROX(m1.abs().rowwise().sum().sum(), m1.abs().sum());
  58. using std::abs;
  59. VERIFY_IS_MUCH_SMALLER_THAN(abs(m1.colwise().sum().sum() - m1.sum()), m1.abs().sum());
  60. VERIFY_IS_MUCH_SMALLER_THAN(abs(m1.rowwise().sum().sum() - m1.sum()), m1.abs().sum());
  61. if (!internal::isMuchSmallerThan(abs(m1.sum() - (m1+m2).sum()), m1.abs().sum(), test_precision<Scalar>()))
  62. VERIFY_IS_NOT_APPROX(((m1+m2).rowwise().sum()).sum(), m1.sum());
  63. VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));
  64. // vector-wise ops
  65. m3 = m1;
  66. VERIFY_IS_APPROX(m3.colwise() += cv1, m1.colwise() + cv1);
  67. m3 = m1;
  68. VERIFY_IS_APPROX(m3.colwise() -= cv1, m1.colwise() - cv1);
  69. m3 = m1;
  70. VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1);
  71. m3 = m1;
  72. VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1);
  73. // Conversion from scalar
  74. VERIFY_IS_APPROX((m3 = s1), ArrayType::Constant(rows,cols,s1));
  75. VERIFY_IS_APPROX((m3 = 1), ArrayType::Constant(rows,cols,1));
  76. VERIFY_IS_APPROX((m3.topLeftCorner(rows,cols) = 1), ArrayType::Constant(rows,cols,1));
  77. typedef Array<Scalar,
  78. ArrayType::RowsAtCompileTime==Dynamic?2:ArrayType::RowsAtCompileTime,
  79. ArrayType::ColsAtCompileTime==Dynamic?2:ArrayType::ColsAtCompileTime,
  80. ArrayType::Options> FixedArrayType;
  81. FixedArrayType f1(s1);
  82. VERIFY_IS_APPROX(f1, FixedArrayType::Constant(s1));
  83. FixedArrayType f2(numext::real(s1));
  84. VERIFY_IS_APPROX(f2, FixedArrayType::Constant(numext::real(s1)));
  85. FixedArrayType f3((int)100*numext::real(s1));
  86. VERIFY_IS_APPROX(f3, FixedArrayType::Constant((int)100*numext::real(s1)));
  87. f1.setRandom();
  88. FixedArrayType f4(f1.data());
  89. VERIFY_IS_APPROX(f4, f1);
  90. // Check possible conflicts with 1D ctor
  91. typedef Array<Scalar, Dynamic, 1> OneDArrayType;
  92. OneDArrayType o1(rows);
  93. VERIFY(o1.size()==rows);
  94. OneDArrayType o4((int)rows);
  95. VERIFY(o4.size()==rows);
  96. }
  97. template<typename ArrayType> void comparisons(const ArrayType& m)
  98. {
  99. using std::abs;
  100. typedef typename ArrayType::Index Index;
  101. typedef typename ArrayType::Scalar Scalar;
  102. typedef typename NumTraits<Scalar>::Real RealScalar;
  103. Index rows = m.rows();
  104. Index cols = m.cols();
  105. Index r = internal::random<Index>(0, rows-1),
  106. c = internal::random<Index>(0, cols-1);
  107. ArrayType m1 = ArrayType::Random(rows, cols),
  108. m2 = ArrayType::Random(rows, cols),
  109. m3(rows, cols),
  110. m4 = m1;
  111. m4 = (m4.abs()==Scalar(0)).select(1,m4);
  112. VERIFY(((m1 + Scalar(1)) > m1).all());
  113. VERIFY(((m1 - Scalar(1)) < m1).all());
  114. if (rows*cols>1)
  115. {
  116. m3 = m1;
  117. m3(r,c) += 1;
  118. VERIFY(! (m1 < m3).all() );
  119. VERIFY(! (m1 > m3).all() );
  120. }
  121. VERIFY(!(m1 > m2 && m1 < m2).any());
  122. VERIFY((m1 <= m2 || m1 >= m2).all());
  123. // comparisons array to scalar
  124. VERIFY( (m1 != (m1(r,c)+1) ).any() );
  125. VERIFY( (m1 > (m1(r,c)-1) ).any() );
  126. VERIFY( (m1 < (m1(r,c)+1) ).any() );
  127. VERIFY( (m1 == m1(r,c) ).any() );
  128. // comparisons scalar to array
  129. VERIFY( ( (m1(r,c)+1) != m1).any() );
  130. VERIFY( ( (m1(r,c)-1) < m1).any() );
  131. VERIFY( ( (m1(r,c)+1) > m1).any() );
  132. VERIFY( ( m1(r,c) == m1).any() );
  133. // test Select
  134. VERIFY_IS_APPROX( (m1<m2).select(m1,m2), m1.cwiseMin(m2) );
  135. VERIFY_IS_APPROX( (m1>m2).select(m1,m2), m1.cwiseMax(m2) );
  136. Scalar mid = (m1.cwiseAbs().minCoeff() + m1.cwiseAbs().maxCoeff())/Scalar(2);
  137. for (int j=0; j<cols; ++j)
  138. for (int i=0; i<rows; ++i)
  139. m3(i,j) = abs(m1(i,j))<mid ? 0 : m1(i,j);
  140. VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
  141. .select(ArrayType::Zero(rows,cols),m1), m3);
  142. // shorter versions:
  143. VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
  144. .select(0,m1), m3);
  145. VERIFY_IS_APPROX( (m1.abs()>=ArrayType::Constant(rows,cols,mid))
  146. .select(m1,0), m3);
  147. // even shorter version:
  148. VERIFY_IS_APPROX( (m1.abs()<mid).select(0,m1), m3);
  149. // count
  150. VERIFY(((m1.abs()+1)>RealScalar(0.1)).count() == rows*cols);
  151. // and/or
  152. VERIFY( (m1<RealScalar(0) && m1>RealScalar(0)).count() == 0);
  153. VERIFY( (m1<RealScalar(0) || m1>=RealScalar(0)).count() == rows*cols);
  154. RealScalar a = m1.abs().mean();
  155. VERIFY( (m1<-a || m1>a).count() == (m1.abs()>a).count());
  156. typedef Array<typename ArrayType::Index, Dynamic, 1> ArrayOfIndices;
  157. // TODO allows colwise/rowwise for array
  158. VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).colwise().count(), ArrayOfIndices::Constant(cols,rows).transpose());
  159. VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).rowwise().count(), ArrayOfIndices::Constant(rows, cols));
  160. }
  161. template<typename ArrayType> void array_real(const ArrayType& m)
  162. {
  163. using std::abs;
  164. using std::sqrt;
  165. typedef typename ArrayType::Index Index;
  166. typedef typename ArrayType::Scalar Scalar;
  167. typedef typename NumTraits<Scalar>::Real RealScalar;
  168. Index rows = m.rows();
  169. Index cols = m.cols();
  170. ArrayType m1 = ArrayType::Random(rows, cols),
  171. m2 = ArrayType::Random(rows, cols),
  172. m3(rows, cols),
  173. m4 = m1;
  174. m4 = (m4.abs()==Scalar(0)).select(1,m4);
  175. Scalar s1 = internal::random<Scalar>();
  176. // these tests are mostly to check possible compilation issues with free-functions.
  177. VERIFY_IS_APPROX(m1.sin(), sin(m1));
  178. VERIFY_IS_APPROX(m1.cos(), cos(m1));
  179. VERIFY_IS_APPROX(m1.tan(), tan(m1));
  180. VERIFY_IS_APPROX(m1.asin(), asin(m1));
  181. VERIFY_IS_APPROX(m1.acos(), acos(m1));
  182. VERIFY_IS_APPROX(m1.atan(), atan(m1));
  183. VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
  184. VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
  185. VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
  186. #ifdef STORMEIGEN_HAS_C99_MATH
  187. VERIFY_IS_APPROX(m1.lgamma(), lgamma(m1));
  188. VERIFY_IS_APPROX(m1.erf(), erf(m1));
  189. VERIFY_IS_APPROX(m1.erfc(), erfc(m1));
  190. #endif // STORMEIGEN_HAS_C99_MATH
  191. VERIFY_IS_APPROX(m1.arg(), arg(m1));
  192. VERIFY_IS_APPROX(m1.round(), round(m1));
  193. VERIFY_IS_APPROX(m1.floor(), floor(m1));
  194. VERIFY_IS_APPROX(m1.ceil(), ceil(m1));
  195. VERIFY((m1.isNaN() == (StormEigen::isnan)(m1)).all());
  196. VERIFY((m1.isInf() == (StormEigen::isinf)(m1)).all());
  197. VERIFY((m1.isFinite() == (StormEigen::isfinite)(m1)).all());
  198. VERIFY_IS_APPROX(m1.inverse(), inverse(m1));
  199. VERIFY_IS_APPROX(m1.abs(), abs(m1));
  200. VERIFY_IS_APPROX(m1.abs2(), abs2(m1));
  201. VERIFY_IS_APPROX(m1.square(), square(m1));
  202. VERIFY_IS_APPROX(m1.cube(), cube(m1));
  203. VERIFY_IS_APPROX(cos(m1+RealScalar(3)*m2), cos((m1+RealScalar(3)*m2).eval()));
  204. VERIFY_IS_APPROX(m1.sign(), sign(m1));
  205. // avoid NaNs with abs() so verification doesn't fail
  206. m3 = m1.abs();
  207. VERIFY_IS_APPROX(m3.sqrt(), sqrt(abs(m1)));
  208. VERIFY_IS_APPROX(m3.rsqrt(), Scalar(1)/sqrt(abs(m1)));
  209. VERIFY_IS_APPROX(m3.log(), log(m3));
  210. VERIFY_IS_APPROX(m3.log10(), log10(m3));
  211. VERIFY((!(m1>m2) == (m1<=m2)).all());
  212. VERIFY_IS_APPROX(sin(m1.asin()), m1);
  213. VERIFY_IS_APPROX(cos(m1.acos()), m1);
  214. VERIFY_IS_APPROX(tan(m1.atan()), m1);
  215. VERIFY_IS_APPROX(sinh(m1), 0.5*(exp(m1)-exp(-m1)));
  216. VERIFY_IS_APPROX(cosh(m1), 0.5*(exp(m1)+exp(-m1)));
  217. VERIFY_IS_APPROX(tanh(m1), (0.5*(exp(m1)-exp(-m1)))/(0.5*(exp(m1)+exp(-m1))));
  218. VERIFY_IS_APPROX(arg(m1), ((m1<0).template cast<Scalar>())*std::acos(-1.0));
  219. VERIFY((round(m1) <= ceil(m1) && round(m1) >= floor(m1)).all());
  220. VERIFY((StormEigen::isnan)((m1*0.0)/0.0).all());
  221. VERIFY((StormEigen::isinf)(m4/0.0).all());
  222. VERIFY(((StormEigen::isfinite)(m1) && (!(StormEigen::isfinite)(m1*0.0/0.0)) && (!(Eigen::isfinite)(m4/0.0))).all());
  223. VERIFY_IS_APPROX(inverse(inverse(m1)),m1);
  224. VERIFY((abs(m1) == m1 || abs(m1) == -m1).all());
  225. VERIFY_IS_APPROX(m3, sqrt(abs2(m1)));
  226. VERIFY_IS_APPROX( m1.sign(), -(-m1).sign() );
  227. VERIFY_IS_APPROX( m1*m1.sign(),m1.abs());
  228. VERIFY_IS_APPROX(m1.sign() * m1.abs(), m1);
  229. VERIFY_IS_APPROX(numext::abs2(numext::real(m1)) + numext::abs2(numext::imag(m1)), numext::abs2(m1));
  230. VERIFY_IS_APPROX(numext::abs2(real(m1)) + numext::abs2(imag(m1)), numext::abs2(m1));
  231. if(!NumTraits<Scalar>::IsComplex)
  232. VERIFY_IS_APPROX(numext::real(m1), m1);
  233. // shift argument of logarithm so that it is not zero
  234. Scalar smallNumber = NumTraits<Scalar>::dummy_precision();
  235. VERIFY_IS_APPROX((m3 + smallNumber).log() , log(abs(m1) + smallNumber));
  236. VERIFY_IS_APPROX(m1.exp() * m2.exp(), exp(m1+m2));
  237. VERIFY_IS_APPROX(m1.exp(), exp(m1));
  238. VERIFY_IS_APPROX(m1.exp() / m2.exp(),(m1-m2).exp());
  239. VERIFY_IS_APPROX(m1.pow(2), m1.square());
  240. VERIFY_IS_APPROX(pow(m1,2), m1.square());
  241. VERIFY_IS_APPROX(m1.pow(3), m1.cube());
  242. VERIFY_IS_APPROX(pow(m1,3), m1.cube());
  243. VERIFY_IS_APPROX((-m1).pow(3), -m1.cube());
  244. VERIFY_IS_APPROX(pow(2*m1,3), 8*m1.cube());
  245. ArrayType exponents = ArrayType::Constant(rows, cols, RealScalar(2));
  246. VERIFY_IS_APPROX(StormEigen::pow(m1,exponents), m1.square());
  247. VERIFY_IS_APPROX(m1.pow(exponents), m1.square());
  248. VERIFY_IS_APPROX(StormEigen::pow(2*m1,exponents), 4*m1.square());
  249. VERIFY_IS_APPROX((2*m1).pow(exponents), 4*m1.square());
  250. VERIFY_IS_APPROX(StormEigen::pow(m1,2*exponents), m1.square().square());
  251. VERIFY_IS_APPROX(m1.pow(2*exponents), m1.square().square());
  252. VERIFY_IS_APPROX(pow(m1(0,0), exponents), ArrayType::Constant(rows,cols,m1(0,0)*m1(0,0)));
  253. VERIFY_IS_APPROX(m3.pow(RealScalar(0.5)), m3.sqrt());
  254. VERIFY_IS_APPROX(pow(m3,RealScalar(0.5)), m3.sqrt());
  255. VERIFY_IS_APPROX(m3.pow(RealScalar(-0.5)), m3.rsqrt());
  256. VERIFY_IS_APPROX(pow(m3,RealScalar(-0.5)), m3.rsqrt());
  257. VERIFY_IS_APPROX(log10(m3), log(m3)/log(10));
  258. // scalar by array division
  259. const RealScalar tiny = sqrt(std::numeric_limits<RealScalar>::epsilon());
  260. s1 += Scalar(tiny);
  261. m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
  262. VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
  263. // check inplace transpose
  264. m3 = m1;
  265. m3.transposeInPlace();
  266. VERIFY_IS_APPROX(m3, m1.transpose());
  267. m3.transposeInPlace();
  268. VERIFY_IS_APPROX(m3, m1);
  269. }
  270. template<typename ArrayType> void array_complex(const ArrayType& m)
  271. {
  272. typedef typename ArrayType::Index Index;
  273. typedef typename ArrayType::Scalar Scalar;
  274. typedef typename NumTraits<Scalar>::Real RealScalar;
  275. Index rows = m.rows();
  276. Index cols = m.cols();
  277. ArrayType m1 = ArrayType::Random(rows, cols),
  278. m2(rows, cols),
  279. m4 = m1;
  280. m4.real() = (m4.real().abs()==RealScalar(0)).select(RealScalar(1),m4.real());
  281. m4.imag() = (m4.imag().abs()==RealScalar(0)).select(RealScalar(1),m4.imag());
  282. Array<RealScalar, -1, -1> m3(rows, cols);
  283. Scalar s1 = internal::random<Scalar>();
  284. for (Index i = 0; i < m.rows(); ++i)
  285. for (Index j = 0; j < m.cols(); ++j)
  286. m2(i,j) = sqrt(m1(i,j));
  287. // these tests are mostly to check possible compilation issues with free-functions.
  288. VERIFY_IS_APPROX(m1.sin(), sin(m1));
  289. VERIFY_IS_APPROX(m1.cos(), cos(m1));
  290. VERIFY_IS_APPROX(m1.tan(), tan(m1));
  291. VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
  292. VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
  293. VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
  294. VERIFY_IS_APPROX(m1.arg(), arg(m1));
  295. VERIFY((m1.isNaN() == (StormEigen::isnan)(m1)).all());
  296. VERIFY((m1.isInf() == (StormEigen::isinf)(m1)).all());
  297. VERIFY((m1.isFinite() == (StormEigen::isfinite)(m1)).all());
  298. VERIFY_IS_APPROX(m1.inverse(), inverse(m1));
  299. VERIFY_IS_APPROX(m1.log(), log(m1));
  300. VERIFY_IS_APPROX(m1.log10(), log10(m1));
  301. VERIFY_IS_APPROX(m1.abs(), abs(m1));
  302. VERIFY_IS_APPROX(m1.abs2(), abs2(m1));
  303. VERIFY_IS_APPROX(m1.sqrt(), sqrt(m1));
  304. VERIFY_IS_APPROX(m1.square(), square(m1));
  305. VERIFY_IS_APPROX(m1.cube(), cube(m1));
  306. VERIFY_IS_APPROX(cos(m1+RealScalar(3)*m2), cos((m1+RealScalar(3)*m2).eval()));
  307. VERIFY_IS_APPROX(m1.sign(), sign(m1));
  308. VERIFY_IS_APPROX(m1.exp() * m2.exp(), exp(m1+m2));
  309. VERIFY_IS_APPROX(m1.exp(), exp(m1));
  310. VERIFY_IS_APPROX(m1.exp() / m2.exp(),(m1-m2).exp());
  311. VERIFY_IS_APPROX(sinh(m1), 0.5*(exp(m1)-exp(-m1)));
  312. VERIFY_IS_APPROX(cosh(m1), 0.5*(exp(m1)+exp(-m1)));
  313. VERIFY_IS_APPROX(tanh(m1), (0.5*(exp(m1)-exp(-m1)))/(0.5*(exp(m1)+exp(-m1))));
  314. for (Index i = 0; i < m.rows(); ++i)
  315. for (Index j = 0; j < m.cols(); ++j)
  316. m3(i,j) = std::atan2(imag(m1(i,j)), real(m1(i,j)));
  317. VERIFY_IS_APPROX(arg(m1), m3);
  318. std::complex<RealScalar> zero(0.0,0.0);
  319. VERIFY((StormEigen::isnan)(m1*zero/zero).all());
  320. #if STORMEIGEN_COMP_MSVC
  321. // msvc complex division is not robust
  322. VERIFY((StormEigen::isinf)(m4/RealScalar(0)).all());
  323. #else
  324. #if STORMEIGEN_COMP_CLANG
  325. // clang's complex division is notoriously broken too
  326. if((numext::isinf)(m4(0,0)/RealScalar(0))) {
  327. #endif
  328. VERIFY((StormEigen::isinf)(m4/zero).all());
  329. #if STORMEIGEN_COMP_CLANG
  330. }
  331. else
  332. {
  333. VERIFY((StormEigen::isinf)(m4.real()/zero.real()).all());
  334. }
  335. #endif
  336. #endif // MSVC
  337. VERIFY(((StormEigen::isfinite)(m1) && (!(StormEigen::isfinite)(m1*zero/zero)) && (!(Eigen::isfinite)(m1/zero))).all());
  338. VERIFY_IS_APPROX(inverse(inverse(m1)),m1);
  339. VERIFY_IS_APPROX(conj(m1.conjugate()), m1);
  340. VERIFY_IS_APPROX(abs(m1), sqrt(square(real(m1))+square(imag(m1))));
  341. VERIFY_IS_APPROX(abs(m1), sqrt(abs2(m1)));
  342. VERIFY_IS_APPROX(log10(m1), log(m1)/log(10));
  343. VERIFY_IS_APPROX( m1.sign(), -(-m1).sign() );
  344. VERIFY_IS_APPROX( m1.sign() * m1.abs(), m1);
  345. // scalar by array division
  346. const RealScalar tiny = sqrt(std::numeric_limits<RealScalar>::epsilon());
  347. s1 += Scalar(tiny);
  348. m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
  349. VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
  350. // check inplace transpose
  351. m2 = m1;
  352. m2.transposeInPlace();
  353. VERIFY_IS_APPROX(m2, m1.transpose());
  354. m2.transposeInPlace();
  355. VERIFY_IS_APPROX(m2, m1);
  356. }
  357. template<typename ArrayType> void min_max(const ArrayType& m)
  358. {
  359. typedef typename ArrayType::Index Index;
  360. typedef typename ArrayType::Scalar Scalar;
  361. Index rows = m.rows();
  362. Index cols = m.cols();
  363. ArrayType m1 = ArrayType::Random(rows, cols);
  364. // min/max with array
  365. Scalar maxM1 = m1.maxCoeff();
  366. Scalar minM1 = m1.minCoeff();
  367. VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, minM1), (m1.min)(ArrayType::Constant(rows,cols, minM1)));
  368. VERIFY_IS_APPROX(m1, (m1.min)(ArrayType::Constant(rows,cols, maxM1)));
  369. VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, maxM1), (m1.max)(ArrayType::Constant(rows,cols, maxM1)));
  370. VERIFY_IS_APPROX(m1, (m1.max)(ArrayType::Constant(rows,cols, minM1)));
  371. // min/max with scalar input
  372. VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, minM1), (m1.min)( minM1));
  373. VERIFY_IS_APPROX(m1, (m1.min)( maxM1));
  374. VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, maxM1), (m1.max)( maxM1));
  375. VERIFY_IS_APPROX(m1, (m1.max)( minM1));
  376. }
  377. void test_array()
  378. {
  379. for(int i = 0; i < g_repeat; i++) {
  380. CALL_SUBTEST_1( array(Array<float, 1, 1>()) );
  381. CALL_SUBTEST_2( array(Array22f()) );
  382. CALL_SUBTEST_3( array(Array44d()) );
  383. CALL_SUBTEST_4( array(ArrayXXcf(internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE), internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE))) );
  384. CALL_SUBTEST_5( array(ArrayXXf(internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE), internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE))) );
  385. CALL_SUBTEST_6( array(ArrayXXi(internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE), internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE))) );
  386. }
  387. for(int i = 0; i < g_repeat; i++) {
  388. CALL_SUBTEST_1( comparisons(Array<float, 1, 1>()) );
  389. CALL_SUBTEST_2( comparisons(Array22f()) );
  390. CALL_SUBTEST_3( comparisons(Array44d()) );
  391. CALL_SUBTEST_5( comparisons(ArrayXXf(internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE), internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE))) );
  392. CALL_SUBTEST_6( comparisons(ArrayXXi(internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE), internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE))) );
  393. }
  394. for(int i = 0; i < g_repeat; i++) {
  395. CALL_SUBTEST_1( min_max(Array<float, 1, 1>()) );
  396. CALL_SUBTEST_2( min_max(Array22f()) );
  397. CALL_SUBTEST_3( min_max(Array44d()) );
  398. CALL_SUBTEST_5( min_max(ArrayXXf(internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE), internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE))) );
  399. CALL_SUBTEST_6( min_max(ArrayXXi(internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE), internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE))) );
  400. }
  401. for(int i = 0; i < g_repeat; i++) {
  402. CALL_SUBTEST_1( array_real(Array<float, 1, 1>()) );
  403. CALL_SUBTEST_2( array_real(Array22f()) );
  404. CALL_SUBTEST_3( array_real(Array44d()) );
  405. CALL_SUBTEST_5( array_real(ArrayXXf(internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE), internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE))) );
  406. }
  407. for(int i = 0; i < g_repeat; i++) {
  408. CALL_SUBTEST_4( array_complex(ArrayXXcf(internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE), internal::random<int>(1,STORMEIGEN_TEST_MAX_SIZE))) );
  409. }
  410. VERIFY((internal::is_same< internal::global_math_functions_filtering_base<int>::type, int >::value));
  411. VERIFY((internal::is_same< internal::global_math_functions_filtering_base<float>::type, float >::value));
  412. VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Array2i>::type, ArrayBase<Array2i> >::value));
  413. typedef CwiseUnaryOp<internal::scalar_multiple_op<double>, ArrayXd > Xpr;
  414. VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Xpr>::type,
  415. ArrayBase<Xpr>
  416. >::value));
  417. }