Compare commits

...
135 Commits
Author SHA1 Message Date
conrad 80087a3a55 patch bump 2026-05-28 15:12:21 +10:00
conrad d0b07c02a3 skip alias checks when extracting subfield into a fresh field 2026-05-26 22:58:36 +10:00
conrad 1716a6b531 more efficient alias checks 2026-05-26 15:08:10 +10:00
conrad a86cfc932b don't strip const 2026-05-26 12:37:27 +10:00
conrad 8ce3f3aa7d skip alias checks when extracting subview_elem2 into a fresh matrix 2026-05-25 12:49:06 +10:00
conrad 89158f7777 skip alias checks when extracting subview_elem1 into a fresh matrix 2026-05-25 12:29:45 +10:00
conrad cedbd0eb89 simplifications 2026-04-27 10:46:05 +10:00
conrad fd38c47657 better wording 2026-04-27 10:40:02 +10:00
conrad bb5c4469b3 minor fix in error message 2026-04-21 13:50:08 +10:00
conrad 36b0cd37ec patch bump 2026-04-20 00:15:11 +10:00
conrad 59fbefc095 simplifications 2026-04-19 22:59:46 +10:00
conrad b1f3a185bf distinguish between default and user supplied tolerance 2026-04-18 23:48:32 +10:00
conrad adcbf1380a ensure intermediate results are not NaN 2026-04-18 17:45:48 +10:00
conrad 733533f089 ensure intermediate results are not NaN 2026-04-18 17:09:20 +10:00
conrad ae6f216a82 ensure suppled tolerances are not NaN 2026-04-18 17:08:51 +10:00
conrad 417bb37042 ensure default tolerances are not NaN 2026-04-18 16:45:02 +10:00
conrad 95cad27904 ensure default tolerance is finite 2026-04-18 14:13:49 +10:00
conrad 3e66e7b1f0 cleanup 2026-04-16 21:39:49 +10:00
conrad 4a6cc3e9a8 patch bump 2026-04-16 15:14:57 +10:00
conrad 0260b7f1dc fix warning message 2026-04-16 15:09:11 +10:00
conrad 6b180e1943 cleanup 2026-04-16 15:07:09 +10:00
conrad afec1a5f5a use the Proxy only when necessary 2026-04-15 14:10:24 +10:00
conrad 7ab5657470 faster handling of compound vector expressions 2026-04-15 13:42:44 +10:00
conrad fa63e6d717 distinguish between default and user supplied tolerance 2026-04-07 11:33:04 +10:00
conrad bf69c85cb8 show rcond earlier to avoid potential confusion 2026-04-07 10:56:08 +10:00
conrad 5e888a2fc7 simplifications 2026-04-06 21:14:45 +10:00
conrad f0db911a5c handle NaNs when checking ranges 2026-04-06 20:36:34 +10:00
conrad efff7a8f3f simplify warning messages 2026-04-06 19:48:48 +10:00
conrad 7f5569ffba handle NaNs when checking ranges 2026-04-06 19:35:29 +10:00
conrad 7c9ef72802 handle NaNs when checking tolerances 2026-04-05 23:06:49 +10:00
conrad c75af66d72 ensure consistency with subview_row::randu() and subview_row::randn() 2026-04-05 19:40:55 +10:00
conrad ce769c625f handle NaNs when checking tolerances 2026-04-05 02:30:59 +10:00
conrad f1e65e55de handle NaNs when checking conformance 2026-04-05 02:22:30 +10:00
conrad 7e4a956dbd specialisations for randu() and randn() 2026-04-04 19:47:20 +10:00
conrad 43b071020a handle NaNs when checking tolerances 2026-04-02 13:49:58 +10:00
conrad f548057ee7 simplifications 2026-04-02 13:44:30 +10:00
conrad e260407a3e handle NaNs when checking tolerances 2026-04-02 13:09:39 +10:00
conrad f049b04688 simplification: implicit handling of NaNs 2026-04-02 12:33:44 +10:00
conrad 8af4d74bd4 rearrange for consistency with other code 2026-04-01 16:33:36 +10:00
conrad a039d60a47 simplification 2026-03-31 12:42:59 +10:00
conrad a4634e8888 use correct element type 2026-03-31 12:36:05 +10:00
conrad df1eec4fb9 add note on how to enable support for std::int8_t and std::uint8_t 2026-03-30 00:26:09 +10:00
conrad 4524c7580f rearrange ::is_zero() to follow same pattern as arrayops::is_zero() 2026-03-30 00:24:49 +10:00
conrad 536a642b64 add compatibility note 2026-03-28 16:23:34 +10:00
conrad 80e1faa764 shorten temporary suffix and increase its randomness 2026-03-27 11:25:59 +10:00
conrad 4e8e1564e0 simplifications 2026-03-24 12:36:32 +10:00
conrad cd0a21d242 specialisations for .replace() 2026-03-24 12:27:35 +10:00
conrad e43f4f7ef9 fix corner case in is_zero(): explicitly handle nan 2026-03-23 15:23:14 +10:00
conrad f2691c6beb fix corner case in is_zero(): explicitly handle nan 2026-03-23 15:12:22 +10:00
conrad 825dbf7e60 fix corner case in is_zero(): explicitly handle nan 2026-03-23 12:42:46 +10:00
conrad ed078509da fixes for corner cases 2026-03-23 12:17:44 +10:00
conrad 759a36d0b3 fix + specialisations for .is_zero() 2026-03-23 11:59:52 +10:00
conrad e0d2196ae5 faster scalar operations on diagview 2026-03-21 20:06:48 +10:00
conrad 998c7814bc use proper function names in error messages 2026-03-21 11:39:52 +10:00
conrad ebd9209b31 simplify warning messages 2026-03-20 15:34:13 +10:00
conrad 745b02d4d7 simplifications 2026-03-20 14:49:29 +10:00
conrad b28fd1456c update list of changes 2026-03-20 12:54:13 +10:00
conrad 44a7a9cfed add note on arma prefix for span() 2026-03-20 12:38:38 +10:00
conrad ee9e26902f increase randomness of temporary filenames 2026-03-19 14:35:44 +10:00
conrad c14a60deec update year 2026-03-18 11:50:47 +10:00
conrad 33e382b623 simplifications 2026-03-17 12:07:46 +10:00
conrad 7334664999 patch bump 2026-03-15 18:42:19 +10:00
conrad f021766215 speedups for blank sparse submatrices 2026-03-15 17:33:41 +10:00
conrad 5491a20833 simplifications 2026-03-13 12:16:51 +10:00
conrad 1cab3be4df simplifications 2026-03-13 11:52:44 +10:00
conrad 08e1cb5211 specialisation for subview::zeros() 2026-03-13 11:33:39 +10:00
conrad 70c45a2f17 workarounds for ASAN false positives 2026-03-12 18:21:38 +10:00
conrad 2dfed59b94 simplifications 2026-03-12 15:57:37 +10:00
conrad 8bf7834041 simplifications 2026-03-12 15:48:04 +10:00
conrad 1461d33045 simplifications 2026-03-12 15:32:54 +10:00
conrad e05bc82e7b speedups for empty subcubes 2026-03-12 15:30:34 +10:00
conrad 9201e8ddd0 speedups for empty cubes 2026-03-12 15:23:18 +10:00
conrad 30dd62780b speedups for empty cubes 2026-03-12 12:21:15 +10:00
conrad 5dd6c665a5 speedups for empty cubes 2026-03-12 11:55:26 +10:00
conrad 2e6b4ed0a3 speedups for empty cubes 2026-03-11 17:09:31 +10:00
conrad 08c0647e54 speedups for empty matrices 2026-03-11 16:55:26 +10:00
conrad ff7f5d63e6 speedups for empty matrices 2026-03-11 15:12:59 +10:00
conrad 2288ec1497 remove superfluous comments 2026-03-11 15:12:32 +10:00
conrad 1df5fc83b7 speedups for blank sparse matrices 2026-03-10 15:58:00 +10:00
conrad 81df0a1f93 simplifications 2026-03-10 15:51:02 +10:00
conrad bceaf09865 speedups for blank sparse submatrices 2026-03-10 13:14:08 +10:00
conrad 3992546579 speedups for blank sparse submatrices 2026-03-10 12:31:16 +10:00
conrad 602f6217e0 speedups for blank sparse submatrices 2026-03-10 12:01:54 +10:00
conrad 449e6f682f speedups for blank sparse matrices 2026-03-10 11:51:20 +10:00
conrad 03df540096 fix error message 2026-03-09 13:29:19 +10:00
conrad b21700fc85 check if sizes are the same 2026-03-09 13:25:32 +10:00
conrad 02438fff53 speedups for blank sparse submatrices 2026-03-09 13:17:36 +10:00
conrad 451d5d2cec speedups for empty submatrices 2026-03-05 15:50:01 +10:00
conrad 534f135ef5 speedups for empty submatrices 2026-03-04 15:32:54 +10:00
conrad 8bd0d6692a speedups for empty subcubes 2026-03-04 15:24:34 +10:00
conrad ad1bed2686 speedups for empty submatrices 2026-02-28 14:11:47 +10:00
conrad 36e3d67a28 speedups for empty submatrices 2026-02-27 13:35:17 +10:00
conrad e3db651df7 speedup for empty submatrices 2026-02-27 13:07:40 +10:00
conrad fa52e3f5ef speedup for empty subcubes 2026-02-25 13:11:14 +10:00
conrad e6b06b21da speedup for empty matrices 2026-02-23 17:04:55 +10:00
conrad 252708e389 get pointer to first element via dedicated function 2026-02-20 13:17:43 +10:00
conrad 4b468f5009 simplifications 2026-02-20 10:47:28 +10:00
conrad 1244651dda simpler wording 2026-02-11 17:26:57 +10:00
conrad e4b96542b3 improve docs for .col_as_mat() and .row_as_mat() 2026-02-10 12:22:25 +10:00
conrad 5701dd07a8 avoid potentially confusing debug message 2026-02-05 15:21:14 +10:00
conrad bdc89797cd improved wording 2026-02-03 12:15:10 +10:00
conrad 2110b7d82c improved wording and layout 2026-02-03 11:53:05 +10:00
conrad 3bcfde3238 avoid repetition 2026-02-02 16:51:23 +10:00
conrad 3495f87581 better wording 2026-02-02 16:49:09 +10:00
conrad 8a24c0d724 expand fill types 2026-02-02 13:33:39 +10:00
conrad ec75a6107c expand docs for .fill() with notes on element initialisation during construction 2026-01-30 13:29:45 +10:00
conrad 450e1ba8a5 use explicit initialisation 2026-01-29 13:39:36 +10:00
conrad a0dcf97054 use explicit initialisation 2026-01-28 17:11:43 +10:00
conrad cd96c0d9e2 update paper 2026-01-02 12:25:10 +10:00
conrad 5e4ce67bf4 patch bump 2025-12-16 13:25:46 +10:00
conrad 7dbe9fa6c3 add LLM prohibition section 2025-12-16 13:03:19 +10:00
conrad 7da30298dd add RSL section to head 2025-12-15 14:19:05 +10:00
conrad f347a5640e simplification 2025-12-11 19:07:05 +10:00
conrad c7433b6e60 allow memory reuse with size growth 2025-12-11 16:22:29 +10:00
conrad e712b832e8 simplification 2025-12-11 15:14:55 +10:00
conrad 8a736f85a3 reuse memory where possible 2025-12-11 15:09:16 +10:00
conrad 9f8bf056c2 simplification 2025-12-11 14:20:05 +10:00
conrad b79a7e005c use explicit initialisation 2025-12-10 18:57:17 +10:00
conrad cae3a6a4bf optimise .resize() for small vectors that fit within pre-allocated memory 2025-12-10 15:12:17 +10:00
conrad fb6278f692 return early if resized matrix is empty 2025-12-10 15:11:10 +10:00
conrad 8622e81b8a faster repcube() 2025-12-10 12:31:03 +10:00
conrad f788d4032f emit more info on linker config 2025-12-10 12:28:19 +10:00
conrad c2b1eea864 patch bump 2025-11-20 00:09:55 +10:00
conrad 6eb9394e13 prevent bad line breaks 2025-11-17 23:33:52 +10:00
conrad 391a1df2e8 simplification 2025-11-17 23:30:08 +10:00
conrad 7b718b1ae9 sanitise n_threads 2025-11-12 10:43:09 +10:00
conrad bc18db7a51 use ordered clause 2025-11-09 23:42:09 +10:00
conrad 505339b6e5 rename variable 2025-11-09 22:24:17 +10:00
conrad f015fac562 set rng seed for each thread 2025-11-08 19:51:07 +10:00
conrad 502cbca4ba add internal links 2025-10-30 21:44:19 +10:00
conrad 5e5331acd4 cleanup layout 2025-10-30 20:49:25 +10:00
conrad 2dddc1367e add internal link 2025-10-30 20:45:41 +10:00
conrad 5ca720b31f simpler wording 2025-10-30 13:32:01 +10:00
conradsnicta f72922fa68 fix documentation typo 2025-10-30 00:00:52 +00:00
Ryan Curtin c18e7f0aff Fix documentation typo 2025-10-30 00:00:52 +00:00
68 changed files with 2301 additions and 1111 deletions
+4 -2
View File
@@ -381,10 +381,11 @@ else()
set(ARMA_LIBS ${ARMA_LIBS} ${MKL_LIBRARIES})
message(STATUS "")
message(STATUS "*** If the MKL libraries are installed in non-standard locations such as")
message(STATUS "*** If the MKL libraries are installed in a non-standard location such as")
message(STATUS "*** /opt/intel/mkl, /opt/intel/composerxe/, /usr/local/intel/mkl")
message(STATUS "*** make sure the run-time linker can find them.")
message(STATUS "*** On Linux systems this can be done by editing /etc/ld.so.conf")
message(STATUS "*** or specifying the location through a file in /etc/ld.so.conf.d/")
message(STATUS "*** or modifying the LD_LIBRARY_PATH environment variable.")
message(STATUS "")
message(STATUS "*** On systems with SELinux enabled (eg. Fedora, RHEL),")
@@ -419,10 +420,11 @@ else()
endif()
message(STATUS "")
message(STATUS "*** If the OpenBLAS library is installed in")
message(STATUS "*** If the OpenBLAS library is installed in a location such as")
message(STATUS "*** /usr/local/lib or /usr/local/lib64")
message(STATUS "*** make sure the run-time linker can find it.")
message(STATUS "*** On Linux systems this can be done by editing /etc/ld.so.conf")
message(STATUS "*** or specifying the location through a file in /etc/ld.so.conf.d/")
message(STATUS "*** or modifying the LD_LIBRARY_PATH environment variable.")
message(STATUS "")
+2 -2
View File
@@ -1,7 +1,7 @@
Armadillo C++ Linear Algebra Library
Copyright 2008-2025 Conrad Sanderson (https://conradsanderson.id.au)
Copyright 2008-2026 Conrad Sanderson (https://conradsanderson.id.au)
Copyright 2008-2016 National ICT Australia (NICTA)
Copyright 2017-2025 Data61 / CSIRO
Copyright 2017-2026 Data61 / CSIRO
This product includes software developed by Conrad Sanderson (https://conradsanderson.id.au)
This product includes software developed at National ICT Australia (NICTA)
+16 -6
View File
@@ -1,9 +1,9 @@
### Armadillo: C++ Library for Linear Algebra & Scientific Computing
https://arma.sourceforge.net
Copyright 2008-2025 Conrad Sanderson (https://conradsanderson.id.au)
Copyright 2008-2026 Conrad Sanderson (https://conradsanderson.id.au)
Copyright 2008-2016 National ICT Australia (NICTA)
Copyright 2017-2025 Data61 / CSIRO
Copyright 2017-2026 Data61 / CSIRO
---
@@ -38,7 +38,8 @@ Copyright 2017-2025 Data61 / CSIRO
13. [API Stability and Version Policy](#13-api-stability-and-version-policy)
14. [Bug Reports and Frequently Asked Questions](#14-bug-reports-and-frequently-asked-questions)
15. [Related Software Using Armadillo](#15-related-software-using-armadillo)
15. [Prohibition on Use of Large Language Models (LLMs)](#15-prohibition-on-use-of-large-language-models-llms)
16. [Related Software Using Armadillo](#16-related-software-using-armadillo)
---
@@ -390,8 +391,8 @@ Use a web browser to view it.
Use of the C++11 `auto` keyword is not recommended with Armadillo objects and expressions.
Armadillo has a template meta-programming framework which creates short-lived temporaries
that are not properly handled by `auto`.
Armadillo has a template meta-programming framework which creates short-lived
temporary objects that are not properly handled by `auto`.
---
@@ -451,7 +452,16 @@ https://arma.sourceforge.net/faq.html
---
### 15: Related Software Using Armadillo
### 15: Prohibition on Use of Large Language Models (LLMs)
The Armadillo codebase has been developed entirely without the use of LLMs.
We do not accept any code which has been created (directly or indirectly)
with the aid of LLMs. This is due to issues with code provenance and low quality
of LLM generated code.
---
### 16: Related Software Using Armadillo
* MLPACK: extensive library of machine learning algorithms
https://mlpack.org
Binary file not shown.
+207 -297
View File
@@ -21,6 +21,15 @@ limitations under the License.
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
<title>Armadillo: API Documentation</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAARpJREFUOMtjYMABzFuiGYE4BohPA/FvIP6Phv8CMTcuzVxAvAGqeTYQT0HCd6AG3MSlmRWIdwNxLhY5MyC+ADVgLS4DyqAK2NDEBaAuiobKt+Ay4CZUgQRaeKwCYj8gTofKR+My4CNUQSSSWCYQT4ay+6HyprgMOADEs4BYFso3AOITQMwB5W+HGsCPMxCR2LxAfA6INZHE7gHxGwZCAOrvFUDcCsQqUKwFxP+A+CQxBpRgSTwwvIKQZm8gfgbEVkCsgYRToQZ049NsBtVshEUuA2pAAYpfoTQzEEcB8QsgtsdheA/UgFhkwV1AfBuIPwDxOyC2xeO6jVAD5kBd6gQS/AbEX4F4JRDLEwgbUHp4CsRboLETzkApAADMF8+Pl3d18QAAAABJRU5ErkJggg==">
<script type="application/rsl+xml">
<rsl xmlns="https://rslstandard.org/rsl">
<content url="">
<license>
<prohibits type="usage">ai-train ai-input</prohibits>
</license>
</content>
</rsl>
</script>
<style type="text/css">
<!--
body
@@ -245,8 +254,9 @@ Conrad Sanderson and Ryan Curtin.
<tr><td><a href="#Col">Col&lt;<i>type</i>&gt;, colvec, vec</a></td><td>&nbsp;</td><td>dense column vector class</td></tr>
<tr><td><a href="#Row">Row&lt;<i>type</i>&gt;, rowvec</a></td><td>&nbsp;</td><td>dense row vector class</td></tr>
<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><a href="#Cube">Cube&lt;<i>type</i>&gt;, cube, cx_cube</a></td><td>&nbsp;</td><td>dense cube class ("3D matrix")</td></tr>
<tr><td><a href="#Cube">Cube&lt;<i>type</i>&gt;, cube, cx_cube</a></td><td>&nbsp;</td><td>dense cube class (quasi third-order tensor, aka "3D matrix")</td></tr>
<tr><td><a href="#field">field&lt;<i>object&nbsp;type</i>&gt;</a></td><td>&nbsp;</td><td>class for storing arbitrary objects in matrix-like or cube-like layouts</td></tr>
<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><a href="#SpMat">SpMat&lt;<i>type</i>&gt;, sp_mat, sp_cx_mat</a></td><td>&nbsp;</td><td>sparse matrix class</td></tr>
<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><a href="#operators">operators</a></td><td>&nbsp;</td><td><code><big>+</big>&nbsp; <big>&minus;</big>&nbsp; <big>*</big>&nbsp; %&nbsp; /&nbsp; ==&nbsp; !=&nbsp; &lt;=&nbsp; &gt;=&nbsp; &lt;&nbsp; &gt;&nbsp; &amp;&amp;&nbsp; ||</code></td></tr>
@@ -569,8 +579,6 @@ Conrad Sanderson and Ryan Curtin.
<tr style="background-color: #F5F5F5;"><td><a href="#example_prog">example&nbsp;program</a></td><td>&nbsp;</td><td>short example program</td></tr>
<tr><td><a href="#config_hpp">config.hpp</a></td><td>&nbsp;</td><td>configuration options</td></tr>
<tr><td><a href="#changelog">API&nbsp;additions</a></td><td>&nbsp;</td><td>API stability and list of API additions</td></tr>
<!--<tr><td><a href="#log_add">log_add</a></td><td>&nbsp;</td><td>TODO</td></tr>-->
<!--<tr><td><a href="#catching_exceptions">catching exceptions</a></td><td>&nbsp;</td><td>TODO</td></tr>-->
</tbody>
</table>
</ul>
@@ -751,6 +759,8 @@ Functions which use LAPACK (generally matrix decompositions) are only valid for
<a name="constructors_mat"></a>
<li>
Constructors:
<br>
<br>
<ul>
<table>
<tbody>
@@ -775,28 +785,27 @@ Constructors:
<li>
Matrix elements can be explicitly initialised during construction by specifying <i>fill_form</i>,
which is one of:
<br>
<br>
<ul>
<table>
<tbody>
<tr><td><code>fill::zeros</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 0 &nbsp; (default in Armadillo &gt;= 10.5)</td></tr>
<tr><td><code>fill::ones</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 1</td></tr>
<tr><td><code>fill::eye</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set the elements on the main diagonal to 1 and off-diagonal elements to 0</td></tr>
<tr><td><code>fill::randu</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to random values from a uniform distribution in the [0,1] interval</td></tr>
<tr><td><code>fill::randn</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to random values from a normal/Gaussian distribution with zero mean and unit variance</td></tr>
<tr><td><code>fill::value(scalar)</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to specified scalar</td></tr>
<tr><td><code>fill::none</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>do not initialise the elements &nbsp; (matrix may have garbage values)</td></tr>
<tr><td><code>fill::zeros</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 0 &nbsp; (default operation)</td></tr>
<tr><td><code>fill::ones</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 1</td></tr>
<!-- <tr><td><code>fill::nan</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to NaN</td></tr> -->
<!-- <tr><td><code>fill::pos_inf</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to +infinity</td></tr> -->
<!-- <tr><td><code>fill::neg_inf</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to -infinity</td></tr> -->
<tr><td><code>fill::value(scalar)</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to the specified scalar</td></tr>
<tr><td><code>fill::eye</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set elements on the main diagonal to 1 and off-diagonal elements to 0</td></tr>
<tr><td><code>fill::randu</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set elements to random values from a uniform distribution in the [0,1] interval</td></tr>
<tr><td><code>fill::randn</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set elements to random values from a normal/Gaussian distribution with mean&thinsp;=&thinsp;0 and variance&thinsp;=&thinsp;1</td></tr>
</tbody>
</table>
</ul>
</li>
<br>
<li>
<b>Caveat:</b>
<ul>
<li>in Armadillo &gt;= 10.5, the default initialisation is <code>fill::zeros</code></li>
<li>in Armadillo &lt;= 10.4, the default initialisation is <code>fill::none</code></li>
</ul>
</li>
<li>If <i>fill_form</i> is not specified, <i>fill::zeros</i> is used by default (since Armadillo 10.5)</li>
<br>
<li>
For the <i>mat(string)</i> constructor, the format is elements separated by spaces, and rows denoted by semicolons;
@@ -884,6 +893,16 @@ data is copied from auxiliary memory, where <i>ptr_aux_mem</i> is a pointer to t
</ul>
</li>
<br>
<li>
Support for the <i>std::uint8_t</i> and <i>std::int8_t</i> element types can be enabled by defining both <code>ARMA_U8_TYPE</code> and <code>ARMA_S8_TYPE</code> before including the armadillo header:
<ul>
<pre>
#define ARMA_U8_TYPE std::uint8_t
#define ARMA_S8_TYPE std::int8_t
#include &lt;armadillo&gt;
</pre>
</ul>
</li>
<br>
<li>
Examples:
@@ -1151,6 +1170,8 @@ main exceptions are functions which require square matrices
<br>
<li>
Constructors:
<br>
<br>
<ul>
<table>
<tbody>
@@ -1423,6 +1444,8 @@ main exceptions are functions which require square matrices
<br>
<li>
Constructors:
<br>
<br>
<ul>
<table>
<tbody>
@@ -1549,11 +1572,11 @@ rowvec z = A.row(5); // extract a row vector
<br><b>cx_cube</b>
<ul>
<li>
Classes for cubes (quasi 3rd order tensors), also known as "3D matrices"
Classes for cubes (quasi third-order tensors, aka "3D matrices")
</li>
<br>
<li>
Data is stored as a set of slices (matrices) stored contiguously within memory;
Data is stored as an ordered set of slices (matrices) placed contiguously within memory;
within each slice, elements are stored with column-major ordering (ie. column by column)
</li>
<br>
@@ -1701,6 +1724,8 @@ it is possible to use other types instead, eg. <i>fcube</i>
<a name="constructors_cube"></a>
<li>
Constructors:
<br>
<br>
<ul>
<table>
<tbody>
@@ -1719,27 +1744,26 @@ Constructors:
<li>
Cube elements can be explicitly initialised during construction by specifying <i>fill_form</i>,
which is one of:
<br>
<br>
<ul>
<table>
<tbody>
<tr><td><code>fill::zeros</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 0 &nbsp; (default in Armadillo &gt;= 10.5)</td></tr>
<tr><td><code>fill::ones</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 1</td></tr>
<tr><td><code>fill::randu</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to random values from a uniform distribution in the [0,1] interval</td></tr>
<tr><td><code>fill::randn</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to random values from a normal/Gaussian distribution with zero mean and unit variance</td></tr>
<tr><td><code>fill::value(scalar)</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to specified scalar</td></tr>
<tr><td><code>fill::none</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>do not initialise the elements &nbsp; (cube may have garbage values)</td></tr>
<tr><td><code>fill::zeros</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 0 &nbsp; (default operation)</td></tr>
<tr><td><code>fill::ones</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 1</td></tr>
<!-- <tr><td><code>fill::nan</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to NaN</td></tr> -->
<!-- <tr><td><code>fill::pos_inf</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to +infinity</td></tr> -->
<!-- <tr><td><code>fill::neg_inf</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to -infinity</td></tr> -->
<tr><td><code>fill::value(scalar)</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to the specified scalar</td></tr>
<tr><td><code>fill::randu</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set elements to random values from a uniform distribution in the [0,1] interval</td></tr>
<tr><td><code>fill::randn</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set elements to random values from a normal/Gaussian distribution with mean&thinsp;=&thinsp;0 and variance&thinsp;=&thinsp;1</td></tr>
</tbody>
</table>
</ul>
</li>
<br>
<li>
<b>Caveat:</b>
<ul>
<li>in Armadillo &gt;= 10.5, the default initialisation is <code>fill::zeros</code></li>
<li>in Armadillo &lt;= 10.4, the default initialisation is <code>fill::none</code></li>
</ul>
</li>
<li>If <i>fill_form</i> is not specified, <i>fill::zeros</i> is used by default (since Armadillo 10.5)</li>
<br>
<li>
Each instance of <i>cube</i> automatically allocates and releases internal memory.
@@ -1875,6 +1899,8 @@ Each element can have an arbitrary size (eg. in a field of matrices, each matrix
<br>
<li>
Constructors, where <i>object_type</i> is another class, eg. <i>vec</i>, <i>mat</i>, <i>std::string</i>, etc:
<br>
<br>
<ul>
<table>
<tbody>
@@ -1901,6 +1927,7 @@ mat A = randn(2,3);
mat B = randn(4,5);
field&lt;mat&gt; F(2,1);
F(0,0) = A;
F(1,0) = B;
@@ -2075,6 +2102,8 @@ it is possible to use other types instead, eg. <i>sp_fmat</i>
<a name="constructors_sp_mat"></a>
<li>
Constructors:
<br>
<br>
<ul>
<table>
<tbody>
@@ -2112,6 +2141,8 @@ for small matrices use the <a href="#Mat">Mat</a> class, even if most of the ele
<li>
<a name="batch_constructors_sp_mat"></a>
Batch insertion constructors:
<br>
<br>
<ul>
<li>form&nbsp;1: <code>sp_mat(<i>locations</i>, <i>values</i>, <i>sort_locations&thinsp;=&thinsp;true</i>)</code></li>
<li>form&nbsp;2: <code>sp_mat(<i>locations</i>, <i>values</i>, <i>n_rows</i>, <i>n_cols</i>, <i>sort_locations&thinsp;=&thinsp;true</i>, <i>check_for_zeros&thinsp;=&thinsp;true</i>)</code></li>
@@ -2165,6 +2196,8 @@ If <i>check_for_zeros</i> is set to <i>false</i>, the <i>values</i> vector is as
<br>
<li>
The following subset of operations &amp; functions is available for sparse matrices:
<br>
<br>
<ul>
<li>fundamental arithmetic <a href="#operators">operations</a> (such as addition and multiplication)</li>
<li><a href="#submat">submatrix views</a>: most contiguous forms and the non-contiguous form of <i>X.cols(vector_of_column_indices)</i></li>
@@ -2214,10 +2247,6 @@ See also:
<li><a href="#element_access">element access</a></li>
<li><a href="#iterators_spmat">element iterators (sparse matrices)</a></li>
<li><a href="#print">printing matrices</a></li>
<!--
<li><a href="#SpCol">SpCol class</a> (TODO: add to documentation)</li>
<li><a href="#SpRow">SpRow class</a> (TODO: add to documentation)</li>
-->
<li><a href="https://en.wikipedia.org/wiki/Sparse_matrix">Sparse Matrix in Wikipedia</a></li>
<li><a href="#Mat">Mat class</a> (dense matrix)</li>
</ul>
@@ -2944,6 +2973,7 @@ C.eye();
<li>See also:
<ul>
<li><a href="#ones_member">.ones()</a></li>
<li><a href="#fill">.fill()</a></li>
<li><a href="#diag">.diag()</a></li>
<li><a href="#diagmat">diagmat()</a></li>
<li><a href="#diagvec">diagvec()</a></li>
@@ -3102,7 +3132,7 @@ See also:
Member function of <i>Mat</i>, <i>Col</i>, <i>Row</i>, <i>Cube</i>, <i>field</i>
</li>
<br>
<li>Sets the elements to a specified value</li>
<li>Sets all elements to a specified value</li>
<br>
<li>The type of value must match the type of elements used by the container object (eg. for <i>mat</i> the type is <i>double</i>)
</li>
@@ -3113,29 +3143,38 @@ Examples:
<pre>
mat A(5, 6);
A.fill(123.0); // or: mat A(5, 6, fill::value(123.0));
A.fill(123.0);
</pre>
</ul>
</li>
<br>
<li>
<b>Note:</b> to set all elements to zero during matrix construction, use the following more compact form:
<b>Caveats:</b>
<ul>
<li>To initialise all elements during matrix construction, it is more efficient to use a <i><a href="#Mat">fill_form</a></i>:
<ul>
<pre>
mat A(5, 6, fill::zeros);
mat B(5, 6, fill::ones);
mat C(5, 6, fill::value(123.0));
</pre>
</ul>
</li>
<li>If <i>fill_form</i> is not specified, <i>fill::zeros</i> is used by default (since Armadillo 10.5)</li>
</ul>
</li>
<br>
<li>
See also:
<ul>
<li><a href="#imbue">.imbue()</a></li>
<li><a href="#ones_member">.ones()</a></li>
<li><a href="#zeros_member">.zeros()</a></li>
<li><a href="#ones_member">.ones()</a></li>
<li><a href="#eye_member">.eye()</a></li>
<li><a href="#randu_randn_member">.randu() &amp; .randn()</a></li>
<li><a href="#replace">.replace()</a></li>
<li><a href="#constants">constants (pi, nan, inf, ...)</a></li>
<li><a href="#Mat">matrix constructors</a></li>
</ul>
</li>
<br>
@@ -3920,6 +3959,10 @@ Instances of <i>span(start,end)</i> can be replaced by <i>span::all</i> to indic
</li>
<br>
<li>
To distinguish <i>span(start,end)</i> from <i>std::span</i>, use the <i>arma::</i> prefix, ie. <i>arma::span(start,end)</i>
</li>
<br>
<li>
For functions requiring one or more vector of indices,
eg. <i>X.submat(vector_of_row_indices,&nbsp;vector_of_column_indices)</i>,
each vector of indices must be of type <i><a href="#Col">uvec</a></i>
@@ -4083,8 +4126,8 @@ Instances of <i>span(a,b)</i> can be replaced by:
</li>
<br>
<li>
An individual slice, accessed via <i>.slice()</i>, is an instance of the <i>Mat</i> class
(a reference to a matrix is provided)
A single slice, accessed via <i>.slice(slice_number)</i>, is an instance of the <i>Mat</i> class (a reference to a matrix is provided);
<br>see also <i>.<a href="#col_row_as_mat">col_as_mat()</a></i> and <i>.<a href="#col_row_as_mat">row_as_mat()</a></i>
</li>
<br>
<li>
@@ -4299,7 +4342,7 @@ Similar to "broadcasting" in Matlab&thinsp;/&thinsp;Octave
</li>
<br>
<li>
Supported operations for forms 1 and 2:
Supported operations for forms&nbsp;1 and&nbsp;2:
<br>
<br>
<ul>
@@ -4314,7 +4357,7 @@ Supported operations for forms 1 and 2:
</li>
<br>
<li>
For form 2:
For form&nbsp;2:
<ul>
<li>the argument <i>vector_of_indices</i> contains a list of indices of the columns/rows to be used; it must evaluate to a vector of type <i><a href="#Col">uvec</a></i></li>
<li>arithmetic operations as per form 1 are supported</li>
@@ -4322,7 +4365,7 @@ For form 2:
</li>
<br>
<li>
For form 3:
For form&nbsp;3:
<ul>
<li>apply the given <i>lambda_function</i> to each column vector or row vector</li>
<li>the function must accept a reference to a <a href="#Col">Col</a> or <a href="#Row">Row</a> object with the same element type as the underlying matrix</li>
@@ -4395,7 +4438,7 @@ Similar to "broadcasting" in Matlab&thinsp;/&thinsp;Octave
</li>
<br>
<li>
Supported operations for form 1:
Supported operations for form&nbsp;1:
<br>
<br>
<ul>
@@ -4411,7 +4454,7 @@ Supported operations for form 1:
</li>
<br>
<li>
For form 2:
For form&nbsp;2:
<ul>
<li>the argument <i>vector_of_indices</i> contains a list of indices of the slices to be used; it must evaluate to a vector of type <i><a href="#Col">uvec</a></i></li>
<li>arithmetic operations as per form 1 are supported, except for <code><b>*</b></code> and <code><b>*=</b></code> (ie. matrix multiplication)</li>
@@ -4419,7 +4462,7 @@ For form 2:
</li>
<br>
<li>
For form 3:
For form&nbsp;3:
<ul>
<li>apply the given <i>lambda_function</i> to each slice</li>
<li>the function must accept a reference to a <a href="#Mat">Mat</a> object with the same element type as the underlying cube</li>
@@ -4427,7 +4470,7 @@ For form 3:
</li>
<br>
<li>
For form 4:
For form&nbsp;4:
<ul>
<li>apply the given <i>lambda_function</i> to each slice, as per form 3</li>
<li>the argument <i>use_mp</i> is a bool to enable the use of OpenMP for multi-threaded execution of <i>lambda_function</i> on multiple slices at the same time</li>
@@ -5817,6 +5860,7 @@ Examples:
<ul>
<pre>
mat X(4, 5, fill::randu);
vec v = X.as_col();
</pre>
</ul>
@@ -5870,9 +5914,11 @@ Examples:
<pre>
cube Q(5, 4, 3, fill::randu);
mat A = Q.col_as_mat(2); // size of A: 5x3
mat A = Q.slice(2); // size of A: 5x4
mat B = Q.row_as_mat(2); // size of B: 3x4
mat B = Q.col_as_mat(2); // size of B: 5x3
mat C = Q.row_as_mat(2); // size of C: 3x4
</pre>
</ul>
</li>
@@ -6822,6 +6868,7 @@ See also:
<li><a href="#has_nan">.has_nan()</a></li>
<li><a href="#find_finite_nonfinite">find_finite() / find_nonfinite()</a></li>
<li><a href="#find_nan_nonnan">find_nan() / find_nonnan()</a></li>
<li><a href="#omit_nan_nonfinite">omit_nan() / omit_nonfinite()</a></li>
<li><a href="#constants">constants (pi, nan, inf, ...)</a></li>
</ul>
</li>
@@ -6864,6 +6911,7 @@ See also:
<li><a href="#replace">.replace()</a></li>
<li><a href="#is_finite">.is_finite()</a>
<li><a href="#find_finite_nonfinite">find_finite() / find_nonfinite()</a></li>
<li><a href="#omit_nan_nonfinite">omit_nonfinite()</a></li>
<li><a href="#constants">constants (pi, nan, inf, ...)</a></li>
</ul>
</li>
@@ -6911,6 +6959,7 @@ See also:
<li><a href="#replace">.replace()</a></li>
<li><a href="#is_finite">.is_finite()</a>
<li><a href="#find_nan_nonnan">find_nan() / find_nonnan()</a></li>
<li><a href="#omit_nan_nonfinite">omit_nan()</a></li>
<li><a href="#constants">constants (pi, nan, inf, ...)</a></li>
</ul>
</li>
@@ -7129,58 +7178,58 @@ A.brief_print("A:");
<br>
<br>
<ul>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;"><b>auto_detect</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;"><b>auto_detect</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Used only by <i>.load()</i> only: attempt to automatically detect the file type as one of the formats described below;
<br>[&nbsp;default operation for <i>.load()</i>&nbsp;]<br><br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_binary</b><br></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_binary</b><br></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in machine dependent binary format, with a simple header to speed up loading.
The header indicates the type and size of matrix/cube.
<br>[&nbsp;default operation for <i>.save()</i>&nbsp;]
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in human readable text format, with a simple header to speed up loading.
The header indicates the type and size of matrix/cube.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>raw_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>raw_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in machine dependent raw binary format, without a header.
Matrices are loaded to have one column,
while cubes are loaded to have one slice with one column.
The <a href="#reshape_member">.reshape()</a> function can be used to alter the size of the loaded matrix/cube without losing data.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>raw_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>raw_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in raw ASCII format, without a header.
The numbers are separated by whitespace.
The number of columns must be the same in each row.
@@ -7189,26 +7238,26 @@ Data which was saved in Matlab/Octave using the <i>-ascii</i> option can be read
Complex numbers are stored in standard C++ notation, which is a tuple surrounded by brackets: eg. (1.23,4.56) indicates 1.24&thinsp;+&thinsp;4.56i.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>csv_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>csv_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in comma separated value (CSV) text format, <b>without</b> a header.
To save/load <b>with</b> a header, use the <b>csv_name(</b>filename,header<b>)</b> specification instead (more details below).
Handles complex numbers stored in the compound form of 1.24+4.56i.
Applicable to <i>Mat</i> and <i>SpMat</i>.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>coord_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>coord_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored as a text file in coordinate list format, without a header.
Only non-zero values are stored.
<br>
@@ -7219,39 +7268,39 @@ For real matrices, each line contains information in the following format:&nbsp;
<br><b>Caveat:</b> not supported by <i>auto_detect</i>.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>pgm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>pgm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Image data stored in Portable Gray Map (PGM) format.
Applicable to <i>Mat</i> only.
Saving <i>int</i>, <i>float</i> or <i>double</i> matrices is a lossy operation, as each element is copied and converted to an 8 bit representation.
As such the matrix should have values in the [0,255] interval, otherwise the resulting image may not display correctly.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>ppm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>ppm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Image data stored in Portable Pixel Map (PPM) format.
Applicable to <i>Cube</i> only.
Saving <i>int</i>, <i>float</i> or <i>double</i> matrices is a lossy operation, as each element is copied and converted to an 8 bit representation.
As such the cube/field should have values in the [0,255] interval, otherwise the resulting image may not display correctly.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>hdf5_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>hdf5_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in portable <a href="https://en.wikipedia.org/wiki/Hierarchical_Data_Format">HDF5</a> binary format.
<ul>
<li>
@@ -7267,10 +7316,10 @@ for loading, the order of operations is:
to explicitly control the dataset name, specify it via the <b>hdf5_name()</b> argument (more details below)
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</ul>
</li>
<br>
@@ -7387,6 +7436,7 @@ if(ok == false)
<li><a href="https://en.wikipedia.org/wiki/Hierarchical_Data_Format">HDF</a> in Wikipedia</li>
<li><a href="https://en.wikipedia.org/wiki/Comma-separated_values">CSV</a> in Wikipedia
<li><a href="#save_load_field">saving&thinsp;/&thinsp;loading fields</a></li>
<li><a href="#element_initialisation">element initialisation</a></li>
</ul>
</li>
<br>
@@ -7439,26 +7489,26 @@ Other than storing string fields as text files, the following file formats are s
<br>
<br>
<ul>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;"><b>auto_detect</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;"><b>auto_detect</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
<br>
<li>
<i>.load()</i>: attempt to automatically detect the field format type as one of the formats described below;
this is the default operation
</li>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
<br>
<li>
objects are stored in machine dependent binary format
@@ -7469,13 +7519,13 @@ default type for fields of type <i>Mat</i>, <i>Col</i>, <i>Row</i> or <i>Cube</i
only applicable to fields of type <i>Mat</i>, <i>Col</i>, <i>Row</i> or <i>Cube</i>
</li>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>ppm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>ppm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
<br>
<li>
image data stored in Portable Pixmap Map (PPM) format
@@ -7494,11 +7544,10 @@ it is assumed that the red, green and blue components are stored in the first, s
saving <i>int</i>, <i>float</i> or <i>double</i> matrices is a lossy operation,
as each matrix element is copied and converted to an 8 bit representation
</li>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</ul>
</li>
<br>
@@ -9606,7 +9655,7 @@ vec b = diff(a);
</li>
<br>
<li>
<b>Caveat:</b> <a href="#norm">norm()</a> is preferred for calculating the 2-norm, as it reduces the incidence of numerical underflows and overflows
<b>Caveat:</b> to obtain the Euclidean norm, use the more robust <a href="#norm">norm(x)</a> instead of <i>sqrt(dot(x,x))</i>
</li>
<br>
<li>
@@ -9732,10 +9781,6 @@ See also:
<li><i>expmat_sym(B,A)</i> resets <i>B</i> and returns a bool set to <i>false</i> (exception is not thrown)</li>
</ul>
</li>
<!--
<br>
<li><b>Caveat:</b> there is no explicit check whether <i>A</i> is symmetric/hermitian</li>
-->
<br>
<li><b>Caveat:</b> the matrix exponential operation is generally <b>not</b> the same as applying the <a href="#misc_fns">exp()</a> function to each element</li>
<br>
@@ -10706,10 +10751,6 @@ See also:
<li><i>logmat_sympd(B,A)</i> resets <i>B</i> and returns a bool set to <i>false</i> (exception is not thrown)</li>
</ul>
</li>
<!--
<br>
<li><b>Caveat:</b> there is no explicit check whether <i>A</i> is symmetric/hermitian positive definite</li>
-->
<br>
<li><b>Caveat:</b> the matrix logarithm operation is generally <b>not</b> the same as applying the <a href="#misc_fns">log()</a> function to each element</li>
<br>
@@ -11092,6 +11133,9 @@ See also:
<li><a href="#nonzeros">nonzeros()</a>
<li><a href="#vectorise">vectorise()</a>
<li><a href="#for_each">.for_each()</a>
<li><a href="#is_finite">.is_finite()</a>
<li><a href="#has_inf">.has_inf()</a>
<li><a href="#has_nan">.has_nan()</a>
</ul>
</li>
<br>
@@ -11103,11 +11147,6 @@ 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>
@@ -11117,17 +11156,6 @@ See also:
<br>
<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>
<li>form 4: for each row vector of matrix <i>M</i>, raise each element to the power denoted by the corresponding element in row vector <i>R</i>;
<br>the number of columns in <i>M</i> and <i>R</i> must be the same</li>
<br>
<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>
@@ -11144,13 +11172,6 @@ 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);
-->
</ul>
</li>
<br>
@@ -11159,10 +11180,6 @@ See also:
<ul>
<li><a href="#powmat">powmat()</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>
@@ -12047,10 +12064,6 @@ See also:
<li><i>sqrtmat_sympd(B,A)</i> resets <i>B</i> and returns a bool set to <i>false</i> (exception is not thrown)</li>
</ul>
</li>
<!--
<br>
<li><b>Caveat:</b> there is no explicit check whether <i>A</i> is symmetric/hermitian positive definite</li>
-->
<br>
<li><b>Caveat:</b> the matrix square root operation is generally <b>not</b> the same as applying the <a href="#misc_fns">sqrt()</a> function to each element</li>
<br>
@@ -13191,10 +13204,6 @@ the divide-and-conquer method provides slightly different results than the stand
<li><i>eig_sym(eigval,eigvec,X)</i> resets <i>eigval</i> &amp; <i>eigvec</i> and returns a bool set to <i>false</i> (exception is not thrown)</li>
</ul>
</li>
<!--
<br>
<li><b>Caveat:</b> there is no explicit check whether <i>X</i> is symmetric/hermitian</li>
-->
<br>
<li>
Examples:
@@ -13572,10 +13581,6 @@ If <i>A</i> is not square sized, a <i>std::logic_error</i> exception is thrown
<li><i>inv_sympd(B,rcond,A)</i> resets <i>B</i>, sets rcond to zero, and returns a bool set to <i>false</i> (exception is not thrown)</li>
</ul>
</li>
<!--
<br>
<li><b>Caveat:</b> there is no explicit check whether <i>A</i> is symmetric/hermitian positive definite</li>
-->
<br>
<li>
<b>Caveat:</b>
@@ -14967,7 +14972,6 @@ See also:
<ul>
<li><a href="#spsolve_factoriser">spsolve_factoriser</a></li>
<li><a href="#solve">solve()</a> - solve dense system of linear equations</li>
<!-- <li><a href="http://crd-legacy.lbl.gov/~xiaoye/SuperLU/">SuperLU home page</a> -->
<li><a href="https://portal.nersc.gov/project/sparse/superlu/">SuperLU home page</a>
<li><a href="https://mathworld.wolfram.com/LinearSystemofEquations.html">linear system of equations in MathWorld</a></li>
<li><a href="https://en.wikipedia.org/wiki/Linear_system_of_equations">system of linear equations in Wikipedia</a></li>
@@ -17888,7 +17892,6 @@ model.save("my_model.gmm");
</td>
<td style="vertical-align: top;">
machine epsilon; approximately 2.2204e-16; difference between 1 and the next representable value
<!-- machine epsilon: the difference between 1 and the value least greater than 1 that is representable (type and machine dependent) -->
</td>
</tr>
<tr>
@@ -18433,7 +18436,7 @@ An instance of the class has the following member functions:
</td>
<td style="vertical-align: top;">
return the number of seconds since the last call to <code>.tic()</code>,
with the returned number of seconds reduced by any freeze/unfreeze durations
with the number of seconds reduced by any freeze/unfreeze durations
</td>
</tr>
<tr>
@@ -18490,7 +18493,7 @@ See also:
<b>RNG seed setting</b>
<ul>
<li>
There are two functions to change the seed used by the random number generator (RNG):
Functions to change the seed used by the random number generator (RNG):
<br>
<br>
<table style="text-align: left;" border="0" cellpadding="2" cellspacing="2">
@@ -18614,33 +18617,6 @@ See also:
<br>
</ul>
<!--
<div class="pagebreak"></div><div class="noprint"><hr class="greyline"><br></div>
<a name="log_add"></a>
<b>log_add(log_a, log_b)</b>
<ul>
<li>
Safe replacement for log(exp(log_a) + exp(log_b))
</li>
<br>
<li>
Usage:
<ul>
<li>
<i>scalar_type</i> log_c = log_add(log_a, log_b)
</li>
<li>
<i>scalar_type</i> is either <i>float</i> or <i>double</i>
</li>
<li>
log_a, log_b and log_c must have the same type
</li>
</ul>
</li>
</ul>
<br>
-->
<div class="pagebreak"></div><div class="noprint"><hr class="greyline"><br></div>
<a name="uword"></a>
<b>uword</b>, <b>sword</b>
@@ -18781,7 +18757,7 @@ rudimentary <i>fp16</i> hardware support is present on x86-64 CPUs with the F16C
<br>
</ul>
<li>
If no compiler or hardware support is detected, support for <i>fp16</i> element types is <b>not</b> automatically enableds
If no compiler or hardware support is detected, support for <i>fp16</i> element types is <b>not</b> automatically enabled
</li>
<br>
<li>
@@ -18816,7 +18792,6 @@ fp16 val = X(2,3);
<li><a href="#Mat">hmat</a> matrix type
<li><a href="#Col">hvec</a> vector type
<li><a href="https://en.cppreference.com/w/cpp/types/floating-point.html">std::float16_t</a> in cppreference.com</li>
<!-- <li><a href="https://en.cppreference.com/w/cpp/header/stdfloat.html">std::float16_t</a> in cppreference.com</li> -->
<li><a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">half-precision floating point format in Wikipedia</a></li>
<li><a href="https://en.wikipedia.org/wiki/AVX-512">AVX-512 extensions in Wikipedia</a></li>
<!-- <li><a href="https://gcc.gnu.org/onlinedocs/gcc/Half-Precision.html">gcc half-precision documentation</a></li> -->
@@ -20688,60 +20663,6 @@ See also:
<br>
</ul>
<!--
<div class="pagebreak"></div><div class="noprint"><hr class="greyline"><br></div>
<a name="catching_exceptions"></a>
<br>
<b>how to catch std::runtime_error exceptions</b>
<br>
<br>
<ul>
<li>
If a function such as <a href="#inv">inv()</a> fails to find a solution,
an error message is printed and a <i>std::runtime_error</i> exception is thrown.
If the exception is not caught, the program typically terminates.
Below is an example of how to catch exceptions:
<ul>
<pre>
#include &lt;iostream&gt;
#include &lt;armadillo&gt;
using namespace std;
using namespace arma;
int main(int argc, char** argv)
{
// create a non-invertible matrix
mat A(5, 5, fill::zeros);
mat B;
try
{
B = inv(A);
}
catch (std::runtime_error&amp; x)
{
cout &lt;&lt; "caught an exception" &lt;&lt; endl;
}
return 0;
}
</pre>
</ul>
<li>
See also:
<ul>
<li><a href="#logging">logging of warnings and errors</a></li>
<li><a href="https://cplusplus.com/doc/tutorial/exceptions/">tutorial on exceptions</a></li>
<li><a href="https://cplusplus.com/reference/stdexcept/runtime_error/">std::runtime_error</a></li>
</ul>
</li>
<br>
</ul>
<br>
-->
<div class="pagebreak"></div><div class="noprint"><hr class="greyline"><br></div>
<a name="api_additions"></a>
<a name="changelog"></a>
@@ -20789,19 +20710,6 @@ and may be changed or removed without notice.
</ul>
</li>
<!--
<br>
<li>
<a name="deprecated"></a>
List of deprecated functionality; this functionality will be <b>removed</b> in version A.B:
<ul>
<li>
...
</li>
</ul>
</li>
-->
<br>
<br>
<li>
@@ -20818,6 +20726,7 @@ List of additions and changes for each version:
<li>added <a href="#rande">rande()</a> for generating matrices with elements from exponential distributions</li>
<li>shift() has been deprecated in favour of <a href="#circshift">circshift()</a>, for consistency with Matlab/Octave</li>
<li>reworked detection of aliasing, leading to more efficient compiled code</li>
<li>faster handling of submatrices with one row</li>
</ul>
</li>
<br>
@@ -21926,6 +21835,7 @@ use <i>my_function(&nbsp;mat(A+B)&nbsp;)</i>.
<br>
</ul>
<!-- END CONTENT -->
+42 -12
View File
@@ -244,9 +244,9 @@ BaseCube<elem_type,derived>::is_zero(const typename get_pod_type<elem_type>::res
typedef typename get_pod_type<elem_type>::result T;
arma_conform_check( (tol < T(0)), "is_zero(): parameter 'tol' must be >= 0" );
arma_conform_check( ((tol >= T(0)) == false), "is_zero(): parameter 'tol' must be >= 0" );
if(ProxyCube<derived>::use_at || is_Cube<typename ProxyCube<derived>::stored_type>::value)
if(is_Cube<typename ProxyCube<derived>::stored_type>::value || ProxyCube<derived>::use_at)
{
const unwrap_cube<derived> U( (*this).get_ref() );
@@ -263,22 +263,52 @@ BaseCube<elem_type,derived>::is_zero(const typename get_pod_type<elem_type>::res
if(is_cx<elem_type>::yes)
{
for(uword i=0; i<n_elem; ++i)
if(tol == T(0))
{
const elem_type val = Pea[i];
const T val_real = access::tmp_real(val);
const T val_imag = access::tmp_imag(val);
if(eop_aux::arma_abs(val_real) > tol) { return false; }
if(eop_aux::arma_abs(val_imag) > tol) { return false; }
for(uword i=0; i < n_elem; ++i)
{
const elem_type val = Pea[i];
const T val_real = access::tmp_real(val);
const T val_imag = access::tmp_imag(val);
if(eop_aux::arma_abs(val_real) != T(0)) { return false; }
if(eop_aux::arma_abs(val_imag) != T(0)) { return false; }
}
}
else
{
for(uword i=0; i < n_elem; ++i)
{
const elem_type val = Pea[i];
const T val_real = access::tmp_real(val);
const T val_imag = access::tmp_imag(val);
if( (eop_aux::arma_abs(val_real) <= tol) == false ) { return false; }
if( (eop_aux::arma_abs(val_imag) <= tol) == false ) { return false; }
}
}
}
else // not complex
{
for(uword i=0; i < n_elem; ++i)
if(tol == T(0))
{
if(eop_aux::arma_abs(Pea[i]) > tol) { return false; }
for(uword i=0; i < n_elem; ++i)
{
const elem_type val = Pea[i];
if(val != elem_type(0)) { return false; }
}
}
else
{
for(uword i=0; i < n_elem; ++i)
{
const elem_type val = Pea[i];
if( (eop_aux::arma_abs(val) <= tol) == false ) { return false; }
}
}
}
+55 -15
View File
@@ -352,7 +352,7 @@ Base<elem_type,derived>::is_symmetric(const typename get_pod_type<elem_type>::re
if(tol == T(0)) { return (*this).is_symmetric(); }
arma_conform_check( (tol < T(0)), "is_symmetric(): parameter 'tol' must be >= 0" );
arma_conform_check( ((tol >= T(0)) == false), "is_symmetric(): parameter 'tol' must be > 0" );
const quasi_unwrap<derived> U( (*this).get_ref() );
@@ -365,8 +365,12 @@ Base<elem_type,derived>::is_symmetric(const typename get_pod_type<elem_type>::re
if(norm_A == T(0)) { return true; }
if(arma_isnan(norm_A)) { return false; }
const T norm_A_Ast = as_scalar( arma::max(sum(abs(A - A.st()), 1), 0) );
if(arma_isnan(norm_A_Ast)) { return false; }
return ( (norm_A_Ast / norm_A) <= tol );
}
@@ -435,7 +439,7 @@ Base<elem_type,derived>::is_hermitian(const typename get_pod_type<elem_type>::re
if(tol == T(0)) { return (*this).is_hermitian(); }
arma_conform_check( (tol < T(0)), "is_hermitian(): parameter 'tol' must be >= 0" );
arma_conform_check( ((tol >= T(0)) == false), "is_hermitian(): parameter 'tol' must be > 0" );
const quasi_unwrap<derived> U( (*this).get_ref() );
@@ -448,8 +452,12 @@ Base<elem_type,derived>::is_hermitian(const typename get_pod_type<elem_type>::re
if(norm_A == T(0)) { return true; }
if(arma_isnan(norm_A)) { return false; }
const T norm_A_At = as_scalar( arma::max(sum(abs(A - A.t()), 1), 0) );
if(arma_isnan(norm_A_At)) { return false; }
return ( (norm_A_At / norm_A) <= tol );
}
@@ -464,9 +472,9 @@ Base<elem_type,derived>::is_zero(const typename get_pod_type<elem_type>::result
typedef typename get_pod_type<elem_type>::result T;
arma_conform_check( (tol < T(0)), "is_zero(): parameter 'tol' must be >= 0" );
arma_conform_check( ((tol >= T(0)) == false), "is_zero(): parameter 'tol' must be >= 0" );
if(Proxy<derived>::use_at || is_Mat<typename Proxy<derived>::stored_type>::value)
if( (quasi_unwrap<derived>::has_orig_mem) || (is_Mat<typename Proxy<derived>::stored_type>::value) || (Proxy<derived>::use_at) )
{
const quasi_unwrap<derived> U( (*this).get_ref() );
@@ -483,22 +491,52 @@ Base<elem_type,derived>::is_zero(const typename get_pod_type<elem_type>::result
if(is_cx<elem_type>::yes)
{
for(uword i=0; i<n_elem; ++i)
if(tol == T(0))
{
const elem_type val = Pea[i];
const T val_real = access::tmp_real(val);
const T val_imag = access::tmp_imag(val);
if(eop_aux::arma_abs(val_real) > tol) { return false; }
if(eop_aux::arma_abs(val_imag) > tol) { return false; }
for(uword i=0; i < n_elem; ++i)
{
const elem_type val = Pea[i];
const T val_real = access::tmp_real(val);
const T val_imag = access::tmp_imag(val);
if(eop_aux::arma_abs(val_real) != T(0)) { return false; }
if(eop_aux::arma_abs(val_imag) != T(0)) { return false; }
}
}
else
{
for(uword i=0; i < n_elem; ++i)
{
const elem_type val = Pea[i];
const T val_real = access::tmp_real(val);
const T val_imag = access::tmp_imag(val);
if( (eop_aux::arma_abs(val_real) <= tol) == false ) { return false; }
if( (eop_aux::arma_abs(val_imag) <= tol) == false ) { return false; }
}
}
}
else // not complex
{
for(uword i=0; i<n_elem; ++i)
if(tol == T(0))
{
if(eop_aux::arma_abs(Pea[i]) > tol) { return false; }
for(uword i=0; i < n_elem; ++i)
{
const elem_type val = Pea[i];
if(val != elem_type(0)) { return false; }
}
}
else
{
for(uword i=0; i < n_elem; ++i)
{
const elem_type val = Pea[i];
if( (eop_aux::arma_abs(val) <= tol) == false ) { return false; }
}
}
}
@@ -897,6 +935,8 @@ Base_extra_yes<elem_type,derived>::is_sympd() const
// default value for tol
const T tol = T(100) * std::numeric_limits<T>::epsilon() * norm(X, "fro");
if(arma_isnan(tol)) { return false; }
if(X.is_hermitian(tol) == false) { return false; }
if(X.is_empty()) { return false; }
@@ -917,7 +957,7 @@ Base_extra_yes<elem_type,derived>::is_sympd(typename get_pod_type<elem_type>::re
typedef typename get_pod_type<elem_type>::result T;
arma_conform_check( (tol < T(0)), "is_sympd(): parameter 'tol' must be >= 0" );
arma_conform_check( ((tol >= T(0)) == false), "is_sympd(): parameter 'tol' must be >= 0" );
Mat<elem_type> X = static_cast<const derived&>(*this);
+4
View File
@@ -1344,6 +1344,10 @@ Col<eT>::fixed<fixed_n_elem>::fixed(const fill::fill_class<fill_type>&)
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(); }
if(is_same_type<fill_type, fill::fill_nan >::yes) { (*this).fill( priv::Datum_helper::nan <eT>() ); }
if(is_same_type<fill_type, fill::fill_pos_inf>::yes) { (*this).fill( priv::Datum_helper::pos_inf<eT>() ); }
if(is_same_type<fill_type, fill::fill_neg_inf>::yes) { (*this).fill( priv::Datum_helper::neg_inf<eT>() ); }
}
+3
View File
@@ -360,6 +360,9 @@ class Cube : public BaseCube< eT, Cube<eT> >
inline Cube& fill(const eT val);
template<typename fill_type>
inline Cube& fill(const fill::fill_class<fill_type>& f);
inline Cube& zeros();
inline Cube& zeros(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices);
inline Cube& zeros(const SizeCube& s);
+44 -35
View File
@@ -52,7 +52,7 @@ Cube<eT>::Cube()
, n_elem(0)
, n_alloc(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
}
@@ -172,7 +172,7 @@ Cube<eT>::Cube(const SizeCube& s, const arma_initmode_indicator<do_zeros>&)
template<typename eT>
template<typename fill_type>
inline
Cube<eT>::Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices, const fill::fill_class<fill_type>&)
Cube<eT>::Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices, const fill::fill_class<fill_type>& f)
: n_rows(in_n_rows)
, n_cols(in_n_cols)
, n_elem_slice(in_n_rows*in_n_cols)
@@ -186,12 +186,7 @@ Cube<eT>::Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_sl
init_cold();
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(); }
arma_static_check( (is_same_type<fill_type, fill::fill_eye>::yes), "Cube::Cube(): unsupported fill type" );
(*this).fill(f);
}
@@ -199,7 +194,7 @@ Cube<eT>::Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_sl
template<typename eT>
template<typename fill_type>
inline
Cube<eT>::Cube(const SizeCube& s, const fill::fill_class<fill_type>&)
Cube<eT>::Cube(const SizeCube& s, const fill::fill_class<fill_type>& f)
: n_rows(s.n_rows)
, n_cols(s.n_cols)
, n_elem_slice(s.n_rows*s.n_cols)
@@ -213,12 +208,7 @@ Cube<eT>::Cube(const SizeCube& s, const fill::fill_class<fill_type>&)
init_cold();
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(); }
arma_static_check( (is_same_type<fill_type, fill::fill_eye>::yes), "Cube::Cube(): unsupported fill type" );
(*this).fill(f);
}
@@ -934,7 +924,7 @@ Cube<eT>::Cube
, n_elem(0)
, n_alloc(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -1064,7 +1054,7 @@ Cube<eT>::Cube(const subview_cube_slices<eT,T1>& X)
, n_elem(0)
, n_alloc(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -2751,7 +2741,7 @@ Cube<eT>::Cube(const OpCube<T1, op_type>& X)
, n_elem(0)
, n_alloc(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -3048,7 +3038,7 @@ Cube<eT>::Cube(const mtOpCube<eT, T1, op_type>& X)
, n_elem(0)
, n_alloc(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -3144,7 +3134,7 @@ Cube<eT>::Cube(const GlueCube<T1, T2, glue_type>& X)
, n_elem(0)
, n_alloc(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -3401,7 +3391,7 @@ Cube<eT>::Cube(const mtGlueCube<eT, T1, T2, glue_type>& X)
, n_elem(0)
, n_alloc(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -3887,7 +3877,7 @@ arma_inline
eT*
Cube<eT>::slice_memptr(const uword uslice)
{
return const_cast<eT*>( &mem[ uslice*n_elem_slice ] );
return access::rwp( mem + (uslice*n_elem_slice) );
}
@@ -3898,7 +3888,7 @@ arma_inline
const eT*
Cube<eT>::slice_memptr(const uword uslice) const
{
return &mem[ uslice*n_elem_slice ];
return mem + (uslice*n_elem_slice);
}
@@ -3909,7 +3899,7 @@ arma_inline
eT*
Cube<eT>::slice_colptr(const uword uslice, const uword col)
{
return const_cast<eT*>( &mem[ uslice*n_elem_slice + col*n_rows] );
return access::rwp( mem + (uslice*n_elem_slice + col*n_rows) );
}
@@ -3920,7 +3910,7 @@ arma_inline
const eT*
Cube<eT>::slice_colptr(const uword uslice, const uword col) const
{
return &mem[ uslice*n_elem_slice + col*n_rows ];
return mem + (uslice*n_elem_slice + col*n_rows);
}
@@ -4197,12 +4187,12 @@ Cube<eT>::clamp(const eT min_val, const eT max_val)
if(is_cx<eT>::no)
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "Cube::clamp(): min_val must be less than max_val" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "Cube::clamp(): min_val must be less than max_val" );
}
else
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "Cube::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "Cube::clamp(): imag(min_val) must be less than imag(max_val)" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "Cube::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( ((access::tmp_imag(min_val) <= access::tmp_imag(max_val)) == false), "Cube::clamp(): imag(min_val) must be less than imag(max_val)" );
}
arrayops::clamp(memptr(), n_elem, min_val, max_val);
@@ -4227,6 +4217,30 @@ Cube<eT>::fill(const eT val)
template<typename eT>
template<typename fill_type>
inline
Cube<eT>&
Cube<eT>::fill(const fill::fill_class<fill_type>&)
{
arma_debug_sigprint();
arma_static_check( (is_same_type<fill_type, fill::fill_eye>::yes), "Cube::fill(): unsupported fill type" );
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_nan >::yes) { (*this).fill( priv::Datum_helper::nan <eT>() ); }
if(is_same_type<fill_type, fill::fill_pos_inf>::yes) { (*this).fill( priv::Datum_helper::pos_inf<eT>() ); }
if(is_same_type<fill_type, fill::fill_neg_inf>::yes) { (*this).fill( priv::Datum_helper::neg_inf<eT>() ); }
return *this;
}
template<typename eT>
inline
Cube<eT>&
@@ -5458,18 +5472,13 @@ template<typename eT>
template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
template<typename fill_type>
inline
Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::fixed(const fill::fill_class<fill_type>&)
Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::fixed(const fill::fill_class<fill_type>& f)
{
arma_debug_sigprint_this(this);
mem_setup();
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" );
(*this).fill(f);
}
+109 -79
View File
@@ -49,7 +49,7 @@ Mat<eT>::Mat()
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
}
@@ -255,7 +255,7 @@ Mat<eT>::Mat(const arma_vec_indicator&, const uhword in_vec_state)
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
}
@@ -312,15 +312,10 @@ Mat<eT>::init_cold()
const char* error_message = "Mat::init(): requested size is too large; suggest to enable ARMA_64BIT_WORD";
#endif
arma_conform_check
(
(
( (n_rows > ARMA_MAX_UHWORD) || (n_cols > ARMA_MAX_UHWORD) )
? ( (double(n_rows) * double(n_cols)) > double(ARMA_MAX_UWORD) )
: false
),
error_message
);
if( (n_rows > ARMA_MAX_UHWORD) || (n_cols > ARMA_MAX_UHWORD) )
{
arma_conform_check( ( (double(n_rows) * double(n_cols)) > double(ARMA_MAX_UWORD) ), error_message );
}
if(n_elem <= arma_config::mat_prealloc)
{
@@ -383,17 +378,10 @@ Mat<eT>::init_warm(uword in_n_rows, uword in_n_cols)
const char* error_message_4 = "Mat::init(): requested size is too large; suggest to enable ARMA_64BIT_WORD";
#endif
arma_conform_set_error
(
err_state,
err_msg,
(
( (in_n_rows > ARMA_MAX_UHWORD) || (in_n_cols > ARMA_MAX_UHWORD) )
? ( (double(in_n_rows) * double(in_n_cols)) > double(ARMA_MAX_UWORD) )
: false
),
error_message_4
);
if( (in_n_rows > ARMA_MAX_UHWORD) || (in_n_cols > ARMA_MAX_UHWORD) )
{
arma_conform_set_error( err_state, err_msg, ( (double(in_n_rows) * double(in_n_cols)) > double(ARMA_MAX_UWORD) ), error_message_4 );
}
arma_conform_check(err_state, err_msg);
@@ -468,7 +456,7 @@ Mat<eT>::Mat(const char* text)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -502,7 +490,7 @@ Mat<eT>::Mat(const std::string& text)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -690,7 +678,7 @@ Mat<eT>::Mat(const std::initializer_list<eT>& list)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -722,7 +710,7 @@ Mat<eT>::Mat(const std::initializer_list< std::initializer_list<eT> >& list)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -889,7 +877,7 @@ Mat<eT>::Mat(const Mat<eT>& in_mat, const arma_vec_indicator&, const uhword in_v
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint(arma_str::format("this: %x; in_mat: %x") % this % &in_mat);
@@ -1524,7 +1512,7 @@ Mat<eT>::Mat(const BaseCube<eT,T1>& X, const arma_vec_indicator&, const uhword i
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -1543,7 +1531,7 @@ Mat<eT>::Mat(const BaseCube<eT,T1>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -1990,7 +1978,7 @@ Mat<eT>::Mat(const Base<typename Mat<eT>::pod_type,T1>& A, const Base<typename M
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -2010,7 +1998,7 @@ Mat<eT>::Mat(const Base<typename Mat<eT>::pod_type,T1>& A, const Base<typename M
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -2055,7 +2043,7 @@ Mat<eT>::Mat(const subview<eT>& X, const arma_vec_indicator&, const uhword in_ve
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -2278,7 +2266,7 @@ Mat<eT>::Mat(const subview_cube<eT>& x, const arma_vec_indicator&, const uhword
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -2297,7 +2285,7 @@ Mat<eT>::Mat(const subview_cube<eT>& x)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -2407,7 +2395,7 @@ Mat<eT>::Mat(const diagview<eT>& X, const arma_vec_indicator&, const uhword in_v
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -2552,11 +2540,11 @@ Mat<eT>::Mat(const subview_elem1<eT,T1>& X, const arma_vec_indicator&, const uhw
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
(*this).operator=(X);
subview_elem1<eT,T1>::extract_noalias(*this, X);
}
@@ -2571,11 +2559,11 @@ Mat<eT>::Mat(const subview_elem1<eT,T1>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
(*this).operator=(X);
subview_elem1<eT,T1>::extract_noalias(*this, X);
}
@@ -2680,11 +2668,11 @@ Mat<eT>::Mat(const subview_elem2<eT,T1,T2>& X, const arma_vec_indicator&, const
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
(*this).operator=(X);
subview_elem2<eT,T1,T2>::extract_noalias(*this, X);
}
@@ -2699,11 +2687,11 @@ Mat<eT>::Mat(const subview_elem2<eT,T1,T2>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
(*this).operator=(X);
subview_elem2<eT,T1,T2>::extract_noalias(*this, X);
}
@@ -2808,7 +2796,7 @@ Mat<eT>::Mat(const SpBase<eT, T1>& m, const arma_vec_indicator&, const uhword in
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -2827,7 +2815,7 @@ Mat<eT>::Mat(const SpBase<eT, T1>& m)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -2888,6 +2876,8 @@ Mat<eT>::operator+=(const SpBase<eT, T1>& m)
arma_conform_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "addition");
if(p.get_n_nonzero() == 0) { return *this; }
typename SpProxy<T1>::const_iterator_type it = p.begin();
typename SpProxy<T1>::const_iterator_type it_end = p.end();
@@ -2910,6 +2900,8 @@ Mat<eT>::operator-=(const SpBase<eT, T1>& m)
arma_conform_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "subtraction");
if(p.get_n_nonzero() == 0) { return *this; }
typename SpProxy<T1>::const_iterator_type it = p.begin();
typename SpProxy<T1>::const_iterator_type it_end = p.end();
@@ -2928,9 +2920,9 @@ Mat<eT>::operator*=(const SpBase<eT, T1>& m)
{
arma_debug_sigprint();
Mat<eT> z = (*this) * m.get_ref();
Mat<eT> tmp = (*this) * m.get_ref();
steal_mem(z);
steal_mem(tmp);
return *this;
}
@@ -3011,7 +3003,7 @@ Mat<eT>::Mat(const SpSubview<eT>& X, const arma_vec_indicator&, const uhword in_
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -3029,7 +3021,7 @@ Mat<eT>::Mat(const SpSubview<eT>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -3212,7 +3204,7 @@ Mat<eT>::Mat(const spdiagview<eT>& X, const arma_vec_indicator&, const uhword in
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -5140,7 +5132,7 @@ Mat<eT>::Mat(const Gen<T1, gen_type>& X, const arma_vec_indicator&, const uhword
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -5290,7 +5282,7 @@ Mat<eT>::Mat(const Op<T1, op_type>& X, const arma_vec_indicator&, const uhword i
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -5312,7 +5304,7 @@ Mat<eT>::Mat(const Op<T1, op_type>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -5441,7 +5433,7 @@ Mat<eT>::Mat(const eOp<T1, eop_type>& X, const arma_vec_indicator&, const uhword
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -5669,7 +5661,7 @@ Mat<eT>::Mat(const mtOp<eT, T1, op_type>& X, const arma_vec_indicator&, const uh
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -5688,7 +5680,7 @@ Mat<eT>::Mat(const mtOp<eT, T1, op_type>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -5797,7 +5789,7 @@ Mat<eT>::Mat(const CubeToMatOp<T1, op_type>& X, const arma_vec_indicator&, const
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -5818,7 +5810,7 @@ Mat<eT>::Mat(const CubeToMatOp<T1, op_type>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -5941,7 +5933,7 @@ Mat<eT>::Mat(const SpToDOp<T1, op_type>& X, const arma_vec_indicator&, const uhw
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -5962,7 +5954,7 @@ Mat<eT>::Mat(const SpToDOp<T1, op_type>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -6091,7 +6083,7 @@ Mat<eT>::Mat(const mtSpReduceOp<eT, T1, op_type>& X, const arma_vec_indicator&,
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -6110,7 +6102,7 @@ Mat<eT>::Mat(const mtSpReduceOp<eT, T1, op_type>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -6219,7 +6211,7 @@ Mat<eT>::Mat(const Glue<T1, T2, glue_type>& X, const arma_vec_indicator&, const
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -6242,7 +6234,7 @@ Mat<eT>::Mat(const Glue<T1, T2, glue_type>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -6408,7 +6400,7 @@ Mat<eT>::Mat(const eGlue<T1, T2, eglue_type>& X, const arma_vec_indicator&, cons
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -6615,7 +6607,7 @@ Mat<eT>::Mat(const mtGlue<eT, T1, T2, glue_type>& X, const arma_vec_indicator&,
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -6634,7 +6626,7 @@ Mat<eT>::Mat(const mtGlue<eT, T1, T2, glue_type>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -6745,7 +6737,7 @@ Mat<eT>::Mat(const SpToDGlue<T1, T2, glue_type>& X, const arma_vec_indicator&, c
, n_alloc(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -6767,7 +6759,7 @@ Mat<eT>::Mat(const SpToDGlue<T1, T2, glue_type>& X)
, n_alloc(0)
, vec_state(0)
, mem_state(0)
, mem()
, mem(nullptr)
{
arma_debug_sigprint_this(this);
@@ -7487,7 +7479,7 @@ arma_inline
eT*
Mat<eT>::colptr(const uword in_col)
{
return & access::rw(mem[in_col*n_rows]);
return access::rwp( mem + (in_col*n_rows) );
}
@@ -7498,7 +7490,7 @@ arma_inline
const eT*
Mat<eT>::colptr(const uword in_col) const
{
return & mem[in_col*n_rows];
return mem + (in_col*n_rows);
}
@@ -7580,10 +7572,40 @@ Mat<eT>::resize(const uword new_n_elem)
{
arma_debug_sigprint();
const uword new_n_rows = (vec_state == 2) ? uword(1 ) : uword(new_n_elem);
const uword new_n_cols = (vec_state == 2) ? uword(new_n_elem) : uword(1 );
const bool reuse_mem =
( is_vec() && (mem_state == 0) )
&&
(
( (new_n_elem <= arma_config::mat_prealloc) && (n_elem <= arma_config::mat_prealloc) && ( n_elem > 0 ) )
|| ( (new_n_elem > arma_config::mat_prealloc) && (n_elem > arma_config::mat_prealloc) && (new_n_elem <= n_alloc) )
);
return (*this).resize(new_n_rows, new_n_cols);
if(reuse_mem)
{
arma_debug_print("Mat::resize(): reusing memory");
if(new_n_elem > n_elem)
{
arma_debug_print("Mat::resize(): zeroing memory");
eT* t_mem = (*this).memptr(); // the (n_elem > 0) check above ensures that (*this).memptr() is a valid pointer
for(uword ii = n_elem; ii < new_n_elem; ++ii) { t_mem[ii] = eT(0); }
}
access::rw(n_rows) = (vec_state == 2) ? uword(1 ) : uword(new_n_elem);
access::rw(n_cols) = (vec_state == 2) ? uword(new_n_elem) : uword(1 );
access::rw(n_elem) = new_n_elem;
}
else
{
const uword new_n_rows = (vec_state == 2) ? uword(1 ) : uword(new_n_elem);
const uword new_n_cols = (vec_state == 2) ? uword(new_n_elem) : uword(1 );
(*this).resize(new_n_rows, new_n_cols);
}
return (*this);
}
@@ -7863,12 +7885,12 @@ Mat<eT>::clamp(const eT min_val, const eT max_val)
if(is_cx<eT>::no)
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "Mat::clamp(): min_val must be less than max_val" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "Mat::clamp(): min_val must be less than max_val" );
}
else
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "Mat::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "Mat::clamp(): imag(min_val) must be less than imag(max_val)" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "Mat::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( ((access::tmp_imag(min_val) <= access::tmp_imag(max_val)) == false), "Mat::clamp(): imag(min_val) must be less than imag(max_val)" );
}
arrayops::clamp(memptr(), n_elem, min_val, max_val);
@@ -7908,6 +7930,10 @@ Mat<eT>::fill(const fill::fill_class<fill_type>&)
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_nan >::yes) { (*this).fill( priv::Datum_helper::nan <eT>() ); }
if(is_same_type<fill_type, fill::fill_pos_inf>::yes) { (*this).fill( priv::Datum_helper::pos_inf<eT>() ); }
if(is_same_type<fill_type, fill::fill_neg_inf>::yes) { (*this).fill( priv::Datum_helper::neg_inf<eT>() ); }
return *this;
}
@@ -10081,6 +10107,10 @@ Mat<eT>::fixed<fixed_n_rows, fixed_n_cols>::fixed(const fill::fill_class<fill_ty
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(); }
if(is_same_type<fill_type, fill::fill_nan >::yes) { (*this).fill( priv::Datum_helper::nan <eT>() ); }
if(is_same_type<fill_type, fill::fill_pos_inf>::yes) { (*this).fill( priv::Datum_helper::pos_inf<eT>() ); }
if(is_same_type<fill_type, fill::fill_neg_inf>::yes) { (*this).fill( priv::Datum_helper::neg_inf<eT>() ); }
}
@@ -10515,7 +10545,7 @@ Mat<eT>::fixed<fixed_n_rows, fixed_n_cols>::colptr(const uword in_col)
{
eT* mem_actual = (use_extra) ? mem_local_extra : mem_local;
return & access::rw(mem_actual[in_col*fixed_n_rows]);
return access::rwp( mem_actual + (in_col*fixed_n_rows) );
}
@@ -10528,7 +10558,7 @@ Mat<eT>::fixed<fixed_n_rows, fixed_n_cols>::colptr(const uword in_col) const
{
const eT* mem_actual = (use_extra) ? mem_local_extra : mem_local;
return & mem_actual[in_col*fixed_n_rows];
return mem_actual + (in_col*fixed_n_rows);
}
+3 -3
View File
@@ -1537,7 +1537,7 @@ struct Proxy_xtrans_default< Op<T1, op_htrans> >
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 void_ptr(&(U.M)) == void_ptr(&X); }
arma_inline bool is_alias(const Mat<eT2>& X) const { return U.is_alias(X); }
template<typename eT2>
arma_inline bool has_overlap(const subview<eT2>& X) const { return is_alias(X.m); }
@@ -1578,7 +1578,7 @@ struct Proxy_xtrans_default< Op<T1, op_strans> >
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 void_ptr(&(U.M)) == void_ptr(&X); }
arma_inline bool is_alias(const Mat<eT2>& X) const { return U.is_alias(X); }
template<typename eT2>
arma_inline bool has_overlap(const subview<eT2>& X) const { return is_alias(X.m); }
@@ -2441,7 +2441,7 @@ struct Proxy_vectorise_col_mat< Op<T1, op_vectorise_col> >
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 ( void_ptr(&X) == void_ptr(&(U.M)) ); }
arma_inline bool is_alias(const Mat<eT2>& X) const { return U.is_alias(X); }
template<typename eT2>
arma_inline bool has_overlap(const subview<eT2>& X) const { return is_alias(X.m); }
+4
View File
@@ -1351,6 +1351,10 @@ Row<eT>::fixed<fixed_n_elem>::fixed(const fill::fill_class<fill_type>&)
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(); }
if(is_same_type<fill_type, fill::fill_nan >::yes) { (*this).fill( priv::Datum_helper::nan <eT>() ); }
if(is_same_type<fill_type, fill::fill_pos_inf>::yes) { (*this).fill( priv::Datum_helper::pos_inf<eT>() ); }
if(is_same_type<fill_type, fill::fill_neg_inf>::yes) { (*this).fill( priv::Datum_helper::neg_inf<eT>() ); }
}
+4 -4
View File
@@ -527,7 +527,7 @@ SpBase<elem_type,derived>::is_zero(const typename get_pod_type<elem_type>::resul
typedef typename get_pod_type<elem_type>::result T;
arma_conform_check( (tol < T(0)), "is_zero(): parameter 'tol' must be >= 0" );
arma_conform_check( ((tol >= T(0)) == false), "is_zero(): parameter 'tol' must be >= 0" );
const SpProxy<derived> P( (*this).get_ref() );
@@ -554,8 +554,8 @@ SpBase<elem_type,derived>::is_zero(const typename get_pod_type<elem_type>::resul
const T val_real = access::tmp_real(val);
const T val_imag = access::tmp_imag(val);
if(eop_aux::arma_abs(val_real) > tol) { return false; }
if(eop_aux::arma_abs(val_imag) > tol) { return false; }
if( (eop_aux::arma_abs(val_real) <= tol) == false ) { return false; }
if( (eop_aux::arma_abs(val_imag) <= tol) == false ) { return false; }
++it;
}
@@ -564,7 +564,7 @@ SpBase<elem_type,derived>::is_zero(const typename get_pod_type<elem_type>::resul
{
while(it != it_end)
{
if(eop_aux::arma_abs(*it) > tol) { return false; }
if( (eop_aux::arma_abs(*it) <= tol) == false ) { return false; }
++it;
}
+140 -84
View File
@@ -688,15 +688,22 @@ SpMat<eT>::operator=(const SpMat<eT>& x)
template<typename eT>
inline
SpMat<eT>&
SpMat<eT>::operator+=(const SpMat<eT>& x)
SpMat<eT>::operator+=(const SpMat<eT>& X)
{
arma_debug_sigprint();
sync_csc();
SpMat<eT> out = (*this) + x;
steal_mem(out);
if(X.n_nonzero == 0)
{
arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "addition");
}
else
{
SpMat<eT> tmp = (*this) + X;
steal_mem(tmp);
}
return *this;
}
@@ -706,15 +713,22 @@ SpMat<eT>::operator+=(const SpMat<eT>& x)
template<typename eT>
inline
SpMat<eT>&
SpMat<eT>::operator-=(const SpMat<eT>& x)
SpMat<eT>::operator-=(const SpMat<eT>& X)
{
arma_debug_sigprint();
sync_csc();
SpMat<eT> out = (*this) - x;
steal_mem(out);
if(X.n_nonzero == 0)
{
arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "subtraction");
}
else
{
SpMat<eT> tmp = (*this) - X;
steal_mem(tmp);
}
return *this;
}
@@ -724,15 +738,15 @@ SpMat<eT>::operator-=(const SpMat<eT>& x)
template<typename eT>
inline
SpMat<eT>&
SpMat<eT>::operator*=(const SpMat<eT>& y)
SpMat<eT>::operator*=(const SpMat<eT>& X)
{
arma_debug_sigprint();
sync_csc();
SpMat<eT> z = (*this) * y;
SpMat<eT> tmp = (*this) * X;
steal_mem(z);
steal_mem(tmp);
return *this;
}
@@ -743,15 +757,24 @@ SpMat<eT>::operator*=(const SpMat<eT>& y)
template<typename eT>
inline
SpMat<eT>&
SpMat<eT>::operator%=(const SpMat<eT>& y)
SpMat<eT>::operator%=(const SpMat<eT>& X)
{
arma_debug_sigprint();
sync_csc();
SpMat<eT> z = (*this) % y;
steal_mem(z);
if(X.n_nonzero == 0)
{
arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "element-wise multiplication");
(*this).zeros();
}
else
{
SpMat<eT> tmp = (*this) % X;
steal_mem(tmp);
}
return *this;
}
@@ -1338,9 +1361,16 @@ SpMat<eT>::operator+=(const SpSubview<eT>& X)
sync_csc();
SpMat<eT> tmp = (*this) + X;
steal_mem(tmp);
if(X.n_nonzero == 0)
{
arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "addition");
}
else
{
SpMat<eT> tmp = (*this) + X;
steal_mem(tmp);
}
return *this;
}
@@ -1356,64 +1386,82 @@ SpMat<eT>::operator-=(const SpSubview<eT>& X)
sync_csc();
SpMat<eT> tmp = (*this) - X;
steal_mem(tmp);
return *this;
}
template<typename eT>
inline
SpMat<eT>&
SpMat<eT>::operator*=(const SpSubview<eT>& y)
{
arma_debug_sigprint();
sync_csc();
SpMat<eT> z = (*this) * y;
steal_mem(z);
return *this;
}
template<typename eT>
inline
SpMat<eT>&
SpMat<eT>::operator%=(const SpSubview<eT>& x)
{
arma_debug_sigprint();
sync_csc();
SpMat<eT> tmp = (*this) % x;
steal_mem(tmp);
return *this;
}
template<typename eT>
inline
SpMat<eT>&
SpMat<eT>::operator/=(const SpSubview<eT>& x)
{
arma_debug_sigprint();
arma_conform_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element-wise division");
// There is no pretty way to do this.
for(uword elem = 0; elem < n_elem; elem++)
if(X.n_nonzero == 0)
{
at(elem) /= x(elem);
arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "subtraction");
}
else
{
SpMat<eT> tmp = (*this) - X;
steal_mem(tmp);
}
return *this;
}
template<typename eT>
inline
SpMat<eT>&
SpMat<eT>::operator*=(const SpSubview<eT>& X)
{
arma_debug_sigprint();
sync_csc();
SpMat<eT> tmp = (*this) * X;
steal_mem(tmp);
return *this;
}
template<typename eT>
inline
SpMat<eT>&
SpMat<eT>::operator%=(const SpSubview<eT>& X)
{
arma_debug_sigprint();
sync_csc();
if(X.n_nonzero == 0)
{
arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "element-wise multiplication");
(*this).zeros();
}
else
{
SpMat<eT> tmp = (*this) % X;
steal_mem(tmp);
}
return *this;
}
template<typename eT>
inline
SpMat<eT>&
SpMat<eT>::operator/=(const SpSubview<eT>& X)
{
arma_debug_sigprint();
// NOTE: use of this function is not advised; it is implemented only for completeness
arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "element-wise division");
for(uword c = 0; c < n_cols; ++c)
for(uword r = 0; r < n_rows; ++r)
{
at(r, c) /= X.at(r, c);
}
return *this;
@@ -1507,9 +1555,9 @@ SpMat<eT>::operator*=(const SpSubview_col_list<eT,T1>& X)
sync_csc();
SpMat<eT> z = (*this) * X;
SpMat<eT> tmp = (*this) * X;
steal_mem(z);
steal_mem(tmp);
return *this;
}
@@ -3517,7 +3565,7 @@ SpMat<eT>::is_symmetric(const typename get_pod_type<elem_type>::result tol) cons
if(tol == T(0)) { return (*this).is_symmetric(); }
arma_conform_check( (tol < T(0)), "is_symmetric(): parameter 'tol' must be >= 0" );
arma_conform_check( ((tol >= T(0)) == false), "is_symmetric(): parameter 'tol' must be > 0" );
const SpMat<eT>& A = (*this);
@@ -3527,8 +3575,12 @@ SpMat<eT>::is_symmetric(const typename get_pod_type<elem_type>::result tol) cons
if(norm_A == T(0)) { return true; }
if(arma_isnan(norm_A)) { return false; }
const T norm_A_Ast = as_scalar( arma::max(sum(abs(A - A.st()), 1), 0) );
if(arma_isnan(norm_A_Ast)) { return false; }
return ( (norm_A_Ast / norm_A) <= tol );
}
@@ -3563,7 +3615,7 @@ SpMat<eT>::is_hermitian(const typename get_pod_type<elem_type>::result tol) cons
if(tol == T(0)) { return (*this).is_hermitian(); }
arma_conform_check( (tol < T(0)), "is_hermitian(): parameter 'tol' must be >= 0" );
arma_conform_check( ((tol >= T(0)) == false), "is_hermitian(): parameter 'tol' must be > 0" );
const SpMat<eT>& A = (*this);
@@ -3573,8 +3625,12 @@ SpMat<eT>::is_hermitian(const typename get_pod_type<elem_type>::result tol) cons
if(norm_A == T(0)) { return true; }
if(arma_isnan(norm_A)) { return false; }
const T norm_A_At = as_scalar( arma::max(sum(abs(A - A.t()), 1), 0) );
if(arma_isnan(norm_A_At)) { return false; }
return ( (norm_A_At / norm_A) <= tol );
}
@@ -4156,12 +4212,12 @@ SpMat<eT>::clamp(const eT min_val, const eT max_val)
if(is_cx<eT>::no)
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "SpMat::clamp(): min_val must be less than max_val" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "SpMat::clamp(): min_val must be less than max_val" );
}
else
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "SpMat::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "SpMat::clamp(): imag(min_val) must be less than imag(max_val)" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "SpMat::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( ((access::tmp_imag(min_val) <= access::tmp_imag(max_val)) == false), "SpMat::clamp(): imag(min_val) must be less than imag(max_val)" );
}
if(n_nonzero == 0) { return *this; }
@@ -4341,7 +4397,7 @@ SpMat<eT>::sprandu(const uword in_rows, const uword in_cols, const double densit
{
arma_debug_sigprint();
arma_conform_check( ( (density < double(0)) || (density > double(1)) ), "sprandu(): density must be in the [0,1] interval" );
arma_conform_check( ( ((density >= double(0)) == false) || ((density <= double(1)) == false) ), "sprandu(): density must be in the [0,1] interval" );
const uword new_n_nonzero = uword(density * double(in_rows) * double(in_cols) + 0.5);
@@ -4418,7 +4474,7 @@ SpMat<eT>::sprandn(const uword in_rows, const uword in_cols, const double densit
{
arma_debug_sigprint();
arma_conform_check( ( (density < double(0)) || (density > double(1)) ), "sprandn(): density must be in the [0,1] interval" );
arma_conform_check( ( ((density >= double(0)) == false) || ((density <= double(1)) == false) ), "sprandn(): density must be in the [0,1] interval" );
const uword new_n_nonzero = uword(density * double(in_rows) * double(in_cols) + 0.5);
+44 -3
View File
@@ -44,6 +44,8 @@ SpSubview<eT>::SpSubview(const SpMat<eT>& in_m, const uword in_row1, const uword
m.sync_csc();
if( (n_elem == 0) || (m.n_nonzero == 0) ) { return; } // (*this).n_nonzero already set to zero
// count the number of non-zeros in the subview
uword count = 0;
@@ -127,6 +129,8 @@ SpSubview<eT>::operator+=(const eT val)
tmp.fill(val);
if(n_nonzero == 0) { return (*this).operator=(tmp); }
return (*this).operator=( (*this) + tmp );
}
@@ -319,6 +323,15 @@ SpSubview<eT>::operator+=(const Base<eT, T1>& x)
{
arma_debug_sigprint();
if(n_nonzero == 0)
{
const quasi_unwrap<T1> U(x.get_ref());
arma_conform_assert_same_size(n_rows, n_cols, U.M.n_rows, U.M.n_cols, "addition");
return (*this).operator=(U.M);
}
return (*this).operator=( (*this) + x.get_ref() );
}
@@ -369,6 +382,8 @@ SpSubview<eT>::operator%=(const Base<eT, T1>& x)
arma_conform_assert_same_size(sv.n_rows, sv.n_cols, B.n_rows, B.n_cols, "element-wise multiplication");
if(n_nonzero == 0) { return *this; }
SpMat<eT>& sv_m = access::rw(sv.m);
sv_m.sync_csc();
@@ -555,6 +570,15 @@ SpSubview<eT>::operator+=(const SpBase<eT, T1>& x)
{
arma_debug_sigprint();
if(n_nonzero == 0)
{
const unwrap_spmat<T1> U(x.get_ref());
arma_conform_assert_same_size(n_rows, n_cols, U.M.n_rows, U.M.n_cols, "addition");
return (*this).operator_equ_common(U.M);
}
// TODO: implement dedicated machinery
return (*this).operator=( (*this) + x.get_ref() );
}
@@ -596,6 +620,15 @@ SpSubview<eT>::operator%=(const SpBase<eT, T1>& x)
{
arma_debug_sigprint();
if(n_nonzero == 0)
{
const SpProxy<T1> P(x.get_ref());
arma_conform_assert_same_size(n_rows, n_cols, P.get_n_rows(), P.get_n_cols(), "element-wise multiplication");
return *this;
}
// TODO: implement dedicated machinery
return (*this).operator=( (*this) % x.get_ref() );
}
@@ -648,6 +681,8 @@ SpSubview<eT>::for_each(functor F)
m.sync_csc();
m.invalidate_cache();
if(n_nonzero == 0) { return; }
const uword lstart_row = aux_row1;
const uword lend_row = aux_row1 + n_rows;
@@ -704,6 +739,8 @@ SpSubview<eT>::for_each(functor F) const
m.sync_csc();
if(n_nonzero == 0) { return; }
const uword lstart_row = aux_row1;
const uword lend_row = aux_row1 + n_rows;
@@ -743,6 +780,8 @@ SpSubview<eT>::transform(functor F)
m.sync_csc();
m.invalidate_cache();
if(n_nonzero == 0) { return; }
const uword lstart_row = aux_row1;
const uword lend_row = aux_row1 + n_rows;
@@ -813,6 +852,8 @@ SpSubview<eT>::replace(const eT old_val, const eT new_val)
m.sync_csc();
m.invalidate_cache();
if(n_nonzero == 0) { return; }
const uword lstart_row = aux_row1;
const uword lend_row = aux_row1 + n_rows;
@@ -905,12 +946,12 @@ SpSubview<eT>::clamp(const eT min_val, const eT max_val)
if(is_cx<eT>::no)
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "SpSubview::clamp(): min_val must be less than max_val" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "SpSubview::clamp(): min_val must be less than max_val" );
}
else
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "SpSubview::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "SpSubview::clamp(): imag(min_val) must be less than imag(max_val)" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "SpSubview::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( ((access::tmp_imag(min_val) <= access::tmp_imag(max_val)) == false), "SpSubview::clamp(): imag(min_val) must be less than imag(max_val)" );
}
if((n_elem == 0) || (n_nonzero == 0)) { return; }
+73 -12
View File
@@ -26,6 +26,9 @@
#undef ARMA_USE_THREAD_LOCAL
#define ARMA_USE_THREAD_LOCAL
#undef ARMA_USE_THREAD_UNIQUE_RNG_SEED
#define ARMA_USE_THREAD_UNIQUE_RNG_SEED
#if (defined(ARMA_RNG_ALT) || defined(ARMA_DONT_USE_CXX11_RNG))
#undef ARMA_USE_CXX11_RNG
#endif
@@ -34,6 +37,10 @@
#undef ARMA_USE_THREAD_LOCAL
#endif
#if defined(ARMA_DONT_USE_THREAD_UNIQUE_RNG_SEED)
#undef ARMA_USE_THREAD_UNIQUE_RNG_SEED
#endif
// NOTE: ARMA_WARMUP_PRODUCER enables a workaround
// NOTE: for thread_local issue on macOS 11 and/or AppleClang 12.0
@@ -129,24 +136,42 @@ arma_rng::get_producer()
{
#if defined(ARMA_USE_THREAD_LOCAL)
// use a thread-safe RNG, with each thread having its own unique starting seed
// thread-safe RNG
static std::atomic<std::size_t> mt19937_64_producer_counter(0);
static thread_local std::mt19937_64 mt19937_64_producer( std::mt19937_64::default_seed + mt19937_64_producer_counter++ );
arma_rng::warmup_producer(mt19937_64_producer);
#if defined(ARMA_USE_THREAD_UNIQUE_RNG_SEED)
// each thread has unique starting seed
#if defined(ARMA_USE_OPENMP)
static thread_local std::mt19937_64 mt19937_64_producer( std::mt19937_64::default_seed + arma_rng::seed_type(omp_get_thread_num()) );
#else
static std::atomic<std::size_t> mt19937_64_producer_counter(0);
static thread_local std::mt19937_64 mt19937_64_producer( std::mt19937_64::default_seed + mt19937_64_producer_counter++ );
#endif
#else
// each thread has the same starting seed
static thread_local std::mt19937_64 mt19937_64_producer( std::mt19937_64::default_seed );
#endif
#else
// use a plain RNG in case we don't have thread_local
// plain RNG in case we don't have thread_local
static std::mt19937_64 mt19937_64_producer( std::mt19937_64::default_seed );
arma_rng::warmup_producer(mt19937_64_producer);
#endif
arma_rng::warmup_producer(mt19937_64_producer);
return mt19937_64_producer;
}
@@ -226,9 +251,45 @@ arma_rng::set_seed(const arma_rng::seed_type val)
}
#elif defined(ARMA_USE_CXX11_RNG)
{
arma_rng::lock_producer();
arma_rng::get_producer().seed(val);
arma_rng::unlock_producer();
#if defined(ARMA_USE_OPENMP) && defined(ARMA_USE_THREAD_LOCAL)
{
arma_rng::lock_producer();
#if defined(ARMA_USE_THREAD_UNIQUE_RNG_SEED)
constexpr bool thread_unique_rng_seed = true;
#else
constexpr bool thread_unique_rng_seed = false;
#endif
// if we're already in a parallel region, assume the user is setting the seed for each thread
if( (thread_unique_rng_seed == false) || bool(omp_in_parallel()) )
{
arma_rng::get_producer().seed(val);
}
else
{
const int n_threads = int( (std::max)( int(1), int(omp_get_max_threads()) ) );
#pragma omp parallel for ordered schedule(static) num_threads(n_threads)
for(int t=0; t < n_threads; ++t)
{
#pragma omp ordered
{
arma_rng::get_producer().seed(val + arma_rng::seed_type(omp_get_thread_num()));
}
}
}
arma_rng::unlock_producer();
}
#else
{
arma_rng::lock_producer();
arma_rng::get_producer().seed(val);
arma_rng::unlock_producer();
}
#endif
}
#else
{
+1 -1
View File
@@ -23,7 +23,7 @@
#define ARMA_VERSION_MAJOR 15
#define ARMA_VERSION_MINOR 2
#define ARMA_VERSION_PATCH 1
#define ARMA_VERSION_PATCH 7
#define ARMA_VERSION_NAME "Medium Roast Deluxe"
+3 -3
View File
@@ -994,7 +994,7 @@ arrayops::is_zero(const eT* mem, const uword n_elem, const eT abs_limit, const t
{
for(uword i=0; i<n_elem; ++i)
{
if(eop_aux::arma_abs(mem[i]) > abs_limit) { return false; }
if( (eop_aux::arma_abs(mem[i]) <= abs_limit) == false ) { return false; }
}
}
@@ -1028,8 +1028,8 @@ arrayops::is_zero(const std::complex<T>* mem, const uword n_elem, const T abs_li
{
const eT& val = mem[i];
if(std::abs(std::real(val)) > abs_limit) { return false; }
if(std::abs(std::imag(val)) > abs_limit) { return false; }
if( (std::abs(std::real(val)) <= abs_limit) == false ) { return false; }
if( (std::abs(std::imag(val)) <= abs_limit) == false ) { return false; }
}
}
+12 -12
View File
@@ -330,18 +330,6 @@
#undef ARMA_OPTIMISE_POWEXPR
#endif
#if defined(ARMA_DONT_CHECK_CONFORMANCE)
#if defined(ARMA_CHECK_CONFORMANCE) && (ARMA_WARN_LEVEL >= 2)
#pragma message ("WARNING: conformance checks disabled")
#endif
#undef ARMA_CHECK_CONFORMANCE
#endif
#if defined(ARMA_DONT_CHECK_NONFINITE)
#undef ARMA_CHECK_NONFINITE
#endif
#if defined(ARMA_NO_DEBUG)
#undef ARMA_DEBUG
#undef ARMA_EXTRA_DEBUG
@@ -361,6 +349,18 @@
#define ARMA_WARN_LEVEL 3
#endif
#if defined(ARMA_DONT_CHECK_CONFORMANCE)
#if defined(ARMA_CHECK_CONFORMANCE) && (ARMA_WARN_LEVEL >= 2)
#pragma message ("WARNING: conformance checks disabled")
#endif
#undef ARMA_CHECK_CONFORMANCE
#endif
#if defined(ARMA_DONT_CHECK_NONFINITE)
#undef ARMA_CHECK_NONFINITE
#endif
#if defined(ARMA_DONT_PRINT_EXCEPTIONS)
#undef ARMA_PRINT_EXCEPTIONS
#endif
+12 -12
View File
@@ -330,18 +330,6 @@
#undef ARMA_OPTIMISE_POWEXPR
#endif
#if defined(ARMA_DONT_CHECK_CONFORMANCE)
#if defined(ARMA_CHECK_CONFORMANCE) && (ARMA_WARN_LEVEL >= 2)
#pragma message ("WARNING: conformance checks disabled")
#endif
#undef ARMA_CHECK_CONFORMANCE
#endif
#if defined(ARMA_DONT_CHECK_NONFINITE)
#undef ARMA_CHECK_NONFINITE
#endif
#if defined(ARMA_NO_DEBUG)
#undef ARMA_DEBUG
#undef ARMA_EXTRA_DEBUG
@@ -361,6 +349,18 @@
#define ARMA_WARN_LEVEL 3
#endif
#if defined(ARMA_DONT_CHECK_CONFORMANCE)
#if defined(ARMA_CHECK_CONFORMANCE) && (ARMA_WARN_LEVEL >= 2)
#pragma message ("WARNING: conformance checks disabled")
#endif
#undef ARMA_CHECK_CONFORMANCE
#endif
#if defined(ARMA_DONT_CHECK_NONFINITE)
#undef ARMA_CHECK_NONFINITE
#endif
#if defined(ARMA_DONT_PRINT_EXCEPTIONS)
#undef ARMA_PRINT_EXCEPTIONS
#endif
+55 -6
View File
@@ -62,11 +62,14 @@ namespace priv
}
//
template<typename eT>
static
constexpr
typename arma_real_only<eT>::result
inf(typename arma_real_only<eT>::result* junk = nullptr)
pos_inf(typename arma_real_only<eT>::result* junk = nullptr)
{
arma_ignore(junk);
@@ -78,13 +81,13 @@ namespace priv
static
constexpr
typename arma_cx_only<eT>::result
inf(typename arma_cx_only<eT>::result* junk = nullptr)
pos_inf(typename arma_cx_only<eT>::result* junk = nullptr)
{
arma_ignore(junk);
typedef typename get_pod_type<eT>::result T;
return eT( Datum_helper::inf<T>(), Datum_helper::inf<T>() );
return eT( Datum_helper::pos_inf<T>(), Datum_helper::pos_inf<T>() );
}
@@ -92,12 +95,54 @@ namespace priv
static
constexpr
typename arma_integral_only<eT>::result
inf(typename arma_integral_only<eT>::result* junk = nullptr)
pos_inf(typename arma_integral_only<eT>::result* junk = nullptr)
{
arma_ignore(junk);
return std::numeric_limits<eT>::max();
}
//
template<typename eT>
static
constexpr
typename arma_real_only<eT>::result
neg_inf(typename arma_real_only<eT>::result* junk = nullptr)
{
arma_ignore(junk);
return (std::numeric_limits<eT>::has_infinity) ? eT(-std::numeric_limits<eT>::infinity()) : eT(std::numeric_limits<eT>::lowest());
}
template<typename eT>
static
constexpr
typename arma_cx_only<eT>::result
neg_inf(typename arma_cx_only<eT>::result* junk = nullptr)
{
arma_ignore(junk);
typedef typename get_pod_type<eT>::result T;
return eT( Datum_helper::neg_inf<T>(), Datum_helper::neg_inf<T>() );
}
template<typename eT>
static
constexpr
typename arma_integral_only<eT>::result
neg_inf(typename arma_integral_only<eT>::result* junk = nullptr)
{
arma_ignore(junk);
return std::numeric_limits<eT>::lowest();
}
};
}
@@ -125,7 +170,9 @@ struct Datum
static const eT log_min; //!< log of the minimum representable value
static const eT log_max; //!< log of the maximum representable value
static const eT nan; //!< "not a number"
static const eT inf; //!< infinity
static const eT inf; //!< positive infinity
static const eT pos_inf; //!< positive infinity
static const eT neg_inf; //!< negative infinity
//
@@ -176,7 +223,9 @@ template<typename eT> const eT Datum<eT>::eps = std::numeric_limits<eT>:
template<typename eT> const eT Datum<eT>::log_min = std::log(std::numeric_limits<eT>::min());
template<typename eT> const eT Datum<eT>::log_max = std::log(std::numeric_limits<eT>::max());
template<typename eT> const eT Datum<eT>::nan = priv::Datum_helper::nan<eT>();
template<typename eT> const eT Datum<eT>::inf = priv::Datum_helper::inf<eT>();
template<typename eT> const eT Datum<eT>::inf = priv::Datum_helper::pos_inf<eT>();
template<typename eT> const eT Datum<eT>::pos_inf = priv::Datum_helper::pos_inf<eT>();
template<typename eT> const eT Datum<eT>::neg_inf = priv::Datum_helper::neg_inf<eT>();
template<typename eT> const eT Datum<eT>::m_u = eT(1.66053906892e-27);
template<typename eT> const eT Datum<eT>::N_A = eT(6.02214076e23);
+86 -28
View File
@@ -134,15 +134,25 @@ diagview<eT>::operator+=(const eT val)
{
arma_debug_sigprint();
Mat<eT>& t_m = const_cast< Mat<eT>& >(m);
diagview<eT>& d = *this;
const uword t_n_elem = n_elem;
const uword t_row_offset = row_offset;
const uword t_col_offset = col_offset;
Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
for(uword ii=0; ii < t_n_elem; ++ii)
const uword d_n_elem = d.n_elem;
const uword d_row_offset = d.row_offset;
const uword d_col_offset = d.col_offset;
uword ii,jj;
for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
{
t_m.at( ii + t_row_offset, ii + t_col_offset) += val;
d_m.at( ii + d_row_offset, ii + d_col_offset) += val;
d_m.at( jj + d_row_offset, jj + d_col_offset) += val;
}
if(ii < d_n_elem)
{
d_m.at( ii + d_row_offset, ii + d_col_offset) += val;
}
}
@@ -155,15 +165,25 @@ diagview<eT>::operator-=(const eT val)
{
arma_debug_sigprint();
Mat<eT>& t_m = const_cast< Mat<eT>& >(m);
diagview<eT>& d = *this;
const uword t_n_elem = n_elem;
const uword t_row_offset = row_offset;
const uword t_col_offset = col_offset;
Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
for(uword ii=0; ii < t_n_elem; ++ii)
const uword d_n_elem = d.n_elem;
const uword d_row_offset = d.row_offset;
const uword d_col_offset = d.col_offset;
uword ii,jj;
for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
{
t_m.at( ii + t_row_offset, ii + t_col_offset) -= val;
d_m.at( ii + d_row_offset, ii + d_col_offset) -= val;
d_m.at( jj + d_row_offset, jj + d_col_offset) -= val;
}
if(ii < d_n_elem)
{
d_m.at( ii + d_row_offset, ii + d_col_offset) -= val;
}
}
@@ -176,15 +196,25 @@ diagview<eT>::operator*=(const eT val)
{
arma_debug_sigprint();
Mat<eT>& t_m = const_cast< Mat<eT>& >(m);
diagview<eT>& d = *this;
const uword t_n_elem = n_elem;
const uword t_row_offset = row_offset;
const uword t_col_offset = col_offset;
Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
for(uword ii=0; ii < t_n_elem; ++ii)
const uword d_n_elem = d.n_elem;
const uword d_row_offset = d.row_offset;
const uword d_col_offset = d.col_offset;
uword ii,jj;
for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
{
t_m.at( ii + t_row_offset, ii + t_col_offset) *= val;
d_m.at( ii + d_row_offset, ii + d_col_offset) *= val;
d_m.at( jj + d_row_offset, jj + d_col_offset) *= val;
}
if(ii < d_n_elem)
{
d_m.at( ii + d_row_offset, ii + d_col_offset) *= val;
}
}
@@ -197,15 +227,25 @@ diagview<eT>::operator/=(const eT val)
{
arma_debug_sigprint();
Mat<eT>& t_m = const_cast< Mat<eT>& >(m);
diagview<eT>& d = *this;
const uword t_n_elem = n_elem;
const uword t_row_offset = row_offset;
const uword t_col_offset = col_offset;
Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
for(uword ii=0; ii < t_n_elem; ++ii)
const uword d_n_elem = d.n_elem;
const uword d_row_offset = d.row_offset;
const uword d_col_offset = d.col_offset;
uword ii,jj;
for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
{
t_m.at( ii + t_row_offset, ii + t_col_offset) /= val;
d_m.at( ii + d_row_offset, ii + d_col_offset) /= val;
d_m.at( jj + d_row_offset, jj + d_col_offset) /= val;
}
if(ii < d_n_elem)
{
d_m.at( ii + d_row_offset, ii + d_col_offset) /= val;
}
}
@@ -236,6 +276,12 @@ diagview<eT>::operator= (const Base<eT,T1>& o)
"diagview: given object has incompatible size"
);
constexpr bool is_gen_zeros = (is_same_type< T1, Gen<Mat<eT>, gen_zeros> >::yes) || (is_same_type< T1, Gen<Col<eT>, gen_zeros> >::yes);
constexpr bool is_gen_ones = (is_same_type< T1, Gen<Mat<eT>, gen_ones > >::yes) || (is_same_type< T1, Gen<Col<eT>, gen_ones > >::yes);
if(is_gen_zeros) { d.zeros(); return; }
if(is_gen_ones ) { d.ones(); return; }
const bool have_alias = P.is_alias(d_m);
if(have_alias) { arma_debug_print("aliasing detected"); }
@@ -948,13 +994,25 @@ diagview<eT>::fill(const eT val)
{
arma_debug_sigprint();
Mat<eT>& x = const_cast< Mat<eT>& >(m);
diagview<eT>& d = *this;
const uword local_n_elem = n_elem;
Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
for(uword ii=0; ii < local_n_elem; ++ii)
const uword d_n_elem = d.n_elem;
const uword d_row_offset = d.row_offset;
const uword d_col_offset = d.col_offset;
uword ii,jj;
for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
{
x.at(ii+row_offset, ii+col_offset) = val;
d_m.at( ii + d_row_offset, ii + d_col_offset) = val;
d_m.at( jj + d_row_offset, jj + d_col_offset) = val;
}
if(ii < d_n_elem)
{
d_m.at( ii + d_row_offset, ii + d_col_offset) = val;
}
}
+23 -15
View File
@@ -373,29 +373,37 @@ inline
std::string
diskio::gen_tmp_name(const std::string& x)
{
union { uword val; void* ptr; } u;
arma_debug_sigprint();
u.val = uword(0);
u.ptr = const_cast<std::string*>(&x);
const char* charlist = "0123456789abcdefghijklmnopqrstuvwxyz";
const char* suffix1 = ".!";
const u16 a = u16( (u.val >> 8) & 0xFFFF );
const u16 b = u16( (std::clock()) & 0xFFFF );
constexpr std::size_t charlist_length = 36;
constexpr std::size_t suffix1_length = 2;
constexpr std::size_t suffix2_length = 6;
std::ostringstream ss;
typedef typename std::minstd_rand::result_type local_seed_type;
ss << x << ".tmp_";
std::minstd_rand local_engine;
std::uniform_int_distribution<std::size_t> local_distr(0, charlist_length - 1);
ss.setf(std::ios_base::hex, std::ios_base::basefield);
local_engine.seed( static_cast<local_seed_type>( (std::clock()) & 0xFFFF ) );
ss.width(4);
ss.fill('0');
ss << a;
const std::size_t x_length = x.length();
ss.width(4);
ss.fill('0');
ss << b;
std::string out(x_length + suffix1_length + suffix2_length, '0'); // create string filled with char '0' (not 0)
return ss.str();
std::size_t count = 0;
for(; count < x_length; ++count) { out[count] = x[count]; }
for(std::size_t i=0; i < suffix1_length; ++i, ++count) { out[count] = suffix1[i]; }
local_distr(local_engine); // ignore first random number
for(std::size_t i=0; i < suffix2_length; ++i, ++count) { out[count] = charlist[ local_distr(local_engine)]; }
return out;
}
+17 -2
View File
@@ -94,7 +94,9 @@ field<oT>::field(const subview_field<oT>& X)
{
arma_debug_sigprint_this(this);
(*this).operator=(X);
init(X.n_rows, X.n_cols, X.n_slices);
subview_field<oT>::extract(*this, X);
}
@@ -107,7 +109,20 @@ field<oT>::operator=(const subview_field<oT>& X)
{
arma_debug_sigprint();
subview_field<oT>::extract(*this, X);
const bool alias = (this == &(X.f));
if(alias == false)
{
(*this).init(X.n_rows, X.n_cols, X.n_slices);
subview_field<oT>::extract(*this, X);
}
else
{
field<oT> tmp(X);
(*this).operator=(std::move(tmp));
}
return *this;
}
+19 -12
View File
@@ -22,22 +22,29 @@
namespace fill
{
struct fill_none {};
struct fill_zeros {};
struct fill_ones {};
struct fill_eye {};
struct fill_randu {};
struct fill_randn {};
struct fill_none {};
struct fill_zeros {};
struct fill_ones {};
struct fill_eye {};
struct fill_randu {};
struct fill_randn {};
struct fill_nan {};
struct fill_pos_inf {};
struct fill_neg_inf {};
template<typename fill_type>
struct fill_class { inline constexpr fill_class() {} };
static constexpr fill_class<fill_none > none;
static constexpr fill_class<fill_zeros> zeros;
static constexpr fill_class<fill_ones > ones;
static constexpr fill_class<fill_eye > eye;
static constexpr fill_class<fill_randu> randu;
static constexpr fill_class<fill_randn> randn;
static constexpr fill_class<fill_none > none;
static constexpr fill_class<fill_zeros > zeros;
static constexpr fill_class<fill_ones > ones;
static constexpr fill_class<fill_eye > eye;
static constexpr fill_class<fill_randu > randu;
static constexpr fill_class<fill_randn > randn;
static constexpr fill_class<fill_nan > nan;
static constexpr fill_class<fill_pos_inf> inf;
static constexpr fill_class<fill_pos_inf> pos_inf;
static constexpr fill_class<fill_neg_inf> neg_inf;
//
+7 -7
View File
@@ -110,8 +110,8 @@ internal_approx_equal_worker
arma_conform_check( ((use_abs_diff == false) && (use_rel_diff == false)), "internal_approx_equal_worker(): both 'use_abs_diff' and 'use_rel_diff' are false" );
if(use_abs_diff) { arma_conform_check( cond_rel< is_signed<T>::value >::lt(abs_tol, T(0)), "approx_equal(): argument 'abs_tol' must be >= 0" ); }
if(use_rel_diff) { arma_conform_check( cond_rel< is_signed<T>::value >::lt(rel_tol, T(0)), "approx_equal(): argument 'rel_tol' must be >= 0" ); }
if(use_abs_diff) { arma_conform_check( (cond_rel< is_signed<T>::value >::lt(abs_tol, T(0)) || arma_isnan(abs_tol)), "approx_equal(): argument 'abs_tol' must be >= 0" ); }
if(use_rel_diff) { arma_conform_check( (cond_rel< is_signed<T>::value >::lt(rel_tol, T(0)) || arma_isnan(rel_tol)), "approx_equal(): argument 'rel_tol' must be >= 0" ); }
const Proxy<T1> PA(A.get_ref());
const Proxy<T2> PB(B.get_ref());
@@ -203,8 +203,8 @@ internal_approx_equal_worker
arma_conform_check( ((use_abs_diff == false) && (use_rel_diff == false)), "internal_approx_equal_worker(): both 'use_abs_diff' and 'use_rel_diff' are false" );
if(use_abs_diff) { arma_conform_check( cond_rel< is_signed<T>::value >::lt(abs_tol, T(0)), "approx_equal(): argument 'abs_tol' must be >= 0" ); }
if(use_rel_diff) { arma_conform_check( cond_rel< is_signed<T>::value >::lt(rel_tol, T(0)), "approx_equal(): argument 'rel_tol' must be >= 0" ); }
if(use_abs_diff) { arma_conform_check( (cond_rel< is_signed<T>::value >::lt(abs_tol, T(0)) || arma_isnan(abs_tol)), "approx_equal(): argument 'abs_tol' must be >= 0" ); }
if(use_rel_diff) { arma_conform_check( (cond_rel< is_signed<T>::value >::lt(rel_tol, T(0)) || arma_isnan(rel_tol)), "approx_equal(): argument 'rel_tol' must be >= 0" ); }
const ProxyCube<T1> PA(A.get_ref());
const ProxyCube<T2> PB(B.get_ref());
@@ -418,7 +418,7 @@ approx_equal(const SpBase<typename T1::elem_type,T1>& A, const SpBase<typename T
arma_conform_check( (sig == 'r'), "approx_equal(): only the \"absdiff\" method is currently implemented for sparse matrices" );
arma_conform_check( cond_rel< is_signed<T>::value >::lt(tol, T(0)), "approx_equal(): argument 'tol' must be >= 0" );
arma_conform_check( (cond_rel< is_signed<T>::value >::lt(tol, T(0)) || arma_isnan(tol)), "approx_equal(): argument 'tol' must be >= 0" );
const unwrap_spmat<T1> UA(A.get_ref());
const unwrap_spmat<T2> UB(B.get_ref());
@@ -460,8 +460,8 @@ approx_equal(const SpBase<typename T1::elem_type,T1>& A, const SpBase<typename T
arma_conform_check( ((sig == 'r') || (sig == 'b')), "approx_equal(): only the \"absdiff\" method is currently implemented for sparse matrices" );
arma_conform_check( cond_rel< is_signed<T>::value >::lt(abs_tol, T(0)), "approx_equal(): argument 'abs_tol' must be >= 0" );
arma_conform_check( cond_rel< is_signed<T>::value >::lt(rel_tol, T(0)), "approx_equal(): argument 'rel_tol' must be >= 0" );
arma_conform_check( (cond_rel< is_signed<T>::value >::lt(abs_tol, T(0)) || arma_isnan(abs_tol)), "approx_equal(): argument 'abs_tol' must be >= 0" );
arma_conform_check( (cond_rel< is_signed<T>::value >::lt(rel_tol, T(0)) || arma_isnan(rel_tol)), "approx_equal(): argument 'rel_tol' must be >= 0" );
return approx_equal(A.get_ref(), B.get_ref(), "abs", abs_tol);
}
+3 -3
View File
@@ -97,12 +97,12 @@ clamp(const SpBase<typename T1::elem_type,T1>& X, const typename T1::elem_type m
if(is_cx<eT>::no)
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "clamp(): min_val must be less than max_val" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "clamp(): min_val must be less than max_val" );
}
else
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "clamp(): imag(min_val) must be less than imag(max_val)" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( ((access::tmp_imag(min_val) <= access::tmp_imag(max_val)) == false), "clamp(): imag(min_val) must be less than imag(max_val)" );
}
SpMat<eT> out = X.get_ref();
+4 -4
View File
@@ -47,7 +47,7 @@ rande(const uword n_rows, const uword n_cols, const distr_param& param = distr_p
param.get_double_vals(lambda, unused);
arma_conform_check( (lambda <= double(0)), "rande(): incorrect distribution parameters; lambda must be greater than zero" );
arma_conform_check( ((lambda > double(0)) == false), "rande(): incorrect distribution parameters; lambda must be greater than zero" );
obj_type out(n_rows, n_cols, arma_nozeros_indicator());
@@ -138,7 +138,7 @@ rande(const distr_param& param = distr_param())
param.get_double_vals(lambda, unused);
arma_conform_check( (lambda <= double(0)), "rande(): incorrect distribution parameters; lambda must be greater than zero" );
arma_conform_check( ((lambda > double(0)) == false), "rande(): incorrect distribution parameters; lambda must be greater than zero" );
double out_val = double(0);
@@ -162,7 +162,7 @@ rande(const distr_param& param = distr_param())
param.get_double_vals(lambda, unused);
arma_conform_check( (lambda <= double(0)), "rande(): incorrect distribution parameters; lambda must be greater than zero" );
arma_conform_check( ((lambda > double(0)) == false), "rande(): incorrect distribution parameters; lambda must be greater than zero" );
eT out_val = eT(0);
@@ -189,7 +189,7 @@ rande(const uword n_rows, const uword n_cols, const uword n_slices, const distr_
param.get_double_vals(lambda, unused);
arma_conform_check( (lambda <= double(0)), "rande(): incorrect distribution parameters; lambda must be greater than zero" );
arma_conform_check( ((lambda > double(0)) == false), "rande(): incorrect distribution parameters; lambda must be greater than zero" );
cube_type out(n_rows, n_cols, n_slices, arma_nozeros_indicator());
+4 -4
View File
@@ -47,7 +47,7 @@ randg(const uword n_rows, const uword n_cols, const distr_param& param = distr_p
param.get_double_vals(a,b);
arma_conform_check( ((a <= double(0)) || (b <= double(0))), "randg(): incorrect distribution parameters; a and b must be greater than zero" );
arma_conform_check( ( ((a > double(0)) == false) || ((b > double(0)) == false) ), "randg(): incorrect distribution parameters; a and b must be greater than zero" );
obj_type out(n_rows, n_cols, arma_nozeros_indicator());
@@ -138,7 +138,7 @@ randg(const distr_param& param = distr_param())
param.get_double_vals(a,b);
arma_conform_check( ((a <= double(0)) || (b <= double(0))), "randg(): incorrect distribution parameters; a and b must be greater than zero" );
arma_conform_check( ( ((a > double(0)) == false) || ((b > double(0)) == false) ), "randg(): incorrect distribution parameters; a and b must be greater than zero" );
double out_val = double(0);
@@ -162,7 +162,7 @@ randg(const distr_param& param = distr_param())
param.get_double_vals(a,b);
arma_conform_check( ((a <= double(0)) || (b <= double(0))), "randg(): incorrect distribution parameters; a and b must be greater than zero" );
arma_conform_check( ( ((a > double(0)) == false) || ((b > double(0)) == false) ), "randg(): incorrect distribution parameters; a and b must be greater than zero" );
eT out_val = eT(0);
@@ -189,7 +189,7 @@ randg(const uword n_rows, const uword n_cols, const uword n_slices, const distr_
param.get_double_vals(a,b);
arma_conform_check( ((a <= double(0)) || (b <= double(0))), "randg(): incorrect distribution parameters; a and b must be greater than zero" );
arma_conform_check( ( ((a > double(0)) == false) || ((b > double(0)) == false) ), "randg(): incorrect distribution parameters; a and b must be greater than zero" );
cube_type out(n_rows, n_cols, n_slices, arma_nozeros_indicator());
+4 -4
View File
@@ -47,7 +47,7 @@ randi(const uword n_rows, const uword n_cols, const distr_param& param = distr_p
param.get_int_vals(a,b);
arma_conform_check( (a > b), "randi(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a <= b) == false), "randi(): incorrect distribution parameters; a must be less than b" );
obj_type out(n_rows, n_cols, arma_nozeros_indicator());
@@ -142,7 +142,7 @@ randi(const distr_param& param)
param.get_int_vals(a,b);
arma_conform_check( (a > b), "randi(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a <= b) == false), "randi(): incorrect distribution parameters; a must be less than b" );
sword out_val = sword(0);
@@ -166,7 +166,7 @@ randi(const distr_param& param)
param.get_int_vals(a,b);
arma_conform_check( (a > b), "randi(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a <= b) == false), "randi(): incorrect distribution parameters; a must be less than b" );
eT out_val = eT(0);
@@ -218,7 +218,7 @@ randi(const uword n_rows, const uword n_cols, const uword n_slices, const distr_
param.get_int_vals(a,b);
arma_conform_check( (a > b), "randi(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a <= b) == false), "randi(): incorrect distribution parameters; a must be less than b" );
cube_type out(n_rows, n_cols, n_slices, arma_nozeros_indicator());
+8 -8
View File
@@ -62,7 +62,7 @@ randn(const distr_param& param)
param.get_double_vals(mu,sd);
arma_conform_check( (sd <= double(0)), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_conform_check( ((sd > double(0)) == false), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
const double val = double(arma_rng::randn<double>());
@@ -86,7 +86,7 @@ randn(const distr_param& param)
param.get_double_vals(mu,sd);
arma_conform_check( (sd <= double(0)), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_conform_check( ((sd > double(0)) == false), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
eT val = eT(0);
@@ -119,7 +119,7 @@ randn(const uword n_elem, const distr_param& param = distr_param())
param.get_double_vals(mu,sd);
arma_conform_check( (sd <= double(0)), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_conform_check( ((sd > double(0)) == false), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_rng::randn<double>::fill(out.memptr(), n_elem, mu, sd);
}
@@ -156,7 +156,7 @@ randn(const uword n_elem, const distr_param& param = distr_param(), const typena
param.get_double_vals(mu,sd);
arma_conform_check( (sd <= double(0)), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_conform_check( ((sd > double(0)) == false), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_rng::randn<eT>::fill(out.memptr(), out.n_elem, mu, sd);
}
@@ -188,7 +188,7 @@ randn(const uword n_rows, const uword n_cols, const distr_param& param = distr_p
param.get_double_vals(mu,sd);
arma_conform_check( (sd <= double(0)), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_conform_check( ((sd > double(0)) == false), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_rng::randn<double>::fill(out.memptr(), out.n_elem, mu, sd);
}
@@ -237,7 +237,7 @@ randn(const uword n_rows, const uword n_cols, const distr_param& param = distr_p
param.get_double_vals(mu,sd);
arma_conform_check( (sd <= double(0)), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_conform_check( ((sd > double(0)) == false), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_rng::randn<eT>::fill(out.memptr(), out.n_elem, mu, sd);
}
@@ -284,7 +284,7 @@ randn(const uword n_rows, const uword n_cols, const uword n_slices, const distr_
param.get_double_vals(mu,sd);
arma_conform_check( (sd <= double(0)), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_conform_check( ((sd > double(0)) == false), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_rng::randn<double>::fill(out.memptr(), out.n_elem, mu, sd);
}
@@ -330,7 +330,7 @@ randn(const uword n_rows, const uword n_cols, const uword n_slices, const distr_
param.get_double_vals(mu,sd);
arma_conform_check( (sd <= double(0)), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_conform_check( ((sd > double(0)) == false), "randn(): incorrect distribution parameters; standard deviation must be > 0" );
arma_rng::randn<eT>::fill(out.memptr(), out.n_elem, mu, sd);
}
+8 -8
View File
@@ -62,7 +62,7 @@ randu(const distr_param& param)
param.get_double_vals(a,b);
arma_conform_check( (a >= b), "randu(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a < b) == false), "randu(): incorrect distribution parameters; a must be less than b" );
const double val = double(arma_rng::randu<double>());
@@ -86,7 +86,7 @@ randu(const distr_param& param)
param.get_double_vals(a,b);
arma_conform_check( (a >= b), "randu(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a < b) == false), "randu(): incorrect distribution parameters; a must be less than b" );
eT val = eT(0);
@@ -119,7 +119,7 @@ randu(const uword n_elem, const distr_param& param = distr_param())
param.get_double_vals(a,b);
arma_conform_check( (a >= b), "randu(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a < b) == false), "randu(): incorrect distribution parameters; a must be less than b" );
arma_rng::randu<double>::fill(out.memptr(), n_elem, a, b);
}
@@ -156,7 +156,7 @@ randu(const uword n_elem, const distr_param& param = distr_param(), const typena
param.get_double_vals(a,b);
arma_conform_check( (a >= b), "randu(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a < b) == false), "randu(): incorrect distribution parameters; a must be less than b" );
arma_rng::randu<eT>::fill(out.memptr(), out.n_elem, a, b);
}
@@ -188,7 +188,7 @@ randu(const uword n_rows, const uword n_cols, const distr_param& param = distr_p
param.get_double_vals(a,b);
arma_conform_check( (a >= b), "randu(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a < b) == false), "randu(): incorrect distribution parameters; a must be less than b" );
arma_rng::randu<double>::fill(out.memptr(), out.n_elem, a, b);
}
@@ -237,7 +237,7 @@ randu(const uword n_rows, const uword n_cols, const distr_param& param = distr_p
param.get_double_vals(a,b);
arma_conform_check( (a >= b), "randu(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a < b) == false), "randu(): incorrect distribution parameters; a must be less than b" );
arma_rng::randu<eT>::fill(out.memptr(), out.n_elem, a, b);
}
@@ -284,7 +284,7 @@ randu(const uword n_rows, const uword n_cols, const uword n_slices, const distr_
param.get_double_vals(a,b);
arma_conform_check( (a >= b), "randu(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a < b) == false), "randu(): incorrect distribution parameters; a must be less than b" );
arma_rng::randu<double>::fill(out.memptr(), out.n_elem, a, b);
}
@@ -330,7 +330,7 @@ randu(const uword n_rows, const uword n_cols, const uword n_slices, const distr_
param.get_double_vals(a,b);
arma_conform_check( (a >= b), "randu(): incorrect distribution parameters; a must be less than b" );
arma_conform_check( ((a < b) == false), "randu(): incorrect distribution parameters; a must be less than b" );
arma_rng::randu<eT>::fill(out.memptr(), out.n_elem, a, b);
}
+3 -3
View File
@@ -55,7 +55,7 @@ spsolve_helper
const superlu_opts& opts = (settings.id == 1) ? static_cast<const superlu_opts&>(settings) : superlu_opts_default;
arma_conform_check( ( (opts.pivot_thresh < double(0)) || (opts.pivot_thresh > double(1)) ), "spsolve(): pivot_thresh must be in the [0,1] interval" );
arma_conform_check( ( ((opts.pivot_thresh >= double(0)) == false) || ((opts.pivot_thresh <= double(1)) == false) ), "spsolve(): pivot_thresh must be in the [0,1] interval" );
if(sig == 's') // SuperLU solver
{
@@ -110,12 +110,12 @@ spsolve_helper
if( (status == false) && (rcond > T(0)) )
{
arma_warn(2, "spsolve(): system is singular (rcond: ", rcond, ")");
arma_warn(2, "spsolve(): system is singular; rcond: ", rcond);
}
if( (status == true) && (rcond > T(0)) && (rcond < std::numeric_limits<T>::epsilon()) )
{
arma_warn(2, "solve(): solution computed, but system is singular to working precision (rcond: ", rcond, ")");
arma_warn(2, "spsolve(): solution computed, but system is singular to working precision; rcond: ", rcond);
}
return status;
+2 -2
View File
@@ -47,7 +47,7 @@ svds_helper
"svds(): two or more output objects are the same object"
);
arma_conform_check( (tol < T(0)), "svds(): tol must be >= 0" );
arma_conform_check( ((tol >= T(0)) == false), "svds(): tol must be >= 0" );
const unwrap_spmat<T1> tmp(X.get_ref());
const SpMat<eT>& A = tmp.M;
@@ -171,7 +171,7 @@ svds_helper
"svds(): two or more output objects are the same object"
);
arma_conform_check( (tol < T(0)), "svds(): tol must be >= 0" );
arma_conform_check( ((tol >= T(0)) == false), "svds(): tol must be >= 0" );
const unwrap_spmat<T1> tmp(X.get_ref());
const SpMat<eT>& A = tmp.M;
+3 -3
View File
@@ -380,7 +380,7 @@ glue_solve_gen_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
}
else
{
arma_warn(2, "solve(): system is singular (rcond: ", rcond, "); attempting approx solution");
arma_warn(2, "solve(): system is singular; rcond: ", rcond, "; attempting approx solution");
}
// TODO: conditionally recreate A: have a separate state flag which indicates whether A was previously overwritten
@@ -472,7 +472,7 @@ glue_solve_tri_default::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, co
}
else
{
arma_warn(2, "solve(): system is singular (rcond: ", rcond, "); attempting approx solution");
arma_warn(2, "solve(): system is singular; rcond: ", rcond, "; attempting approx solution");
}
Mat<eT> triA = (triu) ? trimatu(A) : trimatl(A); // trimatu() and trimatl() return the same type
@@ -598,7 +598,7 @@ glue_solve_tri_full::apply(Mat<eT>& actual_out, const Base<eT,T1>& A_expr, const
}
else
{
arma_warn(2, "solve(): system is singular (rcond: ", rcond, "); attempting approx solution");
arma_warn(2, "solve(): system is singular; rcond: ", rcond, "; attempting approx solution");
}
Mat<eT> triA = (triu) ? trimatu(A) : trimatl(A); // trimatu() and trimatl() return the same type
+3 -3
View File
@@ -683,9 +683,9 @@ gmm_diag<eT>::learn
|| (seed_mode == random_subset)
|| (seed_mode == random_spread);
arma_conform_check( (dist_mode_ok == false), "gmm_diag::learn(): dist_mode must be eucl_dist or maha_dist" );
arma_conform_check( (seed_mode_ok == false), "gmm_diag::learn(): unknown seed_mode" );
arma_conform_check( (var_floor < eT(0) ), "gmm_diag::learn(): variance floor is negative" );
arma_conform_check( (dist_mode_ok == false), "gmm_diag::learn(): dist_mode must be eucl_dist or maha_dist" );
arma_conform_check( (seed_mode_ok == false), "gmm_diag::learn(): unknown seed_mode" );
arma_conform_check( ((var_floor >= eT(0)) == false), "gmm_diag::learn(): variance floor must be > 0" );
const unwrap<T1> tmp_X(data.get_ref());
const Mat<eT>& X = tmp_X.M;
+3 -3
View File
@@ -722,9 +722,9 @@ gmm_full<eT>::learn
|| (seed_mode == random_subset)
|| (seed_mode == random_spread);
arma_conform_check( (dist_mode_ok == false), "gmm_full::learn(): dist_mode must be eucl_dist or maha_dist" );
arma_conform_check( (seed_mode_ok == false), "gmm_full::learn(): unknown seed_mode" );
arma_conform_check( (var_floor < eT(0) ), "gmm_full::learn(): variance floor is negative" );
arma_conform_check( (dist_mode_ok == false), "gmm_full::learn(): dist_mode must be eucl_dist or maha_dist" );
arma_conform_check( (seed_mode_ok == false), "gmm_full::learn(): unknown seed_mode" );
arma_conform_check( ((var_floor >= eT(0)) == false), "gmm_full::learn(): variance floor must be > 0" );
const unwrap<T1> tmp_X(data.get_ref());
const Mat<eT>& X = tmp_X.M;
@@ -77,8 +77,8 @@ SparseGenRealShiftSolve<eT>::SparseGenRealShiftSolve(const SpMat<eT>& mat_obj, c
if( (x_rcond < std::numeric_limits<eT>::epsilon()) || arma_isnan(x_rcond) )
{
if(x_rcond == eT(0)) { arma_warn(2, "matrix is singular to working precision"); }
else { arma_warn(2, "matrix is singular to working precision (rcond: ", x_rcond, ")"); }
if(x_rcond == eT(0)) { arma_warn(2, "matrix is singular to working precision"); }
else { arma_warn(2, "matrix is singular to working precision; rcond: ", x_rcond); }
return;
}
+8
View File
@@ -80,6 +80,8 @@ op_accu_mat::apply_proxy_at(const Proxy<T1>& P)
const uword n_rows = P.get_n_rows();
const uword n_cols = P.get_n_cols();
if(n_rows == 0) { return eT(0); }
eT val = eT(0);
if(n_rows != 1)
@@ -146,6 +148,8 @@ op_accu_mat::apply_omit_helper(const Proxy<T1>& P, functor is_omitted)
const uword n_rows = P.get_n_rows();
const uword n_cols = P.get_n_cols();
if(n_rows == 0) { return eT_zero; }
for(uword c=0; c < n_cols; ++c)
for(uword r=0; r < n_rows; ++r)
{
@@ -602,6 +606,8 @@ op_accu_mat::apply(const subview<eT>& X)
const uword X_n_rows = X.n_rows;
const uword X_n_cols = X.n_cols;
if( (X_n_rows == 0) || (X_n_cols == 0) ) { return eT(0); }
if(X_n_rows == 1)
{
const uword X_m_n_rows = X.m.n_rows;
@@ -750,6 +756,8 @@ op_accu_cube::apply_proxy_at(const ProxyCube<T1>& P)
const uword n_cols = P.get_n_cols();
const uword n_slices = P.get_n_slices();
if( (n_rows == 0) || (n_cols == 0) ) { return eT(0); }
eT val1 = eT(0);
eT val2 = eT(0);
+11 -11
View File
@@ -34,7 +34,7 @@ op_clamp::apply(Mat<typename T1::elem_type>& out, const mtOp<typename T1::elem_t
const eT min_val = in.aux;
const eT max_val = in.aux_out_eT;
arma_conform_check( (min_val > max_val), "clamp(): min_val must be less than max_val" );
arma_conform_check( ((min_val <= max_val) == false), "clamp(): min_val must be less than max_val" );
if(is_Mat<T1>::value)
{
@@ -83,7 +83,7 @@ op_clamp::apply(Mat_noalias<typename T1::elem_type>& out, const mtOp<typename T1
const eT min_val = in.aux;
const eT max_val = in.aux_out_eT;
arma_conform_check( (min_val > max_val), "clamp(): min_val must be less than max_val" );
arma_conform_check( ((min_val <= max_val) == false), "clamp(): min_val must be less than max_val" );
if((quasi_unwrap<T1>::has_orig_mem) || (is_Mat<typename Proxy<T1>::stored_type>::value) || (arma_config::openmp && Proxy<T1>::use_mp))
{
@@ -186,7 +186,7 @@ op_clamp::apply(Cube<typename T1::elem_type>& out, const mtOpCube<typename T1::e
const eT min_val = in.aux;
const eT max_val = in.aux_out_eT;
arma_conform_check( (min_val > max_val), "clamp(): min_val must be less than max_val" );
arma_conform_check( ((min_val <= max_val) == false), "clamp(): min_val must be less than max_val" );
if(is_Cube<T1>::value)
{
@@ -350,8 +350,8 @@ op_clamp_cx::apply_direct(Mat<eT>& out, const Mat<eT>& X, const eT min_val, cons
const T max_val_real = std::real(max_val);
const T max_val_imag = std::imag(max_val);
arma_conform_check( (min_val_real > max_val_real), "clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( (min_val_imag > max_val_imag), "clamp(): imag(min_val) must be less than imag(max_val)" );
arma_conform_check( ((min_val_real <= max_val_real) == false), "clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( ((min_val_imag <= max_val_imag) == false), "clamp(): imag(min_val) must be less than imag(max_val)" );
if(&out != &X)
{
@@ -401,8 +401,8 @@ op_clamp_cx::apply_proxy_noalias(Mat<typename T1::elem_type>& out, const Proxy<T
const T max_val_real = std::real(max_val);
const T max_val_imag = std::imag(max_val);
arma_conform_check( (min_val_real > max_val_real), "clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( (min_val_imag > max_val_imag), "clamp(): imag(min_val) must be less than imag(max_val)" );
arma_conform_check( ((min_val_real <= max_val_real) == false), "clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( ((min_val_imag <= max_val_imag) == false), "clamp(): imag(min_val) must be less than imag(max_val)" );
const uword n_rows = P.get_n_rows();
const uword n_cols = P.get_n_cols();
@@ -503,8 +503,8 @@ op_clamp_cx::apply_direct(Cube<eT>& out, const Cube<eT>& X, const eT min_val, co
const T max_val_real = std::real(max_val);
const T max_val_imag = std::imag(max_val);
arma_conform_check( (min_val_real > max_val_real), "clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( (min_val_imag > max_val_imag), "clamp(): imag(min_val) must be less than imag(max_val)" );
arma_conform_check( ((min_val_real <= max_val_real) == false), "clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( ((min_val_imag <= max_val_imag) == false), "clamp(): imag(min_val) must be less than imag(max_val)" );
if(&out != &X)
{
@@ -554,8 +554,8 @@ op_clamp_cx::apply_proxy_noalias(Cube<typename T1::elem_type>& out, const ProxyC
const T max_val_real = std::real(max_val);
const T max_val_imag = std::imag(max_val);
arma_conform_check( (min_val_real > max_val_real), "clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( (min_val_imag > max_val_imag), "clamp(): imag(min_val) must be less than imag(max_val)" );
arma_conform_check( ((min_val_real <= max_val_real) == false), "clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( ((min_val_imag <= max_val_imag) == false), "clamp(): imag(min_val) must be less than imag(max_val)" );
const uword n_rows = P.get_n_rows();
const uword n_cols = P.get_n_cols();
+1 -1
View File
@@ -207,7 +207,7 @@ op_expmat_sym::apply_direct(Mat<typename T1::elem_type>& out, const Base<typenam
if((arma_config::check_conform) && (arma_config::warn_level > 0) && (is_cx<eT>::yes) && (sym_helper::check_diag_imag(X) == false))
{
arma_warn(1, "inv_sympd(): imaginary components on diagonal are non-zero");
arma_warn(1, "expmat_sym(): imaginary components on diagonal are non-zero");
}
if(is_op_diagmat<T1>::value || X.is_diagmat())
@@ -65,6 +65,7 @@ op_htrans::apply_mat_noalias(Mat<eT>& out, const Mat<eT>& A, const typename arma
op_htrans::apply_mat_noalias_large(out, A);
}
else
if(A_n_cols != 0)
{
eT* outptr = out.memptr();
+6
View File
@@ -65,12 +65,18 @@ struct op_mean
template<typename T1>
inline static typename T1::elem_type mean_all(const T1& X);
template<typename T1>
inline static typename T1::elem_type mean_all_proxy(const Proxy<T1>& P);
template<typename T1>
inline static typename T1::elem_type mean_all(const Op<T1, op_omit>& X);
template<typename eT, typename functor>
inline static eT mean_all_omit(const eT* X_mem, const uword N, functor is_omitted);
template<typename T1, typename functor>
inline static typename T1::elem_type mean_all_omit(const Proxy<T1>& P, functor is_omitted);
//
template<typename eT>
+159 -16
View File
@@ -435,17 +435,94 @@ op_mean::mean_all(const T1& X)
arma_debug_sigprint();
typedef typename T1::elem_type eT;
typedef typename T1::pod_type T;
const quasi_unwrap<T1> U(X);
eT result = eT(0);
if(U.M.n_elem == 0)
if( (is_Mat<typename Proxy<T1>::stored_type>::value == false) && (Proxy<T1>::use_at == false) && (Proxy<T1>::use_mp == false) && (is_fp16<T>::no) )
{
arma_conform_check(true, "mean(): object has no elements");
arma_debug_print("op_mean::mean_all(): using proxy");
return Datum<eT>::nan;
const Proxy<T1> P(X);
if(P.get_n_elem() == 0)
{
arma_conform_check(true, "mean(): object has no elements");
return Datum<eT>::nan;
}
result = op_mean::mean_all_proxy(P);
}
else
{
arma_debug_print("op_mean::mean_all(): using quasi_unwrap");
const quasi_unwrap<T1> U(X);
if(U.M.n_elem == 0)
{
arma_conform_check(true, "mean(): object has no elements");
return Datum<eT>::nan;
}
result = op_mean::direct_mean(U.M.memptr(), U.M.n_elem);
}
return op_mean::direct_mean(U.M.memptr(), U.M.n_elem);
return result;
}
template<typename T1>
inline
typename T1::elem_type
op_mean::mean_all_proxy(const Proxy<T1>& P)
{
arma_debug_sigprint();
typedef typename T1::elem_type eT;
typedef typename T1::pod_type T;
const uword N = P.get_n_elem();
const typename Proxy<T1>::ea_type Pea = P.get_ea();
eT acc1 = eT(0);
eT acc2 = eT(0);
uword i,j;
for(i=0, j=1; j < N; i+=2, j+=2)
{
acc1 += Pea[i];
acc2 += Pea[j];
}
if(i < N)
{
acc1 += Pea[i];
}
const eT mean = (acc1 + acc2) / T(N);
if(arma_isfinite(mean)) { return mean; }
// handle possible overflow
eT r_mean = eT(0);
for(uword ii=0; ii < N; ++ii)
{
const eT val = Pea[ii];
if(arma_isnonfinite(val)) { return mean; }
r_mean = r_mean + (val - r_mean) / T(ii+1);
}
return r_mean;
}
@@ -467,22 +544,39 @@ op_mean::mean_all(const Op<T1, op_omit>& in)
if(omit_mode == 2) { arma_warn(1, "omit_nonfinite(): detection of non-finite values is not reliable in fast math mode"); }
}
const quasi_unwrap<T1> U(in.m);
if(U.M.n_elem == 0)
{
arma_conform_check(true, "mean(): object has no elements");
return Datum<eT>::nan;
}
auto is_omitted_1 = [](const eT& x) -> bool { return arma_isnan(x); };
auto is_omitted_2 = [](const eT& x) -> bool { return arma_isnonfinite(x); };
eT result = eT(0);
if(omit_mode == 1) { result = op_mean::mean_all_omit(U.M.memptr(), U.M.n_elem, is_omitted_1); }
if(omit_mode == 2) { result = op_mean::mean_all_omit(U.M.memptr(), U.M.n_elem, is_omitted_2); }
if( (is_Mat<typename Proxy<T1>::stored_type>::value == false) && (Proxy<T1>::use_at == false) && (Proxy<T1>::use_mp == false) )
{
const Proxy<T1> P(in.m);
if(P.get_n_elem() == 0)
{
arma_conform_check(true, "mean(): object has no elements");
return Datum<eT>::nan;
}
if(omit_mode == 1) { result = op_mean::mean_all_omit(P, is_omitted_1); }
if(omit_mode == 2) { result = op_mean::mean_all_omit(P, is_omitted_2); }
}
else
{
const quasi_unwrap<T1> U(in.m);
if(U.M.n_elem == 0)
{
arma_conform_check(true, "mean(): object has no elements");
return Datum<eT>::nan;
}
if(omit_mode == 1) { result = op_mean::mean_all_omit(U.M.memptr(), U.M.n_elem, is_omitted_1); }
if(omit_mode == 2) { result = op_mean::mean_all_omit(U.M.memptr(), U.M.n_elem, is_omitted_2); }
}
return result;
}
@@ -535,6 +629,55 @@ op_mean::mean_all_omit(const eT* X_mem, const uword N, functor is_omitted)
template<typename T1, typename functor>
inline
typename T1::elem_type
op_mean::mean_all_omit(const Proxy<T1>& P, functor is_omitted)
{
arma_debug_sigprint();
typedef typename T1::elem_type eT;
typedef typename T1::pod_type T;
const uword N = P.get_n_elem();
uword count = 0;
eT acc = eT(0);
for(uword i=0; i < N; ++i)
{
const eT val = P[i];
if(is_omitted(val) == false) { acc += val; ++count; }
}
acc /= T(count);
if(arma_isfinite(acc)) { return acc; }
// handle possible overflow
eT r_mean = eT(0);
count = 0;
for(uword i=0; i < N; ++i)
{
const eT val = P[i];
if(is_omitted(val) == false)
{
r_mean = r_mean + (val - r_mean) / T(count+1); // kept as count+1 to use same algorithm as op_mean::direct_mean_robust()
++count;
}
}
return r_mean;
}
//
+4 -4
View File
@@ -110,8 +110,8 @@ op_norm2est::norm2est
typedef typename T1::pod_type T;
typedef typename T1::elem_type eT;
arma_conform_check( (tolerance < T(0)), "norm2est(): parameter 'tolerance' must be > 0" );
arma_conform_check( (max_iter == uword(0)), "norm2est(): parameter 'max_iter' must be > 0" );
arma_conform_check( ((tolerance >= T(0)) == false), "norm2est(): parameter 'tolerance' must be > 0" );
arma_conform_check( (max_iter == uword(0)), "norm2est(): parameter 'max_iter' must be > 0" );
const T tol = (tolerance == T(0)) ? T(1e-6) : T(tolerance);
@@ -190,8 +190,8 @@ op_norm2est::norm2est
typedef typename T1::pod_type T;
typedef typename T1::elem_type eT;
arma_conform_check( (tolerance < T(0)), "norm2est(): parameter 'tolerance' must be > 0" );
arma_conform_check( (max_iter == uword(0)), "norm2est(): parameter 'max_iter' must be > 0" );
arma_conform_check( ((tolerance >= T(0)) == false), "norm2est(): parameter 'tolerance' must be > 0" );
arma_conform_check( (max_iter == uword(0)), "norm2est(): parameter 'max_iter' must be > 0" );
const T tol = (tolerance == T(0)) ? T(1e-6) : T(tolerance);
+6 -2
View File
@@ -54,7 +54,7 @@ op_orth::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1::
typedef typename T1::elem_type eT;
typedef typename T1::pod_type T;
arma_conform_check((tol < T(0)), "orth(): tolerance must be >= 0");
arma_conform_check( ((tol >= T(0)) == false), "orth(): tolerance must be > 0" );
Mat<eT> U;
Col< T> s;
@@ -87,6 +87,8 @@ op_orth::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1::
// set tolerance to default if it hasn't been specified
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * s_mem[0] * std::numeric_limits<T>::epsilon(); }
if(arma_isnan(tol)) { return false; }
uword count = 0;
for(uword i=0; i < s_n_elem; ++i) { count += (s_mem[i] > tol) ? uword(1) : uword(0); }
@@ -141,7 +143,7 @@ op_null::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1::
typedef typename T1::elem_type eT;
typedef typename T1::pod_type T;
arma_conform_check((tol < T(0)), "null(): tolerance must be >= 0");
arma_conform_check( ((tol >= T(0)) == false), "null(): tolerance must be > 0" );
Mat<eT> U;
Col< T> s;
@@ -174,6 +176,8 @@ op_null::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1::
// set tolerance to default if it hasn't been specified
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * s_mem[0] * std::numeric_limits<T>::epsilon(); }
if(arma_isnan(tol)) { return false; }
uword count = 0;
for(uword i=0; i < s_n_elem; ++i) { count += (s_mem[i] > tol) ? uword(1) : uword(0); }
+7 -1
View File
@@ -94,7 +94,7 @@ op_pinv::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1::
typedef typename T1::elem_type eT;
typedef typename T1::pod_type T;
arma_conform_check((tol < T(0)), "pinv(): tolerance must be >= 0");
arma_conform_check( ((tol >= T(0)) == false), "pinv(): tolerance must be > 0" );
// method_id = 0 -> default setting
// method_id = 1 -> use standard algorithm
@@ -176,6 +176,8 @@ op_pinv::apply_diag(Mat<eT>& out, const Mat<eT>& A, typename get_pod_type<eT>::r
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * max_abs_Aii * std::numeric_limits<T>::epsilon(); }
if(arma_isnan(tol)) { return false; }
for(uword i=0; i<N; ++i)
{
if(diag_abs_vals[i] >= tol)
@@ -236,6 +238,8 @@ op_pinv::apply_sym(Mat<eT>& out, const Mat<eT>& A, typename get_pod_type<eT>::re
// set tolerance to default if it hasn't been specified
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * abs_eigval[0] * std::numeric_limits<T>::epsilon(); }
if(arma_isnan(tol)) { return false; }
uword count = 0;
for(uword i=0; i < abs_eigval.n_elem; ++i) { count += (abs_eigval[i] >= tol) ? uword(1) : uword(0); }
@@ -310,6 +314,8 @@ op_pinv::apply_gen(Mat<eT>& out, Mat<eT>& A, typename get_pod_type<eT>::result t
// set tolerance to default if it hasn't been specified
if( (tol == T(0)) && (s.n_elem > 0) ) { tol = (std::max)(n_rows, n_cols) * s[0] * std::numeric_limits<T>::epsilon(); }
if(arma_isnan(tol)) { return false; }
uword count = 0;
for(uword i=0; i < s.n_elem; ++i) { count += (s[i] >= tol) ? uword(1) : uword(0); }
+18 -6
View File
@@ -87,6 +87,8 @@ op_rank::apply_diag(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result to
typedef typename get_pod_type<eT>::result T;
out = uword(0);
const uword N = (std::min)(A.n_rows, A.n_cols);
podarray<T> diag_abs_vals(N);
@@ -98,7 +100,7 @@ op_rank::apply_diag(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result to
const eT Aii = A.at(i,i);
const T abs_Aii = std::abs(Aii);
if(arma_isnan(Aii)) { out = uword(0); return false; }
if(arma_isnan(Aii)) { return false; }
diag_abs_vals[i] = abs_Aii;
@@ -108,6 +110,8 @@ op_rank::apply_diag(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result to
// set tolerance to default if it hasn't been specified
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * max_abs_Aii * std::numeric_limits<T>::epsilon(); }
if(arma_isnan(tol)) { return false; }
uword count = 0;
for(uword i=0; i<N; ++i) { count += (diag_abs_vals[i] > tol) ? uword(1) : uword(0); }
@@ -128,18 +132,20 @@ op_rank::apply_sym(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result tol
typedef typename get_pod_type<eT>::result T;
if(A.is_square() == false) { out = uword(0); return false; }
out = uword(0);
if(A.is_square() == false) { return false; }
Col<T> v;
const bool status = auxlib::eig_sym(v, A);
if(status == false) { out = uword(0); return false; }
if(status == false) { return false; }
const uword v_n_elem = v.n_elem;
T* v_mem = v.memptr();
if(v_n_elem == 0) { out = uword(0); return true; }
if(v_n_elem == 0) { return true; }
T max_abs_v = T(0);
@@ -148,6 +154,8 @@ op_rank::apply_sym(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result tol
// set tolerance to default if it hasn't been specified
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * max_abs_v * std::numeric_limits<T>::epsilon(); }
if(arma_isnan(tol)) { return false; }
uword count = 0;
for(uword i=0; i < v_n_elem; ++i) { count += (v_mem[i] > tol) ? uword(1) : uword(0); }
@@ -168,20 +176,24 @@ op_rank::apply_gen(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result tol
typedef typename get_pod_type<eT>::result T;
out = uword(0);
Col<T> s;
const bool status = auxlib::svd_dc(s, A);
if(status == false) { out = uword(0); return false; }
if(status == false) { return false; }
const uword s_n_elem = s.n_elem;
const T* s_mem = s.memptr();
if(s_n_elem == 0) { out = uword(0); return true; }
if(s_n_elem == 0) { return true; }
// set tolerance to default if it hasn't been specified
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * s_mem[0] * std::numeric_limits<T>::epsilon(); }
if(arma_isnan(tol)) { return false; }
uword count = 0;
for(uword i=0; i < s_n_elem; ++i) { count += (s_mem[i] > tol) ? uword(1) : uword(0); }
+12 -8
View File
@@ -153,15 +153,19 @@ op_repcube::apply_noalias(Cube<eT>& out, const Cube<eT>& X, const uword copies_p
if(out.is_empty()) { return; }
// TODO: this is a rudimentary implementation
const SizeCube X_size = SizeCube(X.n_rows, X.n_cols, X.n_slices);
for(uword s = 0; s < out.n_slices; s += X.n_slices)
for(uword c = 0; c < out.n_cols; c += X.n_cols )
for(uword r = 0; r < out.n_rows; r += X.n_rows )
for(uword s=0; s < X.n_slices; ++s)
{
out.subcube(r, c, s, X_size) = X;
// avoid use of Cube::slice() to prevent generating Mat objects that the user may not need
const Mat<eT> X_slice_s(const_cast<eT*>(X.slice_memptr(s)), X.n_rows, X.n_cols, false, true);
Mat<eT> out_slice_s( out.slice_memptr(s) , out.n_rows, out.n_cols, false, true);
op_repmat::apply_noalias(out_slice_s, X_slice_s, copies_per_row, copies_per_col);
for(uword t=1; t < copies_per_slice; ++t)
{
arrayops::copy(out.slice_memptr(s + (t * X.n_slices)), out_slice_s.memptr(), out_slice_s.n_elem);
}
}
}
+1 -1
View File
@@ -81,7 +81,7 @@ op_resize::apply_mat_inplace(Mat<eT>& A, const uword new_n_rows, const uword new
arma_conform_check( (A.vec_state == 1) && (new_n_cols != 1), "resize(): requested size is not compatible with column vector layout" );
arma_conform_check( (A.vec_state == 2) && (new_n_rows != 1), "resize(): requested size is not compatible with row vector layout" );
if(A.is_empty()) { A.zeros(new_n_rows, new_n_cols); return; }
if( A.is_empty() || (new_n_rows == 0) || (new_n_cols == 0) ) { A.zeros(new_n_rows, new_n_cols); return; }
Mat<eT> B(new_n_rows, new_n_cols, arma_nozeros_indicator());
@@ -200,6 +200,7 @@ op_strans::apply_mat_noalias(Mat<eT>& out, const TA& A)
op_strans::apply_mat_noalias_large(out, A);
}
else
if(A_n_cols != 0)
{
eT* outptr = out.memptr();
@@ -176,6 +176,8 @@ op_vectorise_col::apply_subview(Mat<eT>& out, const subview<eT>& sv)
out.set_size(sv.n_elem, 1);
if(sv.n_elem == 0) { return; }
eT* out_mem = out.memptr();
for(uword col=0; col < sv_n_cols; ++col)
@@ -201,6 +203,8 @@ op_vectorise_col::apply_proxy(Mat<typename T1::elem_type>& out, const Proxy<T1>&
out.set_size(N, 1);
if(N == 0) { return; }
eT* outmem = out.memptr();
if(Proxy<T1>::use_at == false)
@@ -305,6 +309,8 @@ op_vectorise_row::apply_proxy(Mat<typename T1::elem_type>& out, const Proxy<T1>&
out.set_size(1, n_elem);
if(n_elem == 0) { return; }
eT* outmem = out.memptr();
if(n_cols == 1)
@@ -471,6 +477,8 @@ op_vectorise_cube_col::apply_proxy(Mat<typename T1::elem_type>& out, const T1& e
out.set_size(N, 1);
if(N == 0) { return; }
eT* outmem = out.memptr();
if(ProxyCube<T1>::use_at == false)
+2 -2
View File
@@ -113,7 +113,7 @@ op_wishrnd::apply_noalias_mode2(Mat<eT>& out, const Mat<eT>& D, const eT df)
{
arma_debug_sigprint();
arma_conform_check( (df <= eT(0)), "df must be greater than zero" );
arma_conform_check( ((df > eT(0)) == false), "df must be greater than zero" );
arma_conform_check( (D.is_square() == false), "wishrnd(): given matrix must be square sized" );
if(D.is_empty()) { out.reset(); return true; }
@@ -256,7 +256,7 @@ op_iwishrnd::apply_noalias_mode2(Mat<eT>& out, const Mat<eT>& Dinv, const eT df)
{
arma_debug_sigprint();
arma_conform_check( (df <= eT(0)), "df must be greater than zero" );
arma_conform_check( ((df > eT(0)) == false), "df must be greater than zero" );
arma_conform_check( (Dinv.is_square() == false), "iwishrnd(): given matrix must be square sized" );
if(Dinv.is_empty()) { out.reset(); return true; }
+17 -11
View File
@@ -214,6 +214,8 @@ sp_auxlib::eigs_sym_newarp(Col<eT>& eigval, Mat<eT>& eigvec, const SpMat<eT>& X,
if(ncv < (n_eigvals + 1)) { ncv = (n_eigvals + 1); }
if(ncv > n ) { ncv = n; }
if(arma_isnan(opts.tol)) { return false; }
eT tol = (std::max)(eT(opts.tol), std::numeric_limits<eT>::epsilon());
uword maxiter = uword(opts.maxiter);
@@ -347,6 +349,8 @@ sp_auxlib::eigs_sym_newarp(Col<eT>& eigval, Mat<eT>& eigvec, const SpMat<eT>& X,
if(ncv < (n_eigvals + 1)) { ncv = (n_eigvals + 1); }
if(ncv > n ) { ncv = n; }
if(arma_isnan(opts.tol)) { return false; }
eT tol = (std::max)(eT(opts.tol), std::numeric_limits<eT>::epsilon());
uword maxiter = uword(opts.maxiter);
@@ -503,7 +507,7 @@ sp_auxlib::eigs_sym_arpack(Col<eT>& eigval, Mat<eT>& eigvec, const SpMat<eT>& X,
arpack::seupd(&rvec, &howmny, select.memptr(), eigval.memptr(), eigvec.memptr(), &ldz, (eT*) &sigma, &bmat, &n, which, &nev, &tol, resid.memptr(), &ncv, v.memptr(), &ldv, iparam.memptr(), ipntr.memptr(), workd.memptr(), workl.memptr(), &lworkl, &info);
// Check for errors.
if(info != 0) { arma_warn(1, "eigs_sym(): ARPACK error ", info, " in seupd()"); return false; }
if(info != 0) { arma_warn(1, "eigs_sym(): arpack::seupd() error: ", info); return false; }
return (info == 0);
}
@@ -667,6 +671,8 @@ sp_auxlib::eigs_gen_newarp(Col< std::complex<T> >& eigval, Mat< std::complex<T>
if(ncv < (n_eigvals + 3)) { ncv = (n_eigvals + 3); }
if(ncv > n ) { ncv = n; }
if(arma_isnan(opts.tol)) { return false; }
T tol = (std::max)(T(opts.tol), std::numeric_limits<T>::epsilon());
uword maxiter = uword(opts.maxiter);
@@ -890,7 +896,7 @@ sp_auxlib::eigs_gen_arpack(Col< std::complex<T> >& eigval, Mat< std::complex<T>
arpack::neupd(&rvec, &howmny, select.memptr(), dr.memptr(), di.memptr(), z.memptr(), &ldz, (T*) &sigmar, (T*) &sigmai, workev.memptr(), &bmat, &n, which, &nev, &tol, resid.memptr(), &ncv, v.memptr(), &ldv, iparam.memptr(), ipntr.memptr(), workd.memptr(), workl.memptr(), &lworkl, rwork.memptr(), &info);
// Check for errors.
if(info != 0) { arma_warn(1, "eigs_gen(): ARPACK error ", info, " in neupd()"); return false; }
if(info != 0) { arma_warn(1, "eigs_gen(): arpack::neupd() error: ", info); return false; }
// Put it into the outputs.
eigval.set_size(n_eigvals);
@@ -1138,7 +1144,7 @@ sp_auxlib::eigs_gen(Col< std::complex<T> >& eigval, Mat< std::complex<T> >& eigv
(std::complex<T>*) NULL, eigvec.memptr(), &ldz, (std::complex<T>*) &sigma, (std::complex<T>*) NULL, workev.memptr(), &bmat, &n, which, &nev, &tol, resid.memptr(), &ncv, v.memptr(), &ldv, iparam.memptr(), ipntr.memptr(), workd.memptr(), workl.memptr(), &lworkl, rwork.memptr(), &info);
// Check for errors.
if(info != 0) { arma_warn(1, "eigs_gen(): ARPACK error ", info, " in neupd()"); return false; }
if(info != 0) { arma_warn(1, "eigs_gen(): arpack::neupd() error: ", info); return false; }
return (info == 0);
}
@@ -1258,7 +1264,7 @@ sp_auxlib::spsolve_simple(Mat<typename T1::elem_type>& X, const SpBase<typename
else
if(info < 0)
{
arma_warn(1, "spsolve(): unknown SuperLU error code from gssv(): ", info);
arma_warn(1, "spsolve(): superlu::gssv() error: ", info);
}
// No need to extract the data from x, since it's using the same memory as X
@@ -1406,7 +1412,7 @@ sp_auxlib::spsolve_refine(Mat<typename T1::elem_type>& X, typename T1::pod_type&
else
if( (info == superlu::int_t(A.n_cols+1)) && (user_opts.allow_ugly) )
{
arma_warn(2, "spsolve(): system is singular to working precision (rcond: ", rcond, ")");
arma_warn(2, "spsolve(): system is singular to working precision; rcond: ", rcond);
status = true;
}
else
@@ -1417,7 +1423,7 @@ sp_auxlib::spsolve_refine(Mat<typename T1::elem_type>& X, typename T1::pod_type&
else
if(info < 0)
{
arma_warn(1, "spsolve(): unknown SuperLU error code from gssvx(): ", info);
arma_warn(1, "spsolve(): superlu::gssvx() error: ", info);
}
// No need to extract the data from x, since it's using the same memory as X
@@ -2013,11 +2019,11 @@ sp_auxlib::run_aupd_plain
if(sym)
{
arma_warn(1, "eigs_sym(): ARPACK error ", info, " in saupd()");
arma_warn(1, "eigs_sym(): arpack::saupd() error: ", info);
}
else
{
arma_warn(1, "eigs_gen(): ARPACK error ", info, " in naupd()");
arma_warn(1, "eigs_gen(): arpack::naupd() error: ", info);
}
return; // Parent frame can look at the value of info.
@@ -2200,7 +2206,7 @@ sp_auxlib::run_aupd_shiftinvert
if( (x_rcond < std::numeric_limits<eT>::epsilon()) || arma_isnan(x_rcond) )
{
arma_warn(2, "matrix is singular to working precision (rcond: ", x_rcond, ")");
arma_warn(2, "matrix is singular to working precision; rcond: ", x_rcond);
info = blas_int(-1);
return;
}
@@ -2270,11 +2276,11 @@ sp_auxlib::run_aupd_shiftinvert
if(sym)
{
arma_warn(2, "eigs_sym(): ARPACK error ", info, " in saupd()");
arma_warn(2, "eigs_sym(): arpack::saupd() error: ", info);
}
else
{
arma_warn(2, "eigs_gen(): ARPACK error ", info, " in naupd()");
arma_warn(2, "eigs_gen(): arpack::naupd() error: ", info);
}
return; // Parent frame can look at the value of info.
+1 -1
View File
@@ -923,7 +923,7 @@ spdiagview<eT>::clamp(const eT min_val, const eT max_val)
{
arma_debug_sigprint();
SpMat<eT> tmp(*this);
Mat<eT> tmp(*this);
tmp.clamp(min_val, max_val);
+13
View File
@@ -142,6 +142,9 @@ class subview : public Base< eT, subview<eT> >
arma_inline eT* colptr(const uword in_col);
arma_inline const eT* colptr(const uword in_col) const;
arma_inline eT* startptr();
arma_inline const eT* startptr() const;
template<typename eT2>
inline bool check_overlap(const subview<eT2>& x) const;
@@ -392,11 +395,16 @@ class subview_col : public subview<eT>
arma_warn_unused arma_inline const Op<subview_col<eT>,op_strans> as_row() const;
inline void replace(const eT old_val, const eT new_val);
inline void fill(const eT val);
inline void zeros();
inline void ones();
inline void randu();
inline void randn();
arma_warn_unused inline bool is_finite() const;
arma_warn_unused inline bool is_zero(const pod_type tol = 0) const;
arma_warn_unused inline bool has_inf() const;
arma_warn_unused inline bool has_nan() const;
@@ -552,11 +560,16 @@ class subview_row : public subview<eT>
arma_warn_unused arma_inline const Op<subview_row<eT>,op_strans> as_col() const;
inline void replace(const eT old_val, const eT new_val);
inline void fill(const eT val);
inline void zeros();
inline void ones();
inline void randu();
inline void randn();
arma_warn_unused inline bool is_finite() const;
arma_warn_unused inline bool is_zero(const pod_type tol = 0) const;
arma_warn_unused inline bool has_inf() const;
arma_warn_unused inline bool has_nan() const;
+114 -40
View File
@@ -109,6 +109,8 @@ subview_cube_each1<eT>::operator= (const Base<eT,T1>& in)
const uword p_n_slices = p.n_slices;
const uword p_n_elem_slice = p.n_elem_slice;
if(p_n_elem_slice == 0) { return; }
const eT* A_mem = A.memptr();
for(uword i=0; i < p_n_slices; ++i) { arrayops::copy( p.slice_memptr(i), A_mem, p_n_elem_slice ); }
@@ -134,6 +136,8 @@ subview_cube_each1<eT>::operator+= (const Base<eT,T1>& in)
const uword p_n_slices = p.n_slices;
const uword p_n_elem_slice = p.n_elem_slice;
if(p_n_elem_slice == 0) { return; }
const eT* A_mem = A.memptr();
for(uword i=0; i < p_n_slices; ++i) { arrayops::inplace_plus( p.slice_memptr(i), A_mem, p_n_elem_slice ); }
@@ -159,6 +163,8 @@ subview_cube_each1<eT>::operator-= (const Base<eT,T1>& in)
const uword p_n_slices = p.n_slices;
const uword p_n_elem_slice = p.n_elem_slice;
if(p_n_elem_slice == 0) { return; }
const eT* A_mem = A.memptr();
for(uword i=0; i < p_n_slices; ++i) { arrayops::inplace_minus( p.slice_memptr(i), A_mem, p_n_elem_slice ); }
@@ -184,6 +190,8 @@ subview_cube_each1<eT>::operator%= (const Base<eT,T1>& in)
const uword p_n_slices = p.n_slices;
const uword p_n_elem_slice = p.n_elem_slice;
if(p_n_elem_slice == 0) { return; }
const eT* A_mem = A.memptr();
for(uword i=0; i < p_n_slices; ++i) { arrayops::inplace_mul( p.slice_memptr(i), A_mem, p_n_elem_slice ); }
@@ -209,6 +217,8 @@ subview_cube_each1<eT>::operator/= (const Base<eT,T1>& in)
const uword p_n_slices = p.n_slices;
const uword p_n_elem_slice = p.n_elem_slice;
if(p_n_elem_slice == 0) { return; }
const eT* A_mem = A.memptr();
for(uword i=0; i < p_n_slices; ++i) { arrayops::inplace_div( p.slice_memptr(i), A_mem, p_n_elem_slice ); }
@@ -300,6 +310,8 @@ subview_cube_each2<eT,TB>::operator= (const Base<eT,T1>& in)
arma_conform_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
if(p_n_elem_slice == 0) { continue; }
arrayops::copy(p.slice_memptr(slice), A_mem, p_n_elem_slice);
}
}
@@ -339,6 +351,8 @@ subview_cube_each2<eT,TB>::operator+= (const Base<eT,T1>& in)
arma_conform_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
if(p_n_elem_slice == 0) { continue; }
arrayops::inplace_plus(p.slice_memptr(slice), A_mem, p_n_elem_slice);
}
}
@@ -378,6 +392,8 @@ subview_cube_each2<eT,TB>::operator-= (const Base<eT,T1>& in)
arma_conform_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
if(p_n_elem_slice == 0) { continue; }
arrayops::inplace_minus(p.slice_memptr(slice), A_mem, p_n_elem_slice);
}
}
@@ -417,6 +433,8 @@ subview_cube_each2<eT,TB>::operator%= (const Base<eT,T1>& in)
arma_conform_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
if(p_n_elem_slice == 0) { continue; }
arrayops::inplace_mul(p.slice_memptr(slice), A_mem, p_n_elem_slice);
}
}
@@ -456,6 +474,8 @@ subview_cube_each2<eT,TB>::operator/= (const Base<eT,T1>& in)
arma_conform_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
if(p_n_elem_slice == 0) { continue; }
arrayops::inplace_div(p.slice_memptr(slice), A_mem, p_n_elem_slice);
}
}
@@ -492,12 +512,15 @@ subview_cube_each1_aux::operator_plus
X.check_size(A);
for(uword i=0; i < p_n_slices; ++i)
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = p_slice + A;
for(uword i=0; i < p_n_slices; ++i)
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = p_slice + A;
}
}
return out;
@@ -529,12 +552,15 @@ subview_cube_each1_aux::operator_minus
X.check_size(A);
for(uword i=0; i < p_n_slices; ++i)
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = p_slice - A;
for(uword i=0; i < p_n_slices; ++i)
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = p_slice - A;
}
}
return out;
@@ -566,12 +592,15 @@ subview_cube_each1_aux::operator_minus
Y.check_size(A);
for(uword i=0; i < p_n_slices; ++i)
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = A - p_slice;
for(uword i=0; i < p_n_slices; ++i)
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = A - p_slice;
}
}
return out;
@@ -603,12 +632,15 @@ subview_cube_each1_aux::operator_schur
X.check_size(A);
for(uword i=0; i < p_n_slices; ++i)
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = p_slice % A;
for(uword i=0; i < p_n_slices; ++i)
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = p_slice % A;
}
}
return out;
@@ -640,12 +672,15 @@ subview_cube_each1_aux::operator_div
X.check_size(A);
for(uword i=0; i < p_n_slices; ++i)
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = p_slice / A;
for(uword i=0; i < p_n_slices; ++i)
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = p_slice / A;
}
}
return out;
@@ -677,12 +712,15 @@ subview_cube_each1_aux::operator_div
Y.check_size(A);
for(uword i=0; i < p_n_slices; ++i)
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = A / p_slice;
for(uword i=0; i < p_n_slices; ++i)
{
Mat<eT> out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
out_slice = A / p_slice;
}
}
return out;
@@ -706,14 +744,26 @@ subview_cube_each1_aux::operator_times
const unwrap<T2> tmp(Y.get_ref());
const Mat<eT>& M = tmp.M;
if(arma_config::check_conform)
{
if(C.n_cols != M.n_rows) { arma_stop_logic_error("each_slice(): incompatible sizes for matrix multiplication"); }
}
Cube<eT> out(C.n_rows, M.n_cols, C.n_slices, arma_nozeros_indicator());
for(uword i=0; i < C.n_slices; ++i)
if( (C.n_elem == 0) || (M.n_elem == 0) )
{
Mat<eT> out_slice( out.slice_memptr(i), C.n_rows, M.n_cols, false, true);
const Mat<eT> C_slice(const_cast<eT*>(C.slice_memptr(i)), C.n_rows, C.n_cols, false, true);
out_slice = C_slice * M;
out.zeros();
}
else
{
for(uword i=0; i < C.n_slices; ++i)
{
Mat<eT> out_slice( out.slice_memptr(i), C.n_rows, M.n_cols, false, true);
const Mat<eT> C_slice(const_cast<eT*>(C.slice_memptr(i)), C.n_rows, C.n_cols, false, true);
out_slice = C_slice * M;
}
}
return out;
@@ -737,14 +787,26 @@ subview_cube_each1_aux::operator_times
const Cube<eT>& C = Y.P;
if(arma_config::check_conform)
{
if(M.n_cols != C.n_rows) { arma_stop_logic_error("each_slice(): incompatible sizes for matrix multiplication"); }
}
Cube<eT> out(M.n_rows, C.n_cols, C.n_slices, arma_nozeros_indicator());
for(uword i=0; i < C.n_slices; ++i)
if( (M.n_elem == 0) || (C.n_elem == 0) )
{
Mat<eT> out_slice( out.slice_memptr(i), M.n_rows, C.n_cols, false, true);
const Mat<eT> C_slice(const_cast<eT*>(C.slice_memptr(i)), C.n_rows, C.n_cols, false, true);
out_slice = M * C_slice;
out.zeros();
}
else
{
for(uword i=0; i < C.n_slices; ++i)
{
Mat<eT> out_slice( out.slice_memptr(i), M.n_rows, C.n_cols, false, true);
const Mat<eT> C_slice(const_cast<eT*>(C.slice_memptr(i)), C.n_rows, C.n_cols, false, true);
out_slice = M * C_slice;
}
}
return out;
@@ -795,6 +857,8 @@ subview_cube_each2_aux::operator_plus
arma_conform_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
if(p_n_elem_slice == 0) { continue; }
arrayops::inplace_plus(out.slice_memptr(slice), A_mem, p_n_elem_slice);
}
@@ -840,6 +904,8 @@ subview_cube_each2_aux::operator_minus
arma_conform_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
if(p_n_elem_slice == 0) { continue; }
arrayops::inplace_minus(out.slice_memptr(slice), A_mem, p_n_elem_slice);
}
@@ -884,6 +950,8 @@ subview_cube_each2_aux::operator_minus
arma_conform_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
if( (p_n_rows == 0) || (p_n_cols == 0) ) { continue; }
Mat<eT> out_slice( out.slice_memptr(slice), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(slice)), p_n_rows, p_n_cols, false, true);
@@ -932,6 +1000,8 @@ subview_cube_each2_aux::operator_schur
arma_conform_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
if(p_n_elem_slice == 0) { continue; }
arrayops::inplace_mul(out.slice_memptr(slice), A_mem, p_n_elem_slice);
}
@@ -977,6 +1047,8 @@ subview_cube_each2_aux::operator_div
arma_conform_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
if(p_n_elem_slice == 0) { continue; }
arrayops::inplace_div(out.slice_memptr(slice), A_mem, p_n_elem_slice);
}
@@ -1021,6 +1093,8 @@ subview_cube_each2_aux::operator_div
arma_conform_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
if( (p_n_rows == 0) || (p_n_cols == 0) ) { continue; }
Mat<eT> out_slice( out.slice_memptr(slice), p_n_rows, p_n_cols, false, true);
const Mat<eT> p_slice(const_cast<eT*>(p.slice_memptr(slice)), p_n_rows, p_n_cols, false, true);
+66 -18
View File
@@ -117,6 +117,8 @@ subview_cube<eT>::inplace_op(const eT val)
const uword t_n_cols = t.n_cols;
const uword t_n_slices = t.n_slices;
if( (t_n_rows == 0) || (t_n_cols == 0) ) { return; }
for(uword s=0; s < t_n_slices; ++s)
for(uword c=0; c < t_n_cols; ++c)
{
@@ -150,6 +152,8 @@ subview_cube<eT>::inplace_op(const BaseCube<eT,T1>& in, const char* identifier)
arma_conform_assert_same_size(t, P, identifier);
if( (t_n_rows == 0) || (t_n_cols == 0) || (t_n_slices == 0) ) { return; }
const bool use_mp = arma_config::openmp && ProxyCube<T1>::use_mp && mp_gate<eT>::eval(t.n_elem);
const bool has_overlap = P.has_overlap(t);
@@ -258,6 +262,8 @@ subview_cube<eT>::inplace_op(const subview_cube<eT>& x, const char* identifier)
const uword t_n_cols = t.n_cols;
const uword t_n_slices = t.n_slices;
if( (t_n_rows == 0) || (t_n_cols == 0) ) { return; }
for(uword s=0; s < t_n_slices; ++s)
for(uword c=0; c < t_n_cols; ++c)
{
@@ -1174,6 +1180,8 @@ subview_cube<eT>::replace(const eT old_val, const eT new_val)
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
if( (local_n_rows == 0) || (local_n_cols == 0) ) { return; }
for(uword slice = 0; slice < local_n_slices; ++slice)
{
for(uword col = 0; col < local_n_cols; ++col)
@@ -1196,6 +1204,8 @@ subview_cube<eT>::clean(const typename get_pod_type<eT>::result threshold)
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
if( (local_n_rows == 0) || (local_n_cols == 0) ) { return; }
for(uword slice = 0; slice < local_n_slices; ++slice)
{
for(uword col = 0; col < local_n_cols; ++col)
@@ -1216,18 +1226,20 @@ subview_cube<eT>::clamp(const eT min_val, const eT max_val)
if(is_cx<eT>::no)
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "subview_cube::clamp(): min_val must be less than max_val" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "subview_cube::clamp(): min_val must be less than max_val" );
}
else
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "subview_cube::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "subview_cube::clamp(): imag(min_val) must be less than imag(max_val)" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "subview_cube::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( ((access::tmp_imag(min_val) <= access::tmp_imag(max_val)) == false), "subview_cube::clamp(): imag(min_val) must be less than imag(max_val)" );
}
const uword local_n_rows = n_rows;
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
if( (local_n_rows == 0) || (local_n_cols == 0) ) { return; }
for(uword slice = 0; slice < local_n_slices; ++slice)
{
for(uword col = 0; col < local_n_cols; ++col)
@@ -1250,6 +1262,8 @@ subview_cube<eT>::fill(const eT val)
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
if( (local_n_rows == 0) || (local_n_cols == 0) ) { return; }
for(uword slice = 0; slice < local_n_slices; ++slice)
{
for(uword col = 0; col < local_n_cols; ++col)
@@ -1272,6 +1286,8 @@ subview_cube<eT>::zeros()
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
if( (local_n_rows == 0) || (local_n_cols == 0) ) { return; }
for(uword slice = 0; slice < local_n_slices; ++slice)
{
for(uword col = 0; col < local_n_cols; ++col)
@@ -1306,6 +1322,8 @@ subview_cube<eT>::randu()
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
if( (local_n_rows == 0) || (local_n_cols == 0) ) { return; }
for(uword slice = 0; slice < local_n_slices; ++slice)
{
for(uword col = 0; col < local_n_cols; ++col)
@@ -1328,6 +1346,8 @@ subview_cube<eT>::randn()
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
if( (local_n_rows == 0) || (local_n_cols == 0) ) { return; }
for(uword slice = 0; slice < local_n_slices; ++slice)
{
for(uword col = 0; col < local_n_cols; ++col)
@@ -1352,11 +1372,14 @@ subview_cube<eT>::is_finite() const
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
for(uword slice = 0; slice < local_n_slices; ++slice)
if( (local_n_rows != 0) && (local_n_cols != 0) )
{
for(uword col = 0; col < local_n_cols; ++col)
for(uword slice = 0; slice < local_n_slices; ++slice)
{
if(arrayops::is_finite(slice_colptr(slice,col), local_n_rows) == false) { return false; }
for(uword col = 0; col < local_n_cols; ++col)
{
if(arrayops::is_finite(slice_colptr(slice,col), local_n_rows) == false) { return false; }
}
}
}
@@ -1372,10 +1395,16 @@ subview_cube<eT>::is_zero(const typename get_pod_type<eT>::result tol) const
{
arma_debug_sigprint();
typedef typename get_pod_type<elem_type>::result T;
arma_conform_check( ((tol >= T(0)) == false), "is_zero(): parameter 'tol' must be >= 0" );
const uword local_n_rows = n_rows;
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
if( (local_n_rows == 0) || (local_n_cols == 0) || (local_n_slices == 0) ) { return false; }
for(uword slice = 0; slice < local_n_slices; ++slice)
{
for(uword col = 0; col < local_n_cols; ++col)
@@ -1402,11 +1431,14 @@ subview_cube<eT>::has_inf() const
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
for(uword slice = 0; slice < local_n_slices; ++slice)
if( (local_n_rows != 0) && (local_n_cols != 0) )
{
for(uword col = 0; col < local_n_cols; ++col)
for(uword slice = 0; slice < local_n_slices; ++slice)
{
if(arrayops::has_inf(slice_colptr(slice,col), local_n_rows)) { return true; }
for(uword col = 0; col < local_n_cols; ++col)
{
if(arrayops::has_inf(slice_colptr(slice,col), local_n_rows)) { return true; }
}
}
}
@@ -1428,11 +1460,14 @@ subview_cube<eT>::has_nan() const
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
for(uword slice = 0; slice < local_n_slices; ++slice)
if( (local_n_rows != 0) && (local_n_cols != 0) )
{
for(uword col = 0; col < local_n_cols; ++col)
for(uword slice = 0; slice < local_n_slices; ++slice)
{
if(arrayops::has_nan(slice_colptr(slice,col), local_n_rows)) { return true; }
for(uword col = 0; col < local_n_cols; ++col)
{
if(arrayops::has_nan(slice_colptr(slice,col), local_n_rows)) { return true; }
}
}
}
@@ -1454,11 +1489,14 @@ subview_cube<eT>::has_nonfinite() const
const uword local_n_cols = n_cols;
const uword local_n_slices = n_slices;
for(uword slice = 0; slice < local_n_slices; ++slice)
if( (local_n_rows != 0) && (local_n_cols != 0) )
{
for(uword col = 0; col < local_n_cols; ++col)
for(uword slice = 0; slice < local_n_slices; ++slice)
{
if(arrayops::is_finite(slice_colptr(slice,col), local_n_rows) == false) { return true; }
for(uword col = 0; col < local_n_cols; ++col)
{
if(arrayops::is_finite(slice_colptr(slice,col), local_n_rows) == false) { return true; }
}
}
}
@@ -1614,7 +1652,7 @@ arma_inline
eT*
subview_cube<eT>::slice_colptr(const uword in_slice, const uword in_col)
{
return & access::rw((const_cast< Cube<eT>& >(m)).mem[ (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 ]);
return access::rwp( m.mem + ( (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 ) );
}
@@ -1624,7 +1662,7 @@ arma_inline
const eT*
subview_cube<eT>::slice_colptr(const uword in_slice, const uword in_col) const
{
return & m.mem[ (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 ];
return m.mem + ( (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 );
}
@@ -1704,7 +1742,7 @@ void
subview_cube<eT>::extract(Cube<eT>& out, const subview_cube<eT>& in)
{
arma_debug_sigprint();
// NOTE: we're assuming that the cube has already been set to the correct size and there is no aliasing;
// size setting and alias checking is done by either the Cube constructor or operator=()
@@ -1714,6 +1752,8 @@ subview_cube<eT>::extract(Cube<eT>& out, const subview_cube<eT>& in)
arma_debug_print(arma_str::format("out.n_rows: %u; out.n_cols: %u; out.n_slices: %u; in.m.n_rows: %u; in.m.n_cols: %u; in.m.n_slices: %u") % out.n_rows % out.n_cols % out.n_slices % in.m.n_rows % in.m.n_cols % in.m.n_slices);
if( (n_rows == 0) || (n_cols == 0) ) { return; }
if( (in.aux_row1 == 0) && (n_rows == in.m.n_rows) )
{
for(uword s=0; s < n_slices; ++s)
@@ -1747,6 +1787,8 @@ subview_cube<eT>::plus_inplace(Cube<eT>& out, const subview_cube<eT>& in)
const uword n_cols = out.n_cols;
const uword n_slices = out.n_slices;
if( (n_rows == 0) || (n_cols == 0) ) { return; }
for(uword slice = 0; slice<n_slices; ++slice)
{
for(uword col = 0; col<n_cols; ++col)
@@ -1772,6 +1814,8 @@ subview_cube<eT>::minus_inplace(Cube<eT>& out, const subview_cube<eT>& in)
const uword n_cols = out.n_cols;
const uword n_slices = out.n_slices;
if( (n_rows == 0) || (n_cols == 0) ) { return; }
for(uword slice = 0; slice<n_slices; ++slice)
{
for(uword col = 0; col<n_cols; ++col)
@@ -1797,6 +1841,8 @@ subview_cube<eT>::schur_inplace(Cube<eT>& out, const subview_cube<eT>& in)
const uword n_cols = out.n_cols;
const uword n_slices = out.n_slices;
if( (n_rows == 0) || (n_cols == 0) ) { return; }
for(uword slice = 0; slice<n_slices; ++slice)
{
for(uword col = 0; col<n_cols; ++col)
@@ -1822,6 +1868,8 @@ subview_cube<eT>::div_inplace(Cube<eT>& out, const subview_cube<eT>& in)
const uword n_cols = out.n_cols;
const uword n_slices = out.n_slices;
if( (n_rows == 0) || (n_cols == 0) ) { return; }
for(uword slice = 0; slice<n_slices; ++slice)
{
for(uword col = 0; col<n_cols; ++col)
+164 -114
View File
@@ -157,6 +157,8 @@ subview_each1<parent,mode>::operator= (const Base<eT,T1>& in)
const uword p_n_rows = p.n_rows;
const uword p_n_cols = p.n_cols;
if(p_n_rows == 0) { return; }
if(mode == 0) // each column
{
for(uword i=0; i < p_n_cols; ++i)
@@ -194,6 +196,8 @@ subview_each1<parent,mode>::operator+= (const Base<eT,T1>& in)
const uword p_n_rows = p.n_rows;
const uword p_n_cols = p.n_cols;
if(p_n_rows == 0) { return; }
if(mode == 0) // each column
{
for(uword i=0; i < p_n_cols; ++i)
@@ -231,6 +235,8 @@ subview_each1<parent,mode>::operator-= (const Base<eT,T1>& in)
const uword p_n_rows = p.n_rows;
const uword p_n_cols = p.n_cols;
if(p_n_rows == 0) { return; }
if(mode == 0) // each column
{
for(uword i=0; i < p_n_cols; ++i)
@@ -268,6 +274,8 @@ subview_each1<parent,mode>::operator%= (const Base<eT,T1>& in)
const uword p_n_rows = p.n_rows;
const uword p_n_cols = p.n_cols;
if(p_n_rows == 0) { return; }
if(mode == 0) // each column
{
for(uword i=0; i < p_n_cols; ++i)
@@ -305,6 +313,8 @@ subview_each1<parent,mode>::operator/= (const Base<eT,T1>& in)
const uword p_n_rows = p.n_rows;
const uword p_n_cols = p.n_cols;
if(p_n_rows == 0) { return; }
if(mode == 0) // each column
{
for(uword i=0; i < p_n_cols; ++i)
@@ -400,6 +410,8 @@ subview_each2<parent,mode,TB>::operator= (const Base<eT,T1>& in)
arma_conform_check_bounds( (col >= p_n_cols), "each_col(): index out of bounds" );
if(p_n_rows == 0) { continue; }
arrayops::copy( p.colptr(col), A_mem, p_n_rows );
}
}
@@ -456,6 +468,8 @@ subview_each2<parent,mode,TB>::operator+= (const Base<eT,T1>& in)
arma_conform_check_bounds( (col >= p_n_cols), "each_col(): index out of bounds" );
if(p_n_rows == 0) { continue; }
arrayops::inplace_plus( p.colptr(col), A_mem, p_n_rows );
}
}
@@ -509,6 +523,8 @@ subview_each2<parent,mode,TB>::operator-= (const Base<eT,T1>& in)
arma_conform_check_bounds( (col >= p_n_cols), "each_col(): index out of bounds" );
if(p_n_rows == 0) { continue; }
arrayops::inplace_minus( p.colptr(col), A_mem, p_n_rows );
}
}
@@ -562,6 +578,8 @@ subview_each2<parent,mode,TB>::operator%= (const Base<eT,T1>& in)
arma_conform_check_bounds( (col >= p_n_cols), "each_col(): index out of bounds" );
if(p_n_rows == 0) { continue; }
arrayops::inplace_mul( p.colptr(col), A_mem, p_n_rows );
}
}
@@ -615,6 +633,8 @@ subview_each2<parent,mode,TB>::operator/= (const Base<eT,T1>& in)
arma_conform_check_bounds( (col >= p_n_cols), "each_col(): index out of bounds" );
if(p_n_rows == 0) { continue; }
arrayops::inplace_div( p.colptr(col), A_mem, p_n_rows );
}
}
@@ -666,32 +686,35 @@ subview_each1_aux::operator_plus
const eT* A_mem = A.memptr();
if(mode == 0) // each column
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 0) // each column
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = p_mem[row] + A_mem[row];
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = p_mem[row] + A_mem[row];
}
}
}
}
if(mode == 1) // each row
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 1) // each row
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = p_mem[row] + A_val;
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = p_mem[row] + A_val;
}
}
}
}
@@ -728,32 +751,35 @@ subview_each1_aux::operator_minus
const eT* A_mem = A.memptr();
if(mode == 0) // each column
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 0) // each column
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = p_mem[row] - A_mem[row];
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = p_mem[row] - A_mem[row];
}
}
}
}
if(mode == 1) // each row
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 1) // each row
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = p_mem[row] - A_val;
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = p_mem[row] - A_val;
}
}
}
}
@@ -790,32 +816,35 @@ subview_each1_aux::operator_minus
const eT* A_mem = A.memptr();
if(mode == 0) // each column
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 0) // each column
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = A_mem[row] - p_mem[row];
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = A_mem[row] - p_mem[row];
}
}
}
}
if(mode == 1) // each row
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 1) // each row
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = A_val - p_mem[row];
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = A_val - p_mem[row];
}
}
}
}
@@ -852,32 +881,35 @@ subview_each1_aux::operator_schur
const eT* A_mem = A.memptr();
if(mode == 0) // each column
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 0) // each column
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = p_mem[row] * A_mem[row];
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = p_mem[row] * A_mem[row];
}
}
}
}
if(mode == 1) // each row
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 1) // each row
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = p_mem[row] * A_val;
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = p_mem[row] * A_val;
}
}
}
}
@@ -914,32 +946,35 @@ subview_each1_aux::operator_div
const eT* A_mem = A.memptr();
if(mode == 0) // each column
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 0) // each column
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = p_mem[row] / A_mem[row];
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = p_mem[row] / A_mem[row];
}
}
}
}
if(mode == 1) // each row
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 1) // each row
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = p_mem[row] / A_val;
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = p_mem[row] / A_val;
}
}
}
}
@@ -976,32 +1011,35 @@ subview_each1_aux::operator_div
const eT* A_mem = A.memptr();
if(mode == 0) // each column
if( (p_n_rows != 0) && (p_n_cols != 0) )
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 0) // each column
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = A_mem[row] / p_mem[row];
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = A_mem[row] / p_mem[row];
}
}
}
}
if(mode == 1) // each row
{
for(uword i=0; i < p_n_cols; ++i)
if(mode == 1) // each row
{
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
for(uword i=0; i < p_n_cols; ++i)
{
out_mem[row] = A_val / p_mem[row];
const eT* p_mem = p.colptr(i);
eT* out_mem = out.colptr(i);
const eT A_val = A_mem[i];
for(uword row=0; row < p_n_rows; ++row)
{
out_mem[row] = A_val / p_mem[row];
}
}
}
}
@@ -1058,6 +1096,8 @@ subview_each2_aux::operator_plus
arma_conform_check_bounds( (col >= p_n_cols), "each_col(): index out of bounds" );
if(p_n_rows == 0) { continue; }
arrayops::inplace_plus( out.colptr(col), A_mem, p_n_rows );
}
}
@@ -1120,6 +1160,8 @@ subview_each2_aux::operator_minus
arma_conform_check_bounds( (col >= p_n_cols), "each_col(): index out of bounds" );
if(p_n_rows == 0) { continue; }
arrayops::inplace_minus( out.colptr(col), A_mem, p_n_rows );
}
}
@@ -1182,6 +1224,8 @@ subview_each2_aux::operator_minus
arma_conform_check_bounds( (col >= p_n_cols), "each_col(): index out of bounds" );
if(p_n_rows == 0) { continue; }
const eT* p_mem = p.colptr(col);
eT* out_mem = out.colptr(col);
@@ -1250,6 +1294,8 @@ subview_each2_aux::operator_schur
arma_conform_check_bounds( (col >= p_n_cols), "each_col(): index out of bounds" );
if(p_n_rows == 0) { continue; }
arrayops::inplace_mul( out.colptr(col), A_mem, p_n_rows );
}
}
@@ -1312,6 +1358,8 @@ subview_each2_aux::operator_div
arma_conform_check_bounds( (col >= p_n_cols), "each_col(): index out of bounds" );
if(p_n_rows == 0) { continue; }
arrayops::inplace_div( out.colptr(col), A_mem, p_n_rows );
}
}
@@ -1374,6 +1422,8 @@ subview_each2_aux::operator_div
arma_conform_check_bounds( (col >= p_n_cols), "each_col(): index out of bounds" );
if(p_n_rows == 0) { continue; }
const eT* p_mem = p.colptr(col);
eT* out_mem = out.colptr(col);
@@ -90,6 +90,8 @@ class subview_elem1 : public Base< eT, subview_elem1<eT,T1> >
template<typename T2> inline void operator%= (const Base<eT,T2>& x);
template<typename T2> inline void operator/= (const Base<eT,T2>& x);
inline static void extract_noalias(Mat<eT>& out, const subview_elem1& in);
inline static void extract(Mat<eT>& out, const subview_elem1& in);
template<typename op_type> inline static void mat_inplace_op(Mat<eT>& out, const subview_elem1& in);
+53 -4
View File
@@ -759,6 +759,55 @@ subview_elem1<eT,T1>::operator/= (const Base<eT,T2>& x)
template<typename eT, typename T1>
inline
void
subview_elem1<eT,T1>::extract_noalias(Mat<eT>& out, const subview_elem1<eT,T1>& in)
{
arma_debug_sigprint();
const quasi_unwrap<T1> tmp1(in.a.get_ref());
const umat& aa = tmp1.M;
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;
const eT* m_mem = in.m.memptr();
const uword m_n_elem = in.m.n_elem;
out.set_size(aa_n_elem, 1);
eT* out_mem = out.memptr();
uword i,j;
for(i=0, j=1; j<aa_n_elem; i+=2, j+=2)
{
const uword ii = aa_mem[i];
const uword jj = aa_mem[j];
arma_conform_check_bounds( ( (ii >= m_n_elem) || (jj >= m_n_elem) ), "Mat::elem(): index out of bounds" );
out_mem[i] = m_mem[ii];
out_mem[j] = m_mem[jj];
}
if(i < aa_n_elem)
{
const uword ii = aa_mem[i];
arma_conform_check_bounds( (ii >= m_n_elem) , "Mat::elem(): index out of bounds" );
out_mem[i] = m_mem[ii];
}
}
template<typename eT, typename T1>
inline
void
@@ -777,12 +826,12 @@ subview_elem1<eT,T1>::extract(Mat<eT>& actual_out, const subview_elem1<eT,T1>& i
const uword* aa_mem = aa.memptr();
const uword aa_n_elem = aa.n_elem;
const Mat<eT>& m_local = in.m;
const Mat<eT>& m = in.m;
const eT* m_mem = m_local.memptr();
const uword m_n_elem = m_local.n_elem;
const eT* m_mem = m.memptr();
const uword m_n_elem = m.n_elem;
const bool alias = (&actual_out == &m_local);
const bool alias = (&actual_out == &m);
if(alias) { arma_debug_print("subview_elem1::extract(): aliasing detected"); }
@@ -98,6 +98,8 @@ class subview_elem2 : public Base< eT, subview_elem2<eT,T1,T2> >
template<typename expr> inline void operator%= (const SpBase<eT,expr>& x);
template<typename expr> inline void operator/= (const SpBase<eT,expr>& x);
inline static void extract_noalias(Mat<eT>& out, const subview_elem2& in);
inline static void extract(Mat<eT>& out, const subview_elem2& in);
inline static void plus_inplace(Mat<eT>& out, const subview_elem2& in);
+124 -9
View File
@@ -917,6 +917,121 @@ subview_elem2<eT,T1,T2>::operator/= (const SpBase<eT,expr>& x)
template<typename eT, typename T1, typename T2>
inline
void
subview_elem2<eT,T1,T2>::extract_noalias(Mat<eT>& out, const subview_elem2<eT,T1,T2>& in)
{
arma_debug_sigprint();
const Mat<eT>& m = in.m;
const uword m_n_rows = m.n_rows;
const uword m_n_cols = m.n_cols;
if( (in.all_rows == false) && (in.all_cols == false) )
{
const quasi_unwrap<T1> tmp1(in.base_ri.get_ref());
const quasi_unwrap<T2> tmp2(in.base_ci.get_ref());
const umat& ri = tmp1.M;
const umat& ci = tmp2.M;
arma_conform_check
(
( ((ri.is_vec() == false) && (ri.is_empty() == false)) || ((ci.is_vec() == false) && (ci.is_empty() == false)) ),
"Mat::elem(): given object must be a vector"
);
const uword* ri_mem = ri.memptr();
const uword ri_n_elem = ri.n_elem;
const uword* ci_mem = ci.memptr();
const uword ci_n_elem = ci.n_elem;
out.set_size(ri_n_elem, ci_n_elem);
eT* out_mem = out.memptr();
uword out_count = 0;
for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count)
{
const uword col = ci_mem[ci_count];
arma_conform_check_bounds( (col >= m_n_cols), "Mat::elem(): index out of bounds" );
for(uword ri_count=0; ri_count < ri_n_elem; ++ri_count)
{
const uword row = ri_mem[ri_count];
arma_conform_check_bounds( (row >= m_n_rows), "Mat::elem(): index out of bounds" );
out_mem[out_count] = m.at(row,col);
++out_count;
}
}
}
else
if( (in.all_rows == true) && (in.all_cols == false) )
{
const quasi_unwrap<T2> tmp2(in.base_ci.get_ref());
const umat& ci = tmp2.M;
arma_conform_check
(
( (ci.is_vec() == false) && (ci.is_empty() == false) ),
"Mat::elem(): given object must be a vector"
);
const uword* ci_mem = ci.memptr();
const uword ci_n_elem = ci.n_elem;
out.set_size(m_n_rows, ci_n_elem);
for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count)
{
const uword col = ci_mem[ci_count];
arma_conform_check_bounds( (col >= m_n_cols), "Mat::elem(): index out of bounds" );
arrayops::copy( out.colptr(ci_count), m.colptr(col), m_n_rows );
}
}
else
if( (in.all_rows == false) && (in.all_cols == true) )
{
const quasi_unwrap<T1> tmp1(in.base_ri.get_ref());
const umat& ri = tmp1.M;
arma_conform_check
(
( (ri.is_vec() == false) && (ri.is_empty() == false) ),
"Mat::elem(): given object must be a vector"
);
const uword* ri_mem = ri.memptr();
const uword ri_n_elem = ri.n_elem;
out.set_size(ri_n_elem, m_n_cols);
for(uword col=0; col < m_n_cols; ++col)
{
for(uword ri_count=0; ri_count < ri_n_elem; ++ri_count)
{
const uword row = ri_mem[ri_count];
arma_conform_check_bounds( (row >= m_n_rows), "Mat::elem(): index out of bounds" );
out.at(ri_count,col) = m.at(row,col);
}
}
}
}
template<typename eT, typename T1, typename T2>
inline
void
@@ -924,12 +1039,12 @@ subview_elem2<eT,T1,T2>::extract(Mat<eT>& actual_out, const subview_elem2<eT,T1,
{
arma_debug_sigprint();
Mat<eT>& m_local = const_cast< Mat<eT>& >(in.m);
const Mat<eT>& m = in.m;
const uword m_n_rows = m_local.n_rows;
const uword m_n_cols = m_local.n_cols;
const uword m_n_rows = m.n_rows;
const uword m_n_cols = m.n_cols;
const bool alias = (&actual_out == &m_local);
const bool alias = (&actual_out == &m);
if(alias) { arma_debug_print("subview_elem2::extract(): aliasing detected"); }
@@ -973,7 +1088,7 @@ subview_elem2<eT,T1,T2>::extract(Mat<eT>& actual_out, const subview_elem2<eT,T1,
arma_conform_check_bounds( (row >= m_n_rows), "Mat::elem(): index out of bounds" );
out_mem[out_count] = m_local.at(row,col);
out_mem[out_count] = m.at(row,col);
++out_count;
}
}
@@ -981,7 +1096,7 @@ subview_elem2<eT,T1,T2>::extract(Mat<eT>& actual_out, const subview_elem2<eT,T1,
else
if( (in.all_rows == true) && (in.all_cols == false) )
{
const unwrap_check_mixed<T2> tmp2(in.base_ci.get_ref(), m_local);
const unwrap_check_mixed<T2> tmp2(in.base_ci.get_ref(), m);
const umat& ci = tmp2.M;
@@ -1002,13 +1117,13 @@ subview_elem2<eT,T1,T2>::extract(Mat<eT>& actual_out, const subview_elem2<eT,T1,
arma_conform_check_bounds( (col >= m_n_cols), "Mat::elem(): index out of bounds" );
arrayops::copy( out.colptr(ci_count), m_local.colptr(col), m_n_rows );
arrayops::copy( out.colptr(ci_count), m.colptr(col), m_n_rows );
}
}
else
if( (in.all_rows == false) && (in.all_cols == true) )
{
const unwrap_check_mixed<T1> tmp1(in.base_ri.get_ref(), m_local);
const unwrap_check_mixed<T1> tmp1(in.base_ri.get_ref(), m);
const umat& ri = tmp1.M;
@@ -1031,7 +1146,7 @@ subview_elem2<eT,T1,T2>::extract(Mat<eT>& actual_out, const subview_elem2<eT,T1,
arma_conform_check_bounds( (row >= m_n_rows), "Mat::elem(): index out of bounds" );
out.at(ri_count,col) = m_local.at(row,col);
out.at(ri_count,col) = m.at(row,col);
}
}
}
+3 -16
View File
@@ -507,24 +507,17 @@ subview_field<oT>::fill(const oT& x)
template<typename oT>
inline
void
subview_field<oT>::extract(field<oT>& actual_out, const subview_field<oT>& in)
subview_field<oT>::extract(field<oT>& out, const subview_field<oT>& in)
{
arma_debug_sigprint();
//
const bool alias = (&actual_out == &in.f);
field<oT>* tmp = (alias) ? new field<oT> : nullptr;
field<oT>& out = (alias) ? (*tmp) : actual_out;
//
// NOTE: we're assuming that the field has already been set to the correct size and there is no aliasing;
// size setting and alias checking is done by either the field constructor or operator=()
const uword n_rows = in.n_rows;
const uword n_cols = in.n_cols;
const uword n_slices = in.n_slices;
out.set_size(n_rows, n_cols, n_slices);
arma_debug_print(arma_str::format("out.n_rows: %u; out.n_cols: %u; out.n_slices: %u; in.f.n_rows: %u; in.f.n_cols: %u; in.f.n_slices: %u") % out.n_rows % out.n_cols % out.n_slices % in.f.n_rows % in.f.n_cols % in.f.n_slices);
if(n_slices == 1)
@@ -544,12 +537,6 @@ subview_field<oT>::extract(field<oT>& actual_out, const subview_field<oT>& in)
out.at(row,col,slice) = in.at(row,col,slice);
}
}
if(alias)
{
actual_out = out;
delete tmp;
}
}
+433 -145
View File
@@ -95,6 +95,8 @@ subview<eT>::inplace_op(const eT val)
const uword s_n_rows = s.n_rows;
const uword s_n_cols = s.n_cols;
if( (s_n_rows == 0) || (s_n_cols == 0) ) { return; }
if(s_n_rows == 1)
{
Mat<eT>& A = const_cast< Mat<eT>& >(s.m);
@@ -151,6 +153,8 @@ subview<eT>::inplace_op(const Base<eT,T1>& in, const char* identifier)
arma_conform_assert_same_size(s, P, identifier);
if( (s_n_rows == 0) || (s_n_cols == 0) ) { return; }
const bool use_mp = arma_config::openmp && Proxy<T1>::use_mp && mp_gate<eT>::eval(s.n_elem);
const bool has_overlap = P.has_overlap(s);
@@ -348,8 +352,10 @@ subview<eT>::inplace_op(const subview<eT>& x, const char* identifier)
arma_conform_assert_same_size(s, x, identifier);
const uword s_n_cols = s.n_cols;
const uword s_n_rows = s.n_rows;
const uword s_n_cols = s.n_cols;
if( (s_n_rows == 0) || (s_n_cols == 0) ) { return; }
if(s_n_rows == 1)
{
@@ -606,7 +612,8 @@ subview<eT>::operator=(const SpBase<eT, T1>& x)
// Clear the subview.
zeros();
// Iterate through the sparse subview and set the nonzero values appropriately.
if(p.get_n_nonzero() == 0) { return; }
typename SpProxy<T1>::const_iterator_type cit = p.begin();
typename SpProxy<T1>::const_iterator_type cit_end = p.end();
@@ -631,7 +638,8 @@ subview<eT>::operator+=(const SpBase<eT, T1>& x)
arma_conform_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "addition");
// Iterate through the sparse subview and add its values.
if(p.get_n_nonzero() == 0) { return; }
typename SpProxy<T1>::const_iterator_type cit = p.begin();
typename SpProxy<T1>::const_iterator_type cit_end = p.end();
@@ -656,7 +664,8 @@ subview<eT>::operator-=(const SpBase<eT, T1>& x)
arma_conform_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "subtraction");
// Iterate through the sparse subview and subtract its values.
if(p.get_n_nonzero() == 0) { return; }
typename SpProxy<T1>::const_iterator_type cit = p.begin();
typename SpProxy<T1>::const_iterator_type cit_end = p.end();
@@ -725,13 +734,12 @@ subview<eT>::operator/=(const SpBase<eT, T1>& x)
{
arma_debug_sigprint();
// NOTE: use of this function is not advised; it is implemented only for completeness
const SpProxy<T1> p(x.get_ref());
arma_conform_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "element-wise division");
// This is probably going to fill your subview with a bunch of NaNs,
// so I'm not going to bother to implement it fast.
// You can have slow NaNs. They're fine too.
for(uword c = 0; c < n_cols; ++c)
for(uword r = 0; r < n_rows; ++r)
{
@@ -968,35 +976,14 @@ subview<eT>::replace(const eT old_val, const eT new_val)
subview<eT>& s = *this;
const uword s_n_cols = s.n_cols;
const uword s_n_rows = s.n_rows;
const uword s_n_cols = s.n_cols;
if(s_n_rows == 1)
if(s_n_rows == 0) { return; }
if( (s.aux_row1 == 0) && (s_n_rows == s.m.n_rows) )
{
Mat<eT>& A = const_cast< Mat<eT>& >(s.m);
const uword A_n_rows = A.n_rows;
eT* Aptr = &(A.at(s.aux_row1,s.aux_col1));
if(arma_isnan(old_val))
{
for(uword ucol=0; ucol < s_n_cols; ++ucol)
{
(*Aptr) = (arma_isnan(*Aptr)) ? new_val : (*Aptr);
Aptr += A_n_rows;
}
}
else
{
for(uword ucol=0; ucol < s_n_cols; ++ucol)
{
(*Aptr) = ((*Aptr) == old_val) ? new_val : (*Aptr);
Aptr += A_n_rows;
}
}
arrayops::replace(s.colptr(0), s.n_elem, old_val, new_val);
}
else
{
@@ -1018,8 +1005,10 @@ subview<eT>::clean(const typename get_pod_type<eT>::result threshold)
subview<eT>& s = *this;
const uword s_n_cols = s.n_cols;
const uword s_n_rows = s.n_rows;
const uword s_n_cols = s.n_cols;
if(s_n_rows == 0) { return; }
for(uword ucol=0; ucol < s_n_cols; ++ucol)
{
@@ -1038,18 +1027,20 @@ subview<eT>::clamp(const eT min_val, const eT max_val)
if(is_cx<eT>::no)
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "subview::clamp(): min_val must be less than max_val" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "subview::clamp(): min_val must be less than max_val" );
}
else
{
arma_conform_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "subview::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "subview::clamp(): imag(min_val) must be less than imag(max_val)" );
arma_conform_check( ((access::tmp_real(min_val) <= access::tmp_real(max_val)) == false), "subview::clamp(): real(min_val) must be less than real(max_val)" );
arma_conform_check( ((access::tmp_imag(min_val) <= access::tmp_imag(max_val)) == false), "subview::clamp(): imag(min_val) must be less than imag(max_val)" );
}
subview<eT>& s = *this;
const uword s_n_cols = s.n_cols;
const uword s_n_rows = s.n_rows;
const uword s_n_cols = s.n_cols;
if(s_n_rows == 0) { return; }
for(uword ucol=0; ucol < s_n_cols; ++ucol)
{
@@ -1068,34 +1059,20 @@ subview<eT>::fill(const eT val)
subview<eT>& s = *this;
const uword s_n_cols = s.n_cols;
const uword s_n_rows = s.n_rows;
const uword s_n_cols = s.n_cols;
if(s_n_rows == 1)
if(s_n_rows == 0) { return; }
if( (s.aux_row1 == 0) && (s_n_rows == s.m.n_rows) )
{
Mat<eT>& A = const_cast< Mat<eT>& >(s.m);
const uword A_n_rows = A.n_rows;
eT* Aptr = &(A.at(s.aux_row1,s.aux_col1));
for(uword ii=0; ii < s_n_cols; ++ii)
{
(*Aptr) = val; Aptr += A_n_rows;
}
arrayops::inplace_set( s.colptr(0), val, s.n_elem );
}
else
{
if( (s.aux_row1 == 0) && (s_n_rows == s.m.n_rows) )
for(uword ucol=0; ucol < s_n_cols; ++ucol)
{
arrayops::inplace_set( s.colptr(0), val, s.n_elem );
}
else
{
for(uword ucol=0; ucol < s_n_cols; ++ucol)
{
arrayops::inplace_set( s.colptr(ucol), val, s_n_rows );
}
arrayops::inplace_set( s.colptr(ucol), val, s_n_rows );
}
}
}
@@ -1109,7 +1086,24 @@ subview<eT>::zeros()
{
arma_debug_sigprint();
(*this).fill(eT(0));
subview<eT>& s = *this;
const uword s_n_rows = s.n_rows;
const uword s_n_cols = s.n_cols;
if(s_n_rows == 0) { return; }
if( (s.aux_row1 == 0) && (s_n_rows == s.m.n_rows) )
{
arrayops::fill_zeros( s.colptr(0), s.n_elem );
}
else
{
for(uword ucol=0; ucol < s_n_cols; ++ucol)
{
arrayops::fill_zeros( s.colptr(ucol), s_n_rows );
}
}
}
@@ -1157,15 +1151,26 @@ subview<eT>::randu()
const uword s_n_rows = s.n_rows;
const uword s_n_cols = s.n_cols;
if( (s_n_rows == 0) || (s_n_cols == 0) ) { return; }
if(s_n_rows == 1)
{
// NOTE: special handling to ensure that the same sequence is generated as per subview_row::randu()
podarray<eT> tmp(s_n_cols);
eT* tmp_mem = tmp.memptr();
arma_rng::randu<eT>::fill( tmp_mem, s_n_cols );
for(uword ii=0; ii < s_n_cols; ++ii) { at(0,ii) = tmp_mem[ii]; }
eT* mem_ptr = startptr();
const uword m_n_rows = s.m.n_rows;
for(uword ii=0; ii < s_n_cols; ++ii)
{
(*mem_ptr) = tmp_mem[ii]; mem_ptr += m_n_rows;
}
}
else
{
@@ -1197,15 +1202,26 @@ subview<eT>::randn()
const uword s_n_rows = s.n_rows;
const uword s_n_cols = s.n_cols;
if( (s_n_rows == 0) || (s_n_cols == 0) ) { return; }
if(s_n_rows == 1)
{
// NOTE: special handling to ensure that the same sequence is generated as per subview_row::randu()
podarray<eT> tmp(s_n_cols);
eT* tmp_mem = tmp.memptr();
arma_rng::randn<eT>::fill( tmp_mem, s_n_cols );
for(uword ii=0; ii < s_n_cols; ++ii) { at(0,ii) = tmp_mem[ii]; }
eT* mem_ptr = startptr();
const uword m_n_rows = s.m.n_rows;
for(uword ii=0; ii < s_n_cols; ++ii)
{
(*mem_ptr) = tmp_mem[ii]; mem_ptr += m_n_rows;
}
}
else
{
@@ -1410,7 +1426,7 @@ arma_inline
eT*
subview<eT>::colptr(const uword in_col)
{
return & access::rw((const_cast< Mat<eT>& >(m)).mem[ (in_col + aux_col1)*m.n_rows + aux_row1 ]);
return access::rwp( m.mem + ((in_col + aux_col1)*m.n_rows + aux_row1) );
}
@@ -1420,7 +1436,27 @@ arma_inline
const eT*
subview<eT>::colptr(const uword in_col) const
{
return & m.mem[ (in_col + aux_col1)*m.n_rows + aux_row1 ];
return m.mem + ((in_col + aux_col1)*m.n_rows + aux_row1);
}
template<typename eT>
arma_inline
eT*
subview<eT>::startptr()
{
return access::rwp( m.mem + (aux_col1*m.n_rows + aux_row1) );
}
template<typename eT>
arma_inline
const eT*
subview<eT>::startptr() const
{
return m.mem + (aux_col1*m.n_rows + aux_row1);
}
@@ -1483,9 +1519,12 @@ subview<eT>::is_finite() const
const uword local_n_rows = n_rows;
const uword local_n_cols = n_cols;
for(uword ii=0; ii<local_n_cols; ++ii)
if(local_n_rows != 0)
{
if(arrayops::is_finite(colptr(ii), local_n_rows) == false) { return false; }
for(uword ii=0; ii<local_n_cols; ++ii)
{
if(arrayops::is_finite(colptr(ii), local_n_rows) == false) { return false; }
}
}
return true;
@@ -1500,10 +1539,16 @@ subview<eT>::is_zero(const typename get_pod_type<eT>::result tol) const
{
arma_debug_sigprint();
typedef typename get_pod_type<eT>::result T;
arma_conform_check( ((tol >= T(0)) == false), "is_zero(): parameter 'tol' must be >= 0" );
const uword local_n_rows = n_rows;
const uword local_n_cols = n_cols;
for(uword ii=0; ii<local_n_cols; ++ii)
if( (local_n_rows == 0) || (local_n_cols == 0) ) { return false; }
for(uword ii=0; ii < local_n_cols; ++ii)
{
if(arrayops::is_zero(colptr(ii), local_n_rows, tol) == false) { return false; }
}
@@ -1525,9 +1570,12 @@ subview<eT>::has_inf() const
const uword local_n_rows = n_rows;
const uword local_n_cols = n_cols;
for(uword ii=0; ii<local_n_cols; ++ii)
if(local_n_rows != 0)
{
if(arrayops::has_inf(colptr(ii), local_n_rows)) { return true; }
for(uword ii=0; ii<local_n_cols; ++ii)
{
if(arrayops::has_inf(colptr(ii), local_n_rows)) { return true; }
}
}
return false;
@@ -1547,9 +1595,12 @@ subview<eT>::has_nan() const
const uword local_n_rows = n_rows;
const uword local_n_cols = n_cols;
for(uword ii=0; ii<local_n_cols; ++ii)
if(local_n_rows != 0)
{
if(arrayops::has_nan(colptr(ii), local_n_rows)) { return true; }
for(uword ii=0; ii<local_n_cols; ++ii)
{
if(arrayops::has_nan(colptr(ii), local_n_rows)) { return true; }
}
}
return false;
@@ -1569,9 +1620,12 @@ subview<eT>::has_nonfinite() const
const uword local_n_rows = n_rows;
const uword local_n_cols = n_cols;
for(uword ii=0; ii<local_n_cols; ++ii)
if(local_n_rows != 0)
{
if(arrayops::is_finite(colptr(ii), local_n_rows) == false) { return true; }
for(uword ii=0; ii<local_n_cols; ++ii)
{
if(arrayops::is_finite(colptr(ii), local_n_rows) == false) { return true; }
}
}
return false;
@@ -1590,64 +1644,66 @@ subview<eT>::extract(Mat<eT>& out, const subview<eT>& in)
// NOTE: we're assuming that the matrix has already been set to the correct size and there is no aliasing;
// size setting and alias checking is done by either the Mat constructor or operator=()
const uword n_rows = in.n_rows; // number of rows in the subview
const uword n_cols = in.n_cols; // number of columns in the subview
arma_debug_print(arma_str::format("out.n_rows: %u; out.n_cols: %u; in.m.n_rows: %u; in.m.n_cols: %u") % out.n_rows % out.n_cols % in.m.n_rows % in.m.n_cols );
const uword n_rows = in.n_rows;
const uword n_cols = in.n_cols;
if(in.is_vec())
if( (n_rows == 0) || (n_cols == 0) ) { return; }
if(n_cols == 1)
{
if(n_cols == 1) // a column vector
{
arma_debug_print("subview::extract(): copying col");
// in.colptr(0) is the first column of the subview, taking into account any row offset
arrayops::copy( out.memptr(), in.colptr(0), n_rows );
}
else
if(n_rows == 1) // a row vector
{
arma_debug_print("subview::extract(): copying row)");
eT* out_mem = out.memptr();
const uword X_n_rows = in.m.n_rows;
const eT* Xptr = &(in.m.at(in.aux_row1,in.aux_col1));
uword j;
for(j=1; j < n_cols; j+=2)
{
const eT tmp1 = (*Xptr); Xptr += X_n_rows;
const eT tmp2 = (*Xptr); Xptr += X_n_rows;
(*out_mem) = tmp1; out_mem++;
(*out_mem) = tmp2; out_mem++;
}
if((j-1) < n_cols)
{
(*out_mem) = (*Xptr);
}
}
}
else // general submatrix
{
arma_debug_print("subview::extract(): general submatrix");
arma_debug_print("subview::extract(): copying col");
if( (in.aux_row1 == 0) && (n_rows == in.m.n_rows) )
// in.colptr(0) is the first column of the subview, taking into account any row offset
arrayops::copy( out.memptr(), in.colptr(0), n_rows );
return;
}
if(n_rows == 1)
{
arma_debug_print("subview::extract(): copying row");
eT* out_mem = out.memptr();
const uword X_n_rows = in.m.n_rows;
const eT* Xptr = &(in.m.at(in.aux_row1,in.aux_col1));
uword j;
for(j=1; j < n_cols; j+=2)
{
arrayops::copy( out.memptr(), in.colptr(0), in.n_elem );
const eT tmp1 = (*Xptr); Xptr += X_n_rows;
const eT tmp2 = (*Xptr); Xptr += X_n_rows;
(*out_mem) = tmp1; out_mem++;
(*out_mem) = tmp2; out_mem++;
}
else
if((j-1) < n_cols)
{
for(uword col=0; col < n_cols; ++col)
{
arrayops::copy( out.colptr(col), in.colptr(col), n_rows );
}
(*out_mem) = (*Xptr);
}
return;
}
if( (in.aux_row1 == 0) && (n_rows == in.m.n_rows) )
{
arma_debug_print("subview::extract(): contiguous submatrix");
arrayops::copy( out.memptr(), in.colptr(0), in.n_elem );
return;
}
arma_debug_print("subview::extract(): general submatrix");
for(uword col=0; col < n_cols; ++col)
{
arrayops::copy( out.colptr(col), in.colptr(col), n_rows );
}
}
@@ -1666,6 +1722,8 @@ subview<eT>::plus_inplace(Mat<eT>& out, const subview<eT>& in)
const uword n_rows = in.n_rows;
const uword n_cols = in.n_cols;
if( (n_rows == 0) || (n_cols == 0) ) { return; }
if(n_rows == 1)
{
eT* out_mem = out.memptr();
@@ -1714,6 +1772,8 @@ subview<eT>::minus_inplace(Mat<eT>& out, const subview<eT>& in)
const uword n_rows = in.n_rows;
const uword n_cols = in.n_cols;
if( (n_rows == 0) || (n_cols == 0) ) { return; }
if(n_rows == 1)
{
eT* out_mem = out.memptr();
@@ -1762,6 +1822,8 @@ subview<eT>::schur_inplace(Mat<eT>& out, const subview<eT>& in)
const uword n_rows = in.n_rows;
const uword n_cols = in.n_cols;
if( (n_rows == 0) || (n_cols == 0) ) { return; }
if(n_rows == 1)
{
eT* out_mem = out.memptr();
@@ -1810,6 +1872,8 @@ subview<eT>::div_inplace(Mat<eT>& out, const subview<eT>& in)
const uword n_rows = in.n_rows;
const uword n_cols = in.n_cols;
if( (n_rows == 0) || (n_cols == 0) ) { return; }
if(n_rows == 1)
{
eT* out_mem = out.memptr();
@@ -2377,9 +2441,12 @@ subview<eT>::each_col(const std::function< void(Col<eT>&) >& F)
{
arma_debug_sigprint();
for(uword ii=0; ii < n_cols; ++ii)
const uword local_n_rows = n_rows;
const uword local_n_cols = n_cols;
for(uword ii=0; ii < local_n_cols; ++ii)
{
Col<eT> tmp(colptr(ii), n_rows, false, true);
Col<eT> tmp(colptr(ii), local_n_rows, false, true);
F(tmp);
}
}
@@ -2393,9 +2460,12 @@ subview<eT>::each_col(const std::function< void(const Col<eT>&) >& F) const
{
arma_debug_sigprint();
for(uword ii=0; ii < n_cols; ++ii)
const uword local_n_rows = n_rows;
const uword local_n_cols = n_cols;
for(uword ii=0; ii < local_n_cols; ++ii)
{
const Col<eT> tmp(colptr(ii), n_rows, false, true);
const Col<eT> tmp(colptr(ii), local_n_rows, false, true);
F(tmp);
}
}
@@ -2410,20 +2480,23 @@ subview<eT>::each_row(const std::function< void(Row<eT>&) >& F)
{
arma_debug_sigprint();
podarray<eT> array1(n_cols);
podarray<eT> array2(n_cols);
const uword local_n_rows = n_rows;
const uword local_n_cols = n_cols;
Row<eT> tmp1( array1.memptr(), n_cols, false, true );
Row<eT> tmp2( array2.memptr(), n_cols, false, true );
podarray<eT> array1(local_n_cols);
podarray<eT> array2(local_n_cols);
Row<eT> tmp1( array1.memptr(), local_n_cols, false, true );
Row<eT> tmp2( array2.memptr(), local_n_cols, false, true );
eT* tmp1_mem = tmp1.memptr();
eT* tmp2_mem = tmp2.memptr();
uword ii, jj;
for(ii=0, jj=1; jj < n_rows; ii+=2, jj+=2)
for(ii=0, jj=1; jj < local_n_rows; ii+=2, jj+=2)
{
for(uword col_id = 0; col_id < n_cols; ++col_id)
for(uword col_id = 0; col_id < local_n_cols; ++col_id)
{
const eT* col_mem = colptr(col_id);
@@ -2434,7 +2507,7 @@ subview<eT>::each_row(const std::function< void(Row<eT>&) >& F)
F(tmp1);
F(tmp2);
for(uword col_id = 0; col_id < n_cols; ++col_id)
for(uword col_id = 0; col_id < local_n_cols; ++col_id)
{
eT* col_mem = colptr(col_id);
@@ -2443,7 +2516,7 @@ subview<eT>::each_row(const std::function< void(Row<eT>&) >& F)
}
}
if(ii < n_rows)
if(ii < local_n_rows)
{
tmp1 = (*this).row(ii);
@@ -2462,20 +2535,23 @@ subview<eT>::each_row(const std::function< void(const Row<eT>&) >& F) const
{
arma_debug_sigprint();
podarray<eT> array1(n_cols);
podarray<eT> array2(n_cols);
const uword local_n_rows = n_rows;
const uword local_n_cols = n_cols;
Row<eT> tmp1( array1.memptr(), n_cols, false, true );
Row<eT> tmp2( array2.memptr(), n_cols, false, true );
podarray<eT> array1(local_n_cols);
podarray<eT> array2(local_n_cols);
Row<eT> tmp1( array1.memptr(), local_n_cols, false, true );
Row<eT> tmp2( array2.memptr(), local_n_cols, false, true );
eT* tmp1_mem = tmp1.memptr();
eT* tmp2_mem = tmp2.memptr();
uword ii, jj;
for(ii=0, jj=1; jj < n_rows; ii+=2, jj+=2)
for(ii=0, jj=1; jj < local_n_rows; ii+=2, jj+=2)
{
for(uword col_id = 0; col_id < n_cols; ++col_id)
for(uword col_id = 0; col_id < local_n_cols; ++col_id)
{
const eT* col_mem = colptr(col_id);
@@ -2487,7 +2563,7 @@ subview<eT>::each_row(const std::function< void(const Row<eT>&) >& F) const
F(tmp2);
}
if(ii < n_rows)
if(ii < local_n_rows)
{
tmp1 = (*this).row(ii);
@@ -3264,7 +3340,7 @@ template<typename eT>
inline
subview_col<eT>::subview_col(const Mat<eT>& in_m, const uword in_col)
: subview<eT>(in_m, 0, in_col, in_m.n_rows, 1)
, colmem(subview<eT>::colptr(0))
, colmem(subview<eT>::startptr())
{
arma_debug_sigprint();
}
@@ -3275,7 +3351,7 @@ template<typename eT>
inline
subview_col<eT>::subview_col(const Mat<eT>& in_m, const uword in_col, const uword in_row1, const uword in_n_rows)
: subview<eT>(in_m, in_row1, in_col, in_n_rows, 1)
, colmem(subview<eT>::colptr(0))
, colmem(subview<eT>::startptr())
{
arma_debug_sigprint();
}
@@ -3455,6 +3531,18 @@ subview_col<eT>::as_row() const
template<typename eT>
inline
void
subview_col<eT>::replace(const eT old_val, const eT new_val)
{
arma_debug_sigprint();
arrayops::replace( access::rwp(colmem), subview<eT>::n_rows, old_val, new_val );
}
template<typename eT>
inline
void
@@ -3491,6 +3579,30 @@ subview_col<eT>::ones()
template<typename eT>
inline
void
subview_col<eT>::randu()
{
arma_debug_sigprint();
arma_rng::randu<eT>::fill( access::rwp(colmem), subview<eT>::n_rows );
}
template<typename eT>
inline
void
subview_col<eT>::randn()
{
arma_debug_sigprint();
arma_rng::randn<eT>::fill( access::rwp(colmem), subview<eT>::n_rows );
}
template<typename eT>
inline
bool
@@ -3505,6 +3617,22 @@ subview_col<eT>::is_finite() const
template<typename eT>
inline
bool
subview_col<eT>::is_zero(const typename get_pod_type<eT>::result tol) const
{
arma_debug_sigprint();
typedef typename get_pod_type<eT>::result T;
arma_conform_check( ((tol >= T(0)) == false), "is_zero(): parameter 'tol' must be >= 0" );
return arrayops::is_zero(colmem, subview<eT>::n_rows, tol);
}
template<typename eT>
inline
bool
@@ -4268,7 +4396,7 @@ template<typename eT>
inline
subview_row<eT>::subview_row(const Mat<eT>& in_m, const uword in_row)
: subview<eT>(in_m, in_row, 0, 1, in_m.n_cols)
, rowmem(subview<eT>::colptr(0))
, rowmem(subview<eT>::startptr())
{
arma_debug_sigprint();
}
@@ -4279,7 +4407,7 @@ template<typename eT>
inline
subview_row<eT>::subview_row(const Mat<eT>& in_m, const uword in_row, const uword in_col1, const uword in_n_cols)
: subview<eT>(in_m, in_row, in_col1, 1, in_n_cols)
, rowmem(subview<eT>::colptr(0))
, rowmem(subview<eT>::startptr())
{
arma_debug_sigprint();
}
@@ -4486,6 +4614,40 @@ subview_row<eT>::as_col() const
template<typename eT>
inline
void
subview_row<eT>::replace(const eT old_val, const eT new_val)
{
arma_debug_sigprint();
eT* mem_ptr = access::rwp(rowmem);
const uword local_s_n_cols = subview<eT>::n_cols;
const uword local_m_n_rows = subview<eT>::m.n_rows;
if(arma_isnan(old_val))
{
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
eT& val = (*mem_ptr); mem_ptr += local_m_n_rows;
val = (arma_isnan(val)) ? new_val : val;
}
}
else
{
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
eT& val = (*mem_ptr); mem_ptr += local_m_n_rows;
val = (val == old_val) ? new_val : val;
}
}
}
template<typename eT>
inline
void
@@ -4530,6 +4692,58 @@ subview_row<eT>::ones()
template<typename eT>
inline
void
subview_row<eT>::randu()
{
arma_debug_sigprint();
const uword local_s_n_cols = subview<eT>::n_cols;
const uword local_m_n_rows = subview<eT>::m.n_rows;
podarray<eT> tmp(local_s_n_cols);
eT* tmp_mem = tmp.memptr();
arma_rng::randu<eT>::fill( tmp_mem, local_s_n_cols );
eT* mem_ptr = access::rwp(rowmem);
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
(*mem_ptr) = tmp_mem[ii]; mem_ptr += local_m_n_rows;
}
}
template<typename eT>
inline
void
subview_row<eT>::randn()
{
arma_debug_sigprint();
const uword local_s_n_cols = subview<eT>::n_cols;
const uword local_m_n_rows = subview<eT>::m.n_rows;
podarray<eT> tmp(local_s_n_cols);
eT* tmp_mem = tmp.memptr();
arma_rng::randn<eT>::fill( tmp_mem, local_s_n_cols );
eT* mem_ptr = access::rwp(rowmem);
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
(*mem_ptr) = tmp_mem[ii]; mem_ptr += local_m_n_rows;
}
}
template<typename eT>
inline
bool
@@ -4556,6 +4770,80 @@ subview_row<eT>::is_finite() const
template<typename eT>
inline
bool
subview_row<eT>::is_zero(const typename get_pod_type<eT>::result tol) const
{
arma_debug_sigprint();
typedef typename get_pod_type<eT>::result T;
arma_conform_check( ((tol >= T(0)) == false), "is_zero(): parameter 'tol' must be >= 0" );
const uword local_s_n_cols = subview<eT>::n_cols;
const uword local_m_n_rows = subview<eT>::m.n_rows;
if(local_s_n_cols == 0) { return false; }
const eT* mem_ptr = rowmem;
if(is_cx<eT>::yes)
{
if(tol == T(0))
{
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
const eT& val = (*mem_ptr); mem_ptr += local_m_n_rows;
const T val_real = access::tmp_real(val);
const T val_imag = access::tmp_imag(val);
if(eop_aux::arma_abs(val_real) != T(0)) { return false; }
if(eop_aux::arma_abs(val_imag) != T(0)) { return false; }
}
}
else
{
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
const eT& val = (*mem_ptr); mem_ptr += local_m_n_rows;
const T val_real = access::tmp_real(val);
const T val_imag = access::tmp_imag(val);
if( (eop_aux::arma_abs(val_real) <= tol) == false ) { return false; }
if( (eop_aux::arma_abs(val_imag) <= tol) == false ) { return false; }
}
}
}
else // not complex
{
if(tol == T(0))
{
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
const eT val = (*mem_ptr); mem_ptr += local_m_n_rows;
if(val != eT(0)) { return false; }
}
}
else
{
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
const eT val = (*mem_ptr); mem_ptr += local_m_n_rows;
if( (eop_aux::arma_abs(val) <= tol) == false ) { return false; }
}
}
}
return true;
}
template<typename eT>
inline
bool
+1 -1
View File
@@ -26,7 +26,7 @@
#else
#if UCHAR_MAX >= 0xff
typedef unsigned char u8;
typedef char s8;
typedef char s8; // kept for compatibility with earlier versions of Armadillo
#elif defined(UINT8_MAX)
typedef uint8_t u8;
typedef int8_t s8;
+27 -1
View File
@@ -38,6 +38,9 @@ struct unwrap_default
}
const Mat<eT> M;
template<typename eT2>
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
};
@@ -55,6 +58,9 @@ struct unwrap_fixed
}
const T1& M;
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&M) == void_ptr(&X)); }
};
@@ -94,6 +100,9 @@ struct unwrap< Mat<eT> >
}
const Mat<eT>& M;
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&M) == void_ptr(&X)); }
};
@@ -111,6 +120,9 @@ struct unwrap< Row<eT> >
}
const Row<eT>& M;
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&M) == void_ptr(&X)); }
};
@@ -128,6 +140,9 @@ struct unwrap< Col<eT> >
}
const Col<eT>& M;
template<typename eT2>
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&M) == void_ptr(&X)); }
};
@@ -145,6 +160,9 @@ struct unwrap< subview_col<eT> >
}
const Col<eT> M;
template<typename eT2>
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
};
@@ -162,6 +180,9 @@ struct unwrap< subview_cols<eT> >
}
const Mat<eT> M;
template<typename eT2>
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
};
@@ -179,6 +200,9 @@ struct unwrap< mtGlue<out_eT, T1, T2, glue_type> >
}
const Mat<out_eT> M;
template<typename eT2>
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
};
@@ -196,6 +220,9 @@ struct unwrap< mtOp<out_eT, T1, op_type> >
}
const Mat<out_eT> M;
template<typename eT2>
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
};
@@ -311,7 +338,6 @@ struct quasi_unwrap< Mat<eT> >
template<typename eT>
struct quasi_unwrap< Row<eT> >
{
inline
quasi_unwrap(const Row<eT>& A)
: M(A)