15 #ifndef BORNAGAIN_CORE_INTENSITY_LLDATA_H
16 #define BORNAGAIN_CORE_INTENSITY_LLDATA_H
31 LLData(
size_t rank,
const int* dimensions);
39 T& operator[](
size_t i);
40 const T& operator[](
size_t i)
const;
41 T& atCoordinate(
int* coordinate);
42 const T& atCoordinate(
int* coordinate)
const;
51 void setAll(
const T& value);
52 void scaleAll(
const T& factor);
55 size_t getTotalSize()
const;
56 inline size_t getRank()
const {
return m_rank; }
57 const int* getDimensions()
const {
return m_dims; }
58 T getTotalSum()
const;
61 void allocate(
size_t rank,
const int* dimensions);
63 bool checkDimensions(
size_t rank,
const int* dimensions)
const;
64 size_t convertCoordinate(
int* coordinate)
const;
66 T getZeroElement()
const;
84 template <
class T>
bool HaveSameDimensions(
const LLData<T>& left,
const LLData<T>& right);
87 inline LLData<T>::LLData(
size_t rank,
const int* dimensions) : m_rank(0), m_dims(0), m_data_array(0)
89 allocate(rank, dimensions);
94 allocate(right.getRank(), right.getDimensions());
95 for (
size_t i = 0; i < getTotalSize(); ++i) {
96 m_data_array[i] = right[i];
107 if (
this != &right) {
116 return m_data_array[i];
121 return m_data_array[i];
126 return m_data_array[convertCoordinate(coordinate)];
131 return m_data_array[convertCoordinate(coordinate)];
136 if (!HaveSameDimensions(*
this, right))
138 "Operation += on LLData requires both operands to have the same dimensions");
139 for (
size_t i = 0; i < getTotalSize(); ++i) {
140 m_data_array[i] += right[i];
147 if (!HaveSameDimensions(*
this, right))
149 "Operation -= on LLData requires both operands to have the same dimensions");
150 for (
size_t i = 0; i < getTotalSize(); ++i) {
151 m_data_array[i] -= right[i];
158 if (!HaveSameDimensions(*
this, right))
160 "Operation *= on LLData requires both operands to have the same dimensions");
161 for (
size_t i = 0; i < getTotalSize(); ++i) {
162 m_data_array[i] *= right[i];
169 if (!HaveSameDimensions(*
this, right))
171 "Operation /= on LLData requires both operands to have the same dimensions");
172 for (
size_t i = 0; i < getTotalSize(); ++i) {
174 if (std::abs(m_data_array[i] - right[i])
175 <= std::numeric_limits<double>::epsilon() * std::abs(right[i])) {
177 }
else if (std::abs(right[i]) <= std::numeric_limits<double>::min()) {
178 ratio = double(m_data_array[i]) / std::numeric_limits<double>::min();
180 ratio = double(m_data_array[i] / right[i]);
182 m_data_array[i] = (T)ratio;
189 std::fill(m_data_array, m_data_array + getTotalSize(), value);
194 std::transform(m_data_array, m_data_array + getTotalSize(), m_data_array,
195 [&factor](
const T& value) -> T {
return value * factor; });
200 int result = std::accumulate(m_dims, m_dims + m_rank, 1, std::multiplies<int>{});
201 return static_cast<size_t>(result);
206 return std::accumulate(m_data_array, m_data_array + getTotalSize(), getZeroElement());
212 if (!checkDimensions(rank, dimensions)) {
213 throw std::runtime_error(
"LLData<T>::allocate error: dimensions must be > 0");
217 m_dims =
new int[m_rank];
218 std::copy(dimensions, dimensions + rank, m_dims);
219 m_data_array =
new T[getTotalSize()];
221 m_data_array =
new T[1];
229 delete[] m_data_array;
231 m_data_array =
nullptr;
234 delete[] m_data_array;
240 return std::all_of(dimensions, dimensions + rank,
241 [](
const int& dim) ->
bool {
return dim > 0; });
248 for (
size_t i = m_rank; i > 0; --i) {
249 result += offset * coordinate[i - 1];
250 offset *= m_dims[i - 1];
259 std::swap(this->m_data_array, other.m_data_array);
271 (*p_result) += right;
278 (*p_result) -= right;
285 (*p_result) *= right;
296 template <
class T>
bool HaveSameDimensions(
const LLData<T>& left,
const LLData<T>& right)
298 if (left.getRank() != right.getRank())
300 const int* ldims = left.getDimensions();
301 const int* rdims = right.getDimensions();
302 for (
size_t i = 0; i < left.getRank(); ++i) {
303 if (ldims[i] != rdims[i])
Include to deal with Eigen alignment centrally.
Defines many exception classes in namespace Exceptionss.
void swap(OutputDataIterator< TValue, TContainer > &left, OutputDataIterator< TValue, TContainer > &right)
make Swappable
BasicVector3D< T > operator+(const BasicVector3D< T > &v)
Unary plus.
auto operator*(const BasicVector3D< T > &v, const U a)
Multiplication vector by scalar.
BasicVector3D< T > operator/(const BasicVector3D< T > &v, U a)
Division vector by scalar.
BasicVector3D< T > operator-(const BasicVector3D< T > &v)
Unary minus.
Template class to store data of any type in multi-dimensional space (low-level).