Compare commits

...
64 Commits
Author SHA1 Message Date
conrad 78717c2af5 patch bump 2026-07-03 16:04:35 +10:00
conrad 32cdd2fd27 backport fix for infinite recursion bug 2026-07-03 15:06:17 +10:00
conrad e3aebbe0f5 workaround for infinite recursion 2026-06-29 23:26:49 +10:00
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
65 changed files with 1122 additions and 511 deletions
+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)
+2 -2
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
---
+17 -151
View File
@@ -579,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>
@@ -895,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:
@@ -2239,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>
@@ -3955,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>
@@ -9647,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>
@@ -9773,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>
@@ -10747,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>
@@ -11147,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>
@@ -11161,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>
@@ -11188,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>
@@ -11203,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>
@@ -12091,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>
@@ -13235,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:
@@ -13616,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>
@@ -15011,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>
@@ -17932,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>
@@ -18658,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>
@@ -18860,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> -->
@@ -20732,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>
@@ -20833,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>
@@ -20862,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>
@@ -21970,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);
+3 -3
View File
@@ -4187,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);
+7 -7
View File
@@ -2544,7 +2544,7 @@ Mat<eT>::Mat(const subview_elem1<eT,T1>& X, const arma_vec_indicator&, const uhw
{
arma_debug_sigprint_this(this);
(*this).operator=(X);
subview_elem1<eT,T1>::extract_noalias(*this, X);
}
@@ -2563,7 +2563,7 @@ Mat<eT>::Mat(const subview_elem1<eT,T1>& X)
{
arma_debug_sigprint_this(this);
(*this).operator=(X);
subview_elem1<eT,T1>::extract_noalias(*this, X);
}
@@ -2672,7 +2672,7 @@ Mat<eT>::Mat(const subview_elem2<eT,T1,T2>& X, const arma_vec_indicator&, const
{
arma_debug_sigprint_this(this);
(*this).operator=(X);
subview_elem2<eT,T1,T2>::extract_noalias(*this, X);
}
@@ -2691,7 +2691,7 @@ Mat<eT>::Mat(const subview_elem2<eT,T1,T2>& X)
{
arma_debug_sigprint_this(this);
(*this).operator=(X);
subview_elem2<eT,T1,T2>::extract_noalias(*this, X);
}
@@ -7885,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);
+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); }
-2
View File
@@ -52,8 +52,6 @@ struct SpBase
{
arma_inline const derived& get_ref() const;
arma_inline bool is_alias(const SpMat<elem_type>& X) const;
arma_warn_unused inline const SpOp<derived,spop_htrans> t() const; //!< Hermitian transpose
arma_warn_unused inline const SpOp<derived,spop_htrans> ht() const; //!< Hermitian transpose
arma_warn_unused inline const SpOp<derived,spop_strans> st() const; //!< simple transpose
+4 -14
View File
@@ -31,16 +31,6 @@ SpBase<elem_type,derived>::get_ref() const
template<typename elem_type, typename derived>
arma_inline
bool
SpBase<elem_type,derived>::is_alias(const SpMat<elem_type>& X) const
{
return (*this).get_ref().is_alias(X);
}
template<typename elem_type, typename derived>
inline
const SpOp<derived, spop_htrans>
@@ -527,7 +517,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 +544,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 +554,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;
}
+2 -1
View File
@@ -35,7 +35,8 @@ struct SpGlue : public SpBase< typename T1::elem_type, SpGlue<T1, T2, spglue_typ
inline SpGlue(const T1& in_A, const T2& in_B, const elem_type in_aux);
inline ~SpGlue();
arma_inline bool is_alias(const SpMat<elem_type>& X) const;
template<typename eT2>
arma_inline bool is_alias(const SpMat<eT2>& X) const;
const T1& A; //!< first operand; must be derived from SpBase
const T2& B; //!< second operand; must be derived from SpBase
+2 -1
View File
@@ -54,9 +54,10 @@ SpGlue<T1,T2,spglue_type>::~SpGlue()
template<typename T1, typename T2, typename spglue_type>
template<typename eT2>
arma_inline
bool
SpGlue<T1,T2,spglue_type>::is_alias(const SpMat<typename T1::elem_type>& X) const
SpGlue<T1,T2,spglue_type>::is_alias(const SpMat<eT2>& X) const
{
return (A.is_alias(X) || B.is_alias(X));
}
+2 -1
View File
@@ -647,7 +647,8 @@ class SpMat : public SpBase< eT, SpMat<eT> >
template<typename eT2, typename T1, typename Functor> inline void init_xform_mt(const SpBase<eT2,T1>& x, const Functor& func);
//! don't use this unless you're writing internal Armadillo code
arma_inline bool is_alias(const SpMat<eT>& X) const;
template<typename eT2>
arma_inline bool is_alias(const SpMat<eT2>& X) const;
protected:
+20 -9
View File
@@ -3565,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);
@@ -3575,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 );
}
@@ -3611,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);
@@ -3621,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 );
}
@@ -4204,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; }
@@ -4389,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);
@@ -4466,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);
@@ -6007,11 +6015,14 @@ SpMat<eT>::init_xform_mt(const SpBase<eT2,T1>& A, const Functor& func)
template<typename eT>
template<typename eT2>
arma_inline
bool
SpMat<eT>::is_alias(const SpMat<eT>& X) const
SpMat<eT>::is_alias(const SpMat<eT2>& X) const
{
return (&X == this);
arma_debug_sigprint();
return (is_same_type<eT,eT2>::yes) && (void_ptr(this) == void_ptr(&X));
}
+2 -1
View File
@@ -36,7 +36,8 @@ struct SpOp : public SpBase< typename T1::elem_type, SpOp<T1, op_type> >
inline SpOp(const T1& in_m, const uword in_aux_uword_a, const uword in_aux_uword_b);
inline ~SpOp();
arma_inline bool is_alias(const SpMat<elem_type>& X) const;
template<typename eT2>
arma_inline bool is_alias(const SpMat<eT2>& X) const;
const T1& m; //!< the operand; must be derived from SpBase
elem_type aux; //!< auxiliary data, using the element type as used by T1
+2 -1
View File
@@ -64,9 +64,10 @@ SpOp<T1, op_type>::~SpOp()
template<typename T1, typename op_type>
template<typename eT2>
arma_inline
bool
SpOp<T1, op_type>::is_alias(const SpMat<typename T1::elem_type>& X) const
SpOp<T1, op_type>::is_alias(const SpMat<eT2>& X) const
{
return m.is_alias(X);
}
+2 -1
View File
@@ -321,7 +321,8 @@ class SpSubview : public SpBase< eT, SpSubview<eT> >
inline const_row_iterator end_row(const uword row_num) const;
//! don't use this unless you're writing internal Armadillo code
arma_inline bool is_alias(const SpMat<eT>& X) const;
template<typename eT2>
arma_inline bool is_alias(const SpMat<eT2>& X) const;
private:
@@ -87,6 +87,8 @@ class SpSubview_col_list : public SpBase< eT, SpSubview_col_list<eT,T1> >
inline static void schur_inplace(SpMat<eT>& out, const SpSubview_col_list& in);
inline static void div_inplace(SpMat<eT>& out, const SpSubview_col_list& in);
template<typename eT2>
arma_inline bool is_alias(const SpMat<eT2>& X) const;
friend class SpMat<eT>;
};
@@ -714,4 +714,15 @@ SpSubview_col_list<eT,T1>::div_inplace(SpMat<eT>& out, const SpSubview_col_list&
template<typename eT, typename T1>
template<typename eT2>
arma_inline
bool
SpSubview_col_list<eT,T1>::is_alias(const SpMat<eT2>& X) const
{
return m.is_alias(X);
}
//! @}
+5 -4
View File
@@ -946,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; }
@@ -1786,9 +1786,10 @@ SpSubview<eT>::end_row(const uword row_num) const
template<typename eT>
template<typename eT2>
arma_inline
bool
SpSubview<eT>::is_alias(const SpMat<eT>& X) const
SpSubview<eT>::is_alias(const SpMat<eT2>& X) const
{
return m.is_alias(X);
}
+1 -1
View File
@@ -23,7 +23,7 @@
#define ARMA_VERSION_MAJOR 15
#define ARMA_VERSION_MINOR 2
#define ARMA_VERSION_PATCH 4
#define ARMA_VERSION_PATCH 8
#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; }
}
}
+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;
}
+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;
+1 -1
View File
@@ -94,7 +94,7 @@ arma_inline
bool
mtSpOp<out_eT, T1, op_type>::is_alias(const SpMat<eT2>& X) const
{
return (void_ptr(&X) == void_ptr(&m));
return m.is_alias(X);
}
@@ -50,6 +50,9 @@ struct mtSpReduceOp : public SpBase< out_eT, mtSpReduceOp<out_eT, T1, op_type> >
inline mtSpReduceOp(const T1& in_m, const uword in_aux_uword_a, const uword in_aux_uword_b);
inline ~mtSpReduceOp();
template<typename eT2>
arma_inline bool is_alias(const SpMat<eT2>& X) const;
const T1& m; //!< the operand; must be derived from SpBase
uword aux_uword_a; //!< auxiliary data, uword format
uword aux_uword_b; //!< auxiliary data, uword format
@@ -52,4 +52,15 @@ mtSpReduceOp<out_eT, T1, op_type>::~mtSpReduceOp()
template<typename out_eT, typename T1, typename op_type>
template<typename eT2>
arma_inline
bool
mtSpReduceOp<out_eT, T1, op_type>::is_alias(const SpMat<eT2>& X) const
{
return m.is_alias(X);
}
//! @}
@@ -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;
}
+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())
+1 -1
View File
@@ -65,7 +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_rows != 0) && (A_n_cols != 0) )
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); }
+1 -1
View File
@@ -200,7 +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_rows != 0) && (A_n_cols != 0) )
if(A_n_cols != 0)
{
eT* outptr = out.memptr();
+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.
@@ -105,6 +105,9 @@ class spdiagview : public SpBase< eT, spdiagview<eT> >
inline static void extract(SpMat<eT>& out, const spdiagview& in);
inline static void extract( Mat<eT>& out, const spdiagview& in);
template<typename eT2>
arma_inline bool is_alias(const SpMat<eT2>& X) const;
friend class SpMat<eT>;
};
+12 -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);
@@ -1076,4 +1076,15 @@ spdiagview<eT>::randn()
template<typename eT>
template<typename eT2>
arma_inline
bool
spdiagview<eT>::is_alias(const SpMat<eT2>& X) const
{
return m.is_alias(X);
}
//! @}
+10
View File
@@ -395,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;
@@ -555,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;
+12 -9
View File
@@ -1226,12 +1226,12 @@ 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;
@@ -1395,18 +1395,21 @@ 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) )
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 slice = 0; slice < local_n_slices; ++slice)
for(uword col = 0; col < local_n_cols; ++col)
{
for(uword col = 0; col < local_n_cols; ++col)
{
if(arrayops::is_zero(slice_colptr(slice,col), local_n_rows, tol) == false) { return false; }
}
if(arrayops::is_zero(slice_colptr(slice,col), local_n_rows, tol) == false) { return false; }
}
}
@@ -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;
}
}
+256 -80
View File
@@ -979,34 +979,11 @@ subview<eT>::replace(const eT old_val, const eT new_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 == 0) { return; }
if(s_n_rows == 1)
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
{
@@ -1050,12 +1027,12 @@ 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;
@@ -1085,33 +1062,17 @@ subview<eT>::fill(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 == 0) { return; }
if(s_n_rows == 1)
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 );
}
}
}
@@ -1130,35 +1091,17 @@ subview<eT>::zeros()
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 == 0) { return; }
if(s_n_rows == 1)
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));
constexpr eT eT_zero = eT(0);
for(uword ii=0; ii < s_n_cols; ++ii)
{
(*Aptr) = eT_zero; Aptr += A_n_rows;
}
arrayops::fill_zeros( s.colptr(0), 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::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 );
}
arrayops::fill_zeros( s.colptr(ucol), s_n_rows );
}
}
}
@@ -1212,13 +1155,22 @@ subview<eT>::randu()
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
{
@@ -1254,13 +1206,22 @@ subview<eT>::randn()
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
{
@@ -1578,15 +1539,18 @@ 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;
if(local_n_rows != 0)
if( (local_n_rows == 0) || (local_n_cols == 0) ) { return false; }
for(uword ii=0; ii < local_n_cols; ++ii)
{
for(uword ii=0; ii<local_n_cols; ++ii)
{
if(arrayops::is_zero(colptr(ii), local_n_rows, tol) == false) { return false; }
}
if(arrayops::is_zero(colptr(ii), local_n_rows, tol) == false) { return false; }
}
return true;
@@ -3567,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
@@ -3603,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
@@ -3617,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
@@ -4598,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
@@ -4642,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
@@ -4668,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)