Compare commits

...
16 Commits
Author SHA1 Message Date
conrad c2b1eea864 patch bump 2025-11-20 00:09:55 +10:00
conrad 6eb9394e13 prevent bad line breaks 2025-11-17 23:33:52 +10:00
conrad 391a1df2e8 simplification 2025-11-17 23:30:08 +10:00
conrad 7b718b1ae9 sanitise n_threads 2025-11-12 10:43:09 +10:00
conrad bc18db7a51 use ordered clause 2025-11-09 23:42:09 +10:00
conrad 505339b6e5 rename variable 2025-11-09 22:24:17 +10:00
conrad f015fac562 set rng seed for each thread 2025-11-08 19:51:07 +10:00
conrad 502cbca4ba add internal links 2025-10-30 21:44:19 +10:00
conrad 5e5331acd4 cleanup layout 2025-10-30 20:49:25 +10:00
conrad 2dddc1367e add internal link 2025-10-30 20:45:41 +10:00
conrad 5ca720b31f simpler wording 2025-10-30 13:32:01 +10:00
conradsnicta f72922fa68 fix documentation typo 2025-10-30 00:00:52 +00:00
Ryan Curtin c18e7f0aff Fix documentation typo 2025-10-30 00:00:52 +00:00
conrad 0c40604508 patch bump 2025-10-28 12:23:57 +10:00
conrad f16c95c5c5 add internal link 2025-10-26 23:15:57 +10:00
conrad 65c42d01cd faster handling of submatrix rows 2025-10-26 20:07:38 +10:00
6 changed files with 459 additions and 182 deletions
+120 -125
View File
@@ -778,7 +778,7 @@ which is one of:
<ul>
<table>
<tbody>
<tr><td><code>fill::zeros</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 0 &nbsp; (default in Armadillo &gt;= 10.5)</td></tr>
<tr><td><code>fill::zeros</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 0</td></tr>
<tr><td><code>fill::ones</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 1</td></tr>
<tr><td><code>fill::eye</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set the elements on the main diagonal to 1 and off-diagonal elements to 0</td></tr>
<tr><td><code>fill::randu</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to random values from a uniform distribution in the [0,1] interval</td></tr>
@@ -790,13 +790,7 @@ which is one of:
</ul>
</li>
<br>
<li>
<b>Caveat:</b>
<ul>
<li>in Armadillo &gt;= 10.5, the default initialisation is <code>fill::zeros</code></li>
<li>in Armadillo &lt;= 10.4, the default initialisation is <code>fill::none</code></li>
</ul>
</li>
<li>Default element initialisation is <code>fill::zeros</code> (since Armadillo 10.5)</li>
<br>
<li>
For the <i>mat(string)</i> constructor, the format is elements separated by spaces, and rows denoted by semicolons;
@@ -1722,7 +1716,7 @@ which is one of:
<ul>
<table>
<tbody>
<tr><td><code>fill::zeros</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 0 &nbsp; (default in Armadillo &gt;= 10.5)</td></tr>
<tr><td><code>fill::zeros</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 0</td></tr>
<tr><td><code>fill::ones</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to 1</td></tr>
<tr><td><code>fill::randu</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to random values from a uniform distribution in the [0,1] interval</td></tr>
<tr><td><code>fill::randn</code></td><td>&nbsp;&mapsto;&nbsp;</td><td>set all elements to random values from a normal/Gaussian distribution with zero mean and unit variance</td></tr>
@@ -1733,13 +1727,7 @@ which is one of:
</ul>
</li>
<br>
<li>
<b>Caveat:</b>
<ul>
<li>in Armadillo &gt;= 10.5, the default initialisation is <code>fill::zeros</code></li>
<li>in Armadillo &lt;= 10.4, the default initialisation is <code>fill::none</code></li>
</ul>
</li>
<li>Default element initialisation is <code>fill::zeros</code> (since Armadillo 10.5)</li>
<br>
<li>
Each instance of <i>cube</i> automatically allocates and releases internal memory.
@@ -4299,7 +4287,7 @@ Similar to "broadcasting" in Matlab&thinsp;/&thinsp;Octave
</li>
<br>
<li>
Supported operations for forms 1 and 2:
Supported operations for forms&nbsp;1 and&nbsp;2:
<br>
<br>
<ul>
@@ -4314,7 +4302,7 @@ Supported operations for forms 1 and 2:
</li>
<br>
<li>
For form 2:
For form&nbsp;2:
<ul>
<li>the argument <i>vector_of_indices</i> contains a list of indices of the columns/rows to be used; it must evaluate to a vector of type <i><a href="#Col">uvec</a></i></li>
<li>arithmetic operations as per form 1 are supported</li>
@@ -4322,7 +4310,7 @@ For form 2:
</li>
<br>
<li>
For form 3:
For form&nbsp;3:
<ul>
<li>apply the given <i>lambda_function</i> to each column vector or row vector</li>
<li>the function must accept a reference to a <a href="#Col">Col</a> or <a href="#Row">Row</a> object with the same element type as the underlying matrix</li>
@@ -4395,7 +4383,7 @@ Similar to "broadcasting" in Matlab&thinsp;/&thinsp;Octave
</li>
<br>
<li>
Supported operations for form 1:
Supported operations for form&nbsp;1:
<br>
<br>
<ul>
@@ -4411,7 +4399,7 @@ Supported operations for form 1:
</li>
<br>
<li>
For form 2:
For form&nbsp;2:
<ul>
<li>the argument <i>vector_of_indices</i> contains a list of indices of the slices to be used; it must evaluate to a vector of type <i><a href="#Col">uvec</a></i></li>
<li>arithmetic operations as per form 1 are supported, except for <code><b>*</b></code> and <code><b>*=</b></code> (ie. matrix multiplication)</li>
@@ -4419,7 +4407,7 @@ For form 2:
</li>
<br>
<li>
For form 3:
For form&nbsp;3:
<ul>
<li>apply the given <i>lambda_function</i> to each slice</li>
<li>the function must accept a reference to a <a href="#Mat">Mat</a> object with the same element type as the underlying cube</li>
@@ -4427,7 +4415,7 @@ For form 3:
</li>
<br>
<li>
For form 4:
For form&nbsp;4:
<ul>
<li>apply the given <i>lambda_function</i> to each slice, as per form 3</li>
<li>the argument <i>use_mp</i> is a bool to enable the use of OpenMP for multi-threaded execution of <i>lambda_function</i> on multiple slices at the same time</li>
@@ -6822,6 +6810,7 @@ See also:
<li><a href="#has_nan">.has_nan()</a></li>
<li><a href="#find_finite_nonfinite">find_finite() / find_nonfinite()</a></li>
<li><a href="#find_nan_nonnan">find_nan() / find_nonnan()</a></li>
<li><a href="#omit_nan_nonfinite">omit_nan() / omit_nonfinite()</a></li>
<li><a href="#constants">constants (pi, nan, inf, ...)</a></li>
</ul>
</li>
@@ -6864,6 +6853,7 @@ See also:
<li><a href="#replace">.replace()</a></li>
<li><a href="#is_finite">.is_finite()</a>
<li><a href="#find_finite_nonfinite">find_finite() / find_nonfinite()</a></li>
<li><a href="#omit_nan_nonfinite">omit_nonfinite()</a></li>
<li><a href="#constants">constants (pi, nan, inf, ...)</a></li>
</ul>
</li>
@@ -6911,6 +6901,7 @@ See also:
<li><a href="#replace">.replace()</a></li>
<li><a href="#is_finite">.is_finite()</a>
<li><a href="#find_nan_nonnan">find_nan() / find_nonnan()</a></li>
<li><a href="#omit_nan_nonfinite">omit_nan()</a></li>
<li><a href="#constants">constants (pi, nan, inf, ...)</a></li>
</ul>
</li>
@@ -7129,58 +7120,58 @@ A.brief_print("A:");
<br>
<br>
<ul>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;"><b>auto_detect</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;"><b>auto_detect</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Used only by <i>.load()</i> only: attempt to automatically detect the file type as one of the formats described below;
<br>[&nbsp;default operation for <i>.load()</i>&nbsp;]<br><br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_binary</b><br></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_binary</b><br></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in machine dependent binary format, with a simple header to speed up loading.
The header indicates the type and size of matrix/cube.
<br>[&nbsp;default operation for <i>.save()</i>&nbsp;]
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in human readable text format, with a simple header to speed up loading.
The header indicates the type and size of matrix/cube.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>raw_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>raw_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in machine dependent raw binary format, without a header.
Matrices are loaded to have one column,
while cubes are loaded to have one slice with one column.
The <a href="#reshape_member">.reshape()</a> function can be used to alter the size of the loaded matrix/cube without losing data.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>raw_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>raw_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in raw ASCII format, without a header.
The numbers are separated by whitespace.
The number of columns must be the same in each row.
@@ -7189,26 +7180,26 @@ Data which was saved in Matlab/Octave using the <i>-ascii</i> option can be read
Complex numbers are stored in standard C++ notation, which is a tuple surrounded by brackets: eg. (1.23,4.56) indicates 1.24&thinsp;+&thinsp;4.56i.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>csv_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>csv_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in comma separated value (CSV) text format, <b>without</b> a header.
To save/load <b>with</b> a header, use the <b>csv_name(</b>filename,header<b>)</b> specification instead (more details below).
Handles complex numbers stored in the compound form of 1.24+4.56i.
Applicable to <i>Mat</i> and <i>SpMat</i>.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>coord_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>coord_ascii</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored as a text file in coordinate list format, without a header.
Only non-zero values are stored.
<br>
@@ -7219,39 +7210,39 @@ For real matrices, each line contains information in the following format:&nbsp;
<br><b>Caveat:</b> not supported by <i>auto_detect</i>.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>pgm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>pgm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Image data stored in Portable Gray Map (PGM) format.
Applicable to <i>Mat</i> only.
Saving <i>int</i>, <i>float</i> or <i>double</i> matrices is a lossy operation, as each element is copied and converted to an 8 bit representation.
As such the matrix should have values in the [0,255] interval, otherwise the resulting image may not display correctly.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>ppm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>ppm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Image data stored in Portable Pixel Map (PPM) format.
Applicable to <i>Cube</i> only.
Saving <i>int</i>, <i>float</i> or <i>double</i> matrices is a lossy operation, as each element is copied and converted to an 8 bit representation.
As such the cube/field should have values in the [0,255] interval, otherwise the resulting image may not display correctly.
<br>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>hdf5_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>hdf5_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
Numerical data stored in portable <a href="https://en.wikipedia.org/wiki/Hierarchical_Data_Format">HDF5</a> binary format.
<ul>
<li>
@@ -7267,10 +7258,10 @@ for loading, the order of operations is:
to explicitly control the dataset name, specify it via the <b>hdf5_name()</b> argument (more details below)
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</ul>
</li>
<br>
@@ -7387,6 +7378,7 @@ if(ok == false)
<li><a href="https://en.wikipedia.org/wiki/Hierarchical_Data_Format">HDF</a> in Wikipedia</li>
<li><a href="https://en.wikipedia.org/wiki/Comma-separated_values">CSV</a> in Wikipedia
<li><a href="#save_load_field">saving&thinsp;/&thinsp;loading fields</a></li>
<li><a href="#element_initialisation">element initialisation</a></li>
</ul>
</li>
<br>
@@ -7439,26 +7431,26 @@ Other than storing string fields as text files, the following file formats are s
<br>
<br>
<ul>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;"><b>auto_detect</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;"><b>auto_detect</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
<br>
<li>
<i>.load()</i>: attempt to automatically detect the field format type as one of the formats described below;
this is the default operation
</li>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>arma_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
<br>
<li>
objects are stored in machine dependent binary format
@@ -7469,13 +7461,13 @@ default type for fields of type <i>Mat</i>, <i>Col</i>, <i>Row</i> or <i>Cube</i
only applicable to fields of type <i>Mat</i>, <i>Col</i>, <i>Row</i> or <i>Cube</i>
</li>
<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>ppm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
</td>
</tr>
<tr>
<td style="vertical-align: top;"><b>ppm_binary</b></td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">
<br>
<li>
image data stored in Portable Pixmap Map (PPM) format
@@ -7494,11 +7486,10 @@ it is assumed that the red, green and blue components are stored in the first, s
saving <i>int</i>, <i>float</i> or <i>double</i> matrices is a lossy operation,
as each matrix element is copied and converted to an 8 bit representation
</li>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</ul>
</li>
<br>
@@ -11092,6 +11083,9 @@ See also:
<li><a href="#nonzeros">nonzeros()</a>
<li><a href="#vectorise">vectorise()</a>
<li><a href="#for_each">.for_each()</a>
<li><a href="#is_finite">.is_finite()</a>
<li><a href="#has_inf">.has_inf()</a>
<li><a href="#has_nan">.has_nan()</a>
</ul>
</li>
<br>
@@ -18490,7 +18484,7 @@ See also:
<b>RNG seed setting</b>
<ul>
<li>
There are two functions to change the seed used by the random number generator (RNG):
Functions to change the seed used by the random number generator (RNG):
<br>
<br>
<table style="text-align: left;" border="0" cellpadding="2" cellspacing="2">
@@ -18559,6 +18553,7 @@ See also:
<li>
<a href="#randu">randu()</a>,
<a href="#randn">randn()</a>,
<a href="#rande">rande()</a>,
<a href="#randg">randg()</a>,
<a href="#randi">randi()</a>,
<a href="#sprandu_sprandn">sprandu()</a>,
@@ -18780,7 +18775,7 @@ rudimentary <i>fp16</i> hardware support is present on x86-64 CPUs with the F16C
<br>
</ul>
<li>
If no compiler or hardware support is detected, support for <i>fp16</i> element types is <b>not</b> automatically enableds
If no compiler or hardware support is detected, support for <i>fp16</i> element types is <b>not</b> automatically enabled
</li>
<br>
<li>
+73 -12
View File
@@ -26,6 +26,9 @@
#undef ARMA_USE_THREAD_LOCAL
#define ARMA_USE_THREAD_LOCAL
#undef ARMA_USE_THREAD_UNIQUE_RNG_SEED
#define ARMA_USE_THREAD_UNIQUE_RNG_SEED
#if (defined(ARMA_RNG_ALT) || defined(ARMA_DONT_USE_CXX11_RNG))
#undef ARMA_USE_CXX11_RNG
#endif
@@ -34,6 +37,10 @@
#undef ARMA_USE_THREAD_LOCAL
#endif
#if defined(ARMA_DONT_USE_THREAD_UNIQUE_RNG_SEED)
#undef ARMA_USE_THREAD_UNIQUE_RNG_SEED
#endif
// NOTE: ARMA_WARMUP_PRODUCER enables a workaround
// NOTE: for thread_local issue on macOS 11 and/or AppleClang 12.0
@@ -129,24 +136,42 @@ arma_rng::get_producer()
{
#if defined(ARMA_USE_THREAD_LOCAL)
// use a thread-safe RNG, with each thread having its own unique starting seed
// thread-safe RNG
static std::atomic<std::size_t> mt19937_64_producer_counter(0);
static thread_local std::mt19937_64 mt19937_64_producer( std::mt19937_64::default_seed + mt19937_64_producer_counter++ );
arma_rng::warmup_producer(mt19937_64_producer);
#if defined(ARMA_USE_THREAD_UNIQUE_RNG_SEED)
// each thread has unique starting seed
#if defined(ARMA_USE_OPENMP)
static thread_local std::mt19937_64 mt19937_64_producer( std::mt19937_64::default_seed + arma_rng::seed_type(omp_get_thread_num()) );
#else
static std::atomic<std::size_t> mt19937_64_producer_counter(0);
static thread_local std::mt19937_64 mt19937_64_producer( std::mt19937_64::default_seed + mt19937_64_producer_counter++ );
#endif
#else
// each thread has the same starting seed
static thread_local std::mt19937_64 mt19937_64_producer( std::mt19937_64::default_seed );
#endif
#else
// use a plain RNG in case we don't have thread_local
// plain RNG in case we don't have thread_local
static std::mt19937_64 mt19937_64_producer( std::mt19937_64::default_seed );
arma_rng::warmup_producer(mt19937_64_producer);
#endif
arma_rng::warmup_producer(mt19937_64_producer);
return mt19937_64_producer;
}
@@ -226,9 +251,45 @@ arma_rng::set_seed(const arma_rng::seed_type val)
}
#elif defined(ARMA_USE_CXX11_RNG)
{
arma_rng::lock_producer();
arma_rng::get_producer().seed(val);
arma_rng::unlock_producer();
#if defined(ARMA_USE_OPENMP) && defined(ARMA_USE_THREAD_LOCAL)
{
arma_rng::lock_producer();
#if defined(ARMA_USE_THREAD_UNIQUE_RNG_SEED)
constexpr bool thread_unique_rng_seed = true;
#else
constexpr bool thread_unique_rng_seed = false;
#endif
// if we're already in a parallel region, assume the user is setting the seed for each thread
if( (thread_unique_rng_seed == false) || bool(omp_in_parallel()) )
{
arma_rng::get_producer().seed(val);
}
else
{
const int n_threads = int( (std::max)( int(1), int(omp_get_max_threads()) ) );
#pragma omp parallel for ordered schedule(static) num_threads(n_threads)
for(int t=0; t < n_threads; ++t)
{
#pragma omp ordered
{
arma_rng::get_producer().seed(val + arma_rng::seed_type(omp_get_thread_num()));
}
}
}
arma_rng::unlock_producer();
}
#else
{
arma_rng::lock_producer();
arma_rng::get_producer().seed(val);
arma_rng::unlock_producer();
}
#endif
}
#else
{
+1 -1
View File
@@ -23,7 +23,7 @@
#define ARMA_VERSION_MAJOR 15
#define ARMA_VERSION_MINOR 2
#define ARMA_VERSION_PATCH 0
#define ARMA_VERSION_PATCH 2
#define ARMA_VERSION_NAME "Medium Roast Deluxe"
+28 -5
View File
@@ -602,7 +602,30 @@ op_accu_mat::apply(const subview<eT>& X)
const uword X_n_rows = X.n_rows;
const uword X_n_cols = X.n_cols;
if(X_n_rows == 1) { return op_accu_mat::apply( static_cast< const subview_row<eT>& >(X) ); }
if(X_n_rows == 1)
{
const uword X_m_n_rows = X.m.n_rows;
const eT* mem_ptr = X.colptr(0);
eT val1 = eT(0);
eT val2 = eT(0);
uword j;
for(j=1; j < X_n_cols; j+=2)
{
val1 += (*mem_ptr); mem_ptr += X_m_n_rows;
val2 += (*mem_ptr); mem_ptr += X_m_n_rows;
}
if((j-1) < X_n_cols)
{
val1 += (*mem_ptr);
}
return val1 + val2;
}
if(X_n_cols == 1) { return arrayops::accumulate( X.colptr(0), X_n_rows ); }
@@ -640,7 +663,7 @@ op_accu_mat::apply(const subview_row<eT>& X)
const uword X_m_n_rows = X.m.n_rows;
const uword X_n_cols = X.n_cols;
const eT* row_mem = &(X.m.at(X.aux_row1,X.aux_col1));
const eT* mem_ptr = X.rowmem;
eT val1 = eT(0);
eT val2 = eT(0);
@@ -649,13 +672,13 @@ op_accu_mat::apply(const subview_row<eT>& X)
for(j=1; j < X_n_cols; j+=2)
{
val1 += (*row_mem); row_mem += X_m_n_rows;
val2 += (*row_mem); row_mem += X_m_n_rows;
val1 += (*mem_ptr); mem_ptr += X_m_n_rows;
val2 += (*mem_ptr); mem_ptr += X_m_n_rows;
}
if((j-1) < X_n_cols)
{
val1 += (*row_mem);
val1 += (*mem_ptr);
}
return val1 + val2;
+17 -1
View File
@@ -85,7 +85,7 @@ class subview : public Base< eT, subview<eT> >
template<typename T1> inline void operator-= (const SpBase<eT,T1>& x);
template<typename T1> inline void operator%= (const SpBase<eT,T1>& x);
template<typename T1> inline void operator/= (const SpBase<eT,T1>& x);
template<typename T1, typename gen_type>
inline typename enable_if2< is_same_type<typename T1::elem_type, eT>::value, void>::result operator=(const Gen<T1,gen_type>& x);
@@ -396,6 +396,11 @@ class subview_col : public subview<eT>
inline void zeros();
inline void ones();
arma_warn_unused inline bool is_finite() const;
arma_warn_unused inline bool has_inf() const;
arma_warn_unused inline bool has_nan() const;
arma_inline eT at_alt (const uword i) const;
arma_inline eT& operator[](const uword i);
@@ -528,6 +533,8 @@ class subview_row : public subview<eT>
static constexpr bool is_col = false;
static constexpr bool is_xvec = false;
const eT* rowmem;
inline void operator= (const subview<eT>& x);
inline void operator= (const subview_row& x);
inline void operator= (const eT val);
@@ -545,6 +552,15 @@ class subview_row : public subview<eT>
arma_warn_unused arma_inline const Op<subview_row<eT>,op_strans> as_col() const;
inline void fill(const eT val);
inline void zeros();
inline void ones();
arma_warn_unused inline bool is_finite() const;
arma_warn_unused inline bool has_inf() const;
arma_warn_unused inline bool has_nan() const;
inline eT at_alt (const uword i) const;
inline eT& operator[](const uword i);
+220 -38
View File
@@ -1079,16 +1079,9 @@ subview<eT>::fill(const eT val)
eT* Aptr = &(A.at(s.aux_row1,s.aux_col1));
uword jj;
for(jj=1; jj < s_n_cols; jj+=2)
for(uword ii=0; ii < s_n_cols; ++ii)
{
(*Aptr) = val; Aptr += A_n_rows;
(*Aptr) = val; Aptr += A_n_rows;
}
if((jj-1) < s_n_cols)
{
(*Aptr) = val;
}
}
else
@@ -3380,7 +3373,7 @@ subview_col<eT>::operator=(const Base<eT,T1>& expr)
if(is_Mat<T1>::value)
{
const unwrap<T1> U(expr.get_ref());
const unwrap<T1> U(expr.get_ref()); // deliberately not using quasi_unwrap
arma_conform_assert_same_size(subview<eT>::n_rows, uword(1), U.M.n_rows, U.M.n_cols, "copy into submatrix");
@@ -3498,6 +3491,48 @@ subview_col<eT>::ones()
template<typename eT>
inline
bool
subview_col<eT>::is_finite() const
{
arma_debug_sigprint();
if(arma_config::fast_math_warn) { arma_warn(1, "is_finite(): detection of non-finite values is not reliable in fast math mode"); }
return arrayops::is_finite(colmem, subview<eT>::n_rows);
}
template<typename eT>
inline
bool
subview_col<eT>::has_inf() const
{
arma_debug_sigprint();
if(arma_config::fast_math_warn) { arma_warn(1, "has_inf(): detection of non-finite values is not reliable in fast math mode"); }
return arrayops::has_inf(colmem, subview<eT>::n_rows);
}
template<typename eT>
inline
bool
subview_col<eT>::has_nan() const
{
arma_debug_sigprint();
if(arma_config::fast_math_warn) { arma_warn(1, "has_nan(): detection of non-finite values is not reliable in fast math mode"); }
return arrayops::has_nan(colmem, subview<eT>::n_rows);
}
template<typename eT>
arma_inline
eT
@@ -4233,6 +4268,7 @@ template<typename eT>
inline
subview_row<eT>::subview_row(const Mat<eT>& in_m, const uword in_row)
: subview<eT>(in_m, in_row, 0, 1, in_m.n_cols)
, rowmem(subview<eT>::colptr(0))
{
arma_debug_sigprint();
}
@@ -4243,6 +4279,7 @@ template<typename eT>
inline
subview_row<eT>::subview_row(const Mat<eT>& in_m, const uword in_row, const uword in_col1, const uword in_n_cols)
: subview<eT>(in_m, in_row, in_col1, 1, in_n_cols)
, rowmem(subview<eT>::colptr(0))
{
arma_debug_sigprint();
}
@@ -4253,6 +4290,7 @@ template<typename eT>
inline
subview_row<eT>::subview_row(const subview_row<eT>& in)
: subview<eT>(in) // interprets 'subview_row' as 'subview'
, rowmem(in.rowmem)
{
arma_debug_sigprint();
}
@@ -4263,8 +4301,11 @@ template<typename eT>
inline
subview_row<eT>::subview_row(subview_row<eT>&& in)
: subview<eT>(std::move(in)) // interprets 'subview_row' as 'subview'
, rowmem(in.rowmem)
{
arma_debug_sigprint();
access::rw(in.rowmem) = nullptr;
}
@@ -4300,7 +4341,12 @@ subview_row<eT>::operator=(const eT val)
{
arma_debug_sigprint();
subview<eT>::operator=(val); // interprets 'subview_row' as 'subview'
if(subview<eT>::n_elem != 1)
{
arma_conform_assert_same_size(subview<eT>::n_rows, subview<eT>::n_cols, 1, 1, "copy into submatrix");
}
access::rw( rowmem[0] ) = val;
}
@@ -4335,7 +4381,39 @@ subview_row<eT>::operator=(const Base<eT,T1>& X)
{
arma_debug_sigprint();
subview<eT>::operator=(X);
if(is_Mat<T1>::value)
{
const unwrap<T1> U(X.get_ref()); // deliberately not using quasi_unwrap
arma_conform_assert_same_size(uword(1), subview<eT>::n_cols, U.M.n_rows, U.M.n_cols, "copy into submatrix");
const eT* UM_mem = U.M.memptr();
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;
uword j;
for(j=1; j < local_s_n_cols; j+=2)
{
const eT val_i = (*UM_mem); UM_mem++;
const eT val_j = (*UM_mem); UM_mem++;
(*mem_ptr) = val_i; mem_ptr += local_m_n_rows;
(*mem_ptr) = val_j; mem_ptr += local_m_n_rows;
}
if((j-1) < local_s_n_cols)
{
(*mem_ptr) = (*UM_mem);
}
}
else
{
subview<eT>::operator=(X);
}
}
@@ -4408,14 +4486,134 @@ subview_row<eT>::as_col() const
template<typename eT>
inline
void
subview_row<eT>::fill(const eT 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;
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
(*mem_ptr) = val; mem_ptr += local_m_n_rows;
}
}
template<typename eT>
inline
void
subview_row<eT>::zeros()
{
arma_debug_sigprint();
(*this).fill(eT(0));
}
template<typename eT>
inline
void
subview_row<eT>::ones()
{
arma_debug_sigprint();
(*this).fill(eT(1));
}
template<typename eT>
inline
bool
subview_row<eT>::is_finite() const
{
arma_debug_sigprint();
if(arma_config::fast_math_warn) { arma_warn(1, "is_finite(): detection of non-finite values is not reliable in fast math mode"); }
const eT* mem_ptr = rowmem;
const uword local_s_n_cols = subview<eT>::n_cols;
const uword local_m_n_rows = subview<eT>::m.n_rows;
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
const eT val = (*mem_ptr); mem_ptr += local_m_n_rows;
if(arma_isnonfinite(val)) { return false; }
}
return true;
}
template<typename eT>
inline
bool
subview_row<eT>::has_inf() const
{
arma_debug_sigprint();
if(arma_config::fast_math_warn) { arma_warn(1, "has_inf(): detection of non-finite values is not reliable in fast math mode"); }
const eT* mem_ptr = rowmem;
const uword local_s_n_cols = subview<eT>::n_cols;
const uword local_m_n_rows = subview<eT>::m.n_rows;
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
const eT val = (*mem_ptr); mem_ptr += local_m_n_rows;
if(arma_isinf(val)) { return true; }
}
return false;
}
template<typename eT>
inline
bool
subview_row<eT>::has_nan() const
{
arma_debug_sigprint();
if(arma_config::fast_math_warn) { arma_warn(1, "has_nan(): detection of non-finite values is not reliable in fast math mode"); }
const eT* mem_ptr = rowmem;
const uword local_s_n_cols = subview<eT>::n_cols;
const uword local_m_n_rows = subview<eT>::m.n_rows;
for(uword ii=0; ii < local_s_n_cols; ++ii)
{
const eT val = (*mem_ptr); mem_ptr += local_m_n_rows;
if(arma_isnan(val)) { return true; }
}
return false;
}
template<typename eT>
inline
eT
subview_row<eT>::at_alt(const uword ii) const
{
const uword index = (ii + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
return subview<eT>::m.mem[index];
return rowmem[ii * subview<eT>::m.n_rows];
}
@@ -4425,9 +4623,7 @@ inline
eT&
subview_row<eT>::operator[](const uword ii)
{
const uword index = (ii + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
return access::rw( rowmem[ii * subview<eT>::m.n_rows] );
}
@@ -4437,9 +4633,7 @@ inline
eT
subview_row<eT>::operator[](const uword ii) const
{
const uword index = (ii + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
return subview<eT>::m.mem[index];
return rowmem[ii * subview<eT>::m.n_rows];
}
@@ -4450,10 +4644,8 @@ eT&
subview_row<eT>::operator()(const uword ii)
{
arma_conform_check_bounds( (ii >= subview<eT>::n_elem), "subview::operator(): index out of bounds" );
const uword index = (ii + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
return access::rw( rowmem[ii * subview<eT>::m.n_rows] );
}
@@ -4465,9 +4657,7 @@ subview_row<eT>::operator()(const uword ii) const
{
arma_conform_check_bounds( (ii >= subview<eT>::n_elem), "subview::operator(): index out of bounds" );
const uword index = (ii + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
return subview<eT>::m.mem[index];
return rowmem[ii * subview<eT>::m.n_rows];
}
@@ -4479,9 +4669,7 @@ subview_row<eT>::operator()(const uword in_row, const uword in_col)
{
arma_conform_check_bounds( ((in_row > 0) || (in_col >= subview<eT>::n_cols)), "subview::operator(): index out of bounds" );
const uword index = (in_col + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
return access::rw( rowmem[in_col * subview<eT>::m.n_rows] );
}
@@ -4493,9 +4681,7 @@ subview_row<eT>::operator()(const uword in_row, const uword in_col) const
{
arma_conform_check_bounds( ((in_row > 0) || (in_col >= subview<eT>::n_cols)), "subview::operator(): index out of bounds" );
const uword index = (in_col + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
return subview<eT>::m.mem[index];
return rowmem[in_col * subview<eT>::m.n_rows];
}
@@ -4505,9 +4691,7 @@ inline
eT&
subview_row<eT>::at(const uword, const uword in_col)
{
const uword index = (in_col + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
return access::rw( rowmem[in_col * subview<eT>::m.n_rows] );
}
@@ -4517,9 +4701,7 @@ inline
eT
subview_row<eT>::at(const uword, const uword in_col) const
{
const uword index = (in_col + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
return subview<eT>::m.mem[index];
return rowmem[in_col * subview<eT>::m.n_rows];
}