Compare commits

...
138 Commits
Author SHA1 Message Date
conradsnicta ab1eaba0d3 Merge branch '14.2.x' into '14.2.x'
arma_ignore Xst backport

See merge request conradsnicta/armadillo-code!147
2025-07-16 00:53:43 +00:00
Seb James 58832a44ea arma_ignore Xst backport 2025-07-15 15:47:32 +01:00
conrad 45f0ea0f6f fix 2025-06-30 12:42:14 +10:00
conrad 0a37f157a4 reduce delta 2025-03-26 00:35:56 +10:00
conrad 3dcae8d83e backport fix for FFTW3 threading issue 2025-03-26 00:31:46 +10:00
conrad 78f090f132 backport fix 2025-02-19 12:26:07 +10:00
conrad 6c060b9d89 patch bump 2025-02-04 13:56:49 +10:00
conrad 053f0d3133 minor fix 2025-02-04 13:40:42 +10:00
conrad c60cf9ec1a explicitly handle another corner case 2025-01-22 23:50:36 +10:00
conrad eb338e8ed7 change note to warning 2025-01-22 23:23:34 +10:00
conrad 3a23ca275b const qualifier for unwrap 2025-01-19 23:52:34 +10:00
conrad d20277d147 restore original dispatch mechanism 2025-01-18 23:31:55 +10:00
conrad 269ebbad54 better layout 2025-01-17 14:21:54 +10:00
conrad 942a1941bd fix handling of corner cases 2025-01-17 14:14:18 +10:00
conrad e6925c658a add warnings 2025-01-17 14:08:56 +10:00
conrad e9b732faa5 add explanatory note 2025-01-17 14:08:40 +10:00
conrad adb1dc90c8 fix comments 2025-01-12 23:21:16 +10:00
conrad b339eaa4e7 fix 2025-01-09 13:00:21 +10:00
conrad 024ac3b8f2 better layout for sinc() 2025-01-02 13:12:21 +10:00
conrad 6438a10480 improve docs for toeplitz() 2025-01-02 00:03:59 +10:00
conrad 39c28be90a simplify docs for toeplitz() 2025-01-01 23:30:27 +10:00
conrad fdd93b5f40 fix prototypes for xSYCON and xHECON 2024-12-17 12:33:52 +10:00
conrad 794812af6d patch bump 2024-12-06 11:25:13 +10:00
conrad 2656ea3dcf explicitly qualify inherited variables and functions 2024-12-04 12:46:58 +10:00
conrad 9264eef882 avoid clashes with C++20 std::span 2024-12-02 18:36:22 +10:00
conrad 5c5ccac350 explicitly qualify inherited variables and functions 2024-12-02 18:36:03 +10:00
conrad 053907dc1f more selective detection of symmetric/hermitian matrices 2024-12-02 15:08:34 +10:00
conrad 287f80244b patch bump 2024-11-24 17:20:40 +10:00
conrad c8ea9a0fd3 fix 2024-11-24 17:11:12 +10:00
conrad 871c689ed9 expand deprecation warnings with messages 2024-11-23 00:45:56 +10:00
conrad a676522ba5 ensure the first index of extremum value is found 2024-11-22 12:26:10 +10:00
conrad a313b4fd0c version bump 2024-11-16 15:22:53 +10:00
conrad 85233ddbe7 better wording 2024-11-16 12:46:05 +10:00
conrad b6e9484b31 skip conformance check if given expression resolves to a vector 2024-11-15 11:46:29 +10:00
conrad a18a68289b better wording 2024-11-15 00:44:06 +10:00
conrad b3f4e55604 check for aliasing only when the element types match 2024-11-14 19:25:01 +10:00
conrad 702eb6c68b mark as RC1 2024-11-14 12:30:46 +10:00
conrad 0bdd169d38 simplifications 2024-11-14 12:06:57 +10:00
conrad 79f57ff784 update list of changes 2024-11-13 16:57:26 +10:00
conrad a3bc2bc599 ensure consisten handling of symmetric expressions by various forms of inv() 2024-11-13 16:48:20 +10:00
conrad 2cdd3feebb ensure all matrices are checked 2024-11-13 16:14:42 +10:00
conrad ca70fdfba3 more debug statements 2024-11-13 15:08:32 +10:00
conrad 9608d14058 avoid shadowing 2024-11-13 15:02:52 +10:00
conrad 112861df8b add dedicated function for alias detection 2024-11-13 14:55:09 +10:00
conrad 15232980d3 better wording 2024-11-13 14:08:13 +10:00
conrad 6058b46519 adapt to use .index_min() and .index_max() 2024-11-13 12:10:53 +10:00
conrad 0b07572a24 more tests 2024-11-13 12:04:39 +10:00
conrad bb819ee649 update to .index_max() 2024-11-13 12:01:56 +10:00
conrad ee965fc4b7 fix 2024-11-13 11:43:12 +10:00
conrad a7c16f40df update to .index_min() [continued] 2024-11-13 11:40:32 +10:00
conrad e83cea1b48 update to .index_min() 2024-11-12 17:07:20 +10:00
conrad dbca4d6631 wrappers for sytrs and hetrs 2024-11-11 20:05:17 +10:00
conrad 8cdca5cbe9 add redirects for crippled lapack 2024-11-11 19:11:09 +10:00
conrad 121b0a744a extend solve() to detect symmetric expressions 2024-11-11 19:01:04 +10:00
conrad 4ec712dcc6 expand detection of symmetric expressions 2024-11-11 16:21:51 +10:00
conrad e6bfb6941d for unimplemented options, change errors to warnings 2024-11-11 15:39:24 +10:00
conrad d2bdd90982 prevent compiler warnings 2024-11-11 15:29:28 +10:00
conrad 59a24f45f2 use threshold to avoid speed regressions under openblas 2024-11-11 15:21:18 +10:00
conrad ef011e704b minor layout fix 2024-11-11 14:51:32 +10:00
conrad 943fe56b61 fix 2024-11-11 14:48:44 +10:00
conrad 670ca673f8 check for conflicting options 2024-11-11 14:44:22 +10:00
conrad 265e66f43e document solve_opts::force_sym 2024-11-11 14:36:27 +10:00
conrad baf9ab7970 add solve_opts::force_sym option 2024-11-11 14:14:41 +10:00
conrad dd5e73ae20 add solve_sym_rcond 2024-11-11 14:14:20 +10:00
conrad 5d1ceb6aa9 revert 2024-11-11 11:22:16 +10:00
conrad acc8680aa8 restore previous wording 2024-11-11 11:08:27 +10:00
conrad 8cb75d0ac5 ensure consistent handling of symmetric matrices by expressions with inv() 2024-11-09 17:19:01 +10:00
conrad 77fccf7db1 use threshold 2024-11-09 16:21:43 +10:00
conrad 18a2a42061 add fast mode symmetric solver 2024-11-09 14:50:52 +10:00
conrad b2f8023392 simplify docs for solve() 2024-11-08 15:39:41 +10:00
conrad bcc950cb9e minor corrections 2024-11-08 15:21:00 +10:00
conrad 5c313e8a6d definitions for sytrs and hetrs 2024-11-08 15:15:25 +10:00
conrad d13194f8e8 expand MKL search paths 2024-11-07 13:10:31 +10:00
conrad 437c7299b9 remove mentions of ARMA_BLAS_LONG 2024-11-07 12:22:41 +10:00
conrad b744b74533 ensure consistency with documentation 2024-11-07 12:17:54 +10:00
conrad f22d60c74f qualify lapack function names in comment 2024-11-07 12:14:32 +10:00
conrad 44e1beabce update list of changes 2024-11-06 17:24:52 +10:00
conrad f003381651 minor cleanup 2024-11-06 17:24:29 +10:00
conrad 538ae305bf optimisation when all eigenvalues are positive 2024-11-06 17:15:41 +10:00
conrad d00fc06c06 fix 2024-11-06 13:23:30 +10:00
conrad 8650784ac7 detect sym matrices instead of sympd 2024-11-06 12:34:03 +10:00
conrad f0acfbbf63 update debug messages 2024-11-06 12:20:18 +10:00
conrad da8ea7ea20 add note 2024-11-05 18:53:25 +10:00
conrad d484a3d7ad check diagonal for nonfinite values 2024-11-05 16:39:45 +10:00
conrad 978d7d6e76 rearrange 2024-11-04 12:51:43 +10:00
conrad 65eefbfce6 formally deprecate undocumented forms of .min() and .max() 2024-11-03 15:33:19 +10:00
conrad 6e469f1d38 cleanup 2024-11-01 11:46:04 +10:00
conrad 3280fd41ae ensure rcond results are consistent with rcond version of inv() 2024-11-01 11:43:50 +10:00
conrad 97f85611c1 stronger checks for diagonal elements of hermitian matrices 2024-11-01 11:11:19 +10:00
conrad 7b38cfca6e add sanity checks 2024-10-31 16:09:34 +10:00
conrad 30122e7adf simplification 2024-10-31 16:00:43 +10:00
conrad 0481314430 update docs 2024-10-31 13:44:00 +10:00
conrad ef7fec1385 deprecate ARMA_CRIPPLED_LAPACK option 2024-10-31 13:34:51 +10:00
conrad 42623aff06 minor cleanups 2024-10-31 13:21:39 +10:00
conrad 3165f618ed remove unused code 2024-10-31 13:13:34 +10:00
conrad 93a652c50c simplifications 2024-10-31 13:06:52 +10:00
conrad f506e86466 detect hermitian matrices 2024-10-31 11:02:51 +10:00
conrad c7053e8c23 redirect in case of crippled lapack 2024-10-31 10:27:37 +10:00
conrad 95a8229587 more workarounds 2024-10-31 10:14:48 +10:00
conrad 4b3fdadd7f workarounds for crippled implementations of lapack 2024-10-31 10:06:24 +10:00
conrad 7ce8e17e99 simplifications 2024-10-30 16:15:51 +10:00
conrad 25d5285cbd prevent compiler warnings 2024-10-30 15:59:49 +10:00
conrad 53806daa3f replace hard coded constant 2024-10-30 15:58:59 +10:00
conrad bcca9da94d add wrappers 2024-10-30 15:39:21 +10:00
conrad 6da76d1019 update docs 2024-10-30 13:36:36 +10:00
conrad cb73277ec7 add threshold due to inconsistent speedups on OpenBLAS 0.3.26 2024-10-30 13:23:26 +10:00
conrad 6d15ecca58 fix layout 2024-10-30 12:51:47 +10:00
conrad e701de5738 replace rcond_sympd with rcond_sym 2024-10-29 15:49:18 +10:00
conrad b4e2b8de7c more debug statements 2024-10-29 15:30:28 +10:00
conrad b0ff7506b0 update docs 2024-10-29 15:10:16 +10:00
conrad 1bf38c114d fix 2024-10-29 10:34:44 +10:00
conrad 96e98edec9 inv rcond optimisation for sym matrices 2024-10-29 00:10:14 +10:00
conrad 6e838ef11c defintions for sycon and hecon 2024-10-28 16:00:02 +10:00
conrad 55059a4e30 refactor inv_sym() to handle complex hermitian matrices 2024-10-28 15:44:25 +10:00
conrad 98c7800566 add TODOs 2024-10-28 15:12:48 +10:00
conrad 0e5978f981 partial rework of inv() to optimise for symmetric matrices 2024-10-28 14:23:24 +10:00
conrad b52dae4657 mark as unstable 2024-10-14 14:07:18 +10:00
conrad 1b037556da simpler wording 2024-10-05 19:08:45 +10:00
conrad 6a1c5d7ff3 remove handling of rare expressions 2024-10-05 18:59:22 +10:00
conrad ce4d54c82b bump min compiler version 2024-10-05 16:54:40 +10:00
conrad bca1545ae3 deprecate support for gcc < 8.1 2024-10-05 16:48:37 +10:00
conrad b908470f3b change http to https 2024-10-04 11:44:27 +10:00
conrad 7c75e9e594 deprecate ill-designed forms of pow() 2024-10-03 13:57:48 +10:00
conrad 55c30cbc73 restore doc for previous option 2024-10-03 13:15:41 +10:00
conrad d56115ef45 simplifications 2024-10-03 11:35:02 +10:00
conrad c7f1711d6c restore original implementation; subview_each et al are not derived from Base 2024-10-03 11:12:17 +10:00
conrad e280d25c9a add explanatory notes 2024-10-03 11:03:52 +10:00
conrad 27f4297396 more refactoring 2024-10-03 10:56:14 +10:00
conrad 5eabafe2b3 partial rewrite of powext 2024-10-02 14:46:00 +10:00
conrad ed1ec45817 remove deprecated forms 2024-10-02 13:14:41 +10:00
conrad 901c5c3d0c add notes 2024-10-02 13:10:02 +10:00
conrad 19292dff3a rearrange deprecated forms 2024-10-02 12:59:34 +10:00
conrad 53f8e0664f deprecate seldom used forms of pow() 2024-10-02 12:47:46 +10:00
conrad d66e799b5c simplification: remove docs for seldom used forms of pow() 2024-10-02 12:43:12 +10:00
conrad 053d5a5787 stats_fns: clarify caveat and add example for integer vector 2024-09-25 11:07:26 +10:00
conrad cb3203f130 add ARMA_BLAS_64BIT_INT config option 2024-09-04 15:12:07 +10:00
conrad 44411aadee explicitly deprecate old log_add_exp() 2024-09-04 12:36:46 +10:00
conrad c953e836e7 clarify that 'long long' is 64 bit integer 2024-08-21 20:31:10 +10:00
88 changed files with 2896 additions and 1378 deletions
+18 -19
View File
@@ -303,7 +303,7 @@ the active solution platform must be set to x64, instead of win32.
The MSVC project was tested on Windows 10 (64 bit) with Visual Studio C++ 2019.
Adaptations may be required for 32 bit systems, later versions of Windows and/or the compiler.
For example, options such as `ARMA_BLAS_LONG` and `ARMA_BLAS_UNDERSCORE`,
For example, options such as `ARMA_BLAS_LONG_LONG` and `ARMA_BLAS_UNDERSCORE`,
defined in `include/armadillo_bits/config.hpp`, may need to be either enabled or disabled.
The folder `examples/lib_win64` contains a copy of lib and dll files
@@ -333,29 +333,28 @@ as used by the replacement libraries. Specifically, the following defines
may need to be enabled or disabled:
ARMA_USE_WRAPPER
ARMA_BLAS_CAPITALS
ARMA_BLAS_UNDERSCORE
ARMA_BLAS_LONG
ARMA_BLAS_LONG_LONG
ARMA_DONT_USE_FORTRAN_HIDDEN_ARGS
ARMA_BLAS_UNDERSCORE
ARMA_BLAS_CAPITALS
See the documentation for more information on the above defines.
On Linux-based systems, MKL might be installed in a non-standard location such as `/opt`
which can cause problems during linking.
Before installing Armadillo, the system should know where the MKL libraries are located.
For example, `/opt/intel/mkl/lib/intel64/`.
This can be achieved by setting the `LD_LIBRARY_PATH` environment variable,
or for a more permanent solution, adding the directory locations to `/etc/ld.so.conf`.
It may also be possible to store a text file with the locations
in the `/etc/ld.so.conf.d` directory. For example, `/etc/ld.so.conf.d/mkl.conf`.
If `/etc/ld.so.conf` is modified or `/etc/ld.so.conf.d/mkl.conf` is created,
`/sbin/ldconfig` must be run afterwards.
Examples: `/opt/intel/oneapi/mkl/latest/lib`, `/opt/intel/mkl/lib/intel64/`.
Below is an example of `/etc/ld.so.conf.d/mkl.conf`
where Intel MKL is installed in `/opt/intel`
Before installing Armadillo, the system must know where the MKL libraries are located.
This can be achieved via several ways:
/opt/intel/lib/intel64
/opt/intel/mkl/lib/intel64
1. By setting the `LD_LIBRARY_PATH` environment variable.
2. By adding the MKL library directory locations to the `/etc/ld.so.conf` text file,
followed by running `/sbin/ldconfig`.
3. By creating a text file named `/etc/ld.so.conf.d/mkl.conf`
which contains the MKL library directory locations,
followed by running `/sbin/ldconfig`.
If MKL is installed and it is persistently giving problems during linking,
Support for MKL can be disabled by editing the CMakeLists.txt file,
@@ -461,12 +460,12 @@ Octave/Matlab with C++ code that uses Armadillo matrices.
### 16: Related Software Using Armadillo
* ensmallen: C++ library for non-linear numerical optimisation (L-BFGS, SGD, CMA-ES, etc)
https://ensmallen.org/
* MLPACK: extensive library of machine learning algorithms
https://mlpack.org
* ensmallen: C++ library for numerical optimisation (L-BFGS, SGD, CMA-ES, etc)
https://ensmallen.org/
* RcppArmadillo: integration of Armadillo with R
https://dirk.eddelbuettel.com/code/rcpp.armadillo.html
+3
View File
@@ -115,6 +115,9 @@ foreach (MKL_NAME ${MKL_NAMES})
/usr/local/mkl/*/lib/em64t
/usr/local/mkl/*/lib/lib64
/usr/local/mkl/*/lib/32
/usr/local/intel/oneapi/mkl/latest/lib
/opt/intel/oneapi/mkl/latest/lib
/opt/intel/oneapi/mkl/*/lib
)
set(TMP_LIBRARY ${${MKL_NAME}_LIBRARY})
+53 -59
View File
@@ -150,7 +150,7 @@ hr.greyline
<a class="noprint" style="display:scroll; position:fixed; bottom:5px; right:5px;" href="#top"><font size=-1>[top]</font></a>
<a name="top"></a>
<big><b>API Documentation for Armadillo 14.0</b></big>
<big><b>API Documentation for Armadillo 14.2</b></big>
<br>
<br>
<br>
@@ -543,7 +543,7 @@ Conrad Sanderson and Ryan Curtin.
<tr style="background-color: #F5F5F5;"><td><a href="#running_stat">running_stat</a></td><td>&nbsp;</td><td>running statistics of scalars (one dimensional process/signal)</td></tr>
<tr style="background-color: #F5F5F5;"><td><a href="#running_stat_vec">running_stat_vec</a></td><td>&nbsp;</td><td>running statistics of vectors (multi-dimensional process/signal)</td></tr>
<tr><td><a href="#kmeans">kmeans</a></td><td>&nbsp;</td><td>cluster data into disjoint sets</td></tr>
<tr><td><a href="#gmm_diag">gmm_diag/gmm_full</a></td><td>&nbsp;</td><td>probabilistic clustering and likelihood calculation via Gaussian mixture models</td></tr>
<tr><td><a href="#gmm_diag">gmm_diag/gmm_full</a></td><td>&nbsp;</td><td>probabilistic clustering and likelihood calculation via mixture of Gaussians</td></tr>
</tbody>
</table>
</ul>
@@ -4218,7 +4218,6 @@ See also:
<li><a href="#submat">submatrix views</a></li>
<li><a href="#diag">diagonal views</a></li>
<li><a href="#repmat">repmat()</a></li>
<li><a href="#pow">pow()</a></li>
<li><a href="#for_each">.for_each()</a></li>
<li><a href="#each_slice">.each_slice()</a></li>
</ul>
@@ -4323,7 +4322,6 @@ See also:
<ul>
<li><a href="#operators">math &amp; relational operators</a></li>
<li><a href="#subcube">subcube views</a></li>
<li><a href="#pow">pow()</a></li>
<li><a href="#for_each">.for_each()</a></li>
<li><a href="#each_colrow">.each_col() &amp; .each_row()</a> &nbsp;</li>
<li><a href="https://www.cprogramming.com/c++11/c++11-lambda-closures.html">lambda function</a> at cprogramming.com</li>
@@ -8212,18 +8210,13 @@ sp_mat A = sprandu&lt;sp_mat&gt;(100, 200, 0.1);
<a name="toeplitz"></a>
<b>toeplitz( A )</b>
<br><b>toeplitz( A, B )</b>
<br><b>circ_toeplitz( A )</b>
<ul>
<li>
toeplitz(): generate a Toeplitz matrix, with the first column specified by <i>A</i>, and (optionally) the first row specified by <i>B</i>
Generate a Toeplitz matrix, with the first column specified by vector <i>A</i>, and (optionally) the first row specified by vector <i>B</i>
</li>
<br>
<li>
circ_toeplitz(): generate a circulant Toeplitz matrix
</li>
<br>
<li>
A and B must be vectors
If argument <i>B</i> is omitted, the first row is assumed to be the same as the first column
</li>
<br>
<li>
@@ -8231,8 +8224,8 @@ Examples:
<ul>
<pre>
vec A(5, fill::randu);
mat X = toeplitz(A);
mat Y = circ_toeplitz(A);
</pre>
</ul>
</li>
@@ -8241,7 +8234,6 @@ mat Y = circ_toeplitz(A);
<ul>
<li><a href="https://mathworld.wolfram.com/ToeplitzMatrix.html">Toeplitz matrix in MathWorld</a></li>
<li><a href="https://en.wikipedia.org/wiki/Toeplitz_matrix">Toeplitz matrix in Wikipedia</a></li>
<li><a href="https://en.wikipedia.org/wiki/Circulant_matrix">Circulant matrix in Wikipedia</a></li>
</ul>
</li>
<br>
@@ -10757,9 +10749,11 @@ See also:
<tbody>
<tr><td><b>pow( A, scalar )</b></td><td>&nbsp;&nbsp;&nbsp;</td><td>(form&nbsp;1)</td></tr>
<tr><td><b>pow( A, B )</b></td><td>&nbsp;&nbsp;&nbsp;</td><td>(form&nbsp;2)</td></tr>
<!--
<tr><td><b>pow( M.each_col(), C )</b></td><td>&nbsp;&nbsp;&nbsp;</td><td>(form&nbsp;3)</td></tr>
<tr><td><b>pow( M.each_row(), R )</b></td><td>&nbsp;&nbsp;&nbsp;</td><td>(form&nbsp;4)</td></tr>
<tr><td><b>pow( Q.each_slice(), M )</b></td><td>&nbsp;&nbsp;&nbsp;</td><td>(form&nbsp;5)</td></tr>
-->
</tbody>
</table>
<ul>
@@ -10767,9 +10761,9 @@ See also:
<br>
<li>form 1: raise all elements in <i>A</i> to the power denoted by the given scalar</li>
<br>
<li>form 2: raise each element in <i>A</i> to the power denoted by the corresponding element in <i>B</i>;
<br>the sizes of <i>A</i> and <i>B</i> must be the same</li>
<li>form 2: raise each element in <i>A</i> to the power denoted by the corresponding element in <i>B</i>; sizes of <i>A</i> and <i>B</i> must be the same</li>
<br>
<!--
<li>form 3: for each column vector of matrix <i>M</i>, raise each element to the power denoted by the corresponding element in column vector <i>C</i>;
<br>the number of rows in <i>M</i> and <i>C</i> must be the same</li>
<br>
@@ -10779,6 +10773,7 @@ See also:
<li>form 5: for each slice of cube <i>Q</i>, raise each element to the power denoted by the corresponding element in matrix <i>M</i>;
<br>the number of rows and columns in <i>Q</i> and <i>M</i> must be the same</li>
<br>
-->
<li><b>Caveats</b>:
<ul>
<li>to raise all elements to the power 2, use <a href="#misc_fns">square()</a> instead</li>
@@ -10794,13 +10789,14 @@ mat B(5, 6, fill::randu);
mat X = pow(A, 3.45);
mat Y = pow(A, B);
</pre>
<!--
vec C(5, fill::randu);
rowvec R(6, fill::randu);
mat Z1 = pow(A.each_col(), C);
mat Z2 = pow(A.each_row(), R);
</pre>
-->
</ul>
</li>
<br>
@@ -10808,10 +10804,11 @@ mat Z2 = pow(A.each_row(), R);
See also:
<ul>
<li><a href="#powmat">powmat()</a></li>
<li><a href="#abs">abs()</a></li>
<li><a href="#misc_fns">miscellaneous element-wise functions</a></li>
<!--
<li><a href="#each_colrow">.each_col() &amp; .each_row()</a></li>
<li><a href="#each_slice">.each_slice()</a></li>
-->
</ul>
</li>
<br>
@@ -12608,7 +12605,7 @@ For single argument functions, <i>B = trig_fn(A)</i>, where <i>trig_fn</i> is ap
<i>tan</i>, <i>atan</i>, <i>tanh</i>, <i>atanh</i>
</li>
<li>
<i>sinc</i>, defined as sinc(x) = sin(&pi;x)&thinsp;/&thinsp;(&pi;x) for x&thinsp;&ne;&thinsp;0, and sinc(x)&thinsp;=&thinsp;1 for x&thinsp;=&thinsp;0
<i>sinc</i>, defined as sinc(x) = sin(&pi;&middot;x)&thinsp;/&thinsp;(&pi;&middot;x) for x&thinsp;&ne;&thinsp;0, and sinc(x)&thinsp;=&thinsp;1 for x&thinsp;=&thinsp;0
</li>
</ul>
</li>
@@ -13741,7 +13738,7 @@ The number of rows in <i>A</i> and <i>B</i> must be the same
</li>
<br>
<li>
By default, matrix <i>A</i> is analysed to automatically determine whether it is a general matrix, band matrix, diagonal matrix, or symmetric/hermitian positive definite (SPD) matrix;
By default, matrix <i>A</i> is analysed to automatically determine whether it is a general matrix, band matrix, diagonal matrix, or symmetric/hermitian positive definite (sympd) matrix;
based on the detected matrix structure, a specialised solver is used for faster execution;
if no solution is found, an approximate solver is automatically used as a fallback;
see the <a href="armadillo_solver_2020.pdf">associated paper</a> for more details
@@ -13760,13 +13757,16 @@ the solution can be computed faster by explicitly indicating that <i>A</i> is tr
<tr><td><code>solve_opts::fast</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>fast mode: disable determining solution quality via rcond, disable iterative refinement, disable equilibration</td></tr>
<tr><td><code>solve_opts::refine</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>apply iterative refinement to improve solution quality &nbsp; (matrix <i>A</i> must be square)</td></tr>
<tr><td><code>solve_opts::equilibrate</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>equilibrate the system before solving &nbsp; (matrix <i>A</i> must be square)</td></tr>
<tr><td><code>solve_opts::likely_sympd</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>indicate that matrix <i>A</i> is likely symmetric/hermitian positive definite</td></tr>
<tr><td><code>solve_opts::likely_sympd</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>indicate that matrix <i>A</i> is likely symmetric/hermitian positive definite (sympd)</td></tr>
<tr><td><code>solve_opts::allow_ugly</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>keep solutions of systems that are singular to working precision</td></tr>
<tr><td><code>solve_opts::no_approx</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>do not find approximate solutions for rank deficient systems</td></tr>
<!--
<tr><td><code>solve_opts::no_band</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>do not use specialised solver for band matrices or diagonal matrices</td></tr>
<tr><td><code>solve_opts::no_trimat</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>do not use specialised solver for triangular matrices</td></tr>
<tr><td><code>solve_opts::no_sympd</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>do not use specialised solver for symmetric/hermitian positive definite matrices</td></tr>
<tr><td><code>solve_opts::force_approx</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>skip the standard solver and directly use of the approximate solver</td></tr>
-->
<tr><td><code>solve_opts::force_sym</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>force use of the symmetric/hermitian solver (not limited to sympd matrices)</td></tr>
<tr><td><code>solve_opts::force_approx</code></td><td>&nbsp;&nbsp;&nbsp;</td><td>force use of the approximate solver</td></tr>
</tbody>
</table>
<br>
@@ -13774,7 +13774,7 @@ the above settings can be combined using the <code>+</code> operator; for exampl
</li>
<br>
<li>
If a rank deficient system is detected and the <i><code>solve_opts::no_approx</code></i> option is <b>not</b> enabled, a warning is emitted and an approximate solution is attempted;
If a rank deficient system is detected and the <code>solve_opts::no_approx</code> option is <b>not</b> enabled, a warning is emitted and an approximate solution is attempted;
<br>since Armadillo 10.4, this warning can be disabled by setting <a href="#config_hpp">ARMA_WARN_LEVEL</a> to 1 before including the armadillo header:
<br><code>#define ARMA_WARN_LEVEL 1</code>
<br><code>#include&nbsp;&lt;armadillo&gt;</code>
@@ -13783,9 +13783,9 @@ If a rank deficient system is detected and the <i><code>solve_opts::no_approx</c
<li>
<b>Caveats:</b>
<ul>
<li>using <i><code>solve_opts::fast</code></i> will speed up finding the solution, but for poorly conditioned systems the solution may have lower quality</li>
<li>not all SPD matrices are automatically detected; to skip the analysis step and directly indicate that matrix <i>A</i> is likely SPD, use <code>solve_opts::likely_sympd</code></li>
<li>using <i><code>solve_opts::force_approx</code></i> is only advised if the system is known to be rank deficient; the approximate solver is considerably slower</li>
<li>using <code>solve_opts::fast</code> will speed up finding the solution, but for poorly conditioned systems the solution may have lower quality</li>
<li>not all sympd matrices are automatically detected; to directly indicate that matrix <i>A</i> is likely sympd, use <code>solve_opts::likely_sympd</code></li>
<li>using <code>solve_opts::force_approx</code> is only advised if the system is known to be rank deficient; the approximate solver is considerably slower</li>
</ul>
</li>
<br>
@@ -15359,8 +15359,8 @@ For the <i>var()</i> and <i>stddev()</i> functions:
<br>
<li>
<b>Caveat:</b>
to obtain statistics for integer matrices/vectors (eg. <a href="#Mat">umat</a>, <a href="#Mat">imat</a>, <a href="#Col">uvec</a>, <a href="#Col">ivec</a>),
convert to a matrix/vector with floating point values (eg. <a href="#Mat">mat</a>, <a href="#Col">vec</a>) using the <a href="#conv_to">conv_to()</a> function
to obtain statistics for an integer vector or matrix (eg. <a href="#Col">uvec</a>, <a href="#Col">ivec</a>),
first use the <a href="#conv_to">conv_to()</a> function to obtain a floating point representation (eg. <a href="#Col">vec</a>)
</li>
<br>
<li>
@@ -15375,6 +15375,9 @@ double m = mean(mean(A));
vec v(5, fill::randu);
double x = var(v);
ivec w = {1, 2, 3, 4}; // integer vector
double y = mean( conv_to&lt;vec&gt;::from(w) );
</pre>
</ul>
</li>
@@ -19116,7 +19119,7 @@ Armadillo extensively uses template meta-programming,
so it's recommended to enable optimisation when compiling programs (eg. use the -O2 or -O3 options for GCC or clang)
</li>
<br>
<li>See the <a href="http://arma.sourceforge.net/faq.html">Questions</a> page for more info on compiling and linking</li>
<li>See the <a href="https://arma.sourceforge.net/faq.html">Questions</a> page for more info on compiling and linking</li>
<br>
<li>See also the example program that comes with the Armadillo archive</li>
</ul>
@@ -19149,7 +19152,7 @@ Some options can also be specified by explicitly defining them <b>before</b> inc
&nbsp;
</td>
<td style="vertical-align: top;">
Disable going through the run-time Armadillo wrapper library (<i>libarmadillo.so</i>) when calling LAPACK, BLAS, ARPACK, SuperLU and HDF5 functions.
Disable going through the run-time Armadillo wrapper library (<i>libarmadillo.so</i>) when calling LAPACK, BLAS, ARPACK, and SuperLU functions.
You will need to directly link with BLAS, LAPACK, etc (eg. <code><i>-lblas -llapack</i></code>)
</td>
</tr>
@@ -19694,35 +19697,14 @@ Append an underscore to BLAS and LAPACK function names (eg. dgemm_ vs dgemm). En
</tr>
<tr>
<td style="vertical-align: top;">
<code>ARMA_BLAS_LONG</code>
</td>
<td style="vertical-align: top;">
&nbsp;
</td>
<td style="vertical-align: top;">
Use "long" instead of "int" when calling BLAS and LAPACK functions
</td>
</tr>
<tr>
<td style="vertical-align: top;">
&nbsp;
</td>
<td style="vertical-align: top;">
&nbsp;
</td>
<td style="vertical-align: top;">
&nbsp;
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<!-- <code>ARMA_BLAS_64BIT_INT</code> -->
<code>ARMA_BLAS_LONG_LONG</code>
</td>
<td style="vertical-align: top;">
&nbsp;
</td>
<td style="vertical-align: top;">
Use "long&nbsp;long" instead of "int" when calling BLAS and LAPACK functions
Use "long&nbsp;long" instead of "int" when calling BLAS and LAPACK functions; the "long long" type is a 64 bit integer type on all platforms
</td>
</tr>
<tr>
@@ -19837,7 +19819,7 @@ Use Intel MKL <i>mkl_malloc()</i> and <i>mkl_free()</i> instead of standard <i>m
Use Intel MKL types for complex numbers.
You will need to include appropriate MKL headers before the Armadillo header.
You may also need to enable one or more of the following options:
<code>ARMA_BLAS_LONG</code>, <code>ARMA_BLAS_LONG_LONG</code>, <code>ARMA_DONT_USE_FORTRAN_HIDDEN_ARGS</code>
<code>ARMA_BLAS_LONG_LONG</code>, <code>ARMA_DONT_USE_FORTRAN_HIDDEN_ARGS</code>
</td>
</tr>
<tr>
@@ -19860,10 +19842,12 @@ You may also need to enable one or more of the following options:
&nbsp;
</td>
<td style="vertical-align: top;">
Use 64 bit integers. Automatically enabled when using a 64-bit platform, except when using Armadillo in the R environment (via RcppArmadillo).
Use 64 bit integers for matrix and vector sizes.
Automatically enabled when using a 64-bit platform, except when using Armadillo in the R environment (via RcppArmadillo).
Useful if matrices/vectors capable of holding more than 4 billion elements are required.
<!-- Your machine and compiler must have support for 64 bit integers (eg. via "long" or "long&nbsp;long"). -->
This can also be enabled by adding <i>#define&nbsp;ARMA_64BIT_WORD</i> before each instance of <i>#include&nbsp;&lt;armadillo&gt;</i>
This can also be enabled by adding <code>#define&nbsp;ARMA_64BIT_WORD</code> before each instance of <code>#include&nbsp;&lt;armadillo&gt;</code>.
<br>See also the <code>ARMA_BLAS_LONG_LONG</code> option.
</td>
</tr>
<tr>
@@ -20140,6 +20124,16 @@ List of additions and changes for each version:
<a name="version_142"></a>
<li>Version 14.2:
<ul>
<li>faster handling of symmetric matrices by <a href="#inv">inv()</a>, <a href="#rcond">rcond()</a>, <a href="#powmat">powmat()</a></li>
<li>faster handling of hermitian matrices by <a href="#inv">inv()</a>, <a href="#rcond">rcond()</a>, <a href="#powmat">powmat()</a>, <a href="#cond">cond()</a>, <a href="#pinv">pinv()</a>, <a href="#rank">rank()</a></li>
<li>added <code>solve_opts::force_sym</code> option to <a href="#solve">solve()</a> to force use of the symmetric/hermitian solver (not limited to sympd matrices)</li>
<li>more efficient handling of compound expressions by <a href="#solve">solve()</a></li>
</ul>
</li>
<br>
<a name="version_140"></a>
<li>Version 14.0
<ul>
@@ -20210,7 +20204,7 @@ List of additions and changes for each version:
<a name="version_114"></a>
<li>Version 11.4:
<ul>
<li>extended <a href="#pow">pow()</a> with various forms of element-wise power operations</li>
<li>extended <a href="#pow">pow()</a> with secondary element-wise form</li>
<li>added <a href="#find_nan">find_nan()</a> to find indices of NaN elements</li>
<li>faster handling of compound expressions by <a href="#sum">sum()</a></li>
</ul>
@@ -20587,7 +20581,7 @@ this requires a C++11/C++14 compiler with OpenMP 3.1+ support
<ul>
<li>
changed license to the permissive <a href="https://opensource.org/licenses/Apache-2.0">Apache License 2.0</a>;
see the <a href="http://arma.sourceforge.net/faq.html#license">Questions page</a> for more info
see the <a href="https://arma.sourceforge.net/faq.html#license">Questions page</a> for more info
</li>
</ul>
</li>
@@ -21088,7 +21082,7 @@ the <i>uword</i> type then has a minimum width of 64 bits
<li>Version 2.2:
<ul>
<li>added <a href="#svd_econ">svd_econ()</a></li>
<li>added <a href="#toeplitz">circ_toeplitz()</a></li>
<!-- <li>added <a href="#toeplitz">circ_toeplitz()</a></li> -->
<li>added <a href="#is_vec">.is_colvec()</a> and <a href="#is_vec">.is_rowvec()</a></li>
</ul>
<br>
+3 -1
View File
@@ -1,7 +1,9 @@
#include <iostream>
#include <armadillo>
using namespace std;
using std::cout;
using std::endl;
using namespace arma;
// Armadillo documentation is available at:
+4 -4
View File
@@ -127,11 +127,11 @@ struct Base
arma_warn_unused inline elem_type min() const;
arma_warn_unused inline elem_type max() const;
inline elem_type min(uword& index_of_min_val) const;
inline elem_type max(uword& index_of_max_val) const;
arma_frown("use .index_min() instead") inline elem_type min(uword& index_of_min_val) const;
arma_frown("use .index_max() instead") inline elem_type max(uword& index_of_max_val) const;
inline elem_type min(uword& row_of_min_val, uword& col_of_min_val) const;
inline elem_type max(uword& row_of_max_val, uword& col_of_max_val) const;
arma_frown("use .index_min() with ind2sub() instead") inline elem_type min(uword& row_of_min_val, uword& col_of_min_val) const;
arma_frown("use .index_max() with ind2sub() instead") inline elem_type max(uword& row_of_max_val, uword& col_of_max_val) const;
arma_warn_unused inline uword index_min() const;
arma_warn_unused inline uword index_max() const;
+2
View File
@@ -187,6 +187,8 @@ class Col<eT>::fixed : public Col<eT>
{
private:
using Mat<eT>::mem_local;
static constexpr bool use_extra = (fixed_n_elem > arma_config::mat_prealloc);
arma_align_mem eT mem_local_extra[ (use_extra) ? fixed_n_elem : 1 ];
+5 -5
View File
@@ -1345,11 +1345,11 @@ Col<eT>::fixed<fixed_n_elem>::fixed(const fill::fill_class<fill_type>&)
{
arma_debug_sigprint_this(this);
if(is_same_type<fill_type, fill::fill_zeros>::yes) { (*this).zeros(); }
if(is_same_type<fill_type, fill::fill_ones >::yes) { (*this).ones(); }
if(is_same_type<fill_type, fill::fill_eye >::yes) { (*this).eye(); }
if(is_same_type<fill_type, fill::fill_randu>::yes) { (*this).randu(); }
if(is_same_type<fill_type, fill::fill_randn>::yes) { (*this).randn(); }
if(is_same_type<fill_type, fill::fill_zeros>::yes) { (*this).zeros(); }
if(is_same_type<fill_type, fill::fill_ones >::yes) { (*this).ones(); }
if(is_same_type<fill_type, fill::fill_eye >::yes) { Mat<eT>::eye(); }
if(is_same_type<fill_type, fill::fill_randu>::yes) { Mat<eT>::randu(); }
if(is_same_type<fill_type, fill::fill_randn>::yes) { Mat<eT>::randn(); }
}
@@ -36,6 +36,9 @@ class CubeToMatOp : public Base< typename T1::elem_type, CubeToMatOp<T1, op_type
arma_aligned const T1& m; //!< the operand; must be derived from BaseCube
arma_aligned uword aux_uword; //!< auxiliary data, uword format
template<typename eT2>
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
static constexpr bool is_row = op_type::template traits<T1>::is_row;
static constexpr bool is_col = op_type::template traits<T1>::is_col;
static constexpr bool is_xvec = op_type::template traits<T1>::is_xvec;
+7 -5
View File
@@ -387,12 +387,11 @@ class Cube : public BaseCube< eT, Cube<eT> >
arma_warn_unused inline eT min() const;
arma_warn_unused inline eT max() const;
inline eT min(uword& index_of_min_val) const;
inline eT max(uword& index_of_max_val) const;
inline eT min(uword& row_of_min_val, uword& col_of_min_val, uword& slice_of_min_val) const;
inline eT max(uword& row_of_max_val, uword& col_of_max_val, uword& slice_of_max_val) const;
arma_frown("use .index_min() instead") inline eT min(uword& index_of_min_val) const;
arma_frown("use .index_max() instead") inline eT max(uword& index_of_max_val) const;
arma_frown("use .index_min() with ind2sub() instead") inline eT min(uword& row_of_min_val, uword& col_of_min_val, uword& slice_of_min_val) const;
arma_frown("use .index_max() with ind2sub() instead") inline eT max(uword& row_of_max_val, uword& col_of_max_val, uword& slice_of_max_val) const;
arma_cold inline bool save(const std::string name, const file_type type = arma_binary) const;
arma_cold inline bool save(const hdf5_name& spec, const file_type type = hdf5_binary) const;
@@ -486,6 +485,9 @@ class Cube<eT>::fixed : public Cube<eT>
{
private:
using Cube<eT>::mat_ptrs_local;
using Cube<eT>::mem_local;
static constexpr uword fixed_n_elem = fixed_n_rows * fixed_n_cols * fixed_n_slices;
static constexpr uword fixed_n_elem_slice = fixed_n_rows * fixed_n_cols;
+8 -8
View File
@@ -3448,7 +3448,7 @@ Cube<eT>::at_alt(const uword i) const
//! linear element accessor (treats the cube as a vector); bounds checking not done when ARMA_NO_DEBUG is defined
//! linear element accessor (treats the cube as a vector); bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename eT>
arma_inline
eT&
@@ -3461,7 +3461,7 @@ Cube<eT>::operator() (const uword i)
//! linear element accessor (treats the cube as a vector); bounds checking not done when ARMA_NO_DEBUG is defined
//! linear element accessor (treats the cube as a vector); bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename eT>
arma_inline
const eT&
@@ -3517,7 +3517,7 @@ Cube<eT>::at(const uword i) const
//! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
//! element accessor; bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename eT>
arma_inline
eT&
@@ -3537,7 +3537,7 @@ Cube<eT>::operator() (const uword in_row, const uword in_col, const uword in_sli
//! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
//! element accessor; bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename eT>
arma_inline
const eT&
@@ -5412,10 +5412,10 @@ Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::fixed(const fill::f
mem_setup();
if(is_same_type<fill_type, fill::fill_zeros>::yes) { (*this).zeros(); }
if(is_same_type<fill_type, fill::fill_ones >::yes) { (*this).ones(); }
if(is_same_type<fill_type, fill::fill_randu>::yes) { (*this).randu(); }
if(is_same_type<fill_type, fill::fill_randn>::yes) { (*this).randn(); }
if(is_same_type<fill_type, fill::fill_zeros>::yes) { Cube<eT>::zeros(); }
if(is_same_type<fill_type, fill::fill_ones >::yes) { Cube<eT>::ones(); }
if(is_same_type<fill_type, fill::fill_randu>::yes) { Cube<eT>::randu(); }
if(is_same_type<fill_type, fill::fill_randn>::yes) { Cube<eT>::randn(); }
arma_static_check( (is_same_type<fill_type, fill::fill_eye>::yes), "Cube::fixed::fixed(): unsupported fill type" );
}
+3
View File
@@ -54,6 +54,9 @@ class Gen
inline void apply_inplace_div (Mat<elem_type>& out) const;
inline void apply(subview<elem_type>& out) const;
template<typename eT2>
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
};
+3
View File
@@ -56,6 +56,9 @@ class Glue
inline Glue(const T1& in_A, const T2& in_B, const uword in_aux_uword);
inline ~Glue();
template<typename eT2>
inline bool is_alias(const Mat<eT2>& X) const;
const T1& A; //!< first operand; must be derived from Base
const T2& B; //!< second operand; must be derived from Base
uword aux_uword; //!< storage of auxiliary data, uword format
+13
View File
@@ -53,4 +53,17 @@ Glue<T1,T2,glue_type>::~Glue()
template<typename T1, typename T2, typename glue_type>
template<typename eT2>
inline
bool
Glue<T1,T2,glue_type>::is_alias(const Mat<eT2>& X) const
{
arma_debug_sigprint();
return (A.is_alias(X) || B.is_alias(X));
}
//! @}
+9 -4
View File
@@ -541,11 +541,11 @@ class Mat : public Base< eT, Mat<eT> >
arma_warn_unused inline eT min() const;
arma_warn_unused inline eT max() const;
inline eT min(uword& index_of_min_val) const;
inline eT max(uword& index_of_max_val) const;
arma_frown("use .index_min() instead") inline eT min(uword& index_of_min_val) const;
arma_frown("use .index_max() instead") inline eT max(uword& index_of_max_val) const;
inline eT min(uword& row_of_min_val, uword& col_of_min_val) const;
inline eT max(uword& row_of_max_val, uword& col_of_max_val) const;
arma_frown("use .index_min() with ind2sub() instead") inline eT min(uword& row_of_min_val, uword& col_of_min_val) const;
arma_frown("use .index_max() with ind2sub() instead") inline eT max(uword& row_of_max_val, uword& col_of_max_val) const;
arma_cold inline bool save(const std::string name, const file_type type = arma_binary) const;
@@ -771,6 +771,9 @@ class Mat : public Base< eT, Mat<eT> >
inline void steal_mem_col(Mat& X, const uword max_n_rows);
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const; //!< don't use this unless you're writing code internal to Armadillo
template<uword fixed_n_rows, uword fixed_n_cols> class fixed;
@@ -822,6 +825,8 @@ class Mat<eT>::fixed : public Mat<eT>
{
private:
using Mat<eT>::mem_local;
static constexpr uword fixed_n_elem = fixed_n_rows * fixed_n_cols;
static constexpr bool use_extra = (fixed_n_elem > arma_config::mat_prealloc);
+22 -9
View File
@@ -1324,6 +1324,19 @@ Mat<eT>::steal_mem_col(Mat<eT>& x, const uword max_n_rows)
template<typename eT>
template<typename eT2>
arma_inline
bool
Mat<eT>::is_alias(const Mat<eT2>& X) const
{
arma_debug_sigprint();
return (is_same_type<eT,eT2>::yes) && (void_ptr(this) == void_ptr(&X));
}
//! construct a matrix from a given auxiliary array of eTs.
//! if copy_aux_mem is true, new memory is allocated and the array is copied.
//! if copy_aux_mem is false, the auxiliary array is used directly (without allocating memory and copying).
@@ -6378,7 +6391,7 @@ Mat<eT>::at_alt(const uword ii) const
//! linear element accessor (treats the matrix as a vector); bounds checking not done when ARMA_NO_DEBUG is defined
//! linear element accessor (treats the matrix as a vector); bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename eT>
arma_inline
eT&
@@ -6391,7 +6404,7 @@ Mat<eT>::operator() (const uword ii)
//! linear element accessor (treats the matrix as a vector); bounds checking not done when ARMA_NO_DEBUG is defined
//! linear element accessor (treats the matrix as a vector); bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename eT>
arma_inline
const eT&
@@ -6447,7 +6460,7 @@ Mat<eT>::at(const uword ii) const
//! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
//! element accessor; bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename eT>
arma_inline
eT&
@@ -6460,7 +6473,7 @@ Mat<eT>::operator() (const uword in_row, const uword in_col)
//! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
//! element accessor; bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename eT>
arma_inline
const eT&
@@ -9552,11 +9565,11 @@ Mat<eT>::fixed<fixed_n_rows, fixed_n_cols>::fixed(const fill::fill_class<fill_ty
{
arma_debug_sigprint_this(this);
if(is_same_type<fill_type, fill::fill_zeros>::yes) { (*this).zeros(); }
if(is_same_type<fill_type, fill::fill_ones >::yes) { (*this).ones(); }
if(is_same_type<fill_type, fill::fill_eye >::yes) { (*this).eye(); }
if(is_same_type<fill_type, fill::fill_randu>::yes) { (*this).randu(); }
if(is_same_type<fill_type, fill::fill_randn>::yes) { (*this).randn(); }
if(is_same_type<fill_type, fill::fill_zeros>::yes) { (*this).zeros(); }
if(is_same_type<fill_type, fill::fill_ones >::yes) { (*this).ones(); }
if(is_same_type<fill_type, fill::fill_eye >::yes) { Mat<eT>::eye(); }
if(is_same_type<fill_type, fill::fill_randu>::yes) { Mat<eT>::randu(); }
if(is_same_type<fill_type, fill::fill_randn>::yes) { Mat<eT>::randn(); }
}
+3
View File
@@ -58,6 +58,9 @@ class Op
inline Op(const T1& in_m, const uword in_aux_uword_a, const uword in_aux_uword_b);
inline ~Op();
template<typename eT2>
inline bool is_alias(const Mat<eT2>& X) const;
arma_aligned const T1& m; //!< the operand; must be derived from Base
arma_aligned elem_type aux; //!< auxiliary data, using the element type as used by T1
arma_aligned uword aux_uword_a; //!< auxiliary data, uword format
+13
View File
@@ -76,4 +76,17 @@ Op<T1, op_type>::~Op()
template<typename T1, typename op_type>
template<typename eT2>
inline
bool
Op<T1, op_type>::is_alias(const Mat<eT2>& X) const
{
arma_debug_sigprint();
return m.is_alias(X);
}
//! @}
+8 -8
View File
@@ -188,7 +188,7 @@ struct Proxy< Mat<eT> >
arma_inline aligned_ea_type get_aligned_ea() const { return Q; }
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::value) ? (void_ptr(&Q) == void_ptr(&X)) : false; }
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&Q) == void_ptr(&X)); }
template<typename eT2>
arma_inline bool has_overlap(const subview<eT2>& X) const { return is_alias(X.m); }
@@ -235,7 +235,7 @@ struct Proxy< Col<eT> >
arma_inline aligned_ea_type get_aligned_ea() const { return Q; }
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::value) ? (void_ptr(&Q) == void_ptr(&X)) : false; }
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&Q) == void_ptr(&X)); }
template<typename eT2>
arma_inline bool has_overlap(const subview<eT2>& X) const { return is_alias(X.m); }
@@ -282,7 +282,7 @@ struct Proxy< Row<eT> >
arma_inline aligned_ea_type get_aligned_ea() const { return Q; }
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::value) ? (void_ptr(&Q) == void_ptr(&X)) : false; }
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&Q) == void_ptr(&X)); }
template<typename eT2>
arma_inline bool has_overlap(const subview<eT2>& X) const { return is_alias(X.m); }
@@ -1013,7 +1013,7 @@ struct Proxy< subview<eT> >
arma_inline aligned_ea_type get_aligned_ea() const { return Q; }
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::value) ? (void_ptr(&(Q.m)) == void_ptr(&X)) : false; }
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&(Q.m)) == void_ptr(&X)); }
template<typename eT2>
arma_inline bool has_overlap(const subview<eT2>& X) const { return Q.check_overlap(X); }
@@ -1060,7 +1060,7 @@ struct Proxy< subview_col<eT> >
arma_inline aligned_ea_type get_aligned_ea() const { return Q; }
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::value) ? (void_ptr(&(Q.m)) == void_ptr(&X)) : false; }
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&(Q.m)) == void_ptr(&X)); }
template<typename eT2>
arma_inline bool has_overlap(const subview<eT2>& X) const { return Q.check_overlap(X); }
@@ -1109,7 +1109,7 @@ struct Proxy< subview_cols<eT> >
arma_inline aligned_ea_type get_aligned_ea() const { return Q; }
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::value) ? (void_ptr(&(sv.m)) == void_ptr(&X)) : false; }
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&(sv.m)) == void_ptr(&X)); }
template<typename eT2>
arma_inline bool has_overlap(const subview<eT2>& X) const { return sv.check_overlap(X); }
@@ -1156,7 +1156,7 @@ struct Proxy< subview_row<eT> >
arma_inline aligned_ea_type get_aligned_ea() const { return Q; }
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::value) ? (void_ptr(&(Q.m)) == void_ptr(&X)) : false; }
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&(Q.m)) == void_ptr(&X)); }
template<typename eT2>
arma_inline bool has_overlap(const subview<eT2>& X) const { return Q.check_overlap(X); }
@@ -1304,7 +1304,7 @@ struct Proxy< diagview<eT> >
arma_inline aligned_ea_type get_aligned_ea() const { return Q; }
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::value) ? (void_ptr(&(Q.m)) == void_ptr(&X)) : false; }
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&(Q.m)) == void_ptr(&X)); }
template<typename eT2>
arma_inline bool has_overlap(const subview<eT2>& X) const { return is_alias(X.m); }
+2
View File
@@ -187,6 +187,8 @@ class Row<eT>::fixed : public Row<eT>
{
private:
using Mat<eT>::mem_local;
static constexpr bool use_extra = (fixed_n_elem > arma_config::mat_prealloc);
arma_align_mem eT mem_local_extra[ (use_extra) ? fixed_n_elem : 1 ];
+5 -5
View File
@@ -1345,11 +1345,11 @@ Row<eT>::fixed<fixed_n_elem>::fixed(const fill::fill_class<fill_type>&)
{
arma_debug_sigprint_this(this);
if(is_same_type<fill_type, fill::fill_zeros>::yes) { (*this).zeros(); }
if(is_same_type<fill_type, fill::fill_ones >::yes) { (*this).ones(); }
if(is_same_type<fill_type, fill::fill_eye >::yes) { (*this).eye(); }
if(is_same_type<fill_type, fill::fill_randu>::yes) { (*this).randu(); }
if(is_same_type<fill_type, fill::fill_randn>::yes) { (*this).randn(); }
if(is_same_type<fill_type, fill::fill_zeros>::yes) { (*this).zeros(); }
if(is_same_type<fill_type, fill::fill_ones >::yes) { (*this).ones(); }
if(is_same_type<fill_type, fill::fill_eye >::yes) { Mat<eT>::eye(); }
if(is_same_type<fill_type, fill::fill_randu>::yes) { Mat<eT>::randu(); }
if(is_same_type<fill_type, fill::fill_randn>::yes) { Mat<eT>::randn(); }
}
+4 -4
View File
@@ -76,11 +76,11 @@ struct SpBase
arma_warn_unused inline elem_type min() const;
arma_warn_unused inline elem_type max() const;
inline elem_type min(uword& index_of_min_val) const;
inline elem_type max(uword& index_of_max_val) const;
arma_frown("use .index_min() instead") inline elem_type min(uword& index_of_min_val) const;
arma_frown("use .index_max() instead") inline elem_type max(uword& index_of_max_val) const;
inline elem_type min(uword& row_of_min_val, uword& col_of_min_val) const;
inline elem_type max(uword& row_of_max_val, uword& col_of_max_val) const;
arma_frown("use .index_min() with ind2sub() instead") inline elem_type min(uword& row_of_min_val, uword& col_of_min_val) const;
arma_frown("use .index_max() with ind2sub() instead") inline elem_type max(uword& row_of_max_val, uword& col_of_max_val) const;
arma_warn_unused inline uword index_min() const;
arma_warn_unused inline uword index_max() const;
@@ -36,6 +36,9 @@ class SpToDGlue : public Base< typename T1::elem_type, SpToDGlue<T1, T2, glue_ty
inline explicit SpToDGlue(const T1& in_A, const T2& in_B);
inline ~SpToDGlue();
template<typename eT2>
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
const T1& A; //!< first operand; must be derived from Base or SpBase
const T2& B; //!< second operand; must be derived from Base or SpBase
};
+3
View File
@@ -39,6 +39,9 @@ class SpToDOp : public Base< typename T1::elem_type, SpToDOp<T1, op_type> >
inline SpToDOp(const T1& in_m, const uword in_aux_uword_a, const uword in_aux_uword_b);
inline ~SpToDOp();
template<typename eT2>
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
arma_aligned const T1& m; //!< the operand; must be derived from SpBase
arma_aligned elem_type aux; //!< auxiliary data, using the element type as used by T1
arma_aligned uword aux_uword_a; //!< auxiliary data, uword format
+2
View File
@@ -91,6 +91,8 @@ class op_diagmat;
class op_trimat;
class op_vectorise_row;
class op_vectorise_col;
class op_symmatu;
class op_symmatl;
class op_row_as_mat;
class op_col_as_mat;
+3 -3
View File
@@ -22,9 +22,9 @@
#define ARMA_VERSION_MAJOR 14
#define ARMA_VERSION_MINOR 0
#define ARMA_VERSION_PATCH 2
#define ARMA_VERSION_NAME "Stochastic Parrot"
#define ARMA_VERSION_MINOR 2
#define ARMA_VERSION_PATCH 3
#define ARMA_VERSION_NAME "Smooth Caffeine"
+31 -5
View File
@@ -43,6 +43,18 @@ class auxlib
template<typename eT>
inline static bool inv_tr_rcond(Mat<eT>& A, typename get_pod_type<eT>::result& out_rcond, const uword layout);
template<typename eT>
inline static bool inv_sym(Mat<eT>& A);
template<typename T>
inline static bool inv_sym(Mat< std::complex<T> >& A);
template<typename eT>
inline static bool inv_sym_rcond(Mat<eT>& A, eT& out_rcond);
template<typename T>
inline static bool inv_sym_rcond(Mat< std::complex<T> >& A, T& out_rcond);
template<typename eT>
inline static bool inv_sympd(Mat<eT>& A, bool& out_sympd_state);
@@ -50,10 +62,10 @@ class auxlib
inline static bool inv_sympd(Mat<eT>& out, const Mat<eT>& X);
template<typename eT>
inline static bool inv_sympd_rcond(Mat<eT>& A, bool& out_sympd_state, eT& out_rcond);
inline static bool inv_sympd_rcond(Mat<eT>& A, eT& out_rcond);
template<typename T>
inline static bool inv_sympd_rcond(Mat< std::complex<T> >& A, bool& out_sympd_state, T& out_rcond);
inline static bool inv_sympd_rcond(Mat< std::complex<T> >& A, T& out_rcond);
//
@@ -269,6 +281,20 @@ class auxlib
//
template<typename T1>
inline static bool solve_sym_fast(Mat<typename T1::pod_type>& out, Mat<typename T1::pod_type>& A, const Base<typename T1::pod_type,T1>& B_expr);
template<typename T1>
inline static bool solve_sym_fast(Mat< std::complex<typename T1::pod_type> >& out, Mat< std::complex<typename T1::pod_type> >& A, const Base< std::complex<typename T1::pod_type>, T1 >& B_expr);
template<typename T1>
inline static bool solve_sym_rcond(Mat<typename T1::pod_type>& out, typename T1::pod_type& out_rcond, Mat<typename T1::pod_type>& A, const Base<typename T1::pod_type,T1>& B_expr);
template<typename T1>
inline static bool solve_sym_rcond(Mat< std::complex<typename T1::pod_type> >& out, typename T1::pod_type& out_rcond, Mat< std::complex<typename T1::pod_type> >& A, const Base< std::complex<typename T1::pod_type>,T1>& B_expr);
//
template<typename T1>
inline static bool solve_sympd_fast(Mat<typename T1::elem_type>& out, Mat<typename T1::elem_type>& A, const Base<typename T1::elem_type,T1>& B_expr);
@@ -388,10 +414,10 @@ class auxlib
inline static T rcond(Mat< std::complex<T> >& A);
template<typename eT>
inline static eT rcond_sympd(Mat<eT>& A, bool& calc_ok);
inline static eT rcond_sym(Mat<eT>& A);
template<typename T>
inline static T rcond_sympd(Mat< std::complex<T> >& A, bool& calc_ok);
template<typename T>
inline static T rcond_sym(Mat< std::complex<T> >& A);
template<typename eT>
inline static eT rcond_trimat(const Mat<eT>& A, const uword layout);
+714 -63
View File
@@ -28,6 +28,10 @@ auxlib::inv(Mat<eT>& A)
{
arma_debug_sigprint();
// NOTE: given a matrix with NaN values, lapack::getrf() and lapack::getri() do not necessarily fail,
// NOTE: and can produce matrices with NaN values.
// NOTE: we're not checking for non-finite values to avoid breaking existing user code.
if(A.is_empty()) { return true; }
#if defined(ARMA_USE_LAPACK)
@@ -46,7 +50,7 @@ auxlib::inv(Mat<eT>& A)
if(info != 0) { return false; }
if(n > 16)
if(n > blas_int(podarray_prealloc_n_elem::val))
{
eT work_query[2] = {};
blas_int lwork_query = -1;
@@ -130,7 +134,7 @@ auxlib::inv_rcond(Mat<eT>& A, typename get_pod_type<eT>::result& out_rcond)
out_rcond = auxlib::lu_rcond<T>(A, norm_val);
if(n > 16)
if(n > blas_int(podarray_prealloc_n_elem::val))
{
eT work_query[2] = {};
blas_int lwork_query = -1;
@@ -242,6 +246,316 @@ auxlib::inv_tr_rcond(Mat<eT>& A, typename get_pod_type<eT>::result& out_rcond, c
template<typename eT>
inline
bool
auxlib::inv_sym(Mat<eT>& A)
{
arma_debug_sigprint();
if(A.is_empty()) { return true; }
#if defined(ARMA_USE_LAPACK)
{
arma_conform_assert_blas_size(A);
char uplo = 'L';
blas_int n = blas_int(A.n_rows);
blas_int lda = blas_int(A.n_rows);
blas_int lwork = (std::max)(blas_int(podarray_prealloc_n_elem::val), n);
blas_int info = 0;
podarray<blas_int> ipiv(A.n_rows);
if(n > blas_int(podarray_prealloc_n_elem::val))
{
eT work_query[2] = {};
blas_int lwork_query = -1;
arma_debug_print("lapack::sytrf()");
lapack::sytrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &work_query[0], &lwork_query, &info);
if(info != 0) { return false; }
blas_int lwork_proposed = static_cast<blas_int>( access::tmp_real(work_query[0]) );
lwork = (std::max)(lwork_proposed, lwork);
}
podarray<eT> work( static_cast<uword>(lwork) );
arma_debug_print("lapack::sytrf()");
lapack::sytrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &lwork, &info);
if(info != 0) { return false; }
arma_debug_print("lapack::sytri()");
lapack::sytri(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &info);
if(info != 0) { return false; }
A = symmatl(A);
return true;
}
#else
{
arma_ignore(A);
arma_stop_logic_error("inv_sym(): use of LAPACK must be enabled");
return false;
}
#endif
}
template<typename T>
inline
bool
auxlib::inv_sym(Mat< std::complex<T> >& A)
{
arma_debug_sigprint();
// NOTE: the function name is required for overloading, but is a misnomer: it processes complex hermitian matrices
if(A.is_empty()) { return true; }
#if defined(ARMA_CRIPPLED_LAPACK)
{
arma_debug_print("auxlib::inv_sym(): redirecting to auxlib::inv() due to crippled LAPACK");
return auxlib::inv(A);
}
#elif defined(ARMA_USE_LAPACK)
{
typedef typename std::complex<T> eT;
arma_conform_assert_blas_size(A);
char uplo = 'L';
blas_int n = blas_int(A.n_rows);
blas_int lda = blas_int(A.n_rows);
blas_int lwork = (std::max)(blas_int(podarray_prealloc_n_elem::val), n);
blas_int info = 0;
podarray<blas_int> ipiv(A.n_rows);
if(n > blas_int(podarray_prealloc_n_elem::val))
{
eT work_query[2] = {};
blas_int lwork_query = -1;
arma_debug_print("lapack::hetrf()");
lapack::hetrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &work_query[0], &lwork_query, &info);
if(info != 0) { return false; }
blas_int lwork_proposed = static_cast<blas_int>( access::tmp_real(work_query[0]) );
lwork = (std::max)(lwork_proposed, lwork);
}
podarray<eT> work( static_cast<uword>(lwork) );
arma_debug_print("lapack::hetrf()");
lapack::hetrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &lwork, &info);
if(info != 0) { return false; }
arma_debug_print("lapack::hetri()");
lapack::hetri(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &info);
if(info != 0) { return false; }
A = symmatl(A);
return true;
}
#else
{
arma_ignore(A);
arma_stop_logic_error("inv_sym(): use of LAPACK must be enabled");
return false;
}
#endif
}
template<typename eT>
inline
bool
auxlib::inv_sym_rcond(Mat<eT>& A, eT& out_rcond)
{
arma_debug_sigprint();
out_rcond = eT(0);
if(A.is_empty()) { return true; }
#if defined(ARMA_USE_LAPACK)
{
arma_conform_assert_blas_size(A);
char norm_id = '1';
char uplo = 'L';
blas_int n = blas_int(A.n_rows);
blas_int lda = blas_int(A.n_rows);
blas_int lwork = (std::max)(blas_int(podarray_prealloc_n_elem::val), 2*n); // 2*n due to lapack::sycon() requirements
blas_int info = 0;
eT norm_val = eT(0);
eT tmp_rcond = eT(0);
podarray<blas_int> ipiv(A.n_rows);
podarray<blas_int> iwork(A.n_rows);
if( (2*n) > blas_int(podarray_prealloc_n_elem::val) )
{
eT work_query[2] = {};
blas_int lwork_query = -1;
arma_debug_print("lapack::sytrf()");
lapack::sytrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &work_query[0], &lwork_query, &info);
if(info != 0) { return false; }
blas_int lwork_proposed = static_cast<blas_int>( access::tmp_real(work_query[0]) );
lwork = (std::max)(lwork_proposed, lwork);
}
podarray<eT> work( static_cast<uword>(lwork) );
arma_debug_print("lapack::lansy()");
norm_val = (has_blas_float_bug<eT>::value) ? auxlib::norm1_sym(A) : lapack::lansy(&norm_id, &uplo, &n, A.memptr(), &lda, work.memptr());
arma_debug_print("lapack::sytrf()");
lapack::sytrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &lwork, &info);
if(info != 0) { return false; }
arma_debug_print("lapack::sycon()");
lapack::sycon(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &norm_val, &tmp_rcond, work.memptr(), iwork.memptr(), &info);
if(info != 0) { return false; }
out_rcond = tmp_rcond;
if(arma_isnan(out_rcond)) { return false; }
arma_debug_print("lapack::sytri()");
lapack::sytri(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &info);
if(info != 0) { return false; }
A = symmatl(A);
return true;
}
#else
{
arma_ignore(A);
arma_ignore(out_rcond);
arma_stop_logic_error("inv_sym_rcond(): use of LAPACK must be enabled");
return false;
}
#endif
}
template<typename T>
inline
bool
auxlib::inv_sym_rcond(Mat< std::complex<T> >& A, T& out_rcond)
{
arma_debug_sigprint();
// NOTE: the function name is required for overloading, but is a misnomer: it processes complex hermitian matrices
out_rcond = T(0);
if(A.is_empty()) { return true; }
#if defined(ARMA_CRIPPLED_LAPACK)
{
arma_debug_print("auxlib::inv_sym_rcond(): redirecting to auxlib::inv_rcond() due to crippled LAPACK");
return auxlib::inv_rcond(A, out_rcond);
}
#elif defined(ARMA_USE_LAPACK)
{
typedef typename std::complex<T> eT;
arma_conform_assert_blas_size(A);
char norm_id = '1';
char uplo = 'L';
blas_int n = blas_int(A.n_rows);
blas_int lda = blas_int(A.n_rows);
blas_int lwork = (std::max)(blas_int(podarray_prealloc_n_elem::val), 2*n); // 2*n due to lapack::hecon() requirements
blas_int info = 0;
T norm_val = T(0);
T tmp_rcond = T(0);
podarray<blas_int> ipiv(A.n_rows);
podarray<T> lanhe_work(A.n_rows);
if( (2*n) > blas_int(podarray_prealloc_n_elem::val) )
{
eT work_query[2] = {};
blas_int lwork_query = -1;
arma_debug_print("lapack::hetrf()");
lapack::hetrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &work_query[0], &lwork_query, &info);
if(info != 0) { return false; }
blas_int lwork_proposed = static_cast<blas_int>( access::tmp_real(work_query[0]) );
lwork = (std::max)(lwork_proposed, lwork);
}
podarray<eT> work( static_cast<uword>(lwork) );
arma_debug_print("lapack::lanhe()");
norm_val = (has_blas_float_bug<T>::value) ? auxlib::norm1_sym(A) : lapack::lanhe(&norm_id, &uplo, &n, A.memptr(), &lda, lanhe_work.memptr());
arma_debug_print("lapack::hetrf()");
lapack::hetrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &lwork, &info);
if(info != 0) { return false; }
arma_debug_print("lapack::hecon()");
lapack::hecon(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &norm_val, &tmp_rcond, work.memptr(), &info);
if(info != 0) { return false; }
out_rcond = tmp_rcond;
if(arma_isnan(out_rcond)) { return false; }
arma_debug_print("lapack::hetri()");
lapack::hetri(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &info);
if(info != 0) { return false; }
A = symmatl(A);
return true;
}
#else
{
arma_ignore(A);
arma_ignore(out_rcond);
arma_stop_logic_error("inv_sym_rcond(): use of LAPACK must be enabled");
return false;
}
#endif
}
template<typename eT>
inline
bool
@@ -310,12 +624,10 @@ auxlib::inv_sympd(Mat<eT>& out, const Mat<eT>& X)
template<typename eT>
inline
bool
auxlib::inv_sympd_rcond(Mat<eT>& A, bool& out_sympd_state, eT& out_rcond)
auxlib::inv_sympd_rcond(Mat<eT>& A, eT& out_rcond)
{
arma_debug_sigprint();
out_sympd_state = false;
if(A.is_empty()) { return true; }
#if defined(ARMA_USE_LAPACK)
@@ -340,8 +652,6 @@ auxlib::inv_sympd_rcond(Mat<eT>& A, bool& out_sympd_state, eT& out_rcond)
if(info != 0) { out_rcond = eT(0); return false; }
out_sympd_state = true;
out_rcond = auxlib::lu_rcond_sympd<T>(A, norm_val);
if(arma_isnan(out_rcond)) { return false; }
@@ -358,7 +668,6 @@ auxlib::inv_sympd_rcond(Mat<eT>& A, bool& out_sympd_state, eT& out_rcond)
#else
{
arma_ignore(A);
arma_ignore(out_sympd_state);
arma_ignore(out_rcond);
arma_stop_logic_error("inv_sympd_rcond(): use LAPACK must be enabled");
return false;
@@ -371,18 +680,15 @@ auxlib::inv_sympd_rcond(Mat<eT>& A, bool& out_sympd_state, eT& out_rcond)
template<typename T>
inline
bool
auxlib::inv_sympd_rcond(Mat< std::complex<T> >& A, bool& out_sympd_state, T& out_rcond)
auxlib::inv_sympd_rcond(Mat< std::complex<T> >& A, T& out_rcond)
{
arma_debug_sigprint();
out_sympd_state = false;
if(A.is_empty()) { return true; }
#if defined(ARMA_CRIPPLED_LAPACK)
{
arma_ignore(A);
arma_ignore(out_sympd_state);
arma_ignore(out_rcond);
return false;
}
@@ -406,8 +712,6 @@ auxlib::inv_sympd_rcond(Mat< std::complex<T> >& A, bool& out_sympd_state, T& out
if(info != 0) { out_rcond = T(0); return false; }
out_sympd_state = true;
out_rcond = auxlib::lu_rcond_sympd<T>(A, norm_val);
if(arma_isnan(out_rcond)) { return false; }
@@ -424,7 +728,6 @@ auxlib::inv_sympd_rcond(Mat< std::complex<T> >& A, bool& out_sympd_state, T& out
#else
{
arma_ignore(A);
arma_ignore(out_sympd_state);
arma_ignore(out_rcond);
arma_stop_logic_error("inv_sympd_rcond(): use LAPACK must be enabled");
return false;
@@ -4262,6 +4565,328 @@ auxlib::solve_square_refine(Mat< std::complex<typename T1::pod_type> >& out, typ
template<typename T1>
inline
bool
auxlib::solve_sym_fast(Mat<typename T1::pod_type>& out, Mat<typename T1::pod_type>& A, const Base<typename T1::pod_type,T1>& B_expr)
{
arma_debug_sigprint();
out = B_expr.get_ref();
const uword B_n_rows = out.n_rows;
const uword B_n_cols = out.n_cols;
arma_conform_check( (A.n_rows != B_n_rows), "solve(): number of rows in given matrices must be the same", [&](){ out.soft_reset(); } );
if(A.is_empty() || out.is_empty()) { out.zeros(A.n_cols, B_n_cols); return true; }
#if defined(ARMA_USE_LAPACK)
{
typedef typename T1::pod_type eT;
arma_conform_assert_blas_size(A,out);
char uplo = 'L';
blas_int n = blas_int(A.n_rows);
blas_int lda = blas_int(A.n_rows);
blas_int ldb = blas_int(out.n_rows);
blas_int nrhs = blas_int(out.n_cols);
blas_int lwork = (std::max)(blas_int(podarray_prealloc_n_elem::val), n);
blas_int info = 0;
podarray<blas_int> ipiv(A.n_rows);
if(n > blas_int(podarray_prealloc_n_elem::val))
{
eT work_query[2] = {};
blas_int lwork_query = -1;
arma_debug_print("lapack::sytrf()");
lapack::sytrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &work_query[0], &lwork_query, &info);
if(info != 0) { return false; }
blas_int lwork_proposed = static_cast<blas_int>( access::tmp_real(work_query[0]) );
lwork = (std::max)(lwork_proposed, lwork);
}
podarray<eT> work( static_cast<uword>(lwork) );
arma_debug_print("lapack::sytrf()");
lapack::sytrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &lwork, &info);
if(info != 0) { return false; }
arma_debug_print("lapack::sytrs()");
lapack::sytrs(&uplo, &n, &nrhs, A.memptr(), &lda, ipiv.memptr(), out.memptr(), &ldb, &info);
return (info == 0);
}
#else
{
arma_stop_logic_error("solve(): use of LAPACK must be enabled");
return false;
}
#endif
}
template<typename T1>
inline
bool
auxlib::solve_sym_fast(Mat< std::complex<typename T1::pod_type> >& out, Mat< std::complex<typename T1::pod_type> >& A, const Base< std::complex<typename T1::pod_type>, T1 >& B_expr)
{
arma_debug_sigprint();
out = B_expr.get_ref();
const uword B_n_rows = out.n_rows;
const uword B_n_cols = out.n_cols;
arma_conform_check( (A.n_rows != B_n_rows), "solve(): number of rows in given matrices must be the same", [&](){ out.soft_reset(); } );
if(A.is_empty() || out.is_empty()) { out.zeros(A.n_cols, B_n_cols); return true; }
#if defined(ARMA_CRIPPLED_LAPACK)
{
arma_debug_print("auxlib::solve_sym_fast(): redirecting to auxlib::solve_square_fast() due to crippled LAPACK");
return auxlib::solve_square_fast(out, A, B_expr);
}
#elif defined(ARMA_USE_LAPACK)
{
typedef typename T1::pod_type T;
typedef std::complex<T> eT;
arma_conform_assert_blas_size(A,out);
char uplo = 'L';
blas_int n = blas_int(A.n_rows);
blas_int lda = blas_int(A.n_rows);
blas_int ldb = blas_int(out.n_rows);
blas_int nrhs = blas_int(out.n_cols);
blas_int lwork = (std::max)(blas_int(podarray_prealloc_n_elem::val), n);
blas_int info = 0;
podarray<blas_int> ipiv(A.n_rows);
if(n > blas_int(podarray_prealloc_n_elem::val))
{
eT work_query[2] = {};
blas_int lwork_query = -1;
arma_debug_print("lapack::hetrf()");
lapack::hetrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &work_query[0], &lwork_query, &info);
if(info != 0) { return false; }
blas_int lwork_proposed = static_cast<blas_int>( access::tmp_real(work_query[0]) );
lwork = (std::max)(lwork_proposed, lwork);
}
podarray<eT> work( static_cast<uword>(lwork) );
arma_debug_print("lapack::hetrf()");
lapack::hetrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &lwork, &info);
if(info != 0) { return false; }
arma_debug_print("lapack::hetrs()");
lapack::hetrs(&uplo, &n, &nrhs, A.memptr(), &lda, ipiv.memptr(), out.memptr(), &ldb, &info);
return (info == 0);
}
#else
{
arma_stop_logic_error("solve(): use of LAPACK must be enabled");
return false;
}
#endif
}
template<typename T1>
inline
bool
auxlib::solve_sym_rcond(Mat<typename T1::pod_type>& out, typename T1::pod_type& out_rcond, Mat<typename T1::pod_type>& A, const Base<typename T1::pod_type,T1>& B_expr)
{
arma_debug_sigprint();
out = B_expr.get_ref();
const uword B_n_rows = out.n_rows;
const uword B_n_cols = out.n_cols;
arma_conform_check( (A.n_rows != B_n_rows), "solve(): number of rows in given matrices must be the same", [&](){ out.soft_reset(); } );
if(A.is_empty() || out.is_empty()) { out.zeros(A.n_cols, B_n_cols); return true; }
#if defined(ARMA_CRIPPLED_LAPACK)
{
arma_debug_print("auxlib::solve_sym_rcond(): redirecting to auxlib::solve_square_rcond() due to crippled LAPACK");
return auxlib::solve_square_rcond(out, out_rcond, A, B_expr);
}
#elif defined(ARMA_USE_LAPACK)
{
typedef typename T1::pod_type eT;
out_rcond = eT(0);
arma_conform_assert_blas_size(A,out);
char norm_id = '1';
char uplo = 'L';
blas_int n = blas_int(A.n_rows);
blas_int lda = blas_int(A.n_rows);
blas_int ldb = blas_int(out.n_rows);
blas_int nrhs = blas_int(out.n_cols);
blas_int lwork = (std::max)(blas_int(podarray_prealloc_n_elem::val), 2*n); // 2*n due to lapack::sycon() requirements
blas_int info = 0;
eT norm_val = eT(0);
eT tmp_rcond = eT(0);
podarray<blas_int> ipiv(A.n_rows);
podarray<blas_int> iwork(A.n_rows);
if( (2*n) > blas_int(podarray_prealloc_n_elem::val) )
{
eT work_query[2] = {};
blas_int lwork_query = -1;
arma_debug_print("lapack::sytrf()");
lapack::sytrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &work_query[0], &lwork_query, &info);
if(info != 0) { return false; }
blas_int lwork_proposed = static_cast<blas_int>( access::tmp_real(work_query[0]) );
lwork = (std::max)(lwork_proposed, lwork);
}
podarray<eT> work( static_cast<uword>(lwork) );
arma_debug_print("lapack::lansy()");
norm_val = (has_blas_float_bug<eT>::value) ? auxlib::norm1_sym(A) : lapack::lansy(&norm_id, &uplo, &n, A.memptr(), &n, work.memptr());
arma_debug_print("lapack::sytrf()");
lapack::sytrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &lwork, &info);
if(info != 0) { return false; }
arma_debug_print("lapack::sytrs()");
lapack::sytrs(&uplo, &n, &nrhs, A.memptr(), &lda, ipiv.memptr(), out.memptr(), &ldb, &info);
if(info != 0) { return false; }
arma_debug_print("lapack::sycon()");
lapack::sycon(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &norm_val, &tmp_rcond, work.memptr(), iwork.memptr(), &info);
out_rcond = tmp_rcond;
return (info == 0);
}
#else
{
arma_stop_logic_error("solve(): use of LAPACK must be enabled");
return false;
}
#endif
}
template<typename T1>
inline
bool
auxlib::solve_sym_rcond(Mat< std::complex<typename T1::pod_type> >& out, typename T1::pod_type& out_rcond, Mat< std::complex<typename T1::pod_type> >& A, const Base< std::complex<typename T1::pod_type>,T1>& B_expr)
{
arma_debug_sigprint();
out = B_expr.get_ref();
const uword B_n_rows = out.n_rows;
const uword B_n_cols = out.n_cols;
arma_conform_check( (A.n_rows != B_n_rows), "solve(): number of rows in given matrices must be the same", [&](){ out.soft_reset(); } );
if(A.is_empty() || out.is_empty()) { out.zeros(A.n_cols, B_n_cols); return true; }
#if defined(ARMA_USE_LAPACK)
{
typedef typename T1::pod_type T;
typedef typename std::complex<T> eT;
out_rcond = T(0);
arma_conform_assert_blas_size(A,out);
char norm_id = '1';
char uplo = 'L';
blas_int n = blas_int(A.n_rows);
blas_int lda = blas_int(A.n_rows);
blas_int ldb = blas_int(out.n_rows);
blas_int nrhs = blas_int(out.n_cols);
blas_int lwork = (std::max)(blas_int(podarray_prealloc_n_elem::val), 2*n); // 2*n due to lapack::hecon() requirements
blas_int info = 0;
T norm_val = T(0);
T tmp_rcond = T(0);
podarray<blas_int> ipiv(A.n_rows);
podarray<T> lanhe_work(A.n_rows);
if( (2*n) > blas_int(podarray_prealloc_n_elem::val) )
{
eT work_query[2] = {};
blas_int lwork_query = -1;
arma_debug_print("lapack::hetrf()");
lapack::hetrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &work_query[0], &lwork_query, &info);
if(info != 0) { return false; }
blas_int lwork_proposed = static_cast<blas_int>( access::tmp_real(work_query[0]) );
lwork = (std::max)(lwork_proposed, lwork);
}
podarray<eT> work( static_cast<uword>(lwork) );
arma_debug_print("lapack::lanhe()");
norm_val = (has_blas_float_bug<T>::value) ? auxlib::norm1_sym(A) : lapack::lanhe(&norm_id, &uplo, &n, A.memptr(), &lda, lanhe_work.memptr());
arma_debug_print("lapack::hetrf()");
lapack::hetrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &lwork, &info);
if(info != 0) { return false; }
arma_debug_print("lapack::hetrs()");
lapack::hetrs(&uplo, &n, &nrhs, A.memptr(), &lda, ipiv.memptr(), out.memptr(), &ldb, &info);
if(info != 0) { return false; }
arma_debug_print("lapack::hecon()");
lapack::hecon(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &norm_val, &tmp_rcond, work.memptr(), &info);
out_rcond = tmp_rcond;
return (info == 0);
}
#else
{
arma_stop_logic_error("solve(): use of LAPACK must be enabled");
return false;
}
#endif
}
template<typename T1>
inline
bool
@@ -6189,47 +6814,60 @@ auxlib::rcond(Mat< std::complex<T> >& A)
template<typename eT>
inline
eT
auxlib::rcond_sympd(Mat<eT>& A, bool& calc_ok)
auxlib::rcond_sym(Mat<eT>& A)
{
#if defined(ARMA_USE_LAPACK)
{
arma_conform_assert_blas_size(A);
calc_ok = false;
char norm_id = '1';
char uplo = 'L';
blas_int n = blas_int(A.n_rows);
blas_int lda = blas_int(A.n_rows);
blas_int lwork = (std::max)(blas_int(podarray_prealloc_n_elem::val), 2*n); // 2*n due to lapack::sycon() requirements
blas_int info = 0;
eT norm_val = eT(0);
eT out_rcond = eT(0);
char norm_id = '1';
char uplo = 'L';
blas_int n = blas_int(A.n_rows); // assuming square matrix
blas_int lda = blas_int(A.n_rows);
eT norm_val = eT(0);
eT rcond = eT(0);
blas_int info = blas_int(0);
podarray<blas_int> ipiv(A.n_rows);
podarray<blas_int> iwork(A.n_rows);
podarray<eT> work(3*A.n_rows);
podarray<blas_int> iwork( A.n_rows);
if( (2*n) > blas_int(podarray_prealloc_n_elem::val) )
{
eT work_query[2] = {};
blas_int lwork_query = -1;
arma_debug_print("lapack::sytrf()");
lapack::sytrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &work_query[0], &lwork_query, &info);
if(info != 0) { return eT(0); }
blas_int lwork_proposed = static_cast<blas_int>( access::tmp_real(work_query[0]) );
lwork = (std::max)(lwork_proposed, lwork);
}
podarray<eT> work( static_cast<uword>(lwork) );
arma_debug_print("lapack::lansy()");
norm_val = (has_blas_float_bug<eT>::value) ? auxlib::norm1_sym(A) : lapack::lansy(&norm_id, &uplo, &n, A.memptr(), &lda, work.memptr());
arma_debug_print("lapack::potrf()");
lapack::potrf(&uplo, &n, A.memptr(), &lda, &info);
arma_debug_print("lapack::sytrf()");
lapack::sytrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &lwork, &info);
if(info != blas_int(0)) { return eT(0); }
if(info != 0) { return eT(0); }
arma_debug_print("lapack::pocon()");
lapack::pocon(&uplo, &n, A.memptr(), &lda, &norm_val, &rcond, work.memptr(), iwork.memptr(), &info);
arma_debug_print("lapack::sycon()");
lapack::sycon(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &norm_val, &out_rcond, work.memptr(), iwork.memptr(), &info);
if(info != blas_int(0)) { return eT(0); }
if(info != 0) { return eT(0); }
calc_ok = true;
return rcond;
return out_rcond;
}
#else
{
arma_ignore(A);
calc_ok = false;
arma_stop_logic_error("rcond(): use of LAPACK must be enabled");
arma_stop_logic_error("rcond_sym(): use of LAPACK must be enabled");
return eT(0);
}
#endif
@@ -6240,13 +6878,13 @@ auxlib::rcond_sympd(Mat<eT>& A, bool& calc_ok)
template<typename T>
inline
T
auxlib::rcond_sympd(Mat< std::complex<T> >& A, bool& calc_ok)
auxlib::rcond_sym(Mat< std::complex<T> >& A)
{
// NOTE: the function name is required for overloading, but is a misnomer: it processes complex hermitian matrices
#if defined(ARMA_CRIPPLED_LAPACK)
{
arma_debug_print("auxlib::rcond_sympd(): redirecting to auxlib::rcond() due to crippled LAPACK");
calc_ok = true;
arma_debug_print("auxlib::rcond_sym(): redirecting to auxlib::rcond() due to crippled LAPACK");
return auxlib::rcond(A);
}
@@ -6256,41 +6894,54 @@ auxlib::rcond_sympd(Mat< std::complex<T> >& A, bool& calc_ok)
arma_conform_assert_blas_size(A);
calc_ok = false;
char norm_id = '1';
char uplo = 'L';
blas_int n = blas_int(A.n_rows);
blas_int lda = blas_int(A.n_rows);
blas_int lwork = (std::max)(blas_int(podarray_prealloc_n_elem::val), 2*n); // 2*n due to lapack::hecon() requirements
blas_int info = 0;
T norm_val = T(0);
T out_rcond = T(0);
char norm_id = '1';
char uplo = 'L';
blas_int n = blas_int(A.n_rows); // assuming square matrix
blas_int lda = blas_int(A.n_rows);
T norm_val = T(0);
T rcond = T(0);
blas_int info = blas_int(0);
podarray<blas_int> ipiv(A.n_rows);
podarray<T> lanhe_work(A.n_rows);
podarray<eT> work(2*A.n_rows);
podarray< T> rwork( A.n_rows);
if( (2*n) > blas_int(podarray_prealloc_n_elem::val) )
{
eT work_query[2] = {};
blas_int lwork_query = -1;
arma_debug_print("lapack::hetrf()");
lapack::hetrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &work_query[0], &lwork_query, &info);
if(info != 0) { return T(0); }
blas_int lwork_proposed = static_cast<blas_int>( access::tmp_real(work_query[0]) );
lwork = (std::max)(lwork_proposed, lwork);
}
podarray<eT> work( static_cast<uword>(lwork) );
arma_debug_print("lapack::lanhe()");
norm_val = (has_blas_float_bug<eT>::value) ? auxlib::norm1_sym(A) : lapack::lanhe(&norm_id, &uplo, &n, A.memptr(), &lda, rwork.memptr());
norm_val = (has_blas_float_bug<T>::value) ? auxlib::norm1_sym(A) : lapack::lanhe(&norm_id, &uplo, &n, A.memptr(), &lda, lanhe_work.memptr());
arma_debug_print("lapack::potrf()");
lapack::potrf(&uplo, &n, A.memptr(), &lda, &info);
arma_debug_print("lapack::hetrf()");
lapack::hetrf(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), work.memptr(), &lwork, &info);
if(info != blas_int(0)) { return T(0); }
if(info != 0) { return T(0); }
arma_debug_print("lapack::cx_pocon()");
lapack::cx_pocon(&uplo, &n, A.memptr(), &lda, &norm_val, &rcond, work.memptr(), rwork.memptr(), &info);
arma_debug_print("lapack::hecon()");
lapack::hecon(&uplo, &n, A.memptr(), &lda, ipiv.memptr(), &norm_val, &out_rcond, work.memptr(), &info);
if(info != blas_int(0)) { return T(0); }
if(info != 0) { return T(0); }
calc_ok = true;
return rcond;
return out_rcond;
}
#else
{
arma_ignore(A);
calc_ok = false;
arma_stop_logic_error("rcond(): use of LAPACK must be enabled");
arma_stop_logic_error("rcond_sym(): use of LAPACK must be enabled");
return T(0);
}
#endif
+2 -4
View File
@@ -83,10 +83,8 @@
#endif
#if (!defined(ARMA_HAVE_CXX14))
#if (!defined(ARMA_IGNORE_DEPRECATED_MARKER)) || defined(ARMA_DONT_IGNORE_DEPRECATED_MARKER) || defined(ARMA_DEBUG)
#pragma message ("INFO: support for C++11 is deprecated")
#endif
#if (!defined(ARMA_HAVE_CXX14)) && (!defined(ARMA_IGNORE_DEPRECATED_MARKER))
#pragma message ("INFO: support for C++11 is deprecated; minimum recommended standard is C++14")
#endif
+8 -5
View File
@@ -168,6 +168,10 @@
// gcc 6.1 has proper C++14 support and fixes an OpenMP related bug:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57580
#if (ARMA_GCC_VERSION < 80100)
#pragma message("INFO: support for GCC versions older than 8.1 is deprecated")
#endif
#define ARMA_GOOD_COMPILER
#undef arma_hot
@@ -310,7 +314,7 @@
#if defined(_MSC_VER)
#if (_MSC_VER < 1900)
#if (_MSC_VER < 1910)
#error "*** newer compiler required ***"
#endif
@@ -473,11 +477,10 @@
#undef major
// optionally allow disabling of compile-time deprecation messages (not recommended)
// NOTE: option 'ARMA_IGNORE_DEPRECATED_MARKER' will be removed
// NOTE: disabling deprecation messages is counter-productive
// WARNING: option 'ARMA_IGNORE_DEPRECATED_MARKER' will be removed;
// WARNING: disabling deprecation messages is counter-productive
#if defined(ARMA_IGNORE_DEPRECATED_MARKER) && (!defined(ARMA_DONT_IGNORE_DEPRECATED_MARKER)) && (!defined(ARMA_DEBUG))
#if defined(ARMA_IGNORE_DEPRECATED_MARKER)
#undef arma_deprecated
#define arma_deprecated
+23 -5
View File
@@ -102,11 +102,8 @@
//// Uncomment the above line if your BLAS and LAPACK libraries have function names with a trailing underscore.
//// Conversely, comment it out if the function names don't have a trailing underscore.
// #define ARMA_BLAS_LONG
//// Uncomment the above line if your BLAS and LAPACK libraries use "long" instead of "int"
// #define ARMA_BLAS_LONG_LONG
//// Uncomment the above line if your BLAS and LAPACK libraries use "long long" instead of "int"
//// Uncomment the above line if your BLAS and LAPACK libraries use 64 bit integers, ie. "long long" instead of "int"
// #define ARMA_BLAS_NOEXCEPT
//// Uncomment the above line if you require BLAS functions to have the 'noexcept' specification
@@ -131,7 +128,7 @@
//// Uncomment the above line to use Intel MKL types for complex numbers.
//// You will need to include appropriate MKL headers before the Armadillo header.
//// You may also need to enable or disable the following options:
//// ARMA_BLAS_LONG, ARMA_BLAS_LONG_LONG, ARMA_USE_FORTRAN_HIDDEN_ARGS
//// ARMA_BLAS_LONG_LONG, ARMA_USE_FORTRAN_HIDDEN_ARGS
#if !defined(ARMA_USE_OPENMP)
// #define ARMA_USE_OPENMP
@@ -306,6 +303,12 @@
#undef ARMA_64BIT_WORD
#endif
// for compatibility with earlier versions of Armadillo
#if defined(ARMA_BLAS_LONG) || defined(ARMA_BLAS_LONG_LONG)
#undef ARMA_BLAS_64BIT_INT
#define ARMA_BLAS_64BIT_INT
#endif
#if defined(ARMA_DONT_OPTIMISE_BAND) || defined(ARMA_DONT_OPTIMISE_SOLVE_BAND)
#undef ARMA_OPTIMISE_BAND
#endif
@@ -330,6 +333,10 @@
#undef ARMA_CHECK_NONFINITE
#endif
#if defined(ARMA_DONT_IGNORE_DEPRECATED_MARKER)
#undef ARMA_IGNORE_DEPRECATED_MARKER
#endif
#if defined(ARMA_NO_DEBUG)
#undef ARMA_DEBUG
#undef ARMA_EXTRA_DEBUG
@@ -347,6 +354,8 @@
#undef ARMA_WARN_LEVEL
#define ARMA_WARN_LEVEL 3
#undef ARMA_IGNORE_DEPRECATED_MARKER
#endif
#if defined(ARMA_DONT_PRINT_EXCEPTIONS)
@@ -357,6 +366,15 @@
#undef ARMA_CRIPPLED_LAPACK
#endif
// WARNING: option ARMA_IGNORE_DEPRECATED_MARKER will be removed
// WARNING: option ARMA_CRIPPLED_LAPACK will be removed
#if defined(ARMA_CRIPPLED_LAPACK)
#if (!defined(ARMA_IGNORE_DEPRECATED_MARKER))
#pragma message ("option ARMA_CRIPPLED_LAPACK is deprecated and will be removed")
#endif
#endif
// if Armadillo was installed on this system via CMake and ARMA_USE_WRAPPER is not defined,
// ARMA_AUX_LIBS lists the libraries required by Armadillo on this system, and
+23 -5
View File
@@ -102,11 +102,8 @@
//// Uncomment the above line if your BLAS and LAPACK libraries have function names with a trailing underscore.
//// Conversely, comment it out if the function names don't have a trailing underscore.
// #define ARMA_BLAS_LONG
//// Uncomment the above line if your BLAS and LAPACK libraries use "long" instead of "int"
// #define ARMA_BLAS_LONG_LONG
//// Uncomment the above line if your BLAS and LAPACK libraries use "long long" instead of "int"
//// Uncomment the above line if your BLAS and LAPACK libraries use 64 bit integers, ie. "long long" instead of "int"
// #define ARMA_BLAS_NOEXCEPT
//// Uncomment the above line if you require BLAS functions to have the 'noexcept' specification
@@ -131,7 +128,7 @@
//// Uncomment the above line to use Intel MKL types for complex numbers.
//// You will need to include appropriate MKL headers before the Armadillo header.
//// You may also need to enable or disable the following options:
//// ARMA_BLAS_LONG, ARMA_BLAS_LONG_LONG, ARMA_USE_FORTRAN_HIDDEN_ARGS
//// ARMA_BLAS_LONG_LONG, ARMA_USE_FORTRAN_HIDDEN_ARGS
#if !defined(ARMA_USE_OPENMP)
// #define ARMA_USE_OPENMP
@@ -306,6 +303,12 @@
#undef ARMA_64BIT_WORD
#endif
// for compatibility with earlier versions of Armadillo
#if defined(ARMA_BLAS_LONG) || defined(ARMA_BLAS_LONG_LONG)
#undef ARMA_BLAS_64BIT_INT
#define ARMA_BLAS_64BIT_INT
#endif
#if defined(ARMA_DONT_OPTIMISE_BAND) || defined(ARMA_DONT_OPTIMISE_SOLVE_BAND)
#undef ARMA_OPTIMISE_BAND
#endif
@@ -330,6 +333,10 @@
#undef ARMA_CHECK_NONFINITE
#endif
#if defined(ARMA_DONT_IGNORE_DEPRECATED_MARKER)
#undef ARMA_IGNORE_DEPRECATED_MARKER
#endif
#if defined(ARMA_NO_DEBUG)
#undef ARMA_DEBUG
#undef ARMA_EXTRA_DEBUG
@@ -347,6 +354,8 @@
#undef ARMA_WARN_LEVEL
#define ARMA_WARN_LEVEL 3
#undef ARMA_IGNORE_DEPRECATED_MARKER
#endif
#if defined(ARMA_DONT_PRINT_EXCEPTIONS)
@@ -357,6 +366,15 @@
#undef ARMA_CRIPPLED_LAPACK
#endif
// WARNING: option ARMA_IGNORE_DEPRECATED_MARKER will be removed
// WARNING: option ARMA_CRIPPLED_LAPACK will be removed
#if defined(ARMA_CRIPPLED_LAPACK)
#if (!defined(ARMA_IGNORE_DEPRECATED_MARKER))
#pragma message ("option ARMA_CRIPPLED_LAPACK is deprecated and will be removed")
#endif
#endif
// if Armadillo was installed on this system via CMake and ARMA_USE_WRAPPER is not defined,
// ARMA_AUX_LIBS lists the libraries required by Armadillo on this system, and
+112
View File
@@ -269,6 +269,30 @@
#define arma_cpstrf cpstrf
#define arma_zpstrf zpstrf
#define arma_ssytrf ssytrf
#define arma_dsytrf dsytrf
#define arma_chetrf chetrf
#define arma_zhetrf zhetrf
#define arma_ssytrs ssytrs
#define arma_dsytrs dsytrs
#define arma_chetrs chetrs
#define arma_zhetrs zhetrs
#define arma_ssytri ssytri
#define arma_dsytri dsytri
#define arma_chetri chetri
#define arma_zhetri zhetri
#define arma_ssycon ssycon
#define arma_dsycon dsycon
#define arma_checon checon
#define arma_zhecon zhecon
#else
#define arma_sgetrf SGETRF
@@ -505,6 +529,30 @@
#define arma_cpstrf CPSTRF
#define arma_zpstrf ZPSTRF
#define arma_ssytrf SSYTRF
#define arma_dsytrf DSYTRF
#define arma_chetrf CHETRF
#define arma_zhetrf ZHETRF
#define arma_ssytrs SSYTRS
#define arma_dsytrs DSYTRS
#define arma_chetrs CHETRS
#define arma_zhetrs ZHETRS
#define arma_ssytri SSYTRI
#define arma_dsytri DSYTRI
#define arma_chetri CHETRI
#define arma_zhetri ZHETRI
#define arma_ssycon SSYCON
#define arma_dsycon DSYCON
#define arma_checon CHECON
#define arma_zhecon ZHECON
#endif
@@ -846,6 +894,38 @@ extern "C"
void arma_fortran(arma_cpstrf)(const char* uplo, const blas_int* n, blas_cxf* a, const blas_int* lda, blas_int* piv, blas_int* rank, const float* tol, float* work, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
void arma_fortran(arma_zpstrf)(const char* uplo, const blas_int* n, blas_cxd* a, const blas_int* lda, blas_int* piv, blas_int* rank, const double* tol, double* work, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
// factorisation of symmetric matrix (real)
void arma_fortran(arma_ssytrf)(const char* uplo, const blas_int* n, float* a, const blas_int* lda, blas_int* ipiv, float* work, const blas_int* lwork, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
void arma_fortran(arma_dsytrf)(const char* uplo, const blas_int* n, double* a, const blas_int* lda, blas_int* ipiv, double* work, const blas_int* lwork, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
// factorisation of hermitian matrix (complex)
void arma_fortran(arma_chetrf)(const char* uplo, const blas_int* n, blas_cxf* a, const blas_int* lda, blas_int* ipiv, blas_cxf* work, const blas_int* lwork, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
void arma_fortran(arma_zhetrf)(const char* uplo, const blas_int* n, blas_cxd* a, const blas_int* lda, blas_int* ipiv, blas_cxd* work, const blas_int* lwork, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
// solve system using pre-computed factorisation (real)
void arma_fortran(arma_ssytrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const float* a, const blas_int* lda, const blas_int* ipiv, float* b, const blas_int* ldb, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
void arma_fortran(arma_dsytrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const double* a, const blas_int* lda, const blas_int* ipiv, double* b, const blas_int* ldb, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
// solve system using pre-computed factorisation (complex)
void arma_fortran(arma_chetrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const blas_cxf* a, const blas_int* lda, const blas_int* ipiv, blas_cxf* b, const blas_int* ldb, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
void arma_fortran(arma_zhetrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const blas_cxd* a, const blas_int* lda, const blas_int* ipiv, blas_cxd* b, const blas_int* ldb, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
// inverse of symmetric matrix using pre-computed factorisation (real)
void arma_fortran(arma_ssytri)(const char* uplo, const blas_int* n, float* a, const blas_int* lda, const blas_int* ipiv, float* work, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
void arma_fortran(arma_dsytri)(const char* uplo, const blas_int* n, double* a, const blas_int* lda, const blas_int* ipiv, double* work, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
// inverse of hermitian matrix using pre-computed factorisation (complex)
void arma_fortran(arma_chetri)(const char* uplo, const blas_int* n, blas_cxf* a, const blas_int* lda, const blas_int* ipiv, blas_cxf* work, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
void arma_fortran(arma_zhetri)(const char* uplo, const blas_int* n, blas_cxd* a, const blas_int* lda, const blas_int* ipiv, blas_cxd* work, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
// rcond of symmetric matrix using pre-computed factorisation (real)
void arma_fortran(arma_ssycon)(const char* uplo, const blas_int* n, const float* a, const blas_int* lda, const blas_int* ipiv, const float* anorm, float* rcond, float* work, blas_int* iwork, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
void arma_fortran(arma_dsycon)(const char* uplo, const blas_int* n, const double* a, const blas_int* lda, const blas_int* ipiv, const double* anorm, double* rcond, double* work, blas_int* iwork, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
// rcond of hermitian matrix using pre-computed factorisation (complex)
void arma_fortran(arma_checon)(const char* uplo, const blas_int* n, const blas_cxf* a, const blas_int* lda, const blas_int* ipiv, const float* anorm, float* rcond, blas_cxf* work, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
void arma_fortran(arma_zhecon)(const char* uplo, const blas_int* n, const blas_cxd* a, const blas_int* lda, const blas_int* ipiv, const double* anorm, double* rcond, blas_cxd* work, blas_int* info, blas_len uplo_len) ARMA_NOEXCEPT;
#else
// prototypes without hidden arguments
@@ -1170,6 +1250,38 @@ extern "C"
void arma_fortran(arma_cpstrf)(const char* uplo, const blas_int* n, blas_cxf* a, const blas_int* lda, blas_int* piv, blas_int* rank, const float* tol, float* work, blas_int* info) ARMA_NOEXCEPT;
void arma_fortran(arma_zpstrf)(const char* uplo, const blas_int* n, blas_cxd* a, const blas_int* lda, blas_int* piv, blas_int* rank, const double* tol, double* work, blas_int* info) ARMA_NOEXCEPT;
// factorisation of symmetric matrix (real)
void arma_fortran(arma_ssytrf)(const char* uplo, const blas_int* n, float* a, const blas_int* lda, blas_int* ipiv, float* work, const blas_int* lwork, blas_int* info) ARMA_NOEXCEPT;
void arma_fortran(arma_dsytrf)(const char* uplo, const blas_int* n, double* a, const blas_int* lda, blas_int* ipiv, double* work, const blas_int* lwork, blas_int* info) ARMA_NOEXCEPT;
// factorisation of hermitian matrix (complex)
void arma_fortran(arma_chetrf)(const char* uplo, const blas_int* n, blas_cxf* a, const blas_int* lda, blas_int* ipiv, blas_cxf* work, const blas_int* lwork, blas_int* info) ARMA_NOEXCEPT;
void arma_fortran(arma_zhetrf)(const char* uplo, const blas_int* n, blas_cxd* a, const blas_int* lda, blas_int* ipiv, blas_cxd* work, const blas_int* lwork, blas_int* info) ARMA_NOEXCEPT;
// solve system using pre-computed factorisation (real)
void arma_fortran(arma_ssytrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const float* a, const blas_int* lda, const blas_int* ipiv, float* b, const blas_int* ldb, blas_int* info) ARMA_NOEXCEPT;
void arma_fortran(arma_dsytrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const double* a, const blas_int* lda, const blas_int* ipiv, double* b, const blas_int* ldb, blas_int* info) ARMA_NOEXCEPT;
// solve system using pre-computed factorisation (complex)
void arma_fortran(arma_zhetrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const blas_cxd* a, const blas_int* lda, const blas_int* ipiv, blas_cxd* b, const blas_int* ldb, blas_int* info) ARMA_NOEXCEPT;
void arma_fortran(arma_chetrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const blas_cxf* a, const blas_int* lda, const blas_int* ipiv, blas_cxf* b, const blas_int* ldb, blas_int* info) ARMA_NOEXCEPT;
// inverse of symmetric matrix using pre-computed factorisation (real)
void arma_fortran(arma_ssytri)(const char* uplo, const blas_int* n, float* a, const blas_int* lda, const blas_int* ipiv, float* work, blas_int* info) ARMA_NOEXCEPT;
void arma_fortran(arma_dsytri)(const char* uplo, const blas_int* n, double* a, const blas_int* lda, const blas_int* ipiv, double* work, blas_int* info) ARMA_NOEXCEPT;
// inverse of hermitian matrix using pre-computed factorisation (complex)
void arma_fortran(arma_chetri)(const char* uplo, const blas_int* n, blas_cxf* a, const blas_int* lda, const blas_int* ipiv, blas_cxf* work, blas_int* info) ARMA_NOEXCEPT;
void arma_fortran(arma_zhetri)(const char* uplo, const blas_int* n, blas_cxd* a, const blas_int* lda, const blas_int* ipiv, blas_cxd* work, blas_int* info) ARMA_NOEXCEPT;
// rcond of symmetric matrix using pre-computed factorisation (real)
void arma_fortran(arma_ssycon)(const char* uplo, const blas_int* n, const float* a, const blas_int* lda, const blas_int* ipiv, const float* anorm, float* rcond, float* work, blas_int* iwork, blas_int* info) ARMA_NOEXCEPT;
void arma_fortran(arma_dsycon)(const char* uplo, const blas_int* n, const double* a, const blas_int* lda, const blas_int* ipiv, const double* anorm, double* rcond, double* work, blas_int* iwork, blas_int* info) ARMA_NOEXCEPT;
// rcond of hermitian matrix using pre-computed factorisation (complex)
void arma_fortran(arma_checon)(const char* uplo, const blas_int* n, const blas_cxf* a, const blas_int* lda, const blas_int* ipiv, const float* anorm, float* rcond, blas_cxf* work, blas_int* info) ARMA_NOEXCEPT;
void arma_fortran(arma_zhecon)(const char* uplo, const blas_int* n, const blas_cxd* a, const blas_int* lda, const blas_int* ipiv, const double* anorm, double* rcond, blas_cxd* work, blas_int* info) ARMA_NOEXCEPT;
#endif
}
@@ -108,6 +108,9 @@ class diagview : public Base< eT, diagview<eT> >
inline static void schur_inplace(Mat<eT>& out, const diagview& in);
inline static void div_inplace(Mat<eT>& out, const diagview& in);
template<typename eT2>
inline bool is_alias(const Mat<eT2>& X) const;
friend class Mat<eT>;
friend class subview<eT>;
+33 -20
View File
@@ -236,13 +236,13 @@ diagview<eT>::operator= (const Base<eT,T1>& o)
"diagview: given object has incompatible size"
);
const bool is_alias = P.is_alias(d_m);
const bool have_alias = P.is_alias(d_m);
if(is_alias) { arma_debug_print("aliasing detected"); }
if(have_alias) { arma_debug_print("aliasing detected"); }
if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (Proxy<T1>::use_at) || (is_alias) )
if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (Proxy<T1>::use_at) || (have_alias) )
{
const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, is_alias);
const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, have_alias);
const Mat<eT>& x = tmp.M;
const eT* x_mem = x.memptr();
@@ -309,13 +309,13 @@ diagview<eT>::operator+=(const Base<eT,T1>& o)
"diagview: given object has incompatible size"
);
const bool is_alias = P.is_alias(d_m);
const bool have_alias = P.is_alias(d_m);
if(is_alias) { arma_debug_print("aliasing detected"); }
if(have_alias) { arma_debug_print("aliasing detected"); }
if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (Proxy<T1>::use_at) || (is_alias) )
if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (Proxy<T1>::use_at) || (have_alias) )
{
const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, is_alias);
const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, have_alias);
const Mat<eT>& x = tmp.M;
const eT* x_mem = x.memptr();
@@ -382,13 +382,13 @@ diagview<eT>::operator-=(const Base<eT,T1>& o)
"diagview: given object has incompatible size"
);
const bool is_alias = P.is_alias(d_m);
const bool have_alias = P.is_alias(d_m);
if(is_alias) { arma_debug_print("aliasing detected"); }
if(have_alias) { arma_debug_print("aliasing detected"); }
if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (Proxy<T1>::use_at) || (is_alias) )
if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (Proxy<T1>::use_at) || (have_alias) )
{
const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, is_alias);
const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, have_alias);
const Mat<eT>& x = tmp.M;
const eT* x_mem = x.memptr();
@@ -455,13 +455,13 @@ diagview<eT>::operator%=(const Base<eT,T1>& o)
"diagview: given object has incompatible size"
);
const bool is_alias = P.is_alias(d_m);
const bool have_alias = P.is_alias(d_m);
if(is_alias) { arma_debug_print("aliasing detected"); }
if(have_alias) { arma_debug_print("aliasing detected"); }
if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (Proxy<T1>::use_at) || (is_alias) )
if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (Proxy<T1>::use_at) || (have_alias) )
{
const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, is_alias);
const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, have_alias);
const Mat<eT>& x = tmp.M;
const eT* x_mem = x.memptr();
@@ -528,13 +528,13 @@ diagview<eT>::operator/=(const Base<eT,T1>& o)
"diagview: given object has incompatible size"
);
const bool is_alias = P.is_alias(d_m);
const bool have_alias = P.is_alias(d_m);
if(is_alias) { arma_debug_print("aliasing detected"); }
if(have_alias) { arma_debug_print("aliasing detected"); }
if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (Proxy<T1>::use_at) || (is_alias) )
if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (Proxy<T1>::use_at) || (have_alias) )
{
const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, is_alias);
const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, have_alias);
const Mat<eT>& x = tmp.M;
const eT* x_mem = x.memptr();
@@ -1022,4 +1022,17 @@ diagview<eT>::randn()
template<typename eT>
template<typename eT2>
inline
bool
diagview<eT>::is_alias(const Mat<eT2>& X) const
{
arma_debug_sigprint();
return m.is_alias(X);
}
//! @}
+3
View File
@@ -44,6 +44,9 @@ class eGlue : public Base< typename T1::elem_type, eGlue<T1, T2, eglue_type> >
arma_inline ~eGlue();
arma_inline eGlue(const T1& in_A, const T2& in_B);
template<typename eT2>
inline bool is_alias(const Mat<eT2>& X) const;
arma_inline uword get_n_rows() const;
arma_inline uword get_n_cols() const;
arma_inline uword get_n_elem() const;
+11
View File
@@ -49,6 +49,17 @@ eGlue<T1,T2,eglue_type>::eGlue(const T1& in_A, const T2& in_B)
template<typename T1, typename T2, typename eglue_type>
template<typename eT2>
inline
bool
eGlue<T1,T2,eglue_type>::is_alias(const Mat<eT2>& X) const
{
return (P1.is_alias(X) || P2.is_alias(X));
}
template<typename T1, typename T2, typename eglue_type>
arma_inline
uword
+3
View File
@@ -50,6 +50,9 @@ class eOp : public Base< typename T1::elem_type, eOp<T1, eop_type> >
inline eOp(const T1& in_m, const uword in_aux_uword_a, const uword in_aux_uword_b);
inline eOp(const T1& in_m, const elem_type in_aux, const uword in_aux_uword_a, const uword in_aux_uword_b);
template<typename eT2>
inline bool is_alias(const Mat<eT2>& X) const;
arma_inline uword get_n_rows() const;
arma_inline uword get_n_cols() const;
arma_inline uword get_n_elem() const;
+13
View File
@@ -74,7 +74,20 @@ eOp<T1, eop_type>::~eOp()
arma_debug_sigprint();
}
template<typename T1, typename eop_type>
template<typename eT2>
inline
bool
eOp<T1, eop_type>::is_alias(const Mat<eT2>& X) const
{
arma_debug_sigprint();
return P.is_alias(X);
}
template<typename T1, typename eop_type>
arma_inline
+29 -1
View File
@@ -50,7 +50,8 @@ class fft_engine_fftw3
podarray<cx_type> Y_work; // for storing output
inline
~fft_engine_fftw3()
void
finish()
{
arma_debug_sigprint();
@@ -59,6 +60,33 @@ class fft_engine_fftw3
// fftw3::cleanup<cx_type>(); // NOTE: this also removes any wisdom acquired by FFTW3
}
inline
~fft_engine_fftw3()
{
arma_debug_sigprint();
#if defined(ARMA_USE_OPENMP)
{
#pragma omp critical (arma_fft_engine_fftw3)
{
(*this).finish();
}
}
#elif defined(ARMA_USE_STD_MUTEX)
{
std::mutex& plan_mutex = fft_engine_fftw3_aux::get_plan_mutex();
const std::lock_guard<std::mutex> lock(plan_mutex);
(*this).finish();
}
#else
{
(*this).finish();
}
#endif
}
inline
fft_engine_fftw3(const uword in_N)
: N (in_N )
+6 -6
View File
@@ -531,7 +531,7 @@ field<oT>::at(const uword i) const
//! linear element accessor (treats the field as a vector); bounds checking not done when ARMA_NO_DEBUG is defined
//! linear element accessor (treats the field as a vector); bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename oT>
arma_inline
oT&
@@ -544,7 +544,7 @@ field<oT>::operator() (const uword i)
//! linear element accessor (treats the field as a vector); bounds checking not done when ARMA_NO_DEBUG is defined
//! linear element accessor (treats the field as a vector); bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename oT>
arma_inline
const oT&
@@ -557,7 +557,7 @@ field<oT>::operator() (const uword i) const
//! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
//! element accessor; bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename oT>
arma_inline
oT&
@@ -570,7 +570,7 @@ field<oT>::operator() (const uword in_row, const uword in_col)
//! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
//! element accessor; bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename oT>
arma_inline
const oT&
@@ -583,7 +583,7 @@ field<oT>::operator() (const uword in_row, const uword in_col) const
//! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
//! element accessor; bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename oT>
arma_inline
oT&
@@ -596,7 +596,7 @@ field<oT>::operator() (const uword in_row, const uword in_col, const uword in_sl
//! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
//! element accessor; bounds checking not done when ARMA_DONT_CHECK_CONFORMANCE is defined
template<typename oT>
arma_inline
const oT&
+3 -1
View File
@@ -840,7 +840,7 @@ accu(const BaseCube<typename T1::elem_type,T1>& X)
if(is_Cube<typename ProxyCube<T1>::stored_type>::value)
{
unwrap_cube<typename ProxyCube<T1>::stored_type> tmp(P.Q);
const unwrap_cube<typename ProxyCube<T1>::stored_type> tmp(P.Q);
return arrayops::accumulate(tmp.M.memptr(), tmp.M.n_elem);
}
@@ -993,6 +993,8 @@ accu(const SpGlue<T1,T2,spglue_schur>& expr)
const SpProxy<T1> px(expr.A);
const SpProxy<T2> py(expr.B);
arma_conform_assert_same_size(px.get_n_rows(), px.get_n_cols(), py.get_n_rows(), py.get_n_cols(), "element-wise multiplication");
typename SpProxy<T1>::const_iterator_type x_it = px.begin();
typename SpProxy<T1>::const_iterator_type x_it_end = px.end();
+50 -40
View File
@@ -147,46 +147,6 @@ logspace(const double A, const double B, const uword N = 50u)
//
// log_exp_add
template<typename eT>
arma_warn_unused
inline
typename arma_real_only<eT>::result
log_add_exp(eT log_a, eT log_b)
{
if(log_a < log_b)
{
std::swap(log_a, log_b);
}
const eT negdelta = log_b - log_a;
if( (negdelta < Datum<eT>::log_min) || (arma_isfinite(negdelta) == false) )
{
return log_a;
}
else
{
return (log_a + std::log1p(std::exp(negdelta)));
}
}
// for compatibility with earlier versions
template<typename eT>
arma_warn_unused
inline
typename arma_real_only<eT>::result
log_add(eT log_a, eT log_b)
{
return log_add_exp(log_a, log_b);
}
//! kept for compatibility with old user code
template<typename eT>
arma_warn_unused
@@ -584,4 +544,54 @@ affmul(const T1& A, const T2& B)
namespace priv
{
// internal use only
template<typename eT>
arma_warn_unused
inline
typename arma_real_only<eT>::result
internal_log_add_exp(eT log_a, eT log_b)
{
if(log_a < log_b) { std::swap(log_a, log_b); }
const eT negdelta = log_b - log_a;
if( (negdelta < Datum<eT>::log_min) || (arma_isfinite(negdelta) == false) )
{
return log_a;
}
else
{
return (log_a + std::log1p(std::exp(negdelta)));
}
}
}
// DO NOT USE; kept only for compatibility with old user code
template<typename eT>
arma_deprecated
inline
typename arma_real_only<eT>::result
log_add_exp(eT log_a, eT log_b)
{
return priv::internal_log_add_exp(log_a, log_b);
}
// DO NOT USE; kept only for compatibility with old user code
template<typename eT>
arma_deprecated
inline
typename arma_real_only<eT>::result
log_add(eT log_a, eT log_b)
{
return priv::internal_log_add_exp(log_a, log_b);
}
//! @}
+8 -8
View File
@@ -23,7 +23,7 @@
template<typename T1, typename T2>
arma_warn_unused
arma_inline
inline
typename
enable_if2
<
@@ -44,7 +44,7 @@ pow
template<typename parent, unsigned int mode, typename T2>
arma_warn_unused
arma_deprecated
inline
Mat<typename parent::elem_type>
pow
@@ -62,7 +62,7 @@ pow
template<typename T1, typename T2>
arma_warn_unused
arma_inline
inline
const GlueCube<T1, T2, glue_powext>
pow
(
@@ -78,7 +78,7 @@ pow
template<typename eT, typename T2>
arma_warn_unused
arma_deprecated
inline
Cube<eT>
pow
@@ -100,7 +100,7 @@ pow
template<typename T1, typename T2>
arma_warn_unused
arma_inline
inline
typename
enable_if2
<
@@ -121,7 +121,7 @@ pow
template<typename parent, unsigned int mode, typename T2>
arma_warn_unused
arma_deprecated
inline
typename
enable_if2
@@ -144,7 +144,7 @@ pow
template<typename T1, typename T2>
arma_warn_unused
arma_inline
inline
const mtGlueCube<typename T1::elem_type, T1, T2, glue_powext_cx>
pow
(
@@ -160,7 +160,7 @@ pow
template<typename T, typename T2>
arma_warn_unused
arma_deprecated
inline
Cube< std::complex<T> >
pow
@@ -140,6 +140,7 @@ namespace solve_opts
static constexpr uword flag_refine = uword(1u << 9);
static constexpr uword flag_no_trimat = uword(1u << 10);
static constexpr uword flag_force_approx = uword(1u << 11);
static constexpr uword flag_force_sym = uword(1u << 12);
struct opts_none : public opts { inline constexpr opts_none() : opts(flag_none ) {} };
struct opts_fast : public opts { inline constexpr opts_fast() : opts(flag_fast ) {} };
@@ -154,6 +155,7 @@ namespace solve_opts
struct opts_refine : public opts { inline constexpr opts_refine() : opts(flag_refine ) {} };
struct opts_no_trimat : public opts { inline constexpr opts_no_trimat() : opts(flag_no_trimat ) {} };
struct opts_force_approx : public opts { inline constexpr opts_force_approx() : opts(flag_force_approx) {} };
struct opts_force_sym : public opts { inline constexpr opts_force_sym() : opts(flag_force_sym ) {} };
static constexpr opts_none none;
static constexpr opts_fast fast;
@@ -168,6 +170,7 @@ namespace solve_opts
static constexpr opts_refine refine;
static constexpr opts_no_trimat no_trimat;
static constexpr opts_force_approx force_approx;
static constexpr opts_force_sym force_sym;
}
+58 -35
View File
@@ -99,6 +99,7 @@ glue_solve_gen_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
const bool refine = has_user_flags && bool(flags & solve_opts::flag_refine );
const bool no_trimat = has_user_flags && bool(flags & solve_opts::flag_no_trimat );
const bool force_approx = has_user_flags && bool(flags & solve_opts::flag_force_approx);
const bool force_sym = has_user_flags && bool(flags & solve_opts::flag_force_sym );
if(has_user_flags)
{
@@ -114,10 +115,11 @@ glue_solve_gen_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
if(refine ) { arma_debug_print("refine"); }
if(no_trimat ) { arma_debug_print("no_trimat"); }
if(force_approx) { arma_debug_print("force_approx"); }
if(force_sym ) { arma_debug_print("force_sym"); }
arma_conform_check( (fast && equilibrate ), "solve(): options 'fast' and 'equilibrate' are mutually exclusive" );
arma_conform_check( (fast && refine ), "solve(): options 'fast' and 'refine' are mutually exclusive" );
arma_conform_check( (no_sympd && likely_sympd), "solve(): options 'no_sympd' and 'likely_sympd' are mutually exclusive" );
arma_conform_check( (fast && equilibrate ), "solve(): options 'fast' and 'equilibrate' are mutually exclusive" );
arma_conform_check( (fast && refine ), "solve(): options 'fast' and 'refine' are mutually exclusive" );
arma_conform_check( (no_sympd && likely_sympd), "solve(): options 'no_sympd' and 'likely_sympd' are mutually exclusive" );
}
Mat<eT> A = A_expr.get_ref();
@@ -128,26 +130,34 @@ glue_solve_gen_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
arma_conform_check( no_approx, "solve(): options 'no_approx' and 'force_approx' are mutually exclusive" );
if(fast) { arma_warn(2, "solve(): option 'fast' ignored for forced approximate solution" ); }
if(equilibrate) { arma_warn(2, "solve(): option 'equilibrate' ignored for forced approximate solution" ); }
if(refine) { arma_warn(2, "solve(): option 'refine' ignored for forced approximate solution" ); }
if(likely_sympd) { arma_warn(2, "solve(): option 'likely_sympd' ignored for forced approximate solution" ); }
if(fast) { arma_warn(2, "solve(): option 'fast' ignored for forced approximate solution" ); }
if(equilibrate) { arma_warn(2, "solve(): option 'equilibrate' ignored for forced approximate solution" ); }
if(refine) { arma_warn(2, "solve(): option 'refine' ignored for forced approximate solution" ); }
if(likely_sympd) { arma_warn(2, "solve(): option 'likely_sympd' ignored for forced approximate solution" ); }
if(force_sym) { arma_warn(2, "solve(): option 'force_sym' ignored for forced approximate solution" ); }
return auxlib::solve_approx_svd(actual_out, A, B_expr.get_ref()); // A is overwritten
}
if(force_sym)
{
if((arma_config::check_conform) && (auxlib::rudimentary_sym_check(A) == false))
{
if(is_cx<eT>::no ) { arma_warn(1, "solve(): option 'force_sym' enabled, but given matrix is not symmetric"); }
if(is_cx<eT>::yes) { arma_warn(1, "solve(): option 'force_sym' enabled, but given matrix is not hermitian"); }
}
if(likely_sympd) { arma_warn(2, "solve(): option 'likely_sympd' ignored for forced symmetric solver" ); }
if(equilibrate) { arma_warn(2, "solve(): option 'force_sym' ignored as option 'equilibrate' is enabled (combination not implemented yet)" ); }
if(refine) { arma_warn(2, "solve(): option 'force_sym' ignored as option 'refine' is enabled (combination not implemented yet)" ); }
}
// A_expr and B_expr can be used more than once (sympd optimisation fails or approximate solution required),
// so ensure they are not overwritten in case we have aliasing
bool is_alias = true; // assume we have aliasing until we can prove otherwise
const bool is_alias = A_expr.get_ref().is_alias(actual_out) || B_expr.get_ref().is_alias(actual_out);
if(is_Mat<T1>::value && is_Mat<T2>::value)
{
const quasi_unwrap<T1> UA( A_expr.get_ref() );
const quasi_unwrap<T2> UB( B_expr.get_ref() );
is_alias = UA.is_alias(actual_out) || UB.is_alias(actual_out);
}
if(is_alias) { arma_debug_print("glue_solve_gen_full::apply(): aliasing detected"); }
Mat<eT> tmp;
Mat<eT>& out = (is_alias) ? tmp : actual_out;
@@ -162,12 +172,13 @@ glue_solve_gen_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
uword KL = 0;
uword KU = 0;
const bool is_band = arma_config::optimise_band && ((no_band || auxlib::crippled_lapack(A)) ? false : band_helper::is_band(KL, KU, A, uword(32)));
const bool is_band = arma_config::optimise_band && ( (no_band || force_sym || auxlib::crippled_lapack(A)) ? false : band_helper::is_band(KL, KU, A, uword(32)) );
const bool is_triu = (no_trimat || refine || equilibrate || likely_sympd || is_band ) ? false : trimat_helper::is_triu(A);
const bool is_tril = (no_trimat || refine || equilibrate || likely_sympd || is_band || is_triu) ? false : trimat_helper::is_tril(A);
const bool is_triu = (no_trimat || refine || equilibrate || likely_sympd || force_sym || is_band ) ? false : trimat_helper::is_triu(A);
const bool is_tril = (no_trimat || refine || equilibrate || likely_sympd || force_sym || is_band || is_triu) ? false : trimat_helper::is_tril(A);
const bool try_sympd = arma_config::optimise_sym && ((no_sympd || auxlib::crippled_lapack(A) || is_band || is_triu || is_tril) ? false : (likely_sympd ? true : sym_helper::guess_sympd(A, uword(16))));
const bool is_sym = arma_config::optimise_sym && ( (refine || equilibrate || likely_sympd || force_sym || is_band || is_triu || is_tril || auxlib::crippled_lapack(A)) ? false : is_sym_expr<T1>::eval(A_expr.get_ref()) );
const bool try_sympd = arma_config::optimise_sym && ( ( no_sympd || is_sym || force_sym || is_band || is_triu || is_tril || auxlib::crippled_lapack(A)) ? false : (likely_sympd ? true : sym_helper::guess_sympd(A, uword(16))) );
if(fast)
{
@@ -201,6 +212,13 @@ glue_solve_gen_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
status = auxlib::solve_trimat_fast(out, A, B_expr.get_ref(), layout);
}
else
if(force_sym || is_sym)
{
arma_debug_print("glue_solve_gen_full::apply(): fast + sym");
status = auxlib::solve_sym_fast(out, A, B_expr.get_ref()); // A is overwritten
}
else
if(try_sympd)
{
arma_debug_print("glue_solve_gen_full::apply(): fast + try_sympd");
@@ -238,6 +256,10 @@ glue_solve_gen_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
status = auxlib::solve_band_refine(out, rcond, A, KL, KU, B_expr, equilibrate);
}
// else
// if(force_sym || is_sym) // TODO: implement auxlib::solve_sym_refine()
// {
// }
else
if(try_sympd)
{
@@ -287,6 +309,13 @@ glue_solve_gen_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
status = auxlib::solve_trimat_rcond(out, rcond, A, B_expr.get_ref(), layout);
}
else
if(force_sym || is_sym)
{
arma_debug_print("glue_solve_gen_full::apply(): rcond + sym");
status = auxlib::solve_sym_rcond(out, rcond, A, B_expr.get_ref()); // A is overwritten
}
else
if(try_sympd)
{
bool sympd_state = false;
@@ -315,6 +344,7 @@ glue_solve_gen_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
if(equilibrate) { arma_warn(2, "solve(): option 'equilibrate' ignored for non-square matrix" ); }
if(refine) { arma_warn(2, "solve(): option 'refine' ignored for non-square matrix" ); }
if(likely_sympd) { arma_warn(2, "solve(): option 'likely_sympd' ignored for non-square matrix" ); }
if(force_sym) { arma_warn(2, "solve(): option 'force_sym' ignored for non-square matrix" ); }
if(fast)
{
@@ -406,14 +436,9 @@ glue_solve_tri_default::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, co
const uword layout = (triu) ? uword(0) : uword(1);
bool is_alias = true;
const bool is_alias = A_expr.get_ref().is_alias(actual_out) || B_expr.get_ref().is_alias(actual_out);
if(is_Mat<T2>::value)
{
const quasi_unwrap<T2> UB(B_expr.get_ref());
is_alias = UA.is_alias(actual_out) || UB.is_alias(actual_out);
}
if(is_alias) { arma_debug_print("glue_solve_tri_default::apply(): aliasing detected"); }
T rcond = T(0);
bool status = false;
@@ -497,6 +522,7 @@ glue_solve_tri_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
const bool refine = bool(flags & solve_opts::flag_refine );
const bool no_trimat = bool(flags & solve_opts::flag_no_trimat );
const bool force_approx = bool(flags & solve_opts::flag_force_approx);
const bool force_sym = bool(flags & solve_opts::flag_force_sym );
arma_debug_print("glue_solve_tri_full::apply(): enabled flags:");
@@ -510,6 +536,10 @@ glue_solve_tri_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
if(refine ) { arma_debug_print("refine"); }
if(no_trimat ) { arma_debug_print("no_trimat"); }
if(force_approx) { arma_debug_print("force_approx"); }
if(force_sym ) { arma_debug_print("force_sym"); }
arma_conform_check( (likely_sympd), "solve(): option 'likely_sympd' not applicable to triangular matrix" );
arma_conform_check( (force_sym ), "solve(): option 'force_sym' not applicable to triangular matrix" );
if(no_trimat || equilibrate || refine || force_approx)
{
@@ -518,8 +548,6 @@ glue_solve_tri_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
return glue_solve_gen_full::apply(actual_out, ((triu) ? trimatu(A_expr.get_ref()) : trimatl(A_expr.get_ref())), B_expr, (flags & mask));
}
if(likely_sympd) { arma_warn(2, "solve(): option 'likely_sympd' ignored for triangular matrix"); }
const quasi_unwrap<T1> UA(A_expr.get_ref());
const Mat<eT>& A = UA.M;
@@ -527,14 +555,9 @@ glue_solve_tri_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
const uword layout = (triu) ? uword(0) : uword(1);
bool is_alias = true;
const bool is_alias = A_expr.get_ref().is_alias(actual_out) || B_expr.get_ref().is_alias(actual_out);
if(is_Mat<T2>::value)
{
const quasi_unwrap<T2> UB(B_expr.get_ref());
is_alias = UA.is_alias(actual_out) || UB.is_alias(actual_out);
}
if(is_alias) { arma_debug_print("glue_solve_tri_full::apply(): aliasing detected"); }
T rcond = T(0);
bool status = false;
+10 -4
View File
@@ -119,7 +119,9 @@ glue_times_redirect2_helper<true>::apply(Mat<typename T1::elem_type>& out, const
arma_conform_assert_mul_size(A, B, "matrix multiplication");
const bool status = (strip_inv<T1>::do_inv_spd) ? auxlib::solve_sympd_fast(out, A, B) : auxlib::solve_square_fast(out, A, B);
const bool is_sym = (strip_inv<T1>::do_inv_spd) ? false : ( arma_config::optimise_sym && (auxlib::crippled_lapack(A) == false) && (is_sym_expr<T1>::eval(X.A) || sym_helper::is_approx_sym(A, uword(100))) );
const bool status = (strip_inv<T1>::do_inv_spd) ? auxlib::solve_sympd_fast(out, A, B) : ( (is_sym) ? auxlib::solve_sym_fast(out, A, B) : auxlib::solve_square_fast(out, A, B) );
if(status == false)
{
@@ -278,7 +280,9 @@ glue_times_redirect3_helper<true>::apply(Mat<typename T1::elem_type>& out, const
if(is_cx<eT>::yes) { arma_warn(1, "inv_sympd(): given matrix is not hermitian"); }
}
const bool status = (strip_inv<T1>::do_inv_spd) ? auxlib::solve_sympd_fast(out, A, BC) : auxlib::solve_square_fast(out, A, BC);
const bool is_sym = (strip_inv<T1>::do_inv_spd) ? false : ( arma_config::optimise_sym && (auxlib::crippled_lapack(A) == false) && (is_sym_expr<T1>::eval(X.A.A) || sym_helper::is_approx_sym(A, uword(100))) );
const bool status = (strip_inv<T1>::do_inv_spd) ? auxlib::solve_sympd_fast(out, A, BC) : ( (is_sym) ? auxlib::solve_sym_fast(out, A, BC) : auxlib::solve_square_fast(out, A, BC) );
if(status == false)
{
@@ -315,7 +319,9 @@ glue_times_redirect3_helper<true>::apply(Mat<typename T1::elem_type>& out, const
Mat<eT> solve_result;
const bool status = (strip_inv<T2>::do_inv_spd) ? auxlib::solve_sympd_fast(solve_result, B, C) : auxlib::solve_square_fast(solve_result, B, C);
const bool is_sym = (strip_inv<T1>::do_inv_spd) ? false : ( arma_config::optimise_sym && (auxlib::crippled_lapack(B) == false) && (is_sym_expr<T2>::eval(X.A.B) || sym_helper::is_approx_sym(B, uword(100))) );
const bool status = (strip_inv<T2>::do_inv_spd) ? auxlib::solve_sympd_fast(solve_result, B, C) : ( (is_sym) ? auxlib::solve_sym_fast(solve_result, B, C) : auxlib::solve_square_fast(solve_result, B, C) );
if(status == false)
{
@@ -552,7 +558,7 @@ glue_times::apply_inplace_plus(Mat<typename T1::elem_type>& out, const Glue<T1,
const bool use_alpha = partial_unwrap_check<T1>::do_times || partial_unwrap_check<T2>::do_times || (sign < sword(0));
const eT alpha = use_alpha ? ( tmp1.get_val() * tmp2.get_val() * ( (sign > sword(0)) ? eT(1) : eT(-1) ) ) : eT(0);
const eT alpha = use_alpha ? ( tmp1.get_val() * tmp2.get_val() * ( (sign > sword(0)) ? eT(1) : eT(-1) ) ) : eT(0);
arma_conform_assert_mul_size(A, B, do_trans_A, do_trans_B, "matrix multiplication");
+2 -2
View File
@@ -1070,7 +1070,7 @@ gmm_diag<eT>::internal_scalar_log_p(const eT* x) const
{
const eT tmp = internal_scalar_log_p(x, g) + log_hefts_mem[g];
log_sum = log_add_exp(log_sum, tmp);
log_sum = priv::internal_log_add_exp(log_sum, tmp);
}
return log_sum;
@@ -2556,7 +2556,7 @@ gmm_diag<eT>::em_generate_acc
for(uword g=1; g < N_gaus; ++g)
{
log_lhood_sum = log_add_exp(log_lhood_sum, gaus_log_lhoods_mem[g]);
log_lhood_sum = priv::internal_log_add_exp(log_lhood_sum, gaus_log_lhoods_mem[g]);
}
progress_log_lhood += log_lhood_sum;
+3 -3
View File
@@ -937,7 +937,7 @@ gmm_full<eT>::init_constants(const bool calc_chol)
Mat<eT>& inv_fcov = inv_fcovs.slice(g);
//const bool inv_ok = auxlib::inv(tmp_inv, fcov);
const bool inv_ok = auxlib::inv_sympd(tmp_inv, fcov);
const bool inv_ok = auxlib::inv_sympd(tmp_inv, fcov); // using inv_sympd() instead of inv() to ensure we can do cholesky decomp via op_chol
eT log_det_val = eT(0);
eT log_det_sign = eT(0);
@@ -1087,7 +1087,7 @@ gmm_full<eT>::internal_scalar_log_p(const eT* x) const
{
const eT log_val = internal_scalar_log_p(x, g) + log_hefts_mem[g];
log_sum = log_add_exp(log_sum, log_val);
log_sum = priv::internal_log_add_exp(log_sum, log_val);
}
return log_sum;
@@ -2618,7 +2618,7 @@ gmm_full<eT>::em_generate_acc
for(uword g=1; g < N_gaus; ++g)
{
log_lhood_sum = log_add_exp(log_lhood_sum, gaus_log_lhoods_mem[g]);
log_lhood_sum = priv::internal_log_add_exp(log_lhood_sum, gaus_log_lhoods_mem[g]);
}
progress_log_lhood += log_lhood_sum;
+3
View File
@@ -37,6 +37,9 @@ class mtGlue : public Base< out_eT, mtGlue<out_eT, T1, T2, glue_type> >
arma_inline mtGlue(const T1& in_A, const T2& in_B, const uword in_aux_uword);
arma_inline ~mtGlue();
template<typename eT2>
inline bool is_alias(const Mat<eT2>& X) const;
arma_aligned const T1& A; //!< first operand; must be derived from Base
arma_aligned const T2& B; //!< second operand; must be derived from Base
arma_aligned uword aux_uword; //!< storage of auxiliary data, uword format
+13
View File
@@ -53,4 +53,17 @@ mtGlue<out_eT,T1,T2,glue_type>::~mtGlue()
template<typename out_eT, typename T1, typename T2, typename glue_type>
template<typename eT2>
inline
bool
mtGlue<out_eT,T1,T2,glue_type>::is_alias(const Mat<eT2>& X) const
{
arma_debug_sigprint();
return (A.is_alias(X) || B.is_alias(X));
}
//! @}
+4 -1
View File
@@ -47,7 +47,10 @@ class mtOp : public Base< out_eT, mtOp<out_eT, T1, op_type> >
inline mtOp(const mtOp_dual_aux_indicator&, const T1& in_m, const in_eT in_aux_a, const out_eT in_aux_b);
inline ~mtOp();
template<typename eT2>
inline bool is_alias(const Mat<eT2>& X) const;
arma_aligned const T1& m; //!< the operand; must be derived from Base
arma_aligned in_eT aux; //!< auxiliary data, using the element type as used by T1
+13
View File
@@ -101,4 +101,17 @@ mtOp<out_eT, T1, op_type>::~mtOp()
template<typename out_eT, typename T1, typename op_type>
template<typename eT2>
inline
bool
mtOp<out_eT, T1, op_type>::is_alias(const Mat<eT2>& X) const
{
arma_debug_sigprint();
return m.is_alias(X);
}
//! @}
+2 -9
View File
@@ -37,19 +37,12 @@ op_cond::apply(const Base<typename T1::elem_type, T1>& X)
if(is_op_diagmat<T1>::value || A.is_diagmat())
{
arma_debug_print("op_cond::apply(): detected diagonal matrix");
arma_debug_print("op_cond::apply(): diag optimisation");
return op_cond::apply_diag(A);
}
bool is_approx_sym = false;
bool is_approx_sympd = false;
sym_helper::analyse_matrix(is_approx_sym, is_approx_sympd, A);
const bool do_sym = (is_cx<eT>::no) ? (is_approx_sym) : (is_approx_sym && is_approx_sympd);
if(do_sym)
if(sym_helper::is_approx_sym(A))
{
arma_debug_print("op_cond: symmetric/hermitian optimisation");
+3 -15
View File
@@ -75,7 +75,7 @@ op_expmat::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1
if(A.is_diagmat())
{
arma_debug_print("op_expmat: detected diagonal matrix");
arma_debug_print("op_expmat: diag optimisation");
const uword N = (std::min)(A.n_rows, A.n_cols);
@@ -86,19 +86,7 @@ op_expmat::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1
return true;
}
bool do_sym = false;
if( (arma_config::optimise_sym) && (auxlib::crippled_lapack(A) == false) )
{
bool is_approx_sym = false;
bool is_approx_sympd = false;
sym_helper::analyse_matrix(is_approx_sym, is_approx_sympd, A);
do_sym = ((is_cx<eT>::no) ? (is_approx_sym) : (is_approx_sym && is_approx_sympd));
}
if(do_sym)
if( (arma_config::optimise_sym) && (auxlib::crippled_lapack(A) == false) && sym_helper::is_approx_sym(A) )
{
arma_debug_print("op_expmat: symmetric/hermitian optimisation");
@@ -207,7 +195,7 @@ op_expmat_sym::apply_direct(Mat<typename T1::elem_type>& out, const Base<typenam
if(is_op_diagmat<T1>::value || X.is_diagmat())
{
arma_debug_print("op_expmat_sym: detected diagonal matrix");
arma_debug_print("op_expmat_sym: diag optimisation");
out = X;
+12 -36
View File
@@ -185,7 +185,7 @@ op_inv_gen_full::apply_direct(Mat<typename T1::elem_type>& out, const Base<typen
if(is_op_diagmat<T1>::value || out.is_diagmat())
{
arma_debug_print("op_inv_gen_full: detected diagonal matrix");
arma_debug_print("op_inv_gen_full: diag optimisation");
eT* colmem = out.memptr();
@@ -216,28 +216,16 @@ op_inv_gen_full::apply_direct(Mat<typename T1::elem_type>& out, const Base<typen
if(is_triu_expr || is_tril_expr || is_triu_mat || is_tril_mat)
{
arma_debug_print("op_inv_gen_full: tri optimisation");
return auxlib::inv_tr(out, ((is_triu_expr || is_triu_mat) ? uword(0) : uword(1)));
}
const bool try_sympd = arma_config::optimise_sym && sym_helper::guess_sympd(out);
if(try_sympd)
if( (arma_config::optimise_sym) && (auxlib::crippled_lapack(out) == false) && ( is_sym_expr<T1>::eval(expr.get_ref()) || sym_helper::is_approx_sym(out, uword(100)) ) )
{
arma_debug_print("op_inv_gen_full: attempting sympd optimisation");
arma_debug_print("op_inv_gen_full: symmetric/hermitian optimisation");
Mat<eT> tmp = out;
bool sympd_state = false;
const bool status = auxlib::inv_sympd(tmp, sympd_state);
if(status) { out.steal_mem(tmp); return true; }
if((status == false) && (sympd_state == true)) { return false; }
arma_debug_print("op_inv_gen_full: sympd optimisation failed");
// fallthrough if optimisation failed
return auxlib::inv_sym(out);
}
return auxlib::inv(out);
@@ -348,7 +336,7 @@ op_inv_gen_rcond::apply_direct(Mat<typename T1::elem_type>& out, op_inv_gen_stat
if(is_op_diagmat<T1>::value || out.is_diagmat())
{
arma_debug_print("op_inv_gen_rcond: detected diagonal matrix");
arma_debug_print("op_inv_gen_rcond: diag optimisation");
out_state.is_diag = true;
@@ -394,30 +382,18 @@ op_inv_gen_rcond::apply_direct(Mat<typename T1::elem_type>& out, op_inv_gen_stat
if(is_triu_expr || is_tril_expr || is_triu_mat || is_tril_mat)
{
arma_debug_print("op_inv_gen_rcond: tri optimisation");
return auxlib::inv_tr_rcond(out, out_state.rcond, ((is_triu_expr || is_triu_mat) ? uword(0) : uword(1)));
}
const bool try_sympd = arma_config::optimise_sym && ((auxlib::crippled_lapack(out)) ? false : sym_helper::guess_sympd(out));
if(try_sympd)
if( (arma_config::optimise_sym) && (auxlib::crippled_lapack(out) == false) && ( is_sym_expr<T1>::eval(expr.get_ref()) || sym_helper::is_approx_sym(out, uword(100)) ) )
{
arma_debug_print("op_inv_gen_rcond: attempting sympd optimisation");
arma_debug_print("op_inv_gen_rcond: symmetric/hermitian optimisation");
out_state.is_sym = true;
Mat<eT> tmp = out;
bool sympd_state = false;
const bool status = auxlib::inv_sympd_rcond(tmp, sympd_state, out_state.rcond);
if(status) { out.steal_mem(tmp); return true; }
if((status == false) && (sympd_state == true)) { return false; }
arma_debug_print("op_inv_gen_rcond: sympd optimisation failed");
// fallthrough if optimisation failed
return auxlib::inv_sym_rcond(out, out_state.rcond);
}
return auxlib::inv_rcond(out, out_state.rcond);
+3 -5
View File
@@ -191,7 +191,7 @@ op_inv_spd_full::apply_direct(Mat<typename T1::elem_type>& out, const Base<typen
if(is_op_diagmat<T1>::value || out.is_diagmat())
{
arma_debug_print("op_inv_spd_full: detected diagonal matrix");
arma_debug_print("op_inv_spd_full: diag optimisation");
eT* colmem = out.memptr();
@@ -300,7 +300,7 @@ op_inv_spd_rcond::apply_direct(Mat<typename T1::elem_type>& out, op_inv_spd_stat
if(is_op_diagmat<T1>::value || out.is_diagmat())
{
arma_debug_print("op_inv_spd_rcond: detected diagonal matrix");
arma_debug_print("op_inv_spd_rcond: diag optimisation");
out_state.is_diag = true;
@@ -355,9 +355,7 @@ op_inv_spd_rcond::apply_direct(Mat<typename T1::elem_type>& out, op_inv_spd_stat
return true;
}
bool is_sympd_junk = false;
return auxlib::inv_sympd_rcond(out, is_sympd_junk, out_state.rcond);
return auxlib::inv_sympd_rcond(out, out_state.rcond);
}
+1 -1
View File
@@ -202,7 +202,7 @@ op_log_det_sympd::apply_direct(typename T1::pod_type& out_val, const Base<typena
if(is_op_diagmat<T1>::value || A.is_diagmat())
{
arma_debug_print("op_log_det_sympd: detected diagonal matrix");
arma_debug_print("op_log_det_sympd: diag optimisation");
eT* colmem = A.memptr();
+3 -3
View File
@@ -111,7 +111,7 @@ op_logmat::apply_direct(Mat< std::complex<typename T1::elem_type> >& out, const
if(A.is_diagmat())
{
arma_debug_print("op_logmat: detected diagonal matrix");
arma_debug_print("op_logmat: diag optimisation");
const uword N = A.n_rows;
@@ -292,7 +292,7 @@ op_logmat_cx::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename
if(S.is_diagmat())
{
arma_debug_print("op_logmat_cx: detected diagonal matrix");
arma_debug_print("op_logmat_cx: diag optimisation");
const uword N = S.n_rows;
@@ -512,7 +512,7 @@ op_logmat_sympd::apply_direct(Mat<typename T1::elem_type>& out, const Base<typen
if(is_op_diagmat<T1>::value || X.is_diagmat())
{
arma_debug_print("op_logmat_sympd: detected diagonal matrix");
arma_debug_print("op_logmat_sympd: diag optimisation");
out = X;
+15 -20
View File
@@ -393,32 +393,19 @@ op_max::direct_max(const eT* const X, const uword n_elem, uword& index_of_max_va
{
arma_debug_sigprint();
eT max_val_i = priv::most_neg<eT>();
eT max_val_j = priv::most_neg<eT>();
eT best_val = priv::most_neg<eT>();
uword best_index = 0;
uword best_index_i = 0;
uword best_index_j = 0;
uword i,j;
for(i=0, j=1; j<n_elem; i+=2, j+=2)
for(uword i=0; i < n_elem; ++i)
{
const eT X_i = X[i];
const eT X_j = X[j];
const eT val = X[i];
if(X_i > max_val_i) { max_val_i = X_i; best_index_i = i; }
if(X_j > max_val_j) { max_val_j = X_j; best_index_j = j; }
if(val > best_val) { best_val = val; best_index = i; }
}
if(i < n_elem)
{
const eT X_i = X[i];
if(X_i > max_val_i) { max_val_i = X_i; best_index_i = i; }
}
index_of_max_val = best_index;
index_of_max_val = (max_val_i > max_val_j) ? best_index_i : best_index_j;
return (max_val_i > max_val_j) ? max_val_i : max_val_j;
return best_val;
}
@@ -705,6 +692,8 @@ op_max::max_with_index(const Proxy<T1>& P, uword& index_of_max_val)
{
arma_conform_check(true, "max(): object has no elements");
index_of_max_val = 0;
return Datum<eT>::nan;
}
@@ -786,6 +775,8 @@ op_max::max_with_index(const ProxyCube<T1>& P, uword& index_of_max_val)
{
arma_conform_check(true, "max(): object has no elements");
index_of_max_val = 0;
return Datum<eT>::nan;
}
@@ -1160,6 +1151,8 @@ op_max::max_with_index(const Proxy<T1>& P, uword& index_of_max_val)
{
arma_conform_check(true, "max(): object has no elements");
index_of_max_val = 0;
return Datum<eT>::nan;
}
@@ -1263,6 +1256,8 @@ op_max::max_with_index(const ProxyCube<T1>& P, uword& index_of_max_val)
{
arma_conform_check(true, "max(): object has no elements");
index_of_max_val = 0;
return Datum<eT>::nan;
}
+1 -1
View File
@@ -41,7 +41,7 @@ op_median::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_median>& expr)
{
Mat<eT> tmp;
op_median::apply_noalias(out, U.M, dim);
op_median::apply_noalias(tmp, U.M, dim);
out.steal_mem(tmp);
}
+15 -20
View File
@@ -393,32 +393,19 @@ op_min::direct_min(const eT* const X, const uword n_elem, uword& index_of_min_va
{
arma_debug_sigprint();
eT min_val_i = priv::most_pos<eT>();
eT min_val_j = priv::most_pos<eT>();
eT best_val = priv::most_pos<eT>();
uword best_index = 0;
uword best_index_i = 0;
uword best_index_j = 0;
uword i,j;
for(i=0, j=1; j<n_elem; i+=2, j+=2)
for(uword i=0; i < n_elem; ++i)
{
const eT X_i = X[i];
const eT X_j = X[j];
const eT val = X[i];
if(X_i < min_val_i) { min_val_i = X_i; best_index_i = i; }
if(X_j < min_val_j) { min_val_j = X_j; best_index_j = j; }
if(val < best_val) { best_val = val; best_index = i; }
}
if(i < n_elem)
{
const eT X_i = X[i];
if(X_i < min_val_i) { min_val_i = X_i; best_index_i = i; }
}
index_of_min_val = best_index;
index_of_min_val = (min_val_i < min_val_j) ? best_index_i : best_index_j;
return (min_val_i < min_val_j) ? min_val_i : min_val_j;
return best_val;
}
@@ -705,6 +692,8 @@ op_min::min_with_index(const Proxy<T1>& P, uword& index_of_min_val)
{
arma_conform_check(true, "min(): object has no elements");
index_of_min_val = 0;
return Datum<eT>::nan;
}
@@ -786,6 +775,8 @@ op_min::min_with_index(const ProxyCube<T1>& P, uword& index_of_min_val)
{
arma_conform_check(true, "min(): object has no elements");
index_of_min_val = 0;
return Datum<eT>::nan;
}
@@ -1160,6 +1151,8 @@ op_min::min_with_index(const Proxy<T1>& P, uword& index_of_min_val)
{
arma_conform_check(true, "min(): object has no elements");
index_of_min_val = 0;
return Datum<eT>::nan;
}
@@ -1263,6 +1256,8 @@ op_min::min_with_index(const ProxyCube<T1>& P, uword& index_of_min_val)
{
arma_conform_check(true, "min(): object has no elements");
index_of_min_val = 0;
return Datum<eT>::nan;
}
+2 -10
View File
@@ -106,7 +106,7 @@ op_pinv::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1::
if(is_op_diagmat<T1>::value || A.is_diagmat())
{
arma_debug_print("op_pinv: detected diagonal matrix");
arma_debug_print("op_pinv: diag optimisation");
return op_pinv::apply_diag(out, A, tol);
}
@@ -119,15 +119,7 @@ op_pinv::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1::
{
do_sym = is_sym_expr<T1>::eval(expr.get_ref());
if(do_sym == false)
{
bool is_approx_sym = false;
bool is_approx_sympd = false;
sym_helper::analyse_matrix(is_approx_sym, is_approx_sympd, A);
do_sym = ((is_cx<eT>::no) ? (is_approx_sym) : (is_approx_sym && is_approx_sympd));
}
if(do_sym == false) { do_sym = sym_helper::is_approx_sym(A); }
}
if(do_sym)
+33 -10
View File
@@ -96,7 +96,7 @@ op_powmat::apply_direct_positive(Mat<eT>& out, const Mat<eT>& X, const uword y)
if(X.is_diagmat())
{
arma_debug_print("op_powmat: detected diagonal matrix");
arma_debug_print("op_powmat: diag optimisation");
podarray<eT> tmp(N); // use temporary array in case we have aliasing
@@ -194,11 +194,11 @@ op_powmat_cx::apply_direct(Mat< std::complex<typename T1::pod_type> >& out, cons
if(A.is_diagmat())
{
arma_debug_print("op_powmat_cx: detected diagonal matrix");
arma_debug_print("op_powmat_cx: diag optimisation");
podarray<out_eT> tmp(N); // use temporary array in case we have aliasing
for(uword i=0; i<N; ++i) { tmp[i] = eop_aux::pow( std::complex<in_T>(A.at(i,i)), y) ; }
for(uword i=0; i<N; ++i) { tmp[i] = eop_aux::pow( std::complex<in_T>(A.at(i,i)), y ); }
out.zeros(N,N);
@@ -207,11 +207,11 @@ op_powmat_cx::apply_direct(Mat< std::complex<typename T1::pod_type> >& out, cons
return true;
}
const bool try_sympd = arma_config::optimise_sym && sym_helper::guess_sympd(A);
const bool try_sym = arma_config::optimise_sym && sym_helper::is_approx_sym(A);
if(try_sympd)
if(try_sym)
{
arma_debug_print("op_powmat_cx: attempting sympd optimisation");
arma_debug_print("op_powmat_cx: symmetric/hermitian optimisation");
Col<in_T> eigval;
Mat<in_eT> eigvec;
@@ -220,16 +220,39 @@ op_powmat_cx::apply_direct(Mat< std::complex<typename T1::pod_type> >& out, cons
if(eig_status)
{
eigval = pow(eigval, y);
bool all_pos = true;
const Mat<in_eT> tmp = diagmat(eigval) * eigvec.t();
for(uword i=0; i<N; ++i) { all_pos = (eigval[i] <= in_T(0)) ? false : all_pos; }
out = conv_to< Mat<out_eT> >::from(eigvec * tmp);
if(all_pos)
{
arma_debug_print("op_powmat_cx: all_pos = true");
eigval = pow(eigval, y);
const Mat<in_eT> tmp = eigvec * diagmat(eigval);
out = conv_to< Mat<out_eT> >::from(tmp * eigvec.t());
}
else
{
arma_debug_print("op_powmat_cx: all_pos = false");
Col<out_eT> cx_eigval_pow(N, arma_nozeros_indicator());
for(uword i=0; i<N; ++i) { cx_eigval_pow[i] = eop_aux::pow( std::complex<in_T>(eigval[i]), y ); }
const Mat<out_eT> cx_eigvec = conv_to< Mat<out_eT> >::from(eigvec);
const Mat<out_eT> tmp = cx_eigvec * diagmat(cx_eigval_pow);
out = tmp * cx_eigvec.t();
}
return true;
}
arma_debug_print("op_powmat_cx: sympd optimisation failed");
arma_debug_print("op_powmat_cx: symmetric/hermitian optimisation failed");
// fallthrough if optimisation failed
}
+2 -10
View File
@@ -37,7 +37,7 @@ op_rank::apply(uword& out, const Base<typename T1::elem_type,T1>& expr, const ty
if(is_op_diagmat<T1>::value || A.is_diagmat())
{
arma_debug_print("op_rank::apply(): detected diagonal matrix");
arma_debug_print("op_rank::apply(): diag optimisation");
return op_rank::apply_diag(out, A, tol);
}
@@ -50,15 +50,7 @@ op_rank::apply(uword& out, const Base<typename T1::elem_type,T1>& expr, const ty
{
do_sym = is_sym_expr<T1>::eval(expr.get_ref());
if(do_sym == false)
{
bool is_approx_sym = false;
bool is_approx_sympd = false;
sym_helper::analyse_matrix(is_approx_sym, is_approx_sympd, A);
do_sym = (is_cx<eT>::no) ? (is_approx_sym) : (is_approx_sym && is_approx_sympd);
}
if(do_sym == false) { do_sym = sym_helper::is_approx_sym(A); }
}
if(do_sym)
+8 -17
View File
@@ -33,6 +33,8 @@ op_rcond::apply(const Base<typename T1::elem_type, T1>& X)
if(strip_trimat<T1>::do_trimat)
{
arma_debug_print("op_rcond::apply(): tri optimisation");
const strip_trimat<T1> S(X.get_ref());
const quasi_unwrap<typename strip_trimat<T1>::stored_type> U(S.M);
@@ -52,7 +54,7 @@ op_rcond::apply(const Base<typename T1::elem_type, T1>& X)
if(is_op_diagmat<T1>::value || A.is_diagmat())
{
arma_debug_print("op_rcond::apply(): detected diagonal matrix");
arma_debug_print("op_rcond::apply(): diag optimisation");
const eT* colmem = A.memptr();
const uword N = A.n_rows;
@@ -80,29 +82,18 @@ op_rcond::apply(const Base<typename T1::elem_type, T1>& X)
if(is_triu || is_tril)
{
arma_debug_print("op_rcond::apply(): tri optimisation");
const uword layout = (is_triu) ? uword(0) : uword(1);
return auxlib::rcond_trimat(A, layout);
}
const bool try_sympd = arma_config::optimise_sym && (auxlib::crippled_lapack(A) ? false : sym_helper::guess_sympd(A));
if(try_sympd)
if( (arma_config::optimise_sym) && (auxlib::crippled_lapack(A) == false) && ( is_sym_expr<T1>::eval(X.get_ref()) || sym_helper::is_approx_sym(A, uword(100)) ) )
{
arma_debug_print("op_rcond::apply(): attempting sympd optimisation");
arma_debug_print("op_rcond::apply(): symmetric/hermitian optimisation");
bool calc_ok = false;
const T out_val = auxlib::rcond_sympd(A, calc_ok);
if(calc_ok) { return out_val; }
arma_debug_print("op_rcond::apply(): sympd optimisation failed");
// auxlib::rcond_sympd() may have failed because A isn't really sympd
// restore A, as auxlib::rcond_sympd() may have destroyed it
A = X.get_ref();
// fallthrough to the next return statement
return auxlib::rcond_sym(A);
}
return auxlib::rcond(A);
+18 -4
View File
@@ -81,12 +81,19 @@ op_reshape::apply_mat_inplace(Mat<eT>& A, const uword new_n_rows, const uword ne
{
arma_debug_sigprint();
if( (A.n_rows == new_n_rows) && (A.n_cols == new_n_cols) ) { return; }
arma_conform_check( (A.vec_state == 1) && (new_n_cols != 1), "reshape(): requested size is not compatible with column vector layout" );
arma_conform_check( (A.vec_state == 2) && (new_n_rows != 1), "reshape(): requested size is not compatible with row vector layout" );
const uword new_n_elem = new_n_rows * new_n_cols;
if(A.is_empty()) { A.zeros(new_n_rows, new_n_cols); return; }
if(A.n_elem == new_n_elem) { A.set_size(new_n_rows, new_n_cols); return; }
const bool is_into_empty = ( (new_n_cols == uword(0)) || (new_n_rows == uword(0)) );
const bool is_into_colvec = ( (new_n_cols == uword(1)) && (new_n_rows == A.n_elem) );
const bool is_into_rowvec = ( (new_n_rows == uword(1)) && (new_n_cols == A.n_elem) );
const bool is_rowcol_swap = ( (new_n_cols == A.n_rows) && (new_n_rows == A.n_cols) );
if(is_into_empty || is_into_colvec || is_into_rowvec || is_rowcol_swap) { A.set_size(new_n_rows, new_n_cols); return; }
Mat<eT> B;
@@ -208,9 +215,16 @@ op_reshape::apply_cube_inplace(Cube<eT>& A, const uword new_n_rows, const uword
{
arma_debug_sigprint();
const uword new_n_elem = new_n_rows * new_n_cols * new_n_slices;
if( (A.n_rows == new_n_rows) && (A.n_cols == new_n_cols) && (A.n_slices == new_n_slices) ) { return; }
if(A.n_elem == new_n_elem) { A.set_size(new_n_rows, new_n_cols, new_n_slices); return; }
if(A.is_empty()) { A.zeros(new_n_rows, new_n_cols, new_n_slices); return; }
const bool is_into_empty = ( (new_n_cols == uword(0)) || (new_n_rows == uword(0)) || (new_n_slices == uword(0) ) );
const bool is_into_colvec = ( (new_n_cols == uword(1)) && (new_n_rows == A.n_elem) && (new_n_slices == uword(1) ) );
const bool is_into_rowvec = ( (new_n_rows == uword(1)) && (new_n_cols == A.n_elem) && (new_n_slices == uword(1) ) );
const bool is_rowcol_swap = ( (new_n_cols == A.n_rows) && (new_n_rows == A.n_cols) && (new_n_slices == A.n_slices) );
if(is_into_empty || is_into_colvec || is_into_rowvec || is_rowcol_swap) { A.set_size(new_n_rows, new_n_cols, new_n_slices); return; }
Cube<eT> B;
+3 -3
View File
@@ -116,7 +116,7 @@ op_sqrtmat::apply_direct(Mat< std::complex<typename T1::elem_type> >& out, const
if(A.is_diagmat())
{
arma_debug_print("op_sqrtmat: detected diagonal matrix");
arma_debug_print("op_sqrtmat: diag optimisation");
const uword N = A.n_rows;
@@ -325,7 +325,7 @@ op_sqrtmat_cx::apply_direct(Mat<typename T1::elem_type>& out, const Base<typenam
if(S.is_diagmat())
{
arma_debug_print("op_sqrtmat_cx: detected diagonal matrix");
arma_debug_print("op_sqrtmat_cx: diag optimisation");
const uword N = S.n_rows;
@@ -489,7 +489,7 @@ op_sqrtmat_sympd::apply_direct(Mat<typename T1::elem_type>& out, const Base<type
if(is_op_diagmat<T1>::value || X.is_diagmat())
{
arma_debug_print("op_sqrtmat_sympd: detected diagonal matrix");
arma_debug_print("op_sqrtmat_sympd: diag optimisation");
out = X;
-102
View File
@@ -438,108 +438,6 @@ operator-
// TODO: this is an uncommon use case; remove?
//! multiple applications of add/subtract scalars can be condensed
template<typename T1, typename op_type>
inline
typename
enable_if2
<
(is_arma_sparse_type<T1>::value &&
(is_same_type<op_type, op_sp_plus>::value ||
is_same_type<op_type, op_sp_minus_post>::value)),
const SpToDOp<T1, op_sp_minus_post>
>::result
operator-
(
const SpToDOp<T1, op_type>& x,
const typename T1::elem_type k
)
{
arma_debug_sigprint();
const typename T1::elem_type aux = (is_same_type<op_type, op_sp_plus>::value) ? -x.aux : x.aux;
return SpToDOp<T1, op_sp_minus_post>(x.m, aux + k);
}
// TODO: this is an uncommon use case; remove?
//! multiple applications of add/subtract scalars can be condensed
template<typename T1, typename op_type>
inline
typename
enable_if2
<
(is_arma_sparse_type<T1>::value &&
(is_same_type<op_type, op_sp_plus>::value ||
is_same_type<op_type, op_sp_minus_post>::value)),
const SpToDOp<T1, op_sp_minus_pre>
>::result
operator-
(
const typename T1::elem_type k,
const SpToDOp<T1, op_type>& x
)
{
arma_debug_sigprint();
const typename T1::elem_type aux = (is_same_type<op_type, op_sp_plus>::value) ? -x.aux : x.aux;
return SpToDOp<T1, op_sp_minus_pre>(x.m, k + aux);
}
// TODO: this is an uncommon use case; remove?
//! multiple applications of add/subtract scalars can be condensed
template<typename T1, typename op_type>
inline
typename
enable_if2
<
(is_arma_sparse_type<T1>::value &&
is_same_type<op_type, op_sp_minus_pre>::value),
const SpToDOp<T1, op_sp_minus_pre>
>::result
operator-
(
const SpToDOp<T1, op_type>& x,
const typename T1::elem_type k
)
{
arma_debug_sigprint();
return SpToDOp<T1, op_sp_minus_pre>(x.m, x.aux - k);
}
// TODO: this is an uncommon use case; remove?
//! multiple applications of add/subtract scalars can be condensed
template<typename T1, typename op_type>
inline
typename
enable_if2
<
(is_arma_sparse_type<T1>::value &&
is_same_type<op_type, op_sp_minus_pre>::value),
const SpToDOp<T1, op_sp_plus>
>::result
operator-
(
const typename T1::elem_type k,
const SpToDOp<T1, op_type>& x
)
{
arma_debug_sigprint();
return SpToDOp<T1, op_sp_plus>(x.m, k - x.aux);
}
template<typename parent, unsigned int mode, typename T2>
arma_inline
Mat<typename parent::elem_type>
-103
View File
@@ -370,109 +370,6 @@ operator+
// TODO: this is an uncommon use case; remove?
//! multiple applications of add/subtract scalars can be condensed
template<typename T1, typename op_type>
inline
typename
enable_if2
<
(is_arma_sparse_type<T1>::value &&
(is_same_type<op_type, op_sp_plus>::value ||
is_same_type<op_type, op_sp_minus_post>::value)),
const SpToDOp<T1, op_sp_plus>
>::result
operator+
(
const SpToDOp<T1, op_type>& x,
const typename T1::elem_type k
)
{
arma_debug_sigprint();
const typename T1::elem_type aux = (is_same_type<op_type, op_sp_plus>::value) ? x.aux : -x.aux;
return SpToDOp<T1, op_sp_plus>(x.m, aux + k);
}
// TODO: this is an uncommon use case; remove?
//! multiple applications of add/subtract scalars can be condensed
template<typename T1, typename op_type>
inline
typename
enable_if2
<
(is_arma_sparse_type<T1>::value &&
is_same_type<op_type, op_sp_minus_pre>::value),
const SpToDOp<T1, op_sp_minus_pre>
>::result
operator+
(
const SpToDOp<T1, op_type>& x,
const typename T1::elem_type k
)
{
arma_debug_sigprint();
return SpToDOp<T1, op_sp_minus_pre>(x.m, x.aux + k);
}
// TODO: this is an uncommon use case; remove?
//! multiple applications of add/subtract scalars can be condensed
template<typename T1, typename op_type>
inline
typename
enable_if2
<
(is_arma_sparse_type<T1>::value &&
(is_same_type<op_type, op_sp_plus>::value ||
is_same_type<op_type, op_sp_minus_post>::value)),
const SpToDOp<T1, op_sp_plus>
>::result
operator+
(
const typename T1::elem_type k,
const SpToDOp<T1, op_type>& x
)
{
arma_debug_sigprint();
const typename T1::elem_type aux = (is_same_type<op_type, op_sp_plus>::value) ? x.aux : -x.aux;
return SpToDOp<T1, op_sp_plus>(x.m, aux + k);
}
// TODO: this is an uncommon use case; remove?
//! multiple applications of add/subtract scalars can be condensed
template<typename T1, typename op_type>
inline
typename
enable_if2
<
(is_arma_sparse_type<T1>::value &&
is_same_type<op_type, op_sp_minus_pre>::value),
const SpToDOp<T1, op_sp_minus_pre>
>::result
operator+
(
const typename T1::elem_type k,
const SpToDOp<T1, op_type>& x
)
{
arma_debug_sigprint();
return SpToDOp<T1, op_sp_minus_pre>(x.m, x.aux + k);
}
template<typename parent, unsigned int mode, typename T2>
arma_inline
Mat<typename parent::elem_type>
@@ -2027,6 +2027,7 @@ sp_auxlib::run_aupd_plain
arma_ignore(n_eigvals);
arma_ignore(which);
arma_ignore(X);
arma_ignore(Xst);
arma_ignore(sym);
arma_ignore(n);
arma_ignore(tol);
+5 -2
View File
@@ -201,6 +201,9 @@ class subview : public Base< eT, subview<eT> >
inline void swap_rows(const uword in_row1, const uword in_row2);
inline void swap_cols(const uword in_col1, const uword in_col2);
template<typename eT2>
inline bool is_alias(const Mat<eT2>& X) const;
class const_iterator;
@@ -428,8 +431,8 @@ class subview_col : public subview<eT>
arma_warn_unused inline eT min() const;
arma_warn_unused inline eT max() const;
inline eT min(uword& index_of_min_val) const;
inline eT max(uword& index_of_max_val) const;
arma_frown("use .index_min() instead") inline eT min(uword& index_of_min_val) const;
arma_frown("use .index_max() instead") inline eT max(uword& index_of_max_val) const;
arma_warn_unused inline uword index_min() const;
arma_warn_unused inline uword index_max() const;
@@ -43,7 +43,7 @@ class subview_cube_each_common
// NOTE: deliberately not derived from BaseCube
template<typename eT>
class subview_cube_each1 : public subview_cube_each_common<eT>
{
@@ -71,6 +71,7 @@ class subview_cube_each1 : public subview_cube_each_common<eT>
// NOTE: deliberately not derived from BaseCube
template<typename eT, typename TB>
class subview_cube_each2 : public subview_cube_each_common<eT>
{
@@ -50,7 +50,7 @@ class subview_each_common
// NOTE: deliberately not derived from Base
template<typename parent, unsigned int mode>
class subview_each1 : public subview_each_common<parent, mode>
{
@@ -80,6 +80,7 @@ class subview_each1 : public subview_each_common<parent, mode>
// NOTE: deliberately not derived from Base
template<typename parent, unsigned int mode, typename TB>
class subview_each2 : public subview_each_common<parent, mode>
{
@@ -99,6 +99,9 @@ class subview_elem1 : public Base< eT, subview_elem1<eT,T1> >
inline static void schur_inplace(Mat<eT>& out, const subview_elem1& in);
inline static void div_inplace(Mat<eT>& out, const subview_elem1& in);
template<typename eT2>
inline bool is_alias(const Mat<eT2>& X) const;
friend class Mat<eT>;
friend class Cube<eT>;
+44 -38
View File
@@ -67,11 +67,10 @@ subview_elem1<eT,T1>::inplace_op(const eT val)
const unwrap_check_mixed<T1> tmp(a.get_ref(), m_local);
const umat& aa = tmp.M;
arma_conform_check
(
( (aa.is_vec() == false) && (aa.is_empty() == false) ),
"Mat::elem(): given object must be a vector"
);
if(resolves_to_vector<T1>::no)
{
arma_conform_check( ( (aa.is_vec() == false) && (aa.is_empty() == false) ), "Mat::elem(): given object must be a vector" );
}
const uword* aa_mem = aa.memptr();
const uword aa_n_elem = aa.n_elem;
@@ -220,11 +219,10 @@ subview_elem1<eT,T1>::inplace_op(const Base<eT,T2>& x)
const unwrap_check_mixed<T1> aa_tmp(a.get_ref(), m_local);
const umat& aa = aa_tmp.M;
arma_conform_check
(
( (aa.is_vec() == false) && (aa.is_empty() == false) ),
"Mat::elem(): given object must be a vector"
);
if(resolves_to_vector<T1>::no)
{
arma_conform_check( ( (aa.is_vec() == false) && (aa.is_empty() == false) ), "Mat::elem(): given object must be a vector" );
}
const uword* aa_mem = aa.memptr();
const uword aa_n_elem = aa.n_elem;
@@ -233,9 +231,9 @@ subview_elem1<eT,T1>::inplace_op(const Base<eT,T2>& x)
arma_conform_check( (aa_n_elem != P.get_n_elem()), "Mat::elem(): size mismatch" );
const bool is_alias = P.is_alias(m);
const bool have_alias = P.is_alias(m);
if( (is_alias == false) && (Proxy<T2>::use_at == false) )
if( (have_alias == false) && (Proxy<T2>::use_at == false) )
{
typename Proxy<T2>::ea_type X = P.get_ea();
@@ -271,7 +269,7 @@ subview_elem1<eT,T1>::inplace_op(const Base<eT,T2>& x)
{
arma_debug_print("subview_elem1::inplace_op(): aliasing or use_at detected");
const unwrap_check<typename Proxy<T2>::stored_type> tmp(P.Q, is_alias);
const unwrap_check<typename Proxy<T2>::stored_type> tmp(P.Q, have_alias);
const Mat<eT>& M = tmp.M;
const eT* X = M.memptr();
@@ -358,11 +356,10 @@ subview_elem1<eT,T1>::replace(const eT old_val, const eT new_val)
const unwrap_check_mixed<T1> tmp(a.get_ref(), m_local);
const umat& aa = tmp.M;
arma_conform_check
(
( (aa.is_vec() == false) && (aa.is_empty() == false) ),
"Mat::elem(): given object must be a vector"
);
if(resolves_to_vector<T1>::no)
{
arma_conform_check( ( (aa.is_vec() == false) && (aa.is_empty() == false) ), "Mat::elem(): given object must be a vector" );
}
const uword* aa_mem = aa.memptr();
const uword aa_n_elem = aa.n_elem;
@@ -480,11 +477,10 @@ subview_elem1<eT,T1>::randu()
const unwrap_check_mixed<T1> tmp(a.get_ref(), m_local);
const umat& aa = tmp.M;
arma_conform_check
(
( (aa.is_vec() == false) && (aa.is_empty() == false) ),
"Mat::elem(): given object must be a vector"
);
if(resolves_to_vector<T1>::no)
{
arma_conform_check( ( (aa.is_vec() == false) && (aa.is_empty() == false) ), "Mat::elem(): given object must be a vector" );
}
const uword* aa_mem = aa.memptr();
const uword aa_n_elem = aa.n_elem;
@@ -531,11 +527,10 @@ subview_elem1<eT,T1>::randn()
const unwrap_check_mixed<T1> tmp(a.get_ref(), m_local);
const umat& aa = tmp.M;
arma_conform_check
(
( (aa.is_vec() == false) && (aa.is_empty() == false) ),
"Mat::elem(): given object must be a vector"
);
if(resolves_to_vector<T1>::no)
{
arma_conform_check( ( (aa.is_vec() == false) && (aa.is_empty() == false) ), "Mat::elem(): given object must be a vector" );
}
const uword* aa_mem = aa.memptr();
const uword aa_n_elem = aa.n_elem;
@@ -788,11 +783,10 @@ subview_elem1<eT,T1>::extract(Mat<eT>& actual_out, const subview_elem1<eT,T1>& i
const unwrap_check_mixed<T1> tmp1(in.a.get_ref(), actual_out);
const umat& aa = tmp1.M;
arma_conform_check
(
( (aa.is_vec() == false) && (aa.is_empty() == false) ),
"Mat::elem(): given object must be a vector"
);
if(resolves_to_vector<T1>::no)
{
arma_conform_check( ( (aa.is_vec() == false) && (aa.is_empty() == false) ), "Mat::elem(): given object must be a vector" );
}
const uword* aa_mem = aa.memptr();
const uword aa_n_elem = aa.n_elem;
@@ -854,11 +848,10 @@ subview_elem1<eT,T1>::mat_inplace_op(Mat<eT>& out, const subview_elem1& in)
const unwrap<T1> tmp1(in.a.get_ref());
const umat& aa = tmp1.M;
arma_conform_check
(
( (aa.is_vec() == false) && (aa.is_empty() == false) ),
"Mat::elem(): given object must be a vector"
);
if(resolves_to_vector<T1>::no)
{
arma_conform_check( ( (aa.is_vec() == false) && (aa.is_empty() == false) ), "Mat::elem(): given object must be a vector" );
}
const uword* aa_mem = aa.memptr();
const uword aa_n_elem = aa.n_elem;
@@ -950,4 +943,17 @@ subview_elem1<eT,T1>::div_inplace(Mat<eT>& out, const subview_elem1& in)
template<typename eT, typename T1>
template<typename eT2>
inline
bool
subview_elem1<eT,T1>::is_alias(const Mat<eT2>& X) const
{
arma_debug_sigprint();
return (m.is_alias(X) || a.get_ref().is_alias(X));
}
//! @}
@@ -103,6 +103,9 @@ class subview_elem2 : public Base< eT, subview_elem2<eT,T1,T2> >
inline static void schur_inplace(Mat<eT>& out, const subview_elem2& in);
inline static void div_inplace(Mat<eT>& out, const subview_elem2& in);
template<typename eT2>
inline bool is_alias(const Mat<eT2>& X) const;
friend class Mat<eT>;
};
@@ -870,4 +870,17 @@ subview_elem2<eT,T1,T2>::div_inplace(Mat<eT>& out, const subview_elem2& in)
template<typename eT, typename T1, typename T2>
template<typename eT2>
inline
bool
subview_elem2<eT,T1,T2>::is_alias(const Mat<eT2>& X) const
{
arma_debug_sigprint();
return (m.is_alias(X) || base_ri.get_ref().is_alias(X) || base_ci.get_ref().is_alias(X));
}
//! @}
+13
View File
@@ -2617,6 +2617,19 @@ subview<eT>::swap_cols(const uword in_col1, const uword in_col2)
template<typename eT>
template<typename eT2>
inline
bool
subview<eT>::is_alias(const Mat<eT2>& X) const
{
arma_debug_sigprint();
return m.is_alias(X);
}
template<typename eT>
inline
typename subview<eT>::iterator
+83 -82
View File
@@ -50,19 +50,26 @@ guess_sympd_worker(const Mat<eT>& A)
const eT* A_mem = A.memptr();
const eT* A_col = A_mem;
bool diag_below_tol = true;
eT max_diag = eT(0);
for(uword j=0; j < N; ++j)
{
const eT A_jj = A_col[j];
if(A_jj <= eT(0)) { return false; }
if( A_jj <= eT(0)) { return false; }
if(arma_isfinite(A_jj) == false) { return false; }
if(A_jj >= tol) { diag_below_tol = false; }
max_diag = (A_jj > max_diag) ? A_jj : max_diag;
A_col += N;
}
if(diag_below_tol) { return false; } // assume matrix is suspect if all diagonal elements are close to zero
A_col = A_mem;
const uword Nm1 = N-1;
@@ -117,6 +124,8 @@ guess_sympd_worker(const Mat<eT>& A)
// NOTE: assuming A is square-sized
// NOTE: the function name is required for overloading, but is a misnomer: it processes complex hermitian matrices
typedef typename get_pod_type<eT>::result T;
const T tol = T(100) * std::numeric_limits<T>::epsilon(); // allow some leeway
@@ -126,21 +135,33 @@ guess_sympd_worker(const Mat<eT>& A)
const eT* A_mem = A.memptr();
const eT* A_col = A_mem;
bool diag_below_tol = true;
T max_diag = T(0);
for(uword j=0; j < N; ++j)
{
const eT& A_jj = A_col[j];
const T A_jj_real = std::real(A_jj);
const T A_jj_imag = std::imag(A_jj);
const T A_jj_r = std::real(A_jj );
const T A_jj_i = std::imag(A_jj );
const T A_jj_rabs = std::abs(A_jj_r);
const T A_jj_iabs = std::abs(A_jj_i);
if( (A_jj_real <= T(0)) || (std::abs(A_jj_imag) > tol) ) { return false; }
if( A_jj_r <= T(0) ) { return false; } // real should be positive
if(arma_isfinite(A_jj_r) == false) { return false; }
max_diag = (A_jj_real > max_diag) ? A_jj_real : max_diag;
if(A_jj_iabs > tol ) { return false; } // imag should be approx zero
if(A_jj_iabs > A_jj_rabs) { return false; } // corner case: real and imag are close to zero, and imag is dominant
if(A_jj_r >= tol) { diag_below_tol = false; }
max_diag = (A_jj_r > max_diag) ? A_jj_r : max_diag;
A_col += N;
}
if(diag_below_tol) { return false; } // assume matrix is suspect if all diagonal elements are close to zero
const T square_max_diag = max_diag * max_diag;
if(arma_isfinite(square_max_diag) == false) { return false; }
@@ -246,14 +267,11 @@ guess_sympd(const Mat<eT>& A, const uword min_n_rows)
template<typename eT>
inline
typename enable_if2<is_cx<eT>::no, void>::result
analyse_matrix_worker(bool& is_approx_sym, bool& is_approx_sympd, const Mat<eT>& A)
typename enable_if2<is_cx<eT>::no, bool>::result
is_approx_sym_worker(const Mat<eT>& A)
{
arma_debug_sigprint();
is_approx_sym = true;
is_approx_sympd = true;
const eT tol = eT(100) * std::numeric_limits<eT>::epsilon(); // allow some leeway
const uword N = A.n_rows;
@@ -261,31 +279,29 @@ analyse_matrix_worker(bool& is_approx_sym, bool& is_approx_sympd, const Mat<eT>&
const eT* A_mem = A.memptr();
const eT* A_col = A_mem;
eT max_diag = eT(0);
bool diag_below_tol = true;
for(uword j=0; j < N; ++j)
{
const eT A_jj = A_col[j];
if(A_jj <= eT(0)) { is_approx_sympd = false; }
if(arma_isfinite(A_jj) == false) { return false; }
max_diag = (A_jj > max_diag) ? A_jj : max_diag;
if(std::abs(A_jj) >= tol) { diag_below_tol = false; }
A_col += N;
}
if(diag_below_tol) { return false; } // assume matrix is suspect if all diagonal elements are close to zero
A_col = A_mem;
const uword Nm1 = N-1;
const uword Np1 = N+1;
for(uword j=0; j < Nm1; ++j)
{
const eT A_jj = A_col[j];
const uword jp1 = j+1;
const eT* A_ji_ptr = &(A_mem[j + jp1*N]); // &(A.at(j,jp1));
const eT* A_ii_ptr = &(A_mem[jp1 + jp1*N]);
const eT* A_ji_ptr = &(A_mem[j + jp1*N]); // &(A.at(j,jp1));
for(uword i=jp1; i < N; ++i)
{
@@ -298,39 +314,29 @@ analyse_matrix_worker(bool& is_approx_sym, bool& is_approx_sympd, const Mat<eT>&
const eT A_delta = (std::abs)(A_ij - A_ji);
const eT A_abs_max = (std::max)(A_ij_abs, A_ji_abs);
if( (A_delta > tol) && (A_delta > (A_abs_max*tol)) ) { is_approx_sym = false; return; }
if(is_approx_sympd)
{
// if( (A_ij_abs >= max_diag) || (A_ji_abs >= max_diag) ) { is_approx_sympd = false; }
if(A_ij_abs >= max_diag) { is_approx_sympd = false; }
const eT A_ii = (*A_ii_ptr);
if( (A_ij_abs + A_ij_abs) >= (A_ii + A_jj) ) { is_approx_sympd = false; }
}
if( (A_delta > tol) && (A_delta > (A_abs_max*tol)) ) { return false; }
A_ji_ptr += N;
A_ii_ptr += Np1;
}
A_col += N;
}
return true;
}
template<typename eT>
inline
typename enable_if2<is_cx<eT>::yes, void>::result
analyse_matrix_worker(bool& is_approx_sym, bool& is_approx_sympd, const Mat<eT>& A)
typename enable_if2<is_cx<eT>::yes, bool>::result
is_approx_sym_worker(const Mat<eT>& A)
{
arma_debug_sigprint();
typedef typename get_pod_type<eT>::result T;
// NOTE: the function name is required for overloading, but is a misnomer: it processes complex hermitian matrices
is_approx_sym = true;
is_approx_sympd = true;
typedef typename get_pod_type<eT>::result T;
const T tol = T(100) * std::numeric_limits<T>::epsilon(); // allow some leeway
@@ -339,37 +345,37 @@ analyse_matrix_worker(bool& is_approx_sym, bool& is_approx_sympd, const Mat<eT>&
const eT* A_mem = A.memptr();
const eT* A_col = A_mem;
T max_diag = T(0);
bool diag_below_tol = true;
// ensure diagonal has approx real-only elements
for(uword j=0; j < N; ++j)
{
const eT& A_jj = A_col[j];
const T A_jj_real = std::real(A_jj);
const T A_jj_imag = std::imag(A_jj);
const T A_jj_r = std::real(A_jj );
const T A_jj_i = std::imag(A_jj );
const T A_jj_rabs = std::abs(A_jj_r);
const T A_jj_iabs = std::abs(A_jj_i);
if( (A_jj_real <= T(0)) || (std::abs(A_jj_imag) > tol) ) { is_approx_sympd = false; }
if(A_jj_iabs > tol ) { return false; } // imag should be approx zero
if(A_jj_iabs > A_jj_rabs) { return false; } // corner case: real and imag are close to zero, and imag is dominant
max_diag = (A_jj_real > max_diag) ? A_jj_real : max_diag;
if(arma_isfinite(A_jj_r) == false) { return false; }
if(A_jj_rabs >= tol) { diag_below_tol = false; }
A_col += N;
}
const T square_max_diag = max_diag * max_diag;
if(arma_isfinite(square_max_diag) == false) { is_approx_sympd = false; }
if(diag_below_tol) { return false; } // assume matrix is suspect if all diagonal elements are close to zero
A_col = A_mem;
const uword Nm1 = N-1;
const uword Np1 = N+1;
for(uword j=0; j < Nm1; ++j)
{
const uword jp1 = j+1;
const eT* A_ji_ptr = &(A_mem[j + jp1*N]); // &(A.at(j,jp1));
const eT* A_ii_ptr = &(A_mem[jp1 + jp1*N]);
const T A_jj_real = std::real(A_col[j]);
const uword jp1 = j+1;
const eT* A_ji_ptr = &(A_mem[j + jp1*N]); // &(A.at(j,jp1));
for(uword i=jp1; i < N; ++i)
{
@@ -390,63 +396,58 @@ analyse_matrix_worker(bool& is_approx_sym, bool& is_approx_sympd, const Mat<eT>&
const T A_real_delta = (std::abs)(A_ij_real - A_ji_real);
const T A_real_abs_max = (std::max)(A_ij_real_abs, A_ji_real_abs);
if( (A_real_delta > tol) && (A_real_delta > (A_real_abs_max*tol)) ) { is_approx_sym = false; return; }
if( (A_real_delta > tol) && (A_real_delta > (A_real_abs_max*tol)) ) { return false; }
const T A_imag_delta = (std::abs)(A_ij_imag + A_ji_imag); // take into account complex conjugate
const T A_imag_abs_max = (std::max)(A_ij_imag_abs, A_ji_imag_abs);
if( (A_imag_delta > tol) && (A_imag_delta > (A_imag_abs_max*tol)) ) { is_approx_sym = false; return; }
if(is_approx_sympd)
{
// avoid using std::abs(), as that is time consuming due to division and std::sqrt()
const T square_A_ij_abs = (A_ij_real * A_ij_real) + (A_ij_imag * A_ij_imag);
if(arma_isfinite(square_A_ij_abs) == false)
{
is_approx_sympd = false;
}
else
{
const T A_ii_real = std::real(*A_ii_ptr);
if( (A_ij_real_abs + A_ij_real_abs) >= (A_ii_real + A_jj_real) ) { is_approx_sympd = false; }
if(square_A_ij_abs >= square_max_diag) { is_approx_sympd = false; }
}
}
if( (A_imag_delta > tol) && (A_imag_delta > (A_imag_abs_max*tol)) ) { return false; }
A_ji_ptr += N;
A_ii_ptr += Np1;
}
A_col += N;
}
return true;
}
template<typename eT>
inline
void
analyse_matrix(bool& is_approx_sym, bool& is_approx_sympd, const Mat<eT>& A)
bool
is_approx_sym(const Mat<eT>& A)
{
arma_debug_sigprint();
if((A.n_rows != A.n_cols) || (A.n_rows < uword(4)))
{
is_approx_sym = false;
is_approx_sympd = false;
return;
}
// analyse matrices with size >= 4x4
analyse_matrix_worker(is_approx_sym, is_approx_sympd, A);
if((A.n_rows != A.n_cols) || (A.n_rows < uword(4))) { return false; }
if(is_approx_sym == false) { is_approx_sympd = false; }
return is_approx_sym_worker(A);
}
template<typename eT>
inline
bool
is_approx_sym(const Mat<eT>& A, const uword min_n_rows)
{
arma_debug_sigprint();
if((A.n_rows != A.n_cols) || (A.n_rows < min_n_rows)) { return false; }
return is_approx_sym_worker(A);
}
//
template<typename eT>
inline
bool
+24
View File
@@ -1343,5 +1343,29 @@ struct is_sym_expr< Glue< Op<Mat<eT>, op_htrans>, Mat<eT>, glue_times > >
}
};
template<typename T1>
struct is_sym_expr< Op<T1, op_symmatu> >
{
static
arma_inline
bool
eval(const Op<T1, op_symmatu>&)
{
return true;
}
};
template<typename T1>
struct is_sym_expr< Op<T1, op_symmatl> >
{
static
arma_inline
bool
eval(const Op<T1, op_symmatl>&)
{
return true;
}
};
//! @}
+144
View File
@@ -1341,6 +1341,150 @@ namespace lapack
}
template<typename eT>
inline
void
sytrf(const char* uplo, const blas_int* n, eT* a, const blas_int* lda, blas_int* ipiv, eT* work, const blas_int* lwork, blas_int* info)
{
arma_type_check(( is_supported_blas_type<eT>::value == false ));
#if defined(ARMA_USE_FORTRAN_HIDDEN_ARGS)
if( is_float<eT>::value) { typedef float T; arma_fortran(arma_ssytrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info, 1); }
else if(is_double<eT>::value) { typedef double T; arma_fortran(arma_dsytrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info, 1); }
#else
if( is_float<eT>::value) { typedef float T; arma_fortran(arma_ssytrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info); }
else if(is_double<eT>::value) { typedef double T; arma_fortran(arma_dsytrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info); }
#endif
}
template<typename eT>
inline
void
hetrf(const char* uplo, const blas_int* n, eT* a, const blas_int* lda, blas_int* ipiv, eT* work, const blas_int* lwork, blas_int* info)
{
arma_type_check(( is_supported_blas_type<eT>::value == false ));
#if defined(ARMA_USE_FORTRAN_HIDDEN_ARGS)
if( is_cx_float<eT>::value) { typedef blas_cxf T; arma_fortran(arma_chetrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info, 1); }
else if(is_cx_double<eT>::value) { typedef blas_cxd T; arma_fortran(arma_zhetrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info, 1); }
#else
if( is_cx_float<eT>::value) { typedef blas_cxf T; arma_fortran(arma_chetrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info); }
else if(is_cx_double<eT>::value) { typedef blas_cxd T; arma_fortran(arma_zhetrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info); }
#endif
}
template<typename eT>
inline
void
sytrs(const char* uplo, const blas_int* n, const blas_int* nrhs, const eT* a, const blas_int* lda, const blas_int* ipiv, eT* b, const blas_int* ldb, blas_int* info)
{
arma_type_check(( is_supported_blas_type<eT>::value == false ));
#if defined(ARMA_USE_FORTRAN_HIDDEN_ARGS)
if( is_float<eT>::value) { typedef float T; arma_fortran(arma_ssytrs)(uplo, n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info, 1); }
else if(is_double<eT>::value) { typedef double T; arma_fortran(arma_dsytrs)(uplo, n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info, 1); }
#else
if( is_float<eT>::value) { typedef float T; arma_fortran(arma_ssytrs)(uplo, n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info); }
else if(is_double<eT>::value) { typedef double T; arma_fortran(arma_dsytrs)(uplo, n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info); }
#endif
}
template<typename eT>
inline
void
hetrs(const char* uplo, const blas_int* n, const blas_int* nrhs, const eT* a, const blas_int* lda, const blas_int* ipiv, eT* b, const blas_int* ldb, blas_int* info)
{
arma_type_check(( is_supported_blas_type<eT>::value == false ));
#if defined(ARMA_USE_FORTRAN_HIDDEN_ARGS)
if( is_cx_float<eT>::value) { typedef blas_cxf T; arma_fortran(arma_chetrs)(uplo, n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info, 1); }
else if(is_cx_double<eT>::value) { typedef blas_cxd T; arma_fortran(arma_zhetrs)(uplo, n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info, 1); }
#else
if( is_cx_float<eT>::value) { typedef blas_cxf T; arma_fortran(arma_chetrs)(uplo, n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info); }
else if(is_cx_double<eT>::value) { typedef blas_cxd T; arma_fortran(arma_zhetrs)(uplo, n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info); }
#endif
}
template<typename eT>
inline
void
sytri(const char* uplo, const blas_int* n, eT* a, const blas_int* lda, const blas_int* ipiv, eT* work, blas_int* info)
{
arma_type_check(( is_supported_blas_type<eT>::value == false ));
#if defined(ARMA_USE_FORTRAN_HIDDEN_ARGS)
if( is_float<eT>::value) { typedef float T; arma_fortran(arma_ssytri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info, 1); }
else if(is_double<eT>::value) { typedef double T; arma_fortran(arma_dsytri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info, 1); }
#else
if( is_float<eT>::value) { typedef float T; arma_fortran(arma_ssytri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info); }
else if(is_double<eT>::value) { typedef double T; arma_fortran(arma_dsytri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info); }
#endif
}
template<typename eT>
inline
void
hetri(const char* uplo, const blas_int* n, eT* a, const blas_int* lda, const blas_int* ipiv, eT* work, blas_int* info)
{
arma_type_check(( is_supported_blas_type<eT>::value == false ));
#if defined(ARMA_USE_FORTRAN_HIDDEN_ARGS)
if( is_cx_float<eT>::value) { typedef blas_cxf T; arma_fortran(arma_chetri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info, 1); }
else if(is_cx_double<eT>::value) { typedef blas_cxd T; arma_fortran(arma_zhetri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info, 1); }
#else
if( is_cx_float<eT>::value) { typedef blas_cxf T; arma_fortran(arma_chetri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info); }
else if(is_cx_double<eT>::value) { typedef blas_cxd T; arma_fortran(arma_zhetri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info); }
#endif
}
template<typename eT>
inline
void
sycon(const char* uplo, const blas_int* n, const eT* a, const blas_int* lda, const blas_int* ipiv, const eT* anorm, eT* rcond, eT* work, blas_int* iwork, blas_int* info)
{
arma_type_check(( is_supported_blas_type<eT>::value == false ));
#if defined(ARMA_USE_FORTRAN_HIDDEN_ARGS)
if( is_float<eT>::value) { typedef float T; arma_fortran(arma_ssycon)(uplo, n, (const T*)a, lda, ipiv, (const T*)anorm, (T*)rcond, (T*)work, iwork, info, 1); }
else if(is_double<eT>::value) { typedef double T; arma_fortran(arma_dsycon)(uplo, n, (const T*)a, lda, ipiv, (const T*)anorm, (T*)rcond, (T*)work, iwork, info, 1); }
#else
if( is_float<eT>::value) { typedef float T; arma_fortran(arma_ssycon)(uplo, n, (const T*)a, lda, ipiv, (const T*)anorm, (T*)rcond, (T*)work, iwork, info); }
else if(is_double<eT>::value) { typedef double T; arma_fortran(arma_dsycon)(uplo, n, (const T*)a, lda, ipiv, (const T*)anorm, (T*)rcond, (T*)work, iwork, info); }
#endif
}
template<typename T>
inline
void
hecon(const char* uplo, const blas_int* n, const std::complex<T>* a, const blas_int* lda, const blas_int* ipiv, const T* anorm, T* rcond, std::complex<T>* work, blas_int* info)
{
arma_type_check(( is_supported_blas_type<T>::value == false ));
#if defined(ARMA_USE_FORTRAN_HIDDEN_ARGS)
if( is_float<T>::value) { typedef float pod_T; typedef blas_cxf cx_T; arma_fortran(arma_checon)(uplo, n, (const cx_T*)a, lda, ipiv, (const pod_T*)anorm, (pod_T*)rcond, (cx_T*)work, info, 1); }
else if(is_double<T>::value) { typedef double pod_T; typedef blas_cxd cx_T; arma_fortran(arma_zhecon)(uplo, n, (const cx_T*)a, lda, ipiv, (const pod_T*)anorm, (pod_T*)rcond, (cx_T*)work, info, 1); }
#else
if( is_float<T>::value) { typedef float pod_T; typedef blas_cxf cx_T; arma_fortran(arma_checon)(uplo, n, (const cx_T*)a, lda, ipiv, (const pod_T*)anorm, (pod_T*)rcond, (cx_T*)work, info); }
else if(is_double<T>::value) { typedef double pod_T; typedef blas_cxd cx_T; arma_fortran(arma_zhecon)(uplo, n, (const cx_T*)a, lda, ipiv, (const pod_T*)anorm, (pod_T*)rcond, (cx_T*)work, info); }
#endif
}
}
+1 -4
View File
@@ -107,12 +107,9 @@ typedef void* void_ptr;
//
#if defined(ARMA_BLAS_LONG_LONG)
#if defined(ARMA_BLAS_64BIT_INT)
typedef long long blas_int;
#define ARMA_MAX_BLAS_INT 0x7fffffffffffffffULL
#elif defined(ARMA_BLAS_LONG)
typedef long blas_int;
#define ARMA_MAX_BLAS_INT 0x7fffffffffffffffUL
#else
typedef int blas_int;
#define ARMA_MAX_BLAS_INT 0x7fffffffU
+6 -6
View File
@@ -1075,8 +1075,8 @@ struct unwrap_check_mixed< Mat<eT1> >
template<typename eT2>
inline
unwrap_check_mixed(const Mat<eT1>& A, const Mat<eT2>& B)
: M_local( (void_ptr(&A) == void_ptr(&B)) ? new Mat<eT1>(A) : nullptr )
, M ( (void_ptr(&A) == void_ptr(&B)) ? (*M_local) : A )
: M_local( ((is_same_type<eT1,eT2>::yes) && (void_ptr(&A) == void_ptr(&B))) ? new Mat<eT1>(A) : nullptr )
, M ( ((is_same_type<eT1,eT2>::yes) && (void_ptr(&A) == void_ptr(&B))) ? (*M_local) : A )
{
arma_debug_sigprint();
}
@@ -1112,8 +1112,8 @@ struct unwrap_check_mixed< Row<eT1> >
template<typename eT2>
inline
unwrap_check_mixed(const Row<eT1>& A, const Mat<eT2>& B)
: M_local( (void_ptr(&A) == void_ptr(&B)) ? new Row<eT1>(A) : nullptr )
, M ( (void_ptr(&A) == void_ptr(&B)) ? (*M_local) : A )
: M_local( ((is_same_type<eT1,eT2>::yes) && (void_ptr(&A) == void_ptr(&B))) ? new Row<eT1>(A) : nullptr )
, M ( ((is_same_type<eT1,eT2>::yes) && (void_ptr(&A) == void_ptr(&B))) ? (*M_local) : A )
{
arma_debug_sigprint();
}
@@ -1150,8 +1150,8 @@ struct unwrap_check_mixed< Col<eT1> >
template<typename eT2>
inline
unwrap_check_mixed(const Col<eT1>& A, const Mat<eT2>& B)
: M_local( (void_ptr(&A) == void_ptr(&B)) ? new Col<eT1>(A) : nullptr )
, M ( (void_ptr(&A) == void_ptr(&B)) ? (*M_local) : A )
: M_local( ((is_same_type<eT1,eT2>::yes) && (void_ptr(&A) == void_ptr(&B))) ? new Col<eT1>(A) : nullptr )
, M ( ((is_same_type<eT1,eT2>::yes) && (void_ptr(&A) == void_ptr(&B))) ? (*M_local) : A )
{
arma_debug_sigprint();
}
+96
View File
@@ -1287,6 +1287,102 @@ extern "C"
arma_fortran_sans_prefix(arma_zpstrf)(uplo, n, a, lda, piv, rank, tol, work, info);
}
void arma_fortran_with_prefix(arma_ssytrf)(const char* uplo, const blas_int* n, float* a, const blas_int* lda, blas_int* ipiv, float* work, const blas_int* lwork, blas_int* info)
{
arma_fortran_sans_prefix(arma_ssytrf)(uplo, n, a, lda, ipiv, work, lwork, info);
}
void arma_fortran_with_prefix(arma_dsytrf)(const char* uplo, const blas_int* n, double* a, const blas_int* lda, blas_int* ipiv, double* work, const blas_int* lwork, blas_int* info)
{
arma_fortran_sans_prefix(arma_dsytrf)(uplo, n, a, lda, ipiv, work, lwork, info);
}
void arma_fortran_with_prefix(arma_chetrf)(const char* uplo, const blas_int* n, blas_cxf* a, const blas_int* lda, blas_int* ipiv, blas_cxf* work, const blas_int* lwork, blas_int* info)
{
arma_fortran_sans_prefix(arma_chetrf)(uplo, n, a, lda, ipiv, work, lwork, info);
}
void arma_fortran_with_prefix(arma_zhetrf)(const char* uplo, const blas_int* n, blas_cxd* a, const blas_int* lda, blas_int* ipiv, blas_cxd* work, const blas_int* lwork, blas_int* info)
{
arma_fortran_sans_prefix(arma_zhetrf)(uplo, n, a, lda, ipiv, work, lwork, info);
}
void arma_fortran_with_prefix(arma_ssytrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const float* a, const blas_int* lda, const blas_int* ipiv, float* b, const blas_int* ldb, blas_int* info)
{
arma_fortran_sans_prefix(arma_ssytrs)(uplo, n, nrhs, a, lda, ipiv, b, ldb, info);
}
void arma_fortran_with_prefix(arma_dsytrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const double* a, const blas_int* lda, const blas_int* ipiv, double* b, const blas_int* ldb, blas_int* info)
{
arma_fortran_sans_prefix(arma_dsytrs)(uplo, n, nrhs, a, lda, ipiv, b, ldb, info);
}
void arma_fortran_with_prefix(arma_chetrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const blas_cxf* a, const blas_int* lda, const blas_int* ipiv, blas_cxf* b, const blas_int* ldb, blas_int* info)
{
arma_fortran_sans_prefix(arma_chetrs)(uplo, n, nrhs, a, lda, ipiv, b, ldb, info);
}
void arma_fortran_with_prefix(arma_zhetrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const blas_cxd* a, const blas_int* lda, const blas_int* ipiv, blas_cxd* b, const blas_int* ldb, blas_int* info)
{
arma_fortran_sans_prefix(arma_zhetrs)(uplo, n, nrhs, a, lda, ipiv, b, ldb, info);
}
void arma_fortran_with_prefix(arma_ssytri)(const char* uplo, const blas_int* n, float* a, const blas_int* lda, const blas_int* ipiv, float* work, blas_int* info)
{
arma_fortran_sans_prefix(arma_ssytri)(uplo, n, a, lda, ipiv, work, info);
}
void arma_fortran_with_prefix(arma_dsytri)(const char* uplo, const blas_int* n, double* a, const blas_int* lda, const blas_int* ipiv, double* work, blas_int* info)
{
arma_fortran_sans_prefix(arma_dsytri)(uplo, n, a, lda, ipiv, work, info);
}
void arma_fortran_with_prefix(arma_chetri)(const char* uplo, const blas_int* n, blas_cxf* a, const blas_int* lda, const blas_int* ipiv, blas_cxf* work, blas_int* info)
{
arma_fortran_sans_prefix(arma_chetri)(uplo, n, a, lda, ipiv, work, info);
}
void arma_fortran_with_prefix(arma_zhetri)(const char* uplo, const blas_int* n, blas_cxd* a, const blas_int* lda, const blas_int* ipiv, blas_cxd* work, blas_int* info)
{
arma_fortran_sans_prefix(arma_zhetri)(uplo, n, a, lda, ipiv, work, info);
}
void arma_fortran_with_prefix(arma_ssycon)(const char* uplo, const blas_int* n, const float* a, const blas_int* lda, const blas_int* ipiv, const float* anorm, float* rcond, float* work, blas_int* iwork, blas_int* info)
{
arma_fortran_sans_prefix(arma_ssycon)(uplo, n, a, lda, ipiv, anorm, rcond, work, iwork, info);
}
void arma_fortran_with_prefix(arma_dsycon)(const char* uplo, const blas_int* n, const double* a, const blas_int* lda, const blas_int* ipiv, const double* anorm, double* rcond, double* work, blas_int* iwork, blas_int* info)
{
arma_fortran_sans_prefix(arma_dsycon)(uplo, n, a, lda, ipiv, anorm, rcond, work, iwork, info);
}
void arma_fortran_with_prefix(arma_checon)(const char* uplo, const blas_int* n, const blas_cxf* a, const blas_int* lda, const blas_int* ipiv, const float* anorm, float* rcond, blas_cxf* work, blas_int* info)
{
arma_fortran_sans_prefix(arma_checon)(uplo, n, a, lda, ipiv, anorm, rcond, work, info);
}
void arma_fortran_with_prefix(arma_zhecon)(const char* uplo, const blas_int* n, const blas_cxd* a, const blas_int* lda, const blas_int* ipiv, const double* anorm, double* rcond, blas_cxd* work, blas_int* info)
{
arma_fortran_sans_prefix(arma_zhecon)(uplo, n, a, lda, ipiv, anorm, rcond, work, info);
}
#endif
+96
View File
@@ -1156,6 +1156,102 @@ extern "C"
arma_fortran_sans_prefix(arma_zpstrf)(uplo, n, a, lda, piv, rank, tol, work, info, uplo_len);
}
void arma_fortran_with_prefix(arma_ssytrf)(const char* uplo, const blas_int* n, float* a, const blas_int* lda, blas_int* ipiv, float* work, const blas_int* lwork, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_ssytrf)(uplo, n, a, lda, ipiv, work, lwork, info, uplo_len);
}
void arma_fortran_with_prefix(arma_dsytrf)(const char* uplo, const blas_int* n, double* a, const blas_int* lda, blas_int* ipiv, double* work, const blas_int* lwork, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_dsytrf)(uplo, n, a, lda, ipiv, work, lwork, info, uplo_len);
}
void arma_fortran_with_prefix(arma_chetrf)(const char* uplo, const blas_int* n, blas_cxf* a, const blas_int* lda, blas_int* ipiv, blas_cxf* work, const blas_int* lwork, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_chetrf)(uplo, n, a, lda, ipiv, work, lwork, info, uplo_len);
}
void arma_fortran_with_prefix(arma_zhetrf)(const char* uplo, const blas_int* n, blas_cxd* a, const blas_int* lda, blas_int* ipiv, blas_cxd* work, const blas_int* lwork, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_zhetrf)(uplo, n, a, lda, ipiv, work, lwork, info, uplo_len);
}
void arma_fortran_with_prefix(arma_ssytrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const float* a, const blas_int* lda, const blas_int* ipiv, float* b, const blas_int* ldb, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_ssytrs)(uplo, n, nrhs, a, lda, ipiv, b, ldb, info, uplo_len);
}
void arma_fortran_with_prefix(arma_dsytrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const double* a, const blas_int* lda, const blas_int* ipiv, double* b, const blas_int* ldb, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_dsytrs)(uplo, n, nrhs, a, lda, ipiv, b, ldb, info, uplo_len);
}
void arma_fortran_with_prefix(arma_chetrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const blas_cxf* a, const blas_int* lda, const blas_int* ipiv, blas_cxf* b, const blas_int* ldb, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_chetrs)(uplo, n, nrhs, a, lda, ipiv, b, ldb, info, uplo_len);
}
void arma_fortran_with_prefix(arma_zhetrs)(const char* uplo, const blas_int* n, const blas_int* nrhs, const blas_cxd* a, const blas_int* lda, const blas_int* ipiv, blas_cxd* b, const blas_int* ldb, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_zhetrs)(uplo, n, nrhs, a, lda, ipiv, b, ldb, info, uplo_len);
}
void arma_fortran_with_prefix(arma_ssytri)(const char* uplo, const blas_int* n, float* a, const blas_int* lda, const blas_int* ipiv, float* work, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_ssytri)(uplo, n, a, lda, ipiv, work, info, uplo_len);
}
void arma_fortran_with_prefix(arma_dsytri)(const char* uplo, const blas_int* n, double* a, const blas_int* lda, const blas_int* ipiv, double* work, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_dsytri)(uplo, n, a, lda, ipiv, work, info, uplo_len);
}
void arma_fortran_with_prefix(arma_chetri)(const char* uplo, const blas_int* n, blas_cxf* a, const blas_int* lda, const blas_int* ipiv, blas_cxf* work, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_chetri)(uplo, n, a, lda, ipiv, work, info, uplo_len);
}
void arma_fortran_with_prefix(arma_zhetri)(const char* uplo, const blas_int* n, blas_cxd* a, const blas_int* lda, const blas_int* ipiv, blas_cxd* work, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_zhetri)(uplo, n, a, lda, ipiv, work, info, uplo_len);
}
void arma_fortran_with_prefix(arma_ssycon)(const char* uplo, const blas_int* n, const float* a, const blas_int* lda, const blas_int* ipiv, const float* anorm, float* rcond, float* work, blas_int* iwork, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_ssycon)(uplo, n, a, lda, ipiv, anorm, rcond, work, iwork, info, uplo_len);
}
void arma_fortran_with_prefix(arma_dsycon)(const char* uplo, const blas_int* n, const double* a, const blas_int* lda, const blas_int* ipiv, const double* anorm, double* rcond, double* work, blas_int* iwork, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_dsycon)(uplo, n, a, lda, ipiv, anorm, rcond, work, iwork, info, uplo_len);
}
void arma_fortran_with_prefix(arma_checon)(const char* uplo, const blas_int* n, const blas_cxf* a, const blas_int* lda, const blas_int* ipiv, const float* anorm, float* rcond, blas_cxf* work, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_checon)(uplo, n, a, lda, ipiv, anorm, rcond, work, info, uplo_len);
}
void arma_fortran_with_prefix(arma_zhecon)(const char* uplo, const blas_int* n, const blas_cxd* a, const blas_int* lda, const blas_int* ipiv, const double* anorm, double* rcond, blas_cxd* work, blas_int* info, blas_len uplo_len)
{
arma_fortran_sans_prefix(arma_zhecon)(uplo, n, a, lda, ipiv, anorm, rcond, work, info, uplo_len);
}
#endif
+356 -335
View File
@@ -28,18 +28,17 @@ TEST_CASE("fn_max_subview_test")
// Mat.max()...
for (size_t r = 50; r < 150; ++r)
{
mat x;
x.randu(r, r);
mat x(r, r, fill::randn);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_subview_max3;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 0, r - 1, r - 1).index_max();
uword x_subview_max2 = x.cols(0, r - 1).index_max();
uword x_subview_max3 = x.rows(0, r - 1).index_max();
const double mval = x.max(x_max);
const double mval1 = x.submat(0, 0, r - 1, r - 1).max(x_subview_max1);
const double mval2 = x.cols(0, r - 1).max(x_subview_max2);
const double mval3 = x.rows(0, r - 1).max(x_subview_max3);
const double mval = x.max();
const double mval1 = x.submat(0, 0, r - 1, r - 1).max();
const double mval2 = x.cols(0, r - 1).max();
const double mval3 = x.rows(0, r - 1).max();
REQUIRE( x_max == x_subview_max1 );
REQUIRE( x_max == x_subview_max2 );
@@ -48,6 +47,8 @@ TEST_CASE("fn_max_subview_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(mval3) );
REQUIRE( mval == Approx(x(x_max)) );
}
}
@@ -57,22 +58,23 @@ TEST_CASE("fn_max_subview_col_test")
{
for (size_t r = 10; r < 50; ++r)
{
vec x;
x.randu(r);
vec x(r, fill::randn);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 0, r - 1, 0).index_max();
uword x_subview_max2 = x.rows(0, r - 1).index_max();
const double mval = x.max(x_max);
const double mval1 = x.submat(0, 0, r - 1, 0).max(x_subview_max1);
const double mval2 = x.rows(0, r - 1).max(x_subview_max2);
const double mval = x.max();
const double mval1 = x.submat(0, 0, r - 1, 0).max();
const double mval2 = x.rows(0, r - 1).max();
REQUIRE( x_max == x_subview_max1 );
REQUIRE( x_max == x_subview_max2 );
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_max)) );
}
}
@@ -82,66 +84,66 @@ TEST_CASE("fn_max_subview_row_test")
{
for (size_t r = 10; r < 50; ++r)
{
rowvec x;
x.randu(r);
rowvec x(r, fill::randn);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 0, 0, r - 1).index_max();
uword x_subview_max2 = x.cols(0, r - 1).index_max();
const double mval = x.max(x_max);
const double mval1 = x.submat(0, 0, 0, r - 1).max(x_subview_max1);
const double mval2 = x.cols(0, r - 1).max(x_subview_max2);
const double mval = x.max();
const double mval1 = x.submat(0, 0, 0, r - 1).max();
const double mval2 = x.cols(0, r - 1).max();
REQUIRE( x_max == x_subview_max1 );
REQUIRE( x_max == x_subview_max2 );
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_max)) );
}
}
TEST_CASE("fn_max_incomplete_subview_test")
{
for (size_t r = 50; r < 150; ++r)
{
mat x;
x.randu(r, r);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_subview_max3;
const double mval = x.max(x_max);
const double mval1 = x.submat(1, 1, r - 2, r - 2).max(x_subview_max1);
const double mval2 = x.cols(1, r - 2).max(x_subview_max2);
const double mval3 = x.rows(1, r - 2).max(x_subview_max3);
uword row, col;
x.max(row, col);
if (row != 0 && row != r - 1 && col != 0 && col != r - 1)
{
uword srow, scol;
srow = x_subview_max1 % (r - 2);
scol = x_subview_max1 / (r - 2);
REQUIRE( x_max == (srow + 1) + r * (scol + 1) );
REQUIRE( x_max == x_subview_max2 + r );
srow = x_subview_max3 % (r - 2);
scol = x_subview_max3 / (r - 2);
REQUIRE( x_max == (srow + 1) + r * scol );
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(mval3) );
}
}
}
// TEST_CASE("fn_max_incomplete_subview_test")
// {
// for (size_t r = 50; r < 150; ++r)
// {
// mat x(r, r, fill::randn);
//
// uword x_max;
// uword x_subview_max1;
// uword x_subview_max2;
// uword x_subview_max3;
//
// const double mval = x.max(x_max);
// const double mval1 = x.submat(1, 1, r - 2, r - 2).max(x_subview_max1);
// const double mval2 = x.cols(1, r - 2).max(x_subview_max2);
// const double mval3 = x.rows(1, r - 2).max(x_subview_max3);
//
// uword row, col;
// x.max(row, col);
//
// if (row != 0 && row != r - 1 && col != 0 && col != r - 1)
// {
// uword srow, scol;
//
// srow = x_subview_max1 % (r - 2);
// scol = x_subview_max1 / (r - 2);
// REQUIRE( x_max == (srow + 1) + r * (scol + 1) );
// REQUIRE( x_max == x_subview_max2 + r );
//
// srow = x_subview_max3 % (r - 2);
// scol = x_subview_max3 / (r - 2);
// REQUIRE( x_max == (srow + 1) + r * scol );
//
// REQUIRE( mval == Approx(mval1) );
// REQUIRE( mval == Approx(mval2) );
// REQUIRE( mval == Approx(mval3) );
// }
// }
// }
@@ -149,16 +151,15 @@ TEST_CASE("fn_max_incomplete_subview_col_test")
{
for (size_t r = 10; r < 50; ++r)
{
vec x;
x.randu(r);
vec x(r, fill::randn);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(1, 0, r - 2, 0).index_max();
uword x_subview_max2 = x.rows(1, r - 2).index_max();
const double mval = x.max(x_max);
const double mval1 = x.submat(1, 0, r - 2, 0).max(x_subview_max1);
const double mval2 = x.rows(1, r - 2).max(x_subview_max2);
const double mval = x.max();
const double mval1 = x.submat(1, 0, r - 2, 0).max();
const double mval2 = x.rows(1, r - 2).max();
if (x_max != 0 && x_max != r - 1)
{
@@ -167,6 +168,8 @@ TEST_CASE("fn_max_incomplete_subview_col_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_max)) );
}
}
}
@@ -177,16 +180,15 @@ TEST_CASE("fn_max_cx_subview_row_test")
{
for (size_t r = 10; r < 50; ++r)
{
cx_rowvec x;
x.randu(r);
cx_rowvec x(r, fill::randn);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 0, 0, r - 1).index_max();
uword x_subview_max2 = x.cols(0, r - 1).index_max();
const std::complex<double> mval = x.max(x_max);
const std::complex<double> mval1 = x.submat(0, 0, 0, r - 1).max(x_subview_max1);
const std::complex<double> mval2 = x.cols(0, r - 1).max(x_subview_max2);
const std::complex<double> mval = x.max();
const std::complex<double> mval1 = x.submat(0, 0, 0, r - 1).max();
const std::complex<double> mval2 = x.cols(0, r - 1).max();
REQUIRE( x_max == x_subview_max1 );
REQUIRE( x_max == x_subview_max2 );
@@ -195,53 +197,55 @@ TEST_CASE("fn_max_cx_subview_row_test")
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_max).real()) );
REQUIRE( mval.imag() == Approx(x(x_max).imag()) );
}
}
TEST_CASE("fn_max_cx_incomplete_subview_test")
{
for (size_t r = 50; r < 150; ++r)
{
cx_mat x;
x.randu(r, r);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_subview_max3;
const std::complex<double> mval = x.max(x_max);
const std::complex<double> mval1 = x.submat(1, 1, r - 2, r - 2).max(x_subview_max1);
const std::complex<double> mval2 = x.cols(1, r - 2).max(x_subview_max2);
const std::complex<double> mval3 = x.rows(1, r - 2).max(x_subview_max3);
uword row, col;
x.max(row, col);
if (row != 0 && row != r - 1 && col != 0 && col != r - 1)
{
uword srow, scol;
srow = x_subview_max1 % (r - 2);
scol = x_subview_max1 / (r - 2);
REQUIRE( x_max == (srow + 1) + r * (scol + 1) );
REQUIRE( x_max == x_subview_max2 + r );
srow = x_subview_max3 % (r - 2);
scol = x_subview_max3 / (r - 2);
REQUIRE( x_max == (srow + 1) + r * scol );
REQUIRE( mval.real() == Approx(mval1.real()) );
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(mval3.real()) );
REQUIRE( mval.imag() == Approx(mval3.imag()) );
}
}
}
// TEST_CASE("fn_max_cx_incomplete_subview_test")
// {
// for (size_t r = 50; r < 150; ++r)
// {
// cx_mat x(r, r, fill::randn);
//
// uword x_max;
// uword x_subview_max1;
// uword x_subview_max2;
// uword x_subview_max3;
//
// const std::complex<double> mval = x.max(x_max);
// const std::complex<double> mval1 = x.submat(1, 1, r - 2, r - 2).max(x_subview_max1);
// const std::complex<double> mval2 = x.cols(1, r - 2).max(x_subview_max2);
// const std::complex<double> mval3 = x.rows(1, r - 2).max(x_subview_max3);
//
// uword row, col;
// x.max(row, col);
//
// if (row != 0 && row != r - 1 && col != 0 && col != r - 1)
// {
// uword srow, scol;
//
// srow = x_subview_max1 % (r - 2);
// scol = x_subview_max1 / (r - 2);
// REQUIRE( x_max == (srow + 1) + r * (scol + 1) );
// REQUIRE( x_max == x_subview_max2 + r );
//
// srow = x_subview_max3 % (r - 2);
// scol = x_subview_max3 / (r - 2);
// REQUIRE( x_max == (srow + 1) + r * scol );
//
// REQUIRE( mval.real() == Approx(mval1.real()) );
// REQUIRE( mval.imag() == Approx(mval1.imag()) );
// REQUIRE( mval.real() == Approx(mval2.real()) );
// REQUIRE( mval.imag() == Approx(mval2.imag()) );
// REQUIRE( mval.real() == Approx(mval3.real()) );
// REQUIRE( mval.imag() == Approx(mval3.imag()) );
// }
// }
// }
@@ -249,16 +253,15 @@ TEST_CASE("fn_max_cx_incomplete_subview_col_test")
{
for (size_t r = 10; r < 50; ++r)
{
cx_vec x;
x.randu(r);
cx_vec x(r, fill::randn);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(1, 0, r - 2, 0).index_max();
uword x_subview_max2 = x.rows(1, r - 2).index_max();
const std::complex<double> mval = x.max(x_max);
const std::complex<double> mval1 = x.submat(1, 0, r - 2, 0).max(x_subview_max1);
const std::complex<double> mval2 = x.rows(1, r - 2).max(x_subview_max2);
const std::complex<double> mval = x.max();
const std::complex<double> mval1 = x.submat(1, 0, r - 2, 0).max();
const std::complex<double> mval2 = x.rows(1, r - 2).max();
if (x_max != 0 && x_max != r - 1)
{
@@ -269,6 +272,9 @@ TEST_CASE("fn_max_cx_incomplete_subview_col_test")
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_max).real()) );
REQUIRE( mval.imag() == Approx(x(x_max).imag()) );
}
}
}
@@ -279,16 +285,15 @@ TEST_CASE("fn_max_cx_incomplete_subview_row_test")
{
for (size_t r = 10; r < 50; ++r)
{
cx_rowvec x;
x.randu(r);
cx_rowvec x(r, fill::randn);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 1, 0, r - 2).index_max();
uword x_subview_max2 = x.cols(1, r - 2).index_max();
const std::complex<double> mval = x.max(x_max);
const std::complex<double> mval1 = x.submat(0, 1, 0, r - 2).max(x_subview_max1);
const std::complex<double> mval2 = x.cols(1, r - 2).max(x_subview_max2);
const std::complex<double> mval = x.max();
const std::complex<double> mval1 = x.submat(0, 1, 0, r - 2).max();
const std::complex<double> mval2 = x.cols(1, r - 2).max();
if (x_max != 0 && x_max != r - 1)
{
@@ -299,73 +304,73 @@ TEST_CASE("fn_max_cx_incomplete_subview_row_test")
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_max).real()) );
REQUIRE( mval.imag() == Approx(x(x_max).imag()) );
}
}
}
TEST_CASE("fn_max_weird_operation_test")
TEST_CASE("fn_max_weird_operation")
{
mat a(10, 10);
mat b(25, 10);
a.randn();
b.randn();
mat a(10, 10, fill::randn);
mat b(25, 10, fill::randn);
mat output = a * b.t();
uword real_max;
uword operation_max;
uword real_max = output.index_max();
uword operation_max = (a * b.t()).index_max();
const double mval = output.max(real_max);
const double other_mval = (a * b.t()).max(operation_max);
const double mval = output.max();
const double other_mval = (a * b.t()).max();
REQUIRE( real_max == operation_max );
REQUIRE( mval == Approx(other_mval) );
REQUIRE( real_max == operation_max );
REQUIRE( mval == Approx(other_mval) );
REQUIRE( mval == Approx(output(real_max)) );
}
TEST_CASE("fn_max_weird_sparse_operation_test")
TEST_CASE("fn_max_weird_sparse_operation")
{
sp_mat a(10, 10);
sp_mat b(25, 10);
a.sprandn(10, 10, 0.3);
b.sprandn(25, 10, 0.3);
sp_mat a; a.sprandn(10, 10, 0.3);
sp_mat b; b.sprandn(25, 10, 0.3);
sp_mat output = a * b.t();
uword real_max;
uword operation_max;
uword real_max = output.index_max();
uword operation_max = (a * b.t()).index_max();
const double mval = output.max(real_max);
const double other_mval = (a * b.t()).max(operation_max);
const double mval = output.max();
const double other_mval = (a * b.t()).max();
REQUIRE( real_max == operation_max );
REQUIRE( mval == Approx(other_mval) );
REQUIRE( real_max == operation_max );
REQUIRE( mval == Approx(other_mval) );
REQUIRE( mval == Approx(output(real_max)) );
}
TEST_CASE("fn_max_spsubview_test")
TEST_CASE("fn_max_sp_subview_test")
{
// We will assume subview.at() works and returns points within the bounds of
// the matrix, so we just have to ensure the results are the same as
// Mat.max()...
for (size_t r = 50; r < 150; ++r)
{
sp_mat x;
x.sprandn(r, r, 0.3);
sp_mat x; x.sprandn(r, r, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_subview_max3;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 0, r - 1, r - 1).index_max();
uword x_subview_max2 = x.cols(0, r - 1).index_max();
uword x_subview_max3 = x.rows(0, r - 1).index_max();
const double mval = x.max(x_max);
const double mval1 = x.submat(0, 0, r - 1, r - 1).max(x_subview_max1);
const double mval2 = x.cols(0, r - 1).max(x_subview_max2);
const double mval3 = x.rows(0, r - 1).max(x_subview_max3);
const double mval = x.max();
const double mval1 = x.submat(0, 0, r - 1, r - 1).max();
const double mval2 = x.cols(0, r - 1).max();
const double mval3 = x.rows(0, r - 1).max();
if (mval != 0.0)
{
@@ -376,6 +381,8 @@ TEST_CASE("fn_max_spsubview_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(mval3) );
REQUIRE( mval == Approx(x(x_max)) );
}
}
}
@@ -386,16 +393,15 @@ TEST_CASE("fn_max_spsubview_col_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_vec x;
x.sprandn(r, 1, 0.3);
sp_vec x; x.sprandn(r, 1, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 0, r - 1, 0).index_max();
uword x_subview_max2 = x.rows(0, r - 1).index_max();
const double mval = x.max(x_max);
const double mval1 = x.submat(0, 0, r - 1, 0).max(x_subview_max1);
const double mval2 = x.rows(0, r - 1).max(x_subview_max2);
const double mval = x.max();
const double mval1 = x.submat(0, 0, r - 1, 0).max();
const double mval2 = x.rows(0, r - 1).max();
if (mval != 0.0)
{
@@ -404,26 +410,27 @@ TEST_CASE("fn_max_spsubview_col_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_max)) );
}
}
}
TEST_CASE("fn_max_spsubview_row_test")
TEST_CASE("fn_max_spsubview_row_max_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_rowvec x;
x.sprandn(1, r, 0.3);
sp_rowvec x; x.sprandn(1, r, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 0, 0, r - 1).index_max();
uword x_subview_max2 = x.cols(0, r - 1).index_max();
const double mval = x.max(x_max);
const double mval1 = x.submat(0, 0, 0, r - 1).max(x_subview_max1);
const double mval2 = x.cols(0, r - 1).max(x_subview_max2);
const double mval = x.max();
const double mval1 = x.submat(0, 0, 0, r - 1).max();
const double mval2 = x.cols(0, r - 1).max();
if (mval != 0.0)
{
@@ -432,68 +439,69 @@ TEST_CASE("fn_max_spsubview_row_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_max)) );
}
}
}
TEST_CASE("fn_max_spincompletesubview_test")
{
for (size_t r = 50; r < 150; ++r)
{
sp_mat x;
x.sprandn(r, r, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_subview_max3;
const double mval = x.max(x_max);
const double mval1 = x.submat(1, 1, r - 2, r - 2).max(x_subview_max1);
const double mval2 = x.cols(1, r - 2).max(x_subview_max2);
const double mval3 = x.rows(1, r - 2).max(x_subview_max3);
uword row, col;
x.max(row, col);
if (row != 0 && row != r - 1 && col != 0 && col != r - 1 && mval != 0.0)
{
uword srow, scol;
srow = x_subview_max1 % (r - 2);
scol = x_subview_max1 / (r - 2);
REQUIRE( x_max == (srow + 1) + r * (scol + 1) );
REQUIRE( x_max == x_subview_max2 + r );
srow = x_subview_max3 % (r - 2);
scol = x_subview_max3 / (r - 2);
REQUIRE( x_max == (srow + 1) + r * scol );
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(mval3) );
}
}
}
// TEST_CASE("fn_max_spincompletesubview_max_test")
// {
// for (size_t r = 50; r < 150; ++r)
// {
// sp_mat x;
// x.sprandn(r, r, 0.3);
//
// uword x_max;
// uword x_subview_max1;
// uword x_subview_max2;
// uword x_subview_max3;
//
// const double mval = x.max(x_max);
// const double mval1 = x.submat(1, 1, r - 2, r - 2).max(x_subview_max1);
// const double mval2 = x.cols(1, r - 2).max(x_subview_max2);
// const double mval3 = x.rows(1, r - 2).max(x_subview_max3);
//
// uword row, col;
// x.max(row, col);
//
// if (row != 0 && row != r - 1 && col != 0 && col != r - 1 && mval != 0.0)
// {
// uword srow, scol;
//
// srow = x_subview_max1 % (r - 2);
// scol = x_subview_max1 / (r - 2);
// REQUIRE( x_max == (srow + 1) + r * (scol + 1) );
// REQUIRE( x_max == x_subview_max2 + r );
//
// srow = x_subview_max3 % (r - 2);
// scol = x_subview_max3 / (r - 2);
// REQUIRE( x_max == (srow + 1) + r * scol );
//
// REQUIRE( mval == Approx(mval1) );
// REQUIRE( mval == Approx(mval2) );
// REQUIRE( mval == Approx(mval3) );
// }
// }
// }
TEST_CASE("fn_max_spincompletesubview_col_test")
TEST_CASE("fn_max_spincompletesubview_col_max_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_vec x;
x.sprandu(r, 1, 0.3);
sp_vec x; x.sprandu(r, 1, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(1, 0, r - 2, 0).index_max();
uword x_subview_max2 = x.rows(1, r - 2).index_max();
const double mval = x.max(x_max);
const double mval1 = x.submat(1, 0, r - 2, 0).max(x_subview_max1);
const double mval2 = x.rows(1, r - 2).max(x_subview_max2);
const double mval = x.max();
const double mval1 = x.submat(1, 0, r - 2, 0).max();
const double mval2 = x.rows(1, r - 2).max();
if (x_max != 0 && x_max != r - 1 && mval != 0.0)
{
@@ -502,26 +510,27 @@ TEST_CASE("fn_max_spincompletesubview_col_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_max)));
}
}
}
TEST_CASE("fn_max_spincompletesubview_row_test")
TEST_CASE("fn_max_spincompletesubview_row_max_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_rowvec x;
x.sprandn(1, r, 0.3);
sp_rowvec x; x.sprandn(1, r, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 1, 0, r - 2).index_max();
uword x_subview_max2 = x.cols(1, r - 2).index_max();
const double mval = x.max(x_max);
const double mval1 = x.submat(0, 1, 0, r - 2).max(x_subview_max1);
const double mval2 = x.cols(1, r - 2).max(x_subview_max2);
const double mval = x.max();
const double mval1 = x.submat(0, 1, 0, r - 2).max();
const double mval2 = x.cols(1, r - 2).max();
if (mval != 0.0 && x_max != 0 && x_max != r - 1)
{
@@ -530,31 +539,32 @@ TEST_CASE("fn_max_spincompletesubview_row_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx( x(x_max) ) );
}
}
}
TEST_CASE("fn_max_cx_spsubview_test")
TEST_CASE("fn_max_sp_cx_subview_max_test")
{
// We will assume subview.at() works and returns points within the bounds of
// the matrix, so we just have to ensure the results are the same as
// Mat.max()...
for (size_t r = 50; r < 150; ++r)
{
sp_cx_mat x;
x.sprandn(r, r, 0.3);
sp_cx_mat x; x.sprandn(r, r, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_subview_max3;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 0, r - 1, r - 1).index_max();
uword x_subview_max2 = x.cols(0, r - 1).index_max();
uword x_subview_max3 = x.rows(0, r - 1).index_max();
const std::complex<double> mval = x.max(x_max);
const std::complex<double> mval1 = x.submat(0, 0, r - 1, r - 1).max(x_subview_max1);
const std::complex<double> mval2 = x.cols(0, r - 1).max(x_subview_max2);
const std::complex<double> mval3 = x.rows(0, r - 1).max(x_subview_max3);
const std::complex<double> mval = x.max();
const std::complex<double> mval1 = x.submat(0, 0, r - 1, r - 1).max();
const std::complex<double> mval2 = x.cols(0, r - 1).max();
const std::complex<double> mval3 = x.rows(0, r - 1).max();
if (mval != std::complex<double>(0.0))
{
@@ -568,26 +578,28 @@ TEST_CASE("fn_max_cx_spsubview_test")
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(mval3.real()) );
REQUIRE( mval.imag() == Approx(mval3.imag()) );
REQUIRE( mval.real() == Approx(x(x_max).real()) );
REQUIRE( mval.imag() == Approx(x(x_max).imag()) );
}
}
}
TEST_CASE("fn_max_cx_spsubview_col_test")
TEST_CASE("fn_max_sp_cx_subview_col_max_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_cx_vec x;
x.sprandn(r, 1, 0.3);
sp_cx_vec x; x.sprandn(r, 1, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 0, r - 1, 0).index_max();
uword x_subview_max2 = x.rows(0, r - 1).index_max();
const std::complex<double> mval = x.max(x_max);
const std::complex<double> mval1 = x.submat(0, 0, r - 1, 0).max(x_subview_max1);
const std::complex<double> mval2 = x.rows(0, r - 1).max(x_subview_max2);
const std::complex<double> mval = x.max();
const std::complex<double> mval1 = x.submat(0, 0, r - 1, 0).max();
const std::complex<double> mval2 = x.rows(0, r - 1).max();
if (mval != std::complex<double>(0.0))
{
@@ -598,26 +610,28 @@ TEST_CASE("fn_max_cx_spsubview_col_test")
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_max).real()) );
REQUIRE( mval.imag() == Approx(x(x_max).imag()) );
}
}
}
TEST_CASE("fn_max_cx_spsubview_row_test")
TEST_CASE("fn_max_sp_cx_subview_row_max_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_cx_rowvec x;
x.sprandn(1, r, 0.3);
sp_cx_rowvec x; x.sprandn(1, r, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 0, 0, r - 1).index_max();
uword x_subview_max2 = x.cols(0, r - 1).index_max();
const std::complex<double> mval = x.max(x_max);
const std::complex<double> mval1 = x.submat(0, 0, 0, r - 1).max(x_subview_max1);
const std::complex<double> mval2 = x.cols(0, r - 1).max(x_subview_max2);
const std::complex<double> mval = x.max();
const std::complex<double> mval1 = x.submat(0, 0, 0, r - 1).max();
const std::complex<double> mval2 = x.cols(0, r - 1).max();
if (mval != std::complex<double>(0.0))
{
@@ -628,71 +642,73 @@ TEST_CASE("fn_max_cx_spsubview_row_test")
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_max).real()) );
REQUIRE( mval.imag() == Approx(x(x_max).imag()) );
}
}
}
TEST_CASE("fn_max_cx_spincompletesubview_test")
{
for (size_t r = 50; r < 150; ++r)
{
sp_cx_mat x;
x.sprandn(r, r, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_subview_max3;
const std::complex<double> mval = x.max(x_max);
const std::complex<double> mval1 = x.submat(1, 1, r - 2, r - 2).max(x_subview_max1);
const std::complex<double> mval2 = x.cols(1, r - 2).max(x_subview_max2);
const std::complex<double> mval3 = x.rows(1, r - 2).max(x_subview_max3);
uword row, col;
x.max(row, col);
if (row != 0 && row != r - 1 && col != 0 && col != r - 1 && mval != std::complex<double>(0.0))
{
uword srow, scol;
srow = x_subview_max1 % (r - 2);
scol = x_subview_max1 / (r - 2);
REQUIRE( x_max == (srow + 1) + r * (scol + 1) );
REQUIRE( x_max == x_subview_max2 + r );
srow = x_subview_max3 % (r - 2);
scol = x_subview_max3 / (r - 2);
REQUIRE( x_max == (srow + 1) + r * scol );
REQUIRE( mval.real() == Approx(mval1.real()) );
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(mval3.real()) );
REQUIRE( mval.imag() == Approx(mval3.imag()) );
}
}
}
// TEST_CASE("fn_max_sp_cx_incomplete_subview_max_test")
// {
// for (size_t r = 50; r < 150; ++r)
// {
// sp_cx_mat x;
// x.sprandn(r, r, 0.3);
//
// uword x_max;
// uword x_subview_max1;
// uword x_subview_max2;
// uword x_subview_max3;
//
// const std::complex<double> mval = x.max(x_max);
// const std::complex<double> mval1 = x.submat(1, 1, r - 2, r - 2).max(x_subview_max1);
// const std::complex<double> mval2 = x.cols(1, r - 2).max(x_subview_max2);
// const std::complex<double> mval3 = x.rows(1, r - 2).max(x_subview_max3);
//
// uword row, col;
// x.max(row, col);
//
// if (row != 0 && row != r - 1 && col != 0 && col != r - 1 && mval != std::complex<double>(0.0))
// {
// uword srow, scol;
//
// srow = x_subview_max1 % (r - 2);
// scol = x_subview_max1 / (r - 2);
// REQUIRE( x_max == (srow + 1) + r * (scol + 1) );
// REQUIRE( x_max == x_subview_max2 + r );
//
// srow = x_subview_max3 % (r - 2);
// scol = x_subview_max3 / (r - 2);
// REQUIRE( x_max == (srow + 1) + r * scol );
//
// REQUIRE( mval.real() == Approx(mval1.real()) );
// REQUIRE( mval.imag() == Approx(mval1.imag()) );
// REQUIRE( mval.real() == Approx(mval2.real()) );
// REQUIRE( mval.imag() == Approx(mval2.imag()) );
// REQUIRE( mval.real() == Approx(mval3.real()) );
// REQUIRE( mval.imag() == Approx(mval3.imag()) );
// }
// }
// }
TEST_CASE("fn_max_cx_spincompletesubview_col_test")
TEST_CASE("fn_max_sp_cx_incomplete_subview_col_max_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_cx_vec x;
x.sprandn(r, 1, 0.3);
arma::sp_cx_vec x; x.sprandn(r, 1, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(1, 0, r - 2, 0).index_max();
uword x_subview_max2 = x.rows(1, r - 2).index_max();
const std::complex<double> mval = x.max(x_max);
const std::complex<double> mval1 = x.submat(1, 0, r - 2, 0).max(x_subview_max1);
const std::complex<double> mval2 = x.rows(1, r - 2).max(x_subview_max2);
const std::complex<double> mval = x.max();
const std::complex<double> mval1 = x.submat(1, 0, r - 2, 0).max();
const std::complex<double> mval2 = x.rows(1, r - 2).max();
if (x_max != 0 && x_max != r - 1 && mval != std::complex<double>(0.0))
{
@@ -703,26 +719,28 @@ TEST_CASE("fn_max_cx_spincompletesubview_col_test")
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_max).real()) );
REQUIRE( mval.imag() == Approx(x(x_max).imag()) );
}
}
}
TEST_CASE("fn_max_cx_spincompletesubview_row_test")
TEST_CASE("fn_max_sp_cx_incomplete_subview_row_max_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_cx_rowvec x;
x.sprandn(1, r, 0.3);
sp_cx_rowvec x; x.sprandn(1, r, 0.3);
uword x_max;
uword x_subview_max1;
uword x_subview_max2;
uword x_max = x.index_max();
uword x_subview_max1 = x.submat(0, 1, 0, r - 2).index_max();
uword x_subview_max2 = x.cols(1, r - 2).index_max();
const std::complex<double> mval = x.max(x_max);
const std::complex<double> mval1 = x.submat(0, 1, 0, r - 2).max(x_subview_max1);
const std::complex<double> mval2 = x.cols(1, r - 2).max(x_subview_max2);
const std::complex<double> mval = x.max();
const std::complex<double> mval1 = x.submat(0, 1, 0, r - 2).max();
const std::complex<double> mval2 = x.cols(1, r - 2).max();
if (x_max != 0 && x_max != r - 1 && mval != std::complex<double>(0.0))
{
@@ -733,6 +751,9 @@ TEST_CASE("fn_max_cx_spincompletesubview_row_test")
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_max).real()) );
REQUIRE( mval.imag() == Approx(x(x_max).imag()) );
}
}
}
+490 -185
View File
@@ -21,44 +21,334 @@
using namespace arma;
TEST_CASE("fn_min_subview_test")
{
// We will assume subview.at() works and returns points within the bounds of
// the matrix, so we just have to ensure the results are the same as
// Mat.min()...
for (size_t r = 50; r < 150; ++r)
{
mat x(r, r, fill::randn);
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 0, r - 1, r - 1).index_min();
uword x_subview_min2 = x.cols(0, r - 1).index_min();
uword x_subview_min3 = x.rows(0, r - 1).index_min();
const double mval = x.min();
const double mval1 = x.submat(0, 0, r - 1, r - 1).min();
const double mval2 = x.cols(0, r - 1).min();
const double mval3 = x.rows(0, r - 1).min();
REQUIRE( x_min == x_subview_min1 );
REQUIRE( x_min == x_subview_min2 );
REQUIRE( x_min == x_subview_min3 );
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(mval3) );
REQUIRE( mval == Approx(x(x_min)) );
}
}
TEST_CASE("fn_min_subview_col_test")
{
for (size_t r = 10; r < 50; ++r)
{
vec x(r, fill::randn);
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 0, r - 1, 0).index_min();
uword x_subview_min2 = x.rows(0, r - 1).index_min();
const double mval = x.min();
const double mval1 = x.submat(0, 0, r - 1, 0).min();
const double mval2 = x.rows(0, r - 1).min();
REQUIRE( x_min == x_subview_min1 );
REQUIRE( x_min == x_subview_min2 );
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_min)) );
}
}
TEST_CASE("fn_min_subview_row_test")
{
for (size_t r = 10; r < 50; ++r)
{
rowvec x(r, fill::randn);
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 0, 0, r - 1).index_min();
uword x_subview_min2 = x.cols(0, r - 1).index_min();
const double mval = x.min();
const double mval1 = x.submat(0, 0, 0, r - 1).min();
const double mval2 = x.cols(0, r - 1).min();
REQUIRE( x_min == x_subview_min1 );
REQUIRE( x_min == x_subview_min2 );
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_min)) );
}
}
// TEST_CASE("fn_min_incomplete_subview_test")
// {
// for (size_t r = 50; r < 150; ++r)
// {
// mat x(r, r, fill::randn);
//
// uword x_min;
// uword x_subview_min1;
// uword x_subview_min2;
// uword x_subview_min3;
//
// const double mval = x.min(x_min);
// const double mval1 = x.submat(1, 1, r - 2, r - 2).min(x_subview_min1);
// const double mval2 = x.cols(1, r - 2).min(x_subview_min2);
// const double mval3 = x.rows(1, r - 2).min(x_subview_min3);
//
// uword row, col;
// x.min(row, col);
//
// if (row != 0 && row != r - 1 && col != 0 && col != r - 1)
// {
// uword srow, scol;
//
// srow = x_subview_min1 % (r - 2);
// scol = x_subview_min1 / (r - 2);
// REQUIRE( x_min == (srow + 1) + r * (scol + 1) );
// REQUIRE( x_min == x_subview_min2 + r );
//
// srow = x_subview_min3 % (r - 2);
// scol = x_subview_min3 / (r - 2);
// REQUIRE( x_min == (srow + 1) + r * scol );
//
// REQUIRE( mval == Approx(mval1) );
// REQUIRE( mval == Approx(mval2) );
// REQUIRE( mval == Approx(mval3) );
// }
// }
// }
TEST_CASE("fn_min_incomplete_subview_col_test")
{
for (size_t r = 10; r < 50; ++r)
{
vec x(r, fill::randn);
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(1, 0, r - 2, 0).index_min();
uword x_subview_min2 = x.rows(1, r - 2).index_min();
const double mval = x.min();
const double mval1 = x.submat(1, 0, r - 2, 0).min();
const double mval2 = x.rows(1, r - 2).min();
if (x_min != 0 && x_min != r - 1)
{
REQUIRE( x_min == x_subview_min1 + 1 );
REQUIRE( x_min == x_subview_min2 + 1 );
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_min)) );
}
}
}
TEST_CASE("fn_min_cx_subview_row_test")
{
for (size_t r = 10; r < 50; ++r)
{
cx_rowvec x(r, fill::randn);
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 0, 0, r - 1).index_min();
uword x_subview_min2 = x.cols(0, r - 1).index_min();
const std::complex<double> mval = x.min();
const std::complex<double> mval1 = x.submat(0, 0, 0, r - 1).min();
const std::complex<double> mval2 = x.cols(0, r - 1).min();
REQUIRE( x_min == x_subview_min1 );
REQUIRE( x_min == x_subview_min2 );
REQUIRE( mval.real() == Approx(mval1.real()) );
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_min).real()) );
REQUIRE( mval.imag() == Approx(x(x_min).imag()) );
}
}
// TEST_CASE("fn_min_cx_incomplete_subview_test")
// {
// for (size_t r = 50; r < 150; ++r)
// {
// cx_mat x(r, r, fill::randn);
//
// uword x_min;
// uword x_subview_min1;
// uword x_subview_min2;
// uword x_subview_min3;
//
// const std::complex<double> mval = x.min(x_min);
// const std::complex<double> mval1 = x.submat(1, 1, r - 2, r - 2).min(x_subview_min1);
// const std::complex<double> mval2 = x.cols(1, r - 2).min(x_subview_min2);
// const std::complex<double> mval3 = x.rows(1, r - 2).min(x_subview_min3);
//
// uword row, col;
// x.min(row, col);
//
// if (row != 0 && row != r - 1 && col != 0 && col != r - 1)
// {
// uword srow, scol;
//
// srow = x_subview_min1 % (r - 2);
// scol = x_subview_min1 / (r - 2);
// REQUIRE( x_min == (srow + 1) + r * (scol + 1) );
// REQUIRE( x_min == x_subview_min2 + r );
//
// srow = x_subview_min3 % (r - 2);
// scol = x_subview_min3 / (r - 2);
// REQUIRE( x_min == (srow + 1) + r * scol );
//
// REQUIRE( mval.real() == Approx(mval1.real()) );
// REQUIRE( mval.imag() == Approx(mval1.imag()) );
// REQUIRE( mval.real() == Approx(mval2.real()) );
// REQUIRE( mval.imag() == Approx(mval2.imag()) );
// REQUIRE( mval.real() == Approx(mval3.real()) );
// REQUIRE( mval.imag() == Approx(mval3.imag()) );
// }
// }
// }
TEST_CASE("fn_min_cx_incomplete_subview_col_test")
{
for (size_t r = 10; r < 50; ++r)
{
cx_vec x(r, fill::randn);
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(1, 0, r - 2, 0).index_min();
uword x_subview_min2 = x.rows(1, r - 2).index_min();
const std::complex<double> mval = x.min();
const std::complex<double> mval1 = x.submat(1, 0, r - 2, 0).min();
const std::complex<double> mval2 = x.rows(1, r - 2).min();
if (x_min != 0 && x_min != r - 1)
{
REQUIRE( x_min == x_subview_min1 + 1 );
REQUIRE( x_min == x_subview_min2 + 1 );
REQUIRE( mval.real() == Approx(mval1.real()) );
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_min).real()) );
REQUIRE( mval.imag() == Approx(x(x_min).imag()) );
}
}
}
TEST_CASE("fn_min_cx_incomplete_subview_row_test")
{
for (size_t r = 10; r < 50; ++r)
{
cx_rowvec x(r, fill::randn);
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 1, 0, r - 2).index_min();
uword x_subview_min2 = x.cols(1, r - 2).index_min();
const std::complex<double> mval = x.min();
const std::complex<double> mval1 = x.submat(0, 1, 0, r - 2).min();
const std::complex<double> mval2 = x.cols(1, r - 2).min();
if (x_min != 0 && x_min != r - 1)
{
REQUIRE( x_min == x_subview_min1 + 1 );
REQUIRE( x_min == x_subview_min2 + 1 );
REQUIRE( mval.real() == Approx(mval1.real()) );
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_min).real()) );
REQUIRE( mval.imag() == Approx(x(x_min).imag()) );
}
}
}
TEST_CASE("fn_min_weird_operation")
{
mat a(10, 10);
mat b(25, 10);
a.randn();
b.randn();
mat a(10, 10, fill::randn);
mat b(25, 10, fill::randn);
mat output = a * b.t();
uword real_min;
uword operation_min;
uword real_min = output.index_min();
uword operation_min = (a * b.t()).index_min();
const double mval = output.min(real_min);
const double other_mval = (a * b.t()).min(operation_min);
const double mval = output.min();
const double other_mval = (a * b.t()).min();
REQUIRE( real_min == operation_min );
REQUIRE( mval == Approx(other_mval) );
REQUIRE( real_min == operation_min );
REQUIRE( mval == Approx(other_mval) );
REQUIRE( mval == Approx(output(real_min)) );
}
TEST_CASE("fn_min_weird_sparse_operation")
{
sp_mat a(10, 10);
sp_mat b(25, 10);
a.sprandn(10, 10, 0.3);
b.sprandn(25, 10, 0.3);
sp_mat a; a.sprandn(10, 10, 0.3);
sp_mat b; b.sprandn(25, 10, 0.3);
sp_mat output = a * b.t();
uword real_min;
uword operation_min;
uword real_min = output.index_min();
uword operation_min = (a * b.t()).index_min();
const double mval = output.min(real_min);
const double other_mval = (a * b.t()).min(operation_min);
const double mval = output.min();
const double other_mval = (a * b.t()).min();
REQUIRE( real_min == operation_min );
REQUIRE( mval == Approx(other_mval) );
REQUIRE( real_min == operation_min );
REQUIRE( mval == Approx(other_mval) );
REQUIRE( mval == Approx(output(real_min)) );
}
@@ -70,18 +360,17 @@ TEST_CASE("fn_min_sp_subview_test")
// Mat.min()...
for (size_t r = 50; r < 150; ++r)
{
sp_mat x;
x.sprandn(r, r, 0.3);
sp_mat x; x.sprandn(r, r, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_subview_min3;
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 0, r - 1, r - 1).index_min();
uword x_subview_min2 = x.cols(0, r - 1).index_min();
uword x_subview_min3 = x.rows(0, r - 1).index_min();
const double mval = x.min(x_min);
const double mval1 = x.submat(0, 0, r - 1, r - 1).min(x_subview_min1);
const double mval2 = x.cols(0, r - 1).min(x_subview_min2);
const double mval3 = x.rows(0, r - 1).min(x_subview_min3);
const double mval = x.min();
const double mval1 = x.submat(0, 0, r - 1, r - 1).min();
const double mval2 = x.cols(0, r - 1).min();
const double mval3 = x.rows(0, r - 1).min();
if (mval != 0.0)
{
@@ -92,6 +381,8 @@ TEST_CASE("fn_min_sp_subview_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(mval3) );
REQUIRE( mval == Approx(x(x_min)) );
}
}
}
@@ -102,16 +393,15 @@ TEST_CASE("fn_min_spsubview_col_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_vec x;
x.sprandn(r, 1, 0.3);
sp_vec x; x.sprandn(r, 1, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 0, r - 1, 0).index_min();
uword x_subview_min2 = x.rows(0, r - 1).index_min();
const double mval = x.min(x_min);
const double mval1 = x.submat(0, 0, r - 1, 0).min(x_subview_min1);
const double mval2 = x.rows(0, r - 1).min(x_subview_min2);
const double mval = x.min();
const double mval1 = x.submat(0, 0, r - 1, 0).min();
const double mval2 = x.rows(0, r - 1).min();
if (mval != 0.0)
{
@@ -120,6 +410,8 @@ TEST_CASE("fn_min_spsubview_col_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_min)) );
}
}
}
@@ -130,16 +422,15 @@ TEST_CASE("fn_min_spsubview_row_min_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_rowvec x;
x.sprandn(1, r, 0.3);
sp_rowvec x; x.sprandn(1, r, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 0, 0, r - 1).index_min();
uword x_subview_min2 = x.cols(0, r - 1).index_min();
const double mval = x.min(x_min);
const double mval1 = x.submat(0, 0, 0, r - 1).min(x_subview_min1);
const double mval2 = x.cols(0, r - 1).min(x_subview_min2);
const double mval = x.min();
const double mval1 = x.submat(0, 0, 0, r - 1).min();
const double mval2 = x.cols(0, r - 1).min();
if (mval != 0.0)
{
@@ -148,51 +439,53 @@ TEST_CASE("fn_min_spsubview_row_min_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_min)) );
}
}
}
TEST_CASE("fn_min_spincompletesubview_min_test")
{
for (size_t r = 50; r < 150; ++r)
{
sp_mat x;
x.sprandn(r, r, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_subview_min3;
const double mval = x.min(x_min);
const double mval1 = x.submat(1, 1, r - 2, r - 2).min(x_subview_min1);
const double mval2 = x.cols(1, r - 2).min(x_subview_min2);
const double mval3 = x.rows(1, r - 2).min(x_subview_min3);
uword row, col;
x.min(row, col);
if (row != 0 && row != r - 1 && col != 0 && col != r - 1 && mval != 0.0)
{
uword srow, scol;
srow = x_subview_min1 % (r - 2);
scol = x_subview_min1 / (r - 2);
REQUIRE( x_min == (srow + 1) + r * (scol + 1) );
REQUIRE( x_min == x_subview_min2 + r );
srow = x_subview_min3 % (r - 2);
scol = x_subview_min3 / (r - 2);
REQUIRE( x_min == (srow + 1) + r * scol );
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(mval3) );
}
}
}
// TEST_CASE("fn_min_spincompletesubview_min_test")
// {
// for (size_t r = 50; r < 150; ++r)
// {
// sp_mat x;
// x.sprandn(r, r, 0.3);
//
// uword x_min;
// uword x_subview_min1;
// uword x_subview_min2;
// uword x_subview_min3;
//
// const double mval = x.min(x_min);
// const double mval1 = x.submat(1, 1, r - 2, r - 2).min(x_subview_min1);
// const double mval2 = x.cols(1, r - 2).min(x_subview_min2);
// const double mval3 = x.rows(1, r - 2).min(x_subview_min3);
//
// uword row, col;
// x.min(row, col);
//
// if (row != 0 && row != r - 1 && col != 0 && col != r - 1 && mval != 0.0)
// {
// uword srow, scol;
//
// srow = x_subview_min1 % (r - 2);
// scol = x_subview_min1 / (r - 2);
// REQUIRE( x_min == (srow + 1) + r * (scol + 1) );
// REQUIRE( x_min == x_subview_min2 + r );
//
// srow = x_subview_min3 % (r - 2);
// scol = x_subview_min3 / (r - 2);
// REQUIRE( x_min == (srow + 1) + r * scol );
//
// REQUIRE( mval == Approx(mval1) );
// REQUIRE( mval == Approx(mval2) );
// REQUIRE( mval == Approx(mval3) );
// }
// }
// }
@@ -200,16 +493,15 @@ TEST_CASE("fn_min_spincompletesubview_col_min_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_vec x;
x.sprandu(r, 1, 0.3);
sp_vec x; x.sprandu(r, 1, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(1, 0, r - 2, 0).index_min();
uword x_subview_min2 = x.rows(1, r - 2).index_min();
const double mval = x.min(x_min);
const double mval1 = x.submat(1, 0, r - 2, 0).min(x_subview_min1);
const double mval2 = x.rows(1, r - 2).min(x_subview_min2);
const double mval = x.min();
const double mval1 = x.submat(1, 0, r - 2, 0).min();
const double mval2 = x.rows(1, r - 2).min();
if (x_min != 0 && x_min != r - 1 && mval != 0.0)
{
@@ -218,6 +510,8 @@ TEST_CASE("fn_min_spincompletesubview_col_min_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx(x(x_min)));
}
}
}
@@ -228,16 +522,15 @@ TEST_CASE("fn_min_spincompletesubview_row_min_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_rowvec x;
x.sprandn(1, r, 0.3);
sp_rowvec x; x.sprandn(1, r, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 1, 0, r - 2).index_min();
uword x_subview_min2 = x.cols(1, r - 2).index_min();
const double mval = x.min(x_min);
const double mval1 = x.submat(0, 1, 0, r - 2).min(x_subview_min1);
const double mval2 = x.cols(1, r - 2).min(x_subview_min2);
const double mval = x.min();
const double mval1 = x.submat(0, 1, 0, r - 2).min();
const double mval2 = x.cols(1, r - 2).min();
if (mval != 0.0 && x_min != 0 && x_min != r - 1)
{
@@ -246,6 +539,8 @@ TEST_CASE("fn_min_spincompletesubview_row_min_test")
REQUIRE( mval == Approx(mval1) );
REQUIRE( mval == Approx(mval2) );
REQUIRE( mval == Approx( x(x_min) ) );
}
}
}
@@ -259,18 +554,17 @@ TEST_CASE("fn_min_sp_cx_subview_min_test")
// Mat.min()...
for (size_t r = 50; r < 150; ++r)
{
sp_cx_mat x;
x.sprandn(r, r, 0.3);
sp_cx_mat x; x.sprandn(r, r, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_subview_min3;
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 0, r - 1, r - 1).index_min();
uword x_subview_min2 = x.cols(0, r - 1).index_min();
uword x_subview_min3 = x.rows(0, r - 1).index_min();
const std::complex<double> mval = x.min(x_min);
const std::complex<double> mval1 = x.submat(0, 0, r - 1, r - 1).min(x_subview_min1);
const std::complex<double> mval2 = x.cols(0, r - 1).min(x_subview_min2);
const std::complex<double> mval3 = x.rows(0, r - 1).min(x_subview_min3);
const std::complex<double> mval = x.min();
const std::complex<double> mval1 = x.submat(0, 0, r - 1, r - 1).min();
const std::complex<double> mval2 = x.cols(0, r - 1).min();
const std::complex<double> mval3 = x.rows(0, r - 1).min();
if (mval != std::complex<double>(0.0))
{
@@ -284,6 +578,9 @@ TEST_CASE("fn_min_sp_cx_subview_min_test")
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(mval3.real()) );
REQUIRE( mval.imag() == Approx(mval3.imag()) );
REQUIRE( mval.real() == Approx(x(x_min).real()) );
REQUIRE( mval.imag() == Approx(x(x_min).imag()) );
}
}
}
@@ -294,16 +591,15 @@ TEST_CASE("fn_min_sp_cx_subview_col_min_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_cx_vec x;
x.sprandn(r, 1, 0.3);
sp_cx_vec x; x.sprandn(r, 1, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 0, r - 1, 0).index_min();
uword x_subview_min2 = x.rows(0, r - 1).index_min();
const std::complex<double> mval = x.min(x_min);
const std::complex<double> mval1 = x.submat(0, 0, r - 1, 0).min(x_subview_min1);
const std::complex<double> mval2 = x.rows(0, r - 1).min(x_subview_min2);
const std::complex<double> mval = x.min();
const std::complex<double> mval1 = x.submat(0, 0, r - 1, 0).min();
const std::complex<double> mval2 = x.rows(0, r - 1).min();
if (mval != std::complex<double>(0.0))
{
@@ -314,6 +610,9 @@ TEST_CASE("fn_min_sp_cx_subview_col_min_test")
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_min).real()) );
REQUIRE( mval.imag() == Approx(x(x_min).imag()) );
}
}
}
@@ -324,16 +623,15 @@ TEST_CASE("fn_min_sp_cx_subview_row_min_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_cx_rowvec x;
x.sprandn(1, r, 0.3);
sp_cx_rowvec x; x.sprandn(1, r, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 0, 0, r - 1).index_min();
uword x_subview_min2 = x.cols(0, r - 1).index_min();
const std::complex<double> mval = x.min(x_min);
const std::complex<double> mval1 = x.submat(0, 0, 0, r - 1).min(x_subview_min1);
const std::complex<double> mval2 = x.cols(0, r - 1).min(x_subview_min2);
const std::complex<double> mval = x.min();
const std::complex<double> mval1 = x.submat(0, 0, 0, r - 1).min();
const std::complex<double> mval2 = x.cols(0, r - 1).min();
if (mval != std::complex<double>(0.0))
{
@@ -344,54 +642,57 @@ TEST_CASE("fn_min_sp_cx_subview_row_min_test")
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_min).real()) );
REQUIRE( mval.imag() == Approx(x(x_min).imag()) );
}
}
}
TEST_CASE("fn_min_sp_cx_incomplete_subview_min_test")
{
for (size_t r = 50; r < 150; ++r)
{
sp_cx_mat x;
x.sprandn(r, r, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_subview_min3;
const std::complex<double> mval = x.min(x_min);
const std::complex<double> mval1 = x.submat(1, 1, r - 2, r - 2).min(x_subview_min1);
const std::complex<double> mval2 = x.cols(1, r - 2).min(x_subview_min2);
const std::complex<double> mval3 = x.rows(1, r - 2).min(x_subview_min3);
uword row, col;
x.min(row, col);
if (row != 0 && row != r - 1 && col != 0 && col != r - 1 && mval != std::complex<double>(0.0))
{
uword srow, scol;
srow = x_subview_min1 % (r - 2);
scol = x_subview_min1 / (r - 2);
REQUIRE( x_min == (srow + 1) + r * (scol + 1) );
REQUIRE( x_min == x_subview_min2 + r );
srow = x_subview_min3 % (r - 2);
scol = x_subview_min3 / (r - 2);
REQUIRE( x_min == (srow + 1) + r * scol );
REQUIRE( mval.real() == Approx(mval1.real()) );
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(mval3.real()) );
REQUIRE( mval.imag() == Approx(mval3.imag()) );
}
}
}
// TEST_CASE("fn_min_sp_cx_incomplete_subview_min_test")
// {
// for (size_t r = 50; r < 150; ++r)
// {
// sp_cx_mat x;
// x.sprandn(r, r, 0.3);
//
// uword x_min;
// uword x_subview_min1;
// uword x_subview_min2;
// uword x_subview_min3;
//
// const std::complex<double> mval = x.min(x_min);
// const std::complex<double> mval1 = x.submat(1, 1, r - 2, r - 2).min(x_subview_min1);
// const std::complex<double> mval2 = x.cols(1, r - 2).min(x_subview_min2);
// const std::complex<double> mval3 = x.rows(1, r - 2).min(x_subview_min3);
//
// uword row, col;
// x.min(row, col);
//
// if (row != 0 && row != r - 1 && col != 0 && col != r - 1 && mval != std::complex<double>(0.0))
// {
// uword srow, scol;
//
// srow = x_subview_min1 % (r - 2);
// scol = x_subview_min1 / (r - 2);
// REQUIRE( x_min == (srow + 1) + r * (scol + 1) );
// REQUIRE( x_min == x_subview_min2 + r );
//
// srow = x_subview_min3 % (r - 2);
// scol = x_subview_min3 / (r - 2);
// REQUIRE( x_min == (srow + 1) + r * scol );
//
// REQUIRE( mval.real() == Approx(mval1.real()) );
// REQUIRE( mval.imag() == Approx(mval1.imag()) );
// REQUIRE( mval.real() == Approx(mval2.real()) );
// REQUIRE( mval.imag() == Approx(mval2.imag()) );
// REQUIRE( mval.real() == Approx(mval3.real()) );
// REQUIRE( mval.imag() == Approx(mval3.imag()) );
// }
// }
// }
@@ -399,16 +700,15 @@ TEST_CASE("fn_min_sp_cx_incomplete_subview_col_min_test")
{
for (size_t r = 10; r < 50; ++r)
{
arma::sp_cx_vec x;
x.sprandn(r, 1, 0.3);
arma::sp_cx_vec x; x.sprandn(r, 1, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(1, 0, r - 2, 0).index_min();
uword x_subview_min2 = x.rows(1, r - 2).index_min();
const std::complex<double> mval = x.min(x_min);
const std::complex<double> mval1 = x.submat(1, 0, r - 2, 0).min(x_subview_min1);
const std::complex<double> mval2 = x.rows(1, r - 2).min(x_subview_min2);
const std::complex<double> mval = x.min();
const std::complex<double> mval1 = x.submat(1, 0, r - 2, 0).min();
const std::complex<double> mval2 = x.rows(1, r - 2).min();
if (x_min != 0 && x_min != r - 1 && mval != std::complex<double>(0.0))
{
@@ -419,6 +719,9 @@ TEST_CASE("fn_min_sp_cx_incomplete_subview_col_min_test")
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_min).real()) );
REQUIRE( mval.imag() == Approx(x(x_min).imag()) );
}
}
}
@@ -429,16 +732,15 @@ TEST_CASE("fn_min_sp_cx_incomplete_subview_row_min_test")
{
for (size_t r = 10; r < 50; ++r)
{
sp_cx_rowvec x;
x.sprandn(1, r, 0.3);
sp_cx_rowvec x; x.sprandn(1, r, 0.3);
uword x_min;
uword x_subview_min1;
uword x_subview_min2;
uword x_min = x.index_min();
uword x_subview_min1 = x.submat(0, 1, 0, r - 2).index_min();
uword x_subview_min2 = x.cols(1, r - 2).index_min();
const std::complex<double> mval = x.min(x_min);
const std::complex<double> mval1 = x.submat(0, 1, 0, r - 2).min(x_subview_min1);
const std::complex<double> mval2 = x.cols(1, r - 2).min(x_subview_min2);
const std::complex<double> mval = x.min();
const std::complex<double> mval1 = x.submat(0, 1, 0, r - 2).min();
const std::complex<double> mval2 = x.cols(1, r - 2).min();
if (x_min != 0 && x_min != r - 1 && mval != std::complex<double>(0.0))
{
@@ -449,6 +751,9 @@ TEST_CASE("fn_min_sp_cx_incomplete_subview_row_min_test")
REQUIRE( mval.imag() == Approx(mval1.imag()) );
REQUIRE( mval.real() == Approx(mval2.real()) );
REQUIRE( mval.imag() == Approx(mval2.imag()) );
REQUIRE( mval.real() == Approx(x(x_min).real()) );
REQUIRE( mval.imag() == Approx(x(x_min).imag()) );
}
}
}
+7 -13
View File
@@ -510,20 +510,14 @@ TEST_CASE("min_max_test")
a(4, 4) = 0.2;
a(5, 4) = 8.3;
uword index, row, col;
REQUIRE( a.min() == Approx(-0.2) );
REQUIRE( a.min(index) == Approx(-0.2) );
REQUIRE( index == 27 );
REQUIRE( a.min(row, col) == Approx(-0.2) );
REQUIRE( row == 3 );
REQUIRE( col == 4 );
REQUIRE( a.max() == Approx(9.8) );
REQUIRE( a.max(index) == Approx(9.8) );
REQUIRE( index == 19 );
REQUIRE( a.max(row, col) == Approx(9.8) );
REQUIRE( row == 1 );
REQUIRE( col == 3 );
REQUIRE( a.max() == Approx( 9.8) );
uword index1 = a.index_min();
uword index2 = a.index_max();
REQUIRE( index1 == 27 );
REQUIRE( index2 == 19 );
}
TEST_CASE("swap_row_test")