ACF $AcfVersion:0$
TMultidimensionalPolynomial.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR GPL-3.0-or-later OR LicenseRef-ACF-Commercial
2#pragma once
3
4
5// ACF includes
6#include <istd/TArray.h>
7#include <imath/TVector.h>
9#include <imath/CVarMatrix.h>
11
12
13namespace imath
14{
15
16
22template <int Dimensions, class Element = double>
24 virtual public imath::TIMathFunction<TVector<Dimensions>, Element>,
25 virtual public iser::ISerializable
26{
27public:
31
32#if _MSC_VER >= 1900
34 using ResultType = typename BaseClass::ResultType;
35#endif
36
38 explicit TMultidimensionalPolynomial(const Coefficients& coefficients);
39
40 const Coefficients& GetCoefficients() const;
41 void SetCoefficients(const Coefficients& coefficients);
42
43 bool ApproximateCoefficientsFromFulcrums(const CoeffGridSize& coeffGridSize, const ArgumentType* arguments, const ResultType* destValues, int count);
44
45 // reimplemented (imath::TIMathFunction)
46 virtual bool GetValueAt(const ArgumentType& argument, ResultType& result) const override;
47 virtual ResultType GetValueAt(const ArgumentType& argument) const override;
48
49 // reimplemented (iser::ISerializable)
50 virtual bool Serialize(iser::IArchive& archive) override;
51
52 // static public methods
56 static double GetBaseFunctionValue(const ArgumentType& argument, const istd::TIndex<Dimensions>& coeffIndex);
57
58protected:
68 const ArgumentType& argument,
69 int dimension,
70 typename istd::TIndex<Dimensions>& index,
71 ResultType& result) const;
72
73private:
74 Coefficients m_coefficients;
75};
76
77
78// public methods
79
80template <int Dimensions, class Element>
84
85
86template <int Dimensions, class Element>
88: m_coefficients(coefficients)
89{
90}
91
92
93template <int Dimensions, class Element>
98
99
100template <int Dimensions, class Element>
102{
103 m_coefficients = coefficients;
104}
105
106
107template <int Dimensions, class Element>
109 const CoeffGridSize& coeffGridSize,
110 const ArgumentType* arguments,
111 const ResultType* destValues,
112 int count)
113{
114 if (count < coeffGridSize.GetProductVolume()){
115 return false;
116 }
117
118 m_coefficients.SetSizes(coeffGridSize);
119
120 if (coeffGridSize.IsSizeEmpty()){
121 return true;
122 }
123
124 imath::CVarMatrix valueMatrix(istd::CIndex2d(coeffGridSize.GetProductVolume(), count));
125 imath::CVarMatrix destValueVector(istd::CIndex2d(1, count));
126
127 for (int matrixRow = 0; matrixRow < count; ++matrixRow){
128 const ArgumentType& argument = arguments[matrixRow];
129 double measValue = double(destValues[matrixRow]);
130
131 int matrixCol = 0;
132 CoeffGridSize coeffIndex = CoeffGridSize::GetZero();
133 do{
134 double baseValue = GetBaseFunctionValue(argument, coeffIndex);
135
136 valueMatrix.SetAt(istd::CIndex2d(matrixCol++, matrixRow), baseValue);
137 } while (coeffIndex.Increase(coeffGridSize));
138
139 destValueVector.SetAt(istd::CIndex2d(0, matrixRow), measValue);
140 }
141
142 imath::CVarMatrix resultMatrix;
143 if (!valueMatrix.GetSolvedLSP(destValueVector, resultMatrix)){
144 return false;
145 }
146 Q_ASSERT(resultMatrix.GetSizes() == istd::CIndex2d(1, coeffGridSize.GetProductVolume()));
147
148 m_coefficients.SetSizes(coeffGridSize);
149
150 int resultRow = 0;
151 CoeffGridSize coeffIndex = CoeffGridSize::GetZero();
152 do{
153 m_coefficients.SetAt(coeffIndex, resultMatrix.GetAt(istd::CIndex2d(0, resultRow++)));
154 } while (coeffIndex.Increase(coeffGridSize));
155
156 return true;
157}
158
159
160// reimplemented (imath::TIMathFunction)
161
162template <int Dimensions, class Element>
164{
166
167 return true;
168}
169
170
171template <int Dimensions, class Element>
173{
174 typename BaseClass::ResultType retVal;
175
177 CumulateRecursiveValueAt(argument, Dimensions - 1, index, retVal);
178
179 return retVal;
180}
181
182
183template <>
185{
186 double partArgument = argument[0];
187 int dimensionSize = m_coefficients.GetSize(0);
188
189 ResultType result = 0;
190
191 istd::TIndex<1> index;
192 int& indexElement = index[0];
193 for (indexElement = dimensionSize - 1; indexElement >= 0; --indexElement){
194 result = result * partArgument + m_coefficients.GetAt(index);
195 }
196
197 return result;
198}
199
200
201template <>
203{
204 double partArgument1 = argument[0];
205 double partArgument2 = argument[1];
206
207 int dimensionSize1 = m_coefficients.GetSize(0);
208 int dimensionSize2 = m_coefficients.GetSize(1);
209
210 ResultType result = 0;
211
212 istd::TIndex<2> index;
213 int& indexElement1 = index[0];
214 int& indexElement2 = index[1];
215
216 if (dimensionSize1 == 1){
217 indexElement1 = 0;
218 for (indexElement2 = dimensionSize2 - 1; indexElement2 >= 0; --indexElement2){
219 result = result * partArgument2 + m_coefficients.GetAt(index);
220 }
221 }
222 else{
223 for (indexElement2 = dimensionSize2 - 1; indexElement2 >= 0; --indexElement2){
224 indexElement1 = dimensionSize1 - 1;
225 ResultType partResult = m_coefficients.GetAt(index);
226
227 for (indexElement1 = dimensionSize1 - 2; indexElement1 >= 0; --indexElement1){
228 partResult = partResult * partArgument1 + m_coefficients.GetAt(index);
229 }
230
231 result = result * partArgument2 + partResult;
232 }
233 }
234
235 return result;
236}
237
238
239template <>
241{
242 double partArgument1 = argument[0];
243 double partArgument2 = argument[1];
244 double partArgument3 = argument[2];
245
246 int dimensionSize1 = m_coefficients.GetSize(0);
247 int dimensionSize2 = m_coefficients.GetSize(1);
248 int dimensionSize3 = m_coefficients.GetSize(2);
249
250 ResultType result = 0;
251
252 istd::TIndex<3> index;
253 int& indexElement1 = index[0];
254 int& indexElement2 = index[1];
255 int& indexElement3 = index[2];
256
257 if (dimensionSize1 == 1){
258 indexElement1 = 0;
259
260 for (indexElement3 = dimensionSize3 - 1; indexElement3 >= 0; --indexElement3){
261 ResultType partResult = 0;
262 for (indexElement2 = dimensionSize2 - 1; indexElement2 >= 0; --indexElement2){
263 partResult = partResult * partArgument2 + m_coefficients.GetAt(index);
264 }
265 result = result * partArgument3 + partResult;
266 }
267 }
268 else{
269 for (indexElement3 = dimensionSize3 - 1; indexElement3 >= 0; --indexElement3){
270 ResultType partResult2 = 0;
271
272 for (indexElement2 = dimensionSize2 - 1; indexElement2 >= 0; --indexElement2){
273 indexElement1 = dimensionSize1 - 1;
274 ResultType partResult = m_coefficients.GetAt(index);
275
276 for (indexElement1 = dimensionSize1 - 2; indexElement1 >= 0; --indexElement1){
277 partResult = partResult * partArgument1 + m_coefficients.GetAt(index);
278 }
279
280 partResult2 = partResult2 * partArgument2 + partResult;
281 }
282 result = result * partArgument3 + partResult2;
283 }
284 }
285
286 return result;
287}
288
289
290// reimplemented (iser::ISerializable)
291
292template <int Dimensions, class Element>
294{
295 static const iser::CArchiveTag dimensionsTag("Dimensions", "Description of coefficient grid", iser::CArchiveTag::TT_GROUP);
296 static const iser::CArchiveTag coefficientsTag("Coefficients", "List of coefficients", iser::CArchiveTag::TT_GROUP);
297
298 bool retVal = true;
299
300 bool isStoring = archive.IsStoring();
301
302 istd::CChangeNotifier notifier(isStoring? NULL: this);
303
304 CoeffGridSize gridSize = m_coefficients.GetSizes();
305
306 retVal = retVal && archive.BeginTag(dimensionsTag);
307
308 for (int dimensionIndex = 0; dimensionIndex < Dimensions; ++dimensionIndex){
309 retVal = retVal && archive.Process(gridSize[dimensionIndex]);
310 }
311
312 retVal = retVal && archive.EndTag(dimensionsTag);
313
314 if (!retVal){
315 return false;
316 }
317
318 if (!isStoring){
319 m_coefficients.SetSizes(gridSize);
320 }
321
322 retVal = retVal && archive.BeginTag(coefficientsTag);
323
324 for ( typename Coefficients::Iterator iter = m_coefficients.Begin();
325 iter != m_coefficients.End();
326 ++iter){
327 Element& coeff = *iter;
328
329 retVal = retVal && archive.Process(coeff);
330 }
331
332 retVal = retVal && archive.EndTag(coefficientsTag);
333
334 return retVal;
335}
336
337
338// static public methods
339
340template <int Dimensions, class Element>
342{
343 Element retVal = 1;
344
345 for (int dimension = 0; dimension < Dimensions; ++dimension){
346 retVal *= std::pow(argument.GetElement(dimension), coeffIndex.GetAt(dimension));
347 }
348
349 return retVal;
350}
351
352
353// protected methods
354
355template <int Dimensions, class Element>
357 const ArgumentType& argument,
358 int dimension,
359 typename istd::TIndex<Dimensions>& index,
360 ResultType& result) const
361{
362 Q_ASSERT(dimension < Dimensions);
363 Q_ASSERT(dimension >= 0);
364
365 int& indexElement = index[dimension];
366 int dimensionSize = m_coefficients.GetSize(dimension);
367
368 double partArgument = argument[dimension];
369
370 result = 0;
371
372 if (dimension <= 0){
373 for (indexElement = dimensionSize - 1; indexElement >= 0; --indexElement){
374 result = result * partArgument + m_coefficients.GetAt(index);
375 }
376 }
377 else{
378 for (indexElement = dimensionSize - 1; indexElement >= 0; --indexElement){
379 ResultType partResult;
380
381 CumulateRecursiveValueAt(argument, dimension - 1, index, partResult);
382
383 result = result * partArgument + partResult;
384 }
385 }
386}
387
388
389} // namespace imath
390
391
Implementation of variable-size mathematical matrix with double precision elements.
Definition CVarMatrix.h:109
bool GetSolvedLSP(const CVarMatrix &vector, CVarMatrix &result, double minHhNorm=I_BIG_EPSILON) const
Solve 'Least Square Problem'.
Template interface for any mathematical function.
Multidimensional polynomial function.
static double GetBaseFunctionValue(const ArgumentType &argument, const istd::TIndex< Dimensions > &coeffIndex)
Get value of base function for single coefficient.
void SetCoefficients(const Coefficients &coefficients)
istd::TArray< Element, Dimensions > Coefficients
imath::TIMathFunction< TVector< Dimensions >, Element > BaseClass
virtual bool Serialize(iser::IArchive &archive) override
Load or store state of this object as a archive stream.
virtual bool GetValueAt(const ArgumentType &argument, ResultType &result) const override
Get function value for specified argument value.
void CumulateRecursiveValueAt(const ArgumentType &argument, int dimension, typename istd::TIndex< Dimensions > &index, ResultType &result) const
Cumulate interpolated value or derivative at specified recursion level.
bool ApproximateCoefficientsFromFulcrums(const CoeffGridSize &coeffGridSize, const ArgumentType *arguments, const ResultType *destValues, int count)
Process tag used to group data in archive stream.
Definition CArchiveTag.h:22
@ TT_GROUP
Normal tag used for grouping of tags or processed elements.
Definition CArchiveTag.h:37
Represents an input/output persistence archive for object serialization.
Definition IArchive.h:164
virtual bool Process(bool &value)=0
Processes (reads or writes) a boolean value.
virtual bool EndTag(const CArchiveTag &tag)=0
Ends a tagged section in the archive.
virtual bool IsStoring() const =0
Checks if this archive is in storing (writing) or loading (reading) mode.
virtual bool BeginTag(const CArchiveTag &tag)=0
Begins a tagged section in the archive.
Common class for all classes which objects can be archived or restored from archive.
Help class which provides the automatic update mechanism of the model.
Index implementation for addressing elements in 2D-space.
Definition CIndex2d.h:21
Multidimensional array with fixed number of dimensions.
Definition TArray.h:24
bool SetSizes(const SizesType &sizes)
Set list of all sizes.
Definition TArray.h:351
const Element & GetAt(const IndexType &index) const
Get element stored at specified index.
Definition TArray.h:227
void SetAt(const IndexType &index, const Element &value)
Set element at specified index.
Definition TArray.h:251
const SizesType & GetSizes() const
Get list of all sizes.
Definition TArray.h:210
Multidimensional index used to addressing fixed-size array.
Definition TIndex.h:18
int GetAt(int index) const
Get element stored at specified index.
Definition TIndex.h:269
bool Increase(const TIndex &boundaries)
Increase this index inside the boundaries.
Definition TIndex.h:472
Iterator Begin() const
Get begin value of element access iterator.
Definition TIndex.h:313
int GetProductVolume() const
Get total number of elements if this index is treated as size.
Definition TIndex.h:521
bool IsSizeEmpty() const
Check if this index interpreted as size is empty.
Definition TIndex.h:242
#define NULL
Definition istd.h:74
Package with mathematical functions and algebraical primitives.