Antares Simulator
Power System Simulator
Loading...
Searching...
No Matches
matrix.hxx
1/*
2** Copyright 2007-2024, RTE (https://www.rte-france.com)
3** See AUTHORS.txt
4** SPDX-License-Identifier: MPL-2.0
5** This file is part of Antares-Simulator,
6** Adequacy and Performance assessment for interconnected energy networks.
7**
8** Antares_Simulator is free software: you can redistribute it and/or modify
9** it under the terms of the Mozilla Public Licence 2.0 as published by
10** the Mozilla Foundation, either version 2 of the License, or
11** (at your option) any later version.
12**
13** Antares_Simulator is distributed in the hope that it will be useful,
14** but WITHOUT ANY WARRANTY; without even the implied warranty of
15** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16** Mozilla Public Licence 2.0 for more details.
17**
18** You should have received a copy of the Mozilla Public Licence 2.0
19** along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
20*/
21#ifndef __ANTARES_LIBS_ARRAY_MATRIX_HXX__
22#define __ANTARES_LIBS_ARRAY_MATRIX_HXX__
23
24#include <cmath>
25#include <cstdlib>
26#include <utility>
27
28#include <yuni/yuni.h>
29#include <yuni/core/string.h>
30
31#include <antares/io/statistics.h>
32#include <antares/logs/logs.h>
33
34#include "matrix-to-buffer.h"
35
36#define ANTARES_MATRIX_CSV_COMMA "\t;,"
37#define ANTARES_MATRIX_CSV_SEPARATORS "\t\r\n;,"
38
39namespace Antares
40{
41namespace // anonymous
42{
43template<class T>
44class MatrixData final
45{
46public:
47 inline static void Init(T& data)
48 {
49 data = T();
50 }
51
52 template<class U>
53 inline static void Copy(T& data, const U& value)
54 {
55 data = static_cast<T>(value);
56 }
57
58 inline static void Copy(T&, const AnyString&)
59 {
60 // to avoid gcc warnings
61 // must never be called
62 logs.error() << "internal error: matrix data conversion";
63 }
64};
65
66template<uint ChunkSizeT, bool ExpandableT>
67class MatrixData<Yuni::CString<ChunkSizeT, ExpandableT>> final
68{
69public:
70 using StringT = Yuni::CString<ChunkSizeT, ExpandableT>;
71
72public:
73 inline static void Init(StringT& data)
74 {
75 data.clear();
76 }
77
78 template<class U>
79 inline static void Copy(StringT& data, const U& value)
80 {
81 // we must avoid stupid static cast (stupid in this case)
82 data = value;
83 }
84};
85
86template<class ReadWriteType>
87class MatrixStringConverter final
88{
89public:
90 enum
91 {
92 direct = 0
93 };
94
95public:
96 inline static bool Do(const AnyString& str, ReadWriteType& out)
97 {
98 return str.to(out);
99 }
101
102template<>
103class MatrixStringConverter<double> final
105public:
106 enum
107 {
108 direct = 0
109 };
110
111public:
112 inline static bool Do(const AnyString& str, double& out)
113 {
114 char* pend;
115 out = ::strtod(str.c_str(), &pend);
116 return (NULL != pend and '\0' == *pend);
117 }
118};
119
120template<>
121class MatrixStringConverter<float> final
123public:
124 enum
125 {
126 direct = 0
127 };
128
129public:
130 inline static bool Do(const AnyString& str, float& out)
132 char* pend;
133 out = static_cast<float>(::strtod(str.c_str(), &pend));
134 return (NULL != pend and '\0' == *pend);
135 }
136};
137
138template<uint ChunkSizeT, bool ExpandableT>
139class MatrixStringConverter<Yuni::CString<ChunkSizeT, ExpandableT>> final
140{
141public:
142 enum
143 {
144 direct = 1,
145 };
146
147 using StringT = Yuni::CString<ChunkSizeT, ExpandableT>;
148
149public:
150 inline static bool Do(const AnyString& str, StringT& out)
151 {
152 out.assign(str);
153 return true;
154 }
155};
156
157template<unsigned A, bool B>
158Yuni::CString<A, B> trunc(Yuni::CString<A, B>& str)
159{
160 return str;
161}
162
163template<class T>
164static T trunc(T& in)
165{
166 return static_cast<T>(std::trunc(in));
167}
168
169template<class T, class P>
170class MatrixRound final
171{
172public:
173 static T Value(P value)
174 {
175 return static_cast<T>(trunc(value));
176 }
177};
178
179template<class T>
180class MatrixRound<T, double> final
181{
182public:
183 static T Value(double value)
184 {
185 return static_cast<T>(value);
186 }
187};
188
189template<class T>
190class MatrixRound<T, float> final
191{
192public:
193 static T Value(float value)
194 {
195 return static_cast<T>(value);
196 }
198
199} // anonymous namespace
200
201template<class T, class ReadWriteT>
203 width(0),
204 height(0),
205 entry(nullptr),
206 jit(nullptr)
207{
208}
209
210template<class T, class ReadWriteT>
212 width(w),
213 height(h),
214 jit(nullptr)
215{
216 if (0 == width or 0 == height)
217 {
218 entry = nullptr;
219 }
220 else
221 {
222 entry = new typename Antares::Memory::Stored<T>::Type[w + 1];
223 entry[w] = nullptr;
224
225 for (uint i = 0; i != w; ++i)
226 {
227 Antares::Memory::Allocate<T>(entry[i], h);
228 }
229 }
230}
231
232template<class T, class ReadWriteT>
234 width(rhs.width),
235 height(rhs.height),
236 jit(nullptr)
237{
238 if (0 == width or 0 == height)
239 {
240 entry = nullptr;
241 width = 0;
242 height = 0;
243 }
244 else
245 {
246 entry = new typename Antares::Memory::Stored<T>::Type[width + 1];
247 entry[width] = nullptr;
248
249 for (uint i = 0; i != rhs.width; ++i)
250 {
251 Antares::Memory::Allocate<T>(entry[i], height);
252 memcpy(entry[i], rhs.entry[i], sizeof(T) * height);
253 }
254 }
255}
257template<class T, class ReadWriteT>
259{
260 // use Matrix::operator=(Matrix&& rhs)
261 *this = std::move(rhs);
262}
263
264template<class T, class ReadWriteT>
265template<class U, class V>
267 width(0),
268 height(0),
269 entry(nullptr),
270 jit(nullptr)
271{
272 copyFrom(rhs);
274
275template<class T, class ReadWriteT>
277{
278 assert((JIT::enabled or (jit == NULL))
279 and "Internal variable jit is set but JIT is not globally enabled (overflow?)");
280 delete jit;
281
282 if (entry)
283 {
284 for (uint i = 0; i != width; ++i)
286 Antares::Memory::Release(entry[i]);
287 }
288 delete[] entry;
289 }
291
292template<class T, class ReadWriteT>
294{
295 for (uint i = 0; i != width; ++i)
297 ColumnType& column = entry[i];
298 (void)::memset((void*)column, 0, sizeof(T) * height);
299 }
300}
301
302template<class T, class ReadWriteT>
304{
305 if (width > 1)
306 {
307 ColumnType& first = entry[0];
308
309 // add the values of each timeseries to the first one
310 for (uint i = 1; i != width; ++i)
311 {
312 ColumnType& column = entry[i];
313 for (uint j = 0; j != height; ++j)
315 first[j] += column[j];
316 }
317 }
318
319 // average
320 double coeff = 1. / width;
321 if (roundValues)
322 {
323 for (uint j = 0; j != height; ++j)
325 const double d = first[j] * coeff;
326 first[j] = std::round(d);
327 }
328 }
329 else
330 {
331 for (uint j = 0; j != height; ++j)
332 {
333 first[j] *= coeff;
334 }
335 }
336
337 // Release all timeseries no longer needed
338 for (uint i = 1; i != width; ++i)
339 {
340 Antares::Memory::Release(entry[i]);
341 }
342 // reset the width to 1
343 width = 1;
344 }
345}
347template<class T, class ReadWriteT>
349{
350 for (uint i = 0; i != width; ++i)
351 {
352 ColumnType& column = entry[i];
354 for (uint j = 0; j != height; ++j)
355 {
356 column[j] = v;
357 }
359}
360
361template<class T, class ReadWriteT>
363{
364 for (uint i = 0; i != width; ++i)
365 {
366 ColumnType& column = entry[i];
367
368 (void)::memset((void*)column, 0, sizeof(T) * height);
369
370 column[i] = T(1);
372}
373
374template<class T, class ReadWriteT>
377 JIT::Invalidate(jit);
378 return (reload) ? loadAllJITData() : true;
379}
380
381template<class T, class ReadWriteT>
382inline void Matrix<T, ReadWriteT>::reset(uint w, uint h, bool fixedSize)
383{
384 resize(w, h, fixedSize);
385 zero();
386}
387
388template<class T, class ReadWriteT>
389bool Matrix<T, ReadWriteT>::internalLoadJITData(const AnyString& filename,
390 uint minWidth,
391 uint maxHeight,
392 uint options)
393{
394 // To avoid undefined behavior when filename is jit->sourceFilename
395 // we have to make a copy first.
396 jit = JIT::Reset(jit, YString(filename));
397
399 clear();
400 jit->minWidth = minWidth;
401 jit->maxHeight = maxHeight;
402 jit->options = options;
403 return true;
404}
406template<class T, class ReadWriteT>
407inline bool Matrix<T, ReadWriteT>::loadFromCSVFile(const AnyString& filename)
408{
409 return loadFromCSVFile(filename,
410 1,
411 0,
412 optImmediate | optNoWarnIfEmpty | optNeverFails | optQuiet);
413}
414
415template<class T, class ReadWriteT>
416inline bool Matrix<T, ReadWriteT>::loadFromCSVFile(const AnyString& filename,
417 uint minWidth,
418 uint maxHeight,
419 BufferType* buffer)
420{
421 return loadFromCSVFile(filename, minWidth, maxHeight, optNone, buffer);
422}
423
424template<class T, class ReadWriteT>
425bool Matrix<T, ReadWriteT>::loadFromCSVFile(const AnyString& filename,
426 uint minWidth,
427 uint maxHeight,
428 uint options,
429 BufferType* buffer)
430{
431 assert(not filename.empty() and "Matrix<>:: loadFromCSVFile: empty filename");
432 // As the loading might be expensive, especially when dealing with
433 // numerous matrices, we may want to delay this loading (a `lazy` mode)
434 if (JIT::enabled and not(options & optImmediate))
436 return internalLoadJITData(filename, minWidth, maxHeight, options);
437 }
438 else
439 {
440 // Reading data from file
441 return internalLoadCSVFile(filename, minWidth, maxHeight, options, buffer);
442 }
443}
444
445template<class T, class ReadWriteT>
446bool Matrix<T, ReadWriteT>::saveToCSVFile(const AnyString& filename,
447 uint precision,
448 bool print_dimensions,
449 bool saveEvenIfAllZero) const
450{
451 PredicateIdentity predicate;
452 return internalSaveCSVFile(filename, precision, print_dimensions, predicate, saveEvenIfAllZero);
453}
454
455template<class T, class ReadWriteT>
456template<class PredicateT>
457bool Matrix<T, ReadWriteT>::saveToCSVFile(const AnyString& filename,
458 uint precision,
459 bool print_dimensions,
460 PredicateT& predicate,
461 bool saveEvenIfAllZero) const
462{
463 return internalSaveCSVFile(filename, precision, print_dimensions, predicate, saveEvenIfAllZero);
464}
465
466template<class T, class ReadWriteT>
467template<class U>
468void Matrix<T, ReadWriteT>::pasteToColumn(uint x, const U* data)
469{
470 assert(x < width and "Invalid column index (bigger than `this->width`)");
471 ColumnType& column = entry[x];
472
473 // if the two types are strictly equal, we can perform some major
474 // optimisations
475 if (Yuni::Static::Type::StrictlyEqual<T, U>::Yes)
476 {
477 (void)::memcpy(column, data, sizeof(T) * height);
478 }
479 else
480 {
481 // ...otherwise we have to copy each item by hand in any cases
482 for (uint y = 0; y != height; ++y)
483 {
484 column[y] = (T)data[y];
485 }
486 }
487
488 markAsModified();
489}
490
491template<class T, class ReadWriteT>
492void Matrix<T, ReadWriteT>::fillColumn(uint x, const T& value)
493{
494 assert(x < width and "Invalid column index (bigger than `this->width`)");
495 ColumnType& column = entry[x];
496
497 for (uint y = 0; y != height; ++y)
498 {
499 column[y] = value;
500 }
501
502 markAsModified();
503}
504
505template<class T, class ReadWriteT>
507{
508 assert(x < width and "Invalid column index (bigger than `this->width`)");
509 ColumnType& column = entry[x];
510
511 (void)::memset((void*)column, 0, sizeof(T) * height);
512
513 markAsModified();
514}
515
516template<class T, class ReadWriteT>
518{
519 if (jit)
520 {
521 jit->markAsModified();
522 }
523}
524
525template<class T, class ReadWriteT>
527{
528 return (!width) or (!height);
529}
530
531template<class T, class ReadWriteT>
533{
534 if (entry)
535 {
536 for (uint i = 0; i != width; ++i)
537 {
538 Antares::Memory::Release(entry[i]);
539 }
540 delete[] entry;
541 entry = nullptr;
542 }
543 width = 0;
544 height = 0;
545}
546
547template<class T, class ReadWriteT>
549{
550 clear();
551 markAsModified();
552}
553
554template<class T, class ReadWriteT>
555void Matrix<T, ReadWriteT>::resize(uint w, uint h, bool fixedSize)
556{
557 // Asserts
558 // This limit is correlated with the maximal amount of years
559 // See the routine GeneralData::fixBadValues() if some changes are needed
560 assert(w <= 50000 and "The new width seems a bit excessive");
561 assert(h <= 50000 and "The new height seems a bit excessive");
562
563 // Checking if the matrix really needs to be resized
564 if (w != width or h != height)
565 {
566 if (!w or !h)
567 {
568 clear();
569 }
570 else
571 {
572 if (entry)
573 {
574 for (uint i = 0; i != width; ++i)
575 {
576 Antares::Memory::Release(entry[i]);
577 }
578 delete[] entry;
579 }
580 if (!w and !h)
581 {
582 entry = nullptr;
583 width = 0;
584 height = 0;
585 }
586 else
587 {
588 // Assigning the new size
589 width = w;
590 height = h;
591
592 // Allocating the entry for the matrix
593 entry = new typename Antares::Memory::Stored<T>::Type[width + 1];
594 entry[width] = nullptr;
595
596 for (uint i = 0; i != w; ++i)
597 {
598 Antares::Memory::Allocate<T>(entry[i], height);
599 }
600 }
601 }
602 }
603
604 // JIT Update
605 if (JIT::enabled and not jit and fixedSize)
606 {
607 jit = JIT::Reset(jit);
608 }
609
610 if (jit and w != 0 and h != 0)
611 {
612 jit->minWidth = w;
613 jit->maxHeight = h;
614 if (fixedSize)
615 {
616 jit->options = jit->options | optFixedSize;
617 }
618 }
619 markAsModified();
620}
621
622namespace // anonymous
623{
624static inline bool DetectEncoding(const AnyString& filename, const AnyString& data, size_t& offset)
625{
626 if (data.size() > 1)
627 {
628 // UTF-16 Big endian
629 if ((unsigned char)data[0] == 0xFE and ((unsigned char)data[1]) == 0xFF)
630 {
631 if (data.size() > 3 and !data[2] and !data[3])
632 {
633 logs.error() << '`' << filename
634 << "`: UTF-32 Little Endian encoding detected. ASCII/UTF-8 required.";
635 }
636 else
637 {
638 logs.error() << '`' << filename
639 << "`: UTF-16 Big Endian encoding detected. ASCII/UTF-8 required.";
640 }
641 return false;
642 }
643 // UTF-16 Little endian
644 if ((unsigned char)data[0] == 0xFF and ((unsigned char)data[1]) == 0xFE)
645 {
646 logs.error() << '`' << filename
647 << "`: UTF-16 Little Endian encoding detected. ASCII/UTF-8 required.";
648 return false;
649 }
650 // UTF-8 Little endian
651 if ((unsigned char)data[0] == 0xEF and ((unsigned char)data[1]) == 0xBB and data.size() > 2
652 and ((unsigned char)data[2]) == 0xBF)
653 {
654 // Slipping the byte-order mark
655 offset = 3;
656 }
657 if (data.size() > 3)
658 {
659 if (!data[0] and !data[1] and ((unsigned char)data[2]) == 0xFE
660 and ((unsigned char)data[3]) == 0xFF)
661 {
662 logs.error() << '`' << filename
663 << "`: UTF-32 Big Endian encoding detected. ASCII/UTF-8 required.";
664 return false;
665 }
666 }
667 }
668 return true;
669}
670
671} // anonymous namespace
672
673template<class T, class ReadWriteT>
674bool Matrix<T, ReadWriteT>::loadFromBuffer(const AnyString& filename,
675 BufferType& data,
676 uint minWidth,
677 uint maxHeight,
678 const int fixedSize,
679 uint options)
680{
681 using namespace Yuni;
682
683#ifndef NDEBUG
684 logs.debug() << " :: loading `" << filename << "`";
685#endif
686
687 // Detecting BOM
688 // Antares currently only accepts ASCII and/or UTF-8 encodings.
689 size_t bom = 0;
690 if (not DetectEncoding(filename, data, bom))
691 {
692 // gp : dead code - can never be reached
693 reset((minWidth > 0 ? minWidth : 1), maxHeight);
694 return false;
695 }
696
697 uint offset = (uint)bom;
698 uint x = 0;
699
700 // Properly resizing the matrix
701 // Directly resizing the matrix when its size is well-known
702 if (fixedSize)
703 {
704 reset(minWidth, maxHeight, true);
705 }
706 else
707 {
708 // Autodetection of the number of lines
709 if (!maxHeight)
710 {
711 assert(not data.empty());
712 maxHeight = data.countChar('\n');
713 if (data.last() == '\n')
714 {
715 --maxHeight;
716 }
717 else
718 {
719 ++maxHeight;
720 }
721 }
722 // gp : dead code - can never be reached
723 // The first occurence of the carriage return
724 YString::Size max = data.find('\n');
725 if (max == BufferType::npos)
726 {
727 logs.error() << filename << ": At least one line-return must be available";
728 reset(minWidth, maxHeight);
729 return false;
730 }
731 offset = max + 1;
732 // remove all final trailing whitespaces
733 if (max > 0)
734 {
735 do
736 {
737 char c = data[max - 1];
738 if (c == '\r' or c == '\t' or c == ' ')
739 {
740 if (!(--max))
741 {
742 break;
743 }
744 }
745 else
746 {
747 break;
748 }
749 } while (true);
750 }
751
752 if (max > 7 /* ex: size:0x0 */ and data.startsWith("size:"))
753 {
754 CString<64, false> buffer;
755 buffer.assign(data.c_str(), max);
756 int x, y;
757#ifdef YUNI_OS_MSVC
758 sscanf_s(buffer.c_str(), "size:%dx%d", &x, &y);
759#else
760 sscanf(buffer.c_str(), "size:%dx%d", &x, &y);
761#endif
762 if (x < 1)
763 {
764 if (!(options & optQuiet))
765 {
766 logs.warning() << '`' << filename << "`: Invalid header";
767 }
768 x = 1;
769 }
770 if (y < 1)
771 {
772 if (!(options & optQuiet))
773 {
774 logs.warning() << '`' << filename << "`: Invalid header";
775 }
776 y = maxHeight;
777 }
778 maxHeight = y;
779 resize((uint)x, (uint)y);
780 }
781 else
782 {
783 offset = 0;
784 x = ((max > 0) ? 1 : 0);
785
786 if (max > 0)
787 {
788 while ((offset = (uint)data.find_first_of(ANTARES_MATRIX_CSV_COMMA, offset)) < max)
789 {
790 ++offset;
791 ++x;
792 }
793 }
794 resize(((x < minWidth) ? minWidth : x), maxHeight);
795#ifndef NDEBUG
796// logs.debug() << " :: (" << width << 'x' << height << ')';
797#endif
798 if (!x)
799 {
800 if (not(options & optQuiet) and not(options & optNoWarnIfEmpty))
801 {
802 logs.warning() << "`" << filename << "`: Invalid format: The file seems empty";
803 }
804 zero();
805 return false;
806 }
807
808 offset = (uint)bom;
809 }
810 }
811
812 uint y = 0;
813 uint pos;
814 int errorCount = 6;
815 char separator = '\0';
816 AnyString converter;
817 ReadWriteType cellValue;
818 bool result = true;
819
820 while (y < maxHeight and offset < (uint)data.size())
821 {
822 // Starting the reading of the begining of the line
823 x = 0;
824 pos = offset;
825 uint lineOffset = (uint)offset;
826
827 while ((offset = data.find_first_of(ANTARES_MATRIX_CSV_SEPARATORS, offset))
828 != BufferType::npos)
829 {
830 assert(offset != BufferType::npos);
831
832 separator = data[offset];
833 // the final zero is mandatory for string-to-double convertions
834 data[offset] = '\0';
835 // Adding the value
836 converter = (const char*)((const char*)data.c_str() + pos);
837
838 // Convert string into double or something else
839 if (not converter.empty())
840 {
841 if (x >= width) // Out of bounds
842 {
843 if ((options & optNeverFails))
844 {
845 if (separator == '\n')
846 {
847 resizeWithoutDataLost(x + 1, height);
848 }
849 else
850 {
851 // gp : dead code - can never be reached
852 // Looking for the new matrix width
853 uint newOffset = offset;
854 uint newWidth = width + 1;
855
856 while ((newOffset = data.find_first_of(ANTARES_MATRIX_CSV_SEPARATORS,
857 (String::Size)newOffset))
858 != BufferType::npos)
859 {
860 if (data[newOffset] == '\n')
861 {
862 ++newWidth;
863 break;
864 }
865 if (data[newOffset] != '\r')
866 {
867 ++newWidth;
868 }
869 ++newOffset;
870 }
871 resizeWithoutDataLost(newWidth, height);
872 }
873 // logs.debug() << " :: dynamic resize (" << width << 'x' << height << ')';
874 }
875 else
876 {
877 result = false;
878 if (not(options & optQuiet) and errorCount > 0)
879 {
880 logs.warning()
881 << '`' << filename << "`: Invalid format: Too many entry for the row "
882 << y << " (offset: " << (uint)pos << "byte)";
883 if (!(--errorCount))
884 {
885 logs.warning() << " ... (skipped)";
886 }
887 }
888 break;
889 }
890 }
891
892 if (MatrixStringConverter<ReadWriteType>::direct)
893 {
894 // We can perform a direct copy, instead of using a temporary buffer
895 // for complex conversions
896 // This should considerably reduced the loading time
897 MatrixData<T>::Copy(entry[x][y], converter);
898 }
899 else
900 {
901 // We will try to convert the string value into the corresponding
902 // type.
903 if (not MatrixStringConverter<ReadWriteType>::Do(converter, cellValue))
904 {
905 // We may fail in some special cases, like when using old studies
906 // where decimal values can be found instead of integer
907 double fallback;
908 if (not MatrixStringConverter<double>::Do(converter, fallback))
909 {
910 result = false;
911 if (not(options & optQuiet) and errorCount)
912 {
913 logs.warning()
914 << '`' << filename << "`: Invalid numeric value (x:" << x
915 << ",y:" << y << ", offset: " << (uint)pos << "byte), text: `"
916 << converter << " read:" << entry[x][y] << '`';
917 if (not(--errorCount))
918 {
919 logs.warning() << " ... (skipped)";
920 }
921 }
922 MatrixData<T>::Init(entry[x][y]);
923 }
924 else
925 {
926 entry[x][y] = MatrixRound<T, ReadWriteType>::Value(
927 static_cast<ReadWriteType>(fallback));
928 }
929 }
930 else
931 {
932 // Ok, the conversion succeeded
933 MatrixData<T>::Copy(entry[x][y], cellValue);
934 }
935 }
936 }
937 else
938 {
939 // We may encounter final tabs, which must not be managed as an error
940 if (x < width)
941 {
942 MatrixData<T>::Init(entry[x][y]);
943 if (not(options & optQuiet))
944 {
945 logs.debug() << " empty value at " << (x + 1) << 'x' << (y + 1)
946 << " (line offset: " << (offset - lineOffset) << ")";
947 }
948 }
949 }
950
951 // Offset for the next token
952 pos = ++offset;
953
954 // new column
955 ++x;
956
957 // next column
958 if (separator == '\r')
959 {
960 if (data[offset] == '\n')
961 {
962 pos = ++offset;
963 break;
964 }
965 }
966 else
967 {
968 if (separator == '\n')
969 {
970 break;
971 }
972 }
973 }
974
975 // Not enough columns to describe the row of the matrix
976 if (x < width)
977 {
978 if (not(options & optNeverFails))
979 {
980 result = false;
981 if (not(options & optQuiet) and errorCount)
982 {
983 logs.warning()
984 << filename << ": at line " << (y + 1) << ", not enough columns (expected "
985 << width << ", got " << x << ')';
986 if (not(--errorCount))
987 {
988 logs.warning() << " ... (skipped)";
989 }
990 }
991 }
992 while (x < width) // Init for missing entry
993 {
994 MatrixData<T>::Init(entry[x][y]);
995 ++x;
996 }
997 }
998
999 // Go to the next line
1000 ++y;
1001
1002 } // while (y ...)
1003
1004 // Not enough lines to describe our matrix
1005 if (y < height)
1006 {
1007 result = false;
1008 if (!(options & optQuiet))
1009 {
1010 logs.warning() << filename << ": not enough rows (expected " << height << ", got " << y
1011 << ')';
1012 }
1013 // Initialize missing entry
1014 while (y < height)
1015 {
1016 for (x = 0; x < width; ++x)
1017 {
1018 MatrixData<T>::Init(entry[x][y]);
1019 }
1020 ++y;
1021 }
1022 }
1023
1024 return ((0 != (options & optNeverFails)) ? true : result);
1025}
1026
1027template<class T, class ReadWriteT>
1028bool Matrix<T, ReadWriteT>::internalLoadCSVFile(const AnyString& filename,
1029 uint minWidth,
1030 uint maxHeight,
1031 uint options,
1032 BufferType* buffer)
1033{
1034 // Status
1035 bool result = false;
1036
1037 const bool hasOwnership = (NULL == buffer);
1038 if (not buffer)
1039 {
1040 buffer = new BufferType();
1041 }
1042
1043 switch (loadFromFileToBuffer(*buffer, filename))
1044 {
1045 case Yuni::IO::errNone:
1046 {
1047 // Empty files
1048 if (buffer->empty())
1049 {
1050 if (maxHeight and minWidth)
1051 {
1052 reset((minWidth != 0 ? minWidth : 1),
1053 maxHeight); // gp : minWidth always != 0 here ==> Refactoring
1054 }
1055 else
1056 {
1057 clear();
1058 }
1059 result = true;
1060 break;
1061 }
1062
1063 // IO statistics
1064 Statistics::HasReadFromDisk(buffer->size());
1065
1066 // Adding a final \n to make sure we have a line return at the end of the file
1067 *buffer += '\n';
1068 // Load the data
1069 result = loadFromBuffer(filename,
1070 *buffer,
1071 minWidth,
1072 maxHeight,
1073 (options & optFixedSize),
1074 options);
1075
1076 // Mark as modified
1077 if (0 != (options & optMarkAsModified))
1078 {
1079 if (jit)
1080 {
1081 jit->markAsModified();
1082 }
1083 }
1084 break;
1085 }
1086 case Yuni::IO::errNotFound:
1087 {
1088 if (not(options & optQuiet))
1089 {
1090 logs.error() << "I/O Error: not found: '" << filename << "'";
1091 }
1092 break;
1093 }
1094 case Yuni::IO::errMemoryLimit:
1095 {
1096 if (not(options & optQuiet))
1097 {
1098 logs.error() << filename << ": The file is too large (>"
1099 << (filesizeHardLimit / 1024 / 1024) << "Mo)";
1100 }
1101 break;
1102 }
1103 default:
1104 {
1105 if (not(options & optQuiet))
1106 {
1107 logs.error() << "I/O Error: failed to load '" << filename << "'";
1108 }
1109 }
1110 }
1111
1112 if (hasOwnership)
1113 {
1114 delete buffer;
1115 }
1116
1117 // The matrix may not be loaded but we have to initialize it to avoid
1118 // further SegV if the application decides to continue anyway.
1119 if (not result)
1120 {
1121 reset(minWidth, maxHeight);
1122 }
1123
1124 // Post-processing when the Load-on-Demand is enabled
1125 if (JIT::enabled and not jit and (0 != (options & optFixedSize)))
1126 {
1127 jit = JIT::Reset(jit, filename);
1128 }
1129
1130 if (jit)
1131 {
1132 jit->alreadyLoaded = true;
1133 jit->modified = false;
1134 jit->minWidth = (options & optFixedSize) ? (!width ? minWidth : width) : 1;
1135 jit->maxHeight = height;
1136 jit->options = options;
1137 if (jit->sourceFilename.empty())
1138 {
1139 jit->sourceFilename = filename;
1140 assert(not jit->sourceFilename.empty());
1141 }
1142 }
1143
1144 // We return `true` in any cases to not stop the execution of the solver, since
1145 // it may not be a fatal error
1146 return result;
1147}
1148
1149template<class T, class ReadWriteT>
1151{
1152 if (width and height)
1153 {
1154 for (uint x = 0; x != width; ++x)
1155 {
1156 auto& column = entry[x];
1157 for (uint y = 0; y != height; ++y)
1158 {
1159 if (!Utils::isZero((T)column[y]))
1160 {
1161 return false;
1162 }
1163 }
1164 }
1165 }
1166 return true;
1167}
1168
1169template<class T, class ReadWriteT>
1170template<class PredicateT>
1171bool Matrix<T, ReadWriteT>::containsOnlyZero(PredicateT& predicate) const
1172{
1173 if (width and height)
1174 {
1175 for (uint x = 0; x != width; ++x)
1176 {
1177 auto& column = entry[x];
1178 for (uint y = 0; y != height; ++y)
1179 {
1180 if (!Utils::isZero((T)predicate(column[y])))
1181 {
1182 return false;
1183 }
1184 }
1185 }
1186 }
1187 return true;
1188}
1189
1190template<class T, class ReadWriteT>
1191template<class PredicateT>
1192void Matrix<T, ReadWriteT>::saveToBuffer(std::string& data,
1193 uint precision,
1194 bool print_dimensions,
1195 PredicateT& predicate,
1196 bool saveEvenIfAllZero) const
1197{
1198 using namespace Yuni;
1199
1200 enum
1201 {
1202 // Get if the read/write type is a decimal type (e.g. double/float/long double)
1203 isDecimal = Static::Type::IsDecimal<ReadWriteType>::Yes,
1204 };
1205
1206 if (not print_dimensions and (containsOnlyZero(predicate) and not saveEvenIfAllZero))
1207 {
1208 // Does nothing if the matrix only contains zero
1209 return;
1210 }
1211
1212 matrix_to_buffer_dumper_factory mtx_to_buffer_dumper_factory;
1213
1214 I_mtx_to_buffer_dumper<T, ReadWriteT, PredicateT>* mtx_to_buffer_dpr
1215 = mtx_to_buffer_dumper_factory.get_dumper<T, ReadWriteT, PredicateT>(this, data, predicate);
1216
1217 // Determining the string format to use according the given precision
1218 mtx_to_buffer_dpr->set_print_format(isDecimal, precision);
1219
1220 // Pre-allocate memory in the buffer. It should be enough in nearly all cases.
1221 data.reserve(width * height * 6);
1222
1223 if (print_dimensions)
1224 {
1225 data += "size:" + std::to_string(width) + 'x' + std::to_string(height) + '\n';
1226 }
1227
1228 mtx_to_buffer_dpr->run();
1229}
1230
1231template<class T, class ReadWriteT>
1232void Matrix<T, ReadWriteT>::saveToBuffer(std::string& data, uint precision) const
1233{
1234 PredicateIdentity identity;
1235 this->saveToBuffer(data, precision, false, identity, true);
1236}
1237
1238template<class T, class ReadWriteT>
1239bool Matrix<T, ReadWriteT>::openFile(Yuni::IO::File::Stream& file, const AnyString& filename) const
1240{
1241 if (not file.openRW(filename))
1242 {
1243 logs.error() << "I/O error: " << filename
1244 << ": Impossible to write the file (not enough permission ?)";
1245 return false;
1246 }
1247 return true;
1248}
1249
1250template<class T, class ReadWriteT>
1251void Matrix<T, ReadWriteT>::saveBufferToFile(std::string& buffer, Yuni::IO::File::Stream& f) const
1252{
1253 f << buffer;
1254}
1255
1256template<class T, class ReadWriteT>
1257template<class PredicateT>
1258bool Matrix<T, ReadWriteT>::internalSaveCSVFile(const AnyString& filename,
1259 uint precision,
1260 bool print_dimensions,
1261 PredicateT& predicate,
1262 bool saveEvenIfAllZero) const
1263{
1264 JIT::just_in_time_manager jit_mgr(jit, filename);
1265
1266 jit_mgr.record_current_jit_state(width, height);
1267
1268 if (jit_mgr.jit_activated() && jit_mgr.matrix_content_in_memory_is_same_as_on_disk())
1269 {
1270 // No difference between actual matrix content in memory and matrix on disk, so we don't
1271 // need to save on disk. Besides, as jit is on, we do not need it in memory, and matrix is
1272 // cleared.
1273 jit_mgr.clear_matrix(this);
1274 return true;
1275 }
1276
1277 if (jit_mgr.jit_activated() && jit_mgr.do_we_force_matrix_load_from_disk())
1278 {
1279 jit_mgr.load_matrix(this);
1280 }
1281
1282#ifndef NDEBUG
1283 // Attempt to open the file, and to write data
1284 // We have write access to the file
1285 logs.debug() << " :: writing `" << filename << "' (" << width << 'x' << height << ')';
1286#endif
1287
1288 Yuni::IO::File::Stream file;
1289 if (not openFile(file, filename))
1290 {
1291 return false;
1292 }
1293
1294 if (height and width)
1295 {
1296 std::string buffer;
1297
1298 saveToBuffer(buffer, precision, print_dimensions, predicate, saveEvenIfAllZero);
1299 Statistics::HasWrittenToDisk(buffer.size());
1300
1301 saveBufferToFile(buffer, file);
1302 }
1303
1304#ifndef NDEBUG
1305 // Attempt to open the file, and to write data
1306 // We have write access to the file
1307 logs.debug() << " :: [end] writing `" << filename << "' (" << width << 'x' << height << ')';
1308#endif
1309
1310 jit_mgr.unload_matrix_properly_from_memory(this);
1311
1312 return true;
1313}
1314
1315template<class T, class ReadWriteT>
1316void Matrix<T, ReadWriteT>::resizeWithoutDataLost(uint x, uint y, const T& defVal)
1317{
1318 if (!x or !y)
1319 {
1320 clear();
1321 }
1322 else
1323 {
1324 if (x <= width and y <= height) // shrinking
1325 {
1326 for (uint i = x; i < width; ++i)
1327 {
1328 Antares::Memory::Release(entry[i]);
1329 }
1330
1331 // Update the matrix size
1332 width = x;
1333 height = y;
1334 }
1335 else
1336 {
1337 const Matrix<T, ReadWriteT> copy(*this);
1338 resize(x, y);
1339 // Copy values
1340 uint minW = (x < copy.width) ? x : copy.width;
1341 uint minH = (y < copy.height) ? y : copy.height;
1342
1343 for (uint i = 0; i < minW; ++i)
1344 {
1345 ColumnType& column = entry[i];
1346
1347 (void)::memcpy(column, copy.entry[i], sizeof(T) * minH);
1348
1349 for (uint j = minH; j < y; ++j)
1350 {
1351 column[j] = defVal;
1352 }
1353 }
1354
1355 if (defVal == T())
1356 {
1357 for (uint i = minW; i < x; ++i)
1358 {
1359 Memory::Zero(y, entry[i]);
1360 }
1361 }
1362 else
1363 {
1364 for (uint i = minW; i < x; ++i)
1365 {
1366 Memory::Assign(y, entry[i], defVal);
1367 }
1368 }
1369 }
1370 }
1371 markAsModified();
1372 logs.debug() << " :: end resizeWithoutDataLost";
1373}
1374
1375template<class T, class ReadWriteT>
1377{
1378 if (jit and not JIT::IsReady(jit))
1379 {
1380 return (const_cast<Matrix<T, ReadWriteT>*>(this))
1381 ->loadFromCSVFile(jit->sourceFilename,
1382 jit->minWidth,
1383 jit->maxHeight,
1384 jit->options | optImmediate);
1385 }
1386 return true;
1387}
1388
1389template<class T, class ReadWriteT>
1390template<class U>
1392{
1393 if (!entry)
1394 {
1395 return;
1396 }
1397
1398 if (!Utils::isZero(c))
1399 {
1400 for (uint x = 0; x != width; ++x)
1401 {
1402 ColumnType& column = entry[x];
1403
1404 for (uint y = 0; y != height; ++y)
1405 {
1406 column[y] *= (T)c;
1407 }
1408 }
1409 }
1410 else
1411 {
1412 zero();
1413 }
1414}
1415
1416template<class T, class ReadWriteT>
1417template<class U>
1419{
1420 assert(x < width and "Invalid column index (bigger than `this->width`)");
1421 ColumnType& column = entry[x];
1422 for (uint y = 0; y != height; ++y)
1423 {
1424 column[y] *= (T)c;
1425 }
1426}
1427
1428template<class T, class ReadWriteT>
1429template<class U>
1430void Matrix<T, ReadWriteT>::divideColumnBy(uint x, const U& c)
1431{
1432 assert(x < width and "Invalid column index (bigger than `this->width`)");
1433 assert(c != (T)0 && "Dividing by zero");
1434 ColumnType& column = entry[x];
1435 for (uint y = 0; y != height; ++y)
1436 {
1437 column[y] /= (T)c;
1438 }
1439}
1440
1441template<class T, class ReadWriteT>
1443{
1444 for (uint x = 0; x != width; ++x)
1445 {
1446 ColumnType& col = entry[x];
1447 for (uint y = 0; y != height; ++y)
1448 {
1449 col[y] = (T)std::round(col[y]);
1450 }
1451 }
1452}
1453
1454template<class T, class ReadWriteT>
1456{
1457 for (uint x = 0; x != width; ++x)
1458 {
1459 ColumnType& col = entry[x];
1460 for (uint y = 0; y != height; ++y)
1461 {
1462 col[y] = std::abs(col[y]);
1463 }
1464 }
1465}
1466
1467template<class T, class ReadWriteT>
1469{
1470 double r = +1e30;
1471 for (uint x = 0; x != width; ++x)
1472 {
1473 ColumnType& col = entry[x];
1474 for (uint y = 0; y != height; ++y)
1475 {
1476 if (col[y] < r)
1477 {
1478 r = col[y];
1479 }
1480 }
1481 }
1482 return (T)r;
1483}
1484
1485template<class T, class ReadWriteT>
1487{
1488 double r = -1e30;
1489 for (uint x = 0; x != width; ++x)
1490 {
1491 ColumnType& col = entry[x];
1492 for (uint y = 0; y != height; ++y)
1493 {
1494 if (col[y] > r)
1495 {
1496 r = col[y];
1497 }
1498 }
1499 }
1500 return (T)r;
1501}
1502
1503template<class T, class ReadWriteT>
1504template<class U, class V>
1506{
1507 assert((void*)(&rhs) != (void*)this and "Undefined behavior");
1508
1509 rhs.forceReload(true);
1510 if (rhs.empty())
1511 {
1512 clear();
1513 }
1514 else
1515 {
1516 // resize the matrix
1517 resize(rhs.width, rhs.height);
1518 // copy raw values
1519 for (uint x = 0; x != rhs.width; ++x)
1520 {
1521 auto& column = entry[x];
1522 const auto& src = rhs.entry[x];
1523
1524 // if the two types are strictly equal, we can perform some major
1525 // optimisations
1526 if (Yuni::Static::Type::StrictlyEqual<T, U>::Yes)
1527 {
1528 (void)::memcpy((void*)column, (void*)src, sizeof(T) * height);
1529 }
1530 else
1531 {
1532 // ...otherwise we have to copy each item by hand in any cases
1533 for (uint y = 0; y != height; ++y)
1534 {
1535 column[y] = (T)src[y];
1536 }
1537 }
1538 }
1539 }
1540
1541 if (rhs.jit)
1542 {
1543 if (not jit)
1544 {
1545 jit = new JIT::Informations(*rhs.jit);
1546 }
1547 else
1548 {
1549 jit->options = rhs.jit->options;
1550 jit->minWidth = rhs.jit->minWidth;
1551 jit->maxHeight = rhs.jit->maxHeight;
1552 }
1553 }
1554 // mark the matrix as modified
1555 markAsModified();
1556}
1557
1558template<class T, class ReadWriteT>
1559template<class U, class V>
1560inline void Matrix<T, ReadWriteT>::copyFrom(const Matrix<U, V>* rhs)
1561{
1562 if (rhs)
1563 {
1564 copyFrom(*rhs);
1565 }
1566}
1567
1568template<class T, class ReadWriteT>
1570{
1571 // argument deduction lookup (ADL)
1572 using std::swap;
1573 swap(this->width, rhs.width);
1574 swap(this->height, rhs.height);
1575 swap(this->entry, rhs.entry);
1576 swap(this->jit, rhs.jit);
1577}
1578
1579template<class T, class ReadWriteT>
1581{
1582 copyFrom(rhs);
1583 return *this;
1584}
1585
1586template<class T, class ReadWriteT>
1588{
1589 width = rhs.width;
1590 height = rhs.height;
1591 jit = rhs.jit;
1592 if (0 == width || 0 == height)
1593 {
1594 entry = nullptr;
1595 width = 0;
1596 height = 0;
1597 }
1598 else
1599 {
1600 entry = rhs.entry;
1601 }
1602 // Prevent spurious de-allocation from rhs's destructor
1603 rhs.entry = nullptr;
1604 return *this;
1605}
1606
1607template<class T, class ReadWriteT>
1608template<class U>
1609inline Matrix<T, ReadWriteT>& Matrix<T, ReadWriteT>::operator=(const Matrix<U>& rhs)
1610{
1611 copyFrom(rhs);
1612 return *this;
1613}
1614
1615template<class T, class ReadWriteT>
1617{
1618 std::cout << "DUMP:\n";
1619 if (empty())
1620 {
1621 std::cout << "\tempty\n";
1622 return;
1623 }
1624 for (uint y = 0; y != height; ++y)
1625 {
1626 std::cout << "\t[";
1627 for (uint x = 0; x != width; ++x)
1628 {
1629 if (x)
1630 {
1631 std::cout << ",\t";
1632 }
1633 else
1634 {
1635 std::cout << '\t';
1636 }
1637 std::cout << entry[x][y];
1638 }
1639 std::cout << "]\n";
1640 }
1641}
1642
1643template<class T, class ReadWriteT>
1645{
1646 if (jit)
1647 {
1648 if (jit->alreadyLoaded and not jit->modified and not jit->sourceFilename.empty())
1649 {
1650 // ugly, but to not break the whole code design
1651 auto& thisNotConst = const_cast<Matrix&>(*this);
1652
1653 thisNotConst.clear();
1654 JIT::MarkAsNotLoaded(thisNotConst.jit);
1655 }
1656 }
1657}
1658
1659template<class T1, class T2>
1660bool MatrixTestForAtLeastOnePositiveValue(const Matrix<T1, T2>& m)
1661{
1662 if (m.width and m.height)
1663 {
1664 uint y;
1665 for (uint x = 0; x < m.width; ++x)
1666 {
1667 auto& col = m.entry[x];
1668 for (y = 0; y < m.height; ++y)
1669 {
1670 if (col[y] > T1(0))
1671 {
1672 return true;
1673 }
1674 }
1675 }
1676 }
1677 return false;
1678}
1679
1680template<class T, class ReadWriteT>
1682{
1683 if (count != 0)
1684 {
1685 for (uint column = 0; column != width; ++column)
1686 {
1687 circularShiftRows(column, count);
1688 }
1689 markAsModified();
1690 }
1691}
1692
1693template<class T, class ReadWriteT>
1694void Matrix<T, ReadWriteT>::reverseRows(uint column, uint start, uint end)
1695{
1696 if (height <= 1 or !(column < width) or !(start < end))
1697 {
1698 return;
1699 }
1700
1701 // The values of the selected column
1702 auto& values = entry[column];
1703 // temporary value
1704 T swap;
1705 for (uint y = start; y < --end; ++y)
1706 {
1707 swap = values[y];
1708 values[y] = values[end];
1709 values[end] = swap;
1710 }
1711}
1712
1713template<class T, class ReadWriteT>
1714void Matrix<T, ReadWriteT>::circularShiftRows(uint column, uint count)
1715{
1716 assert(column < width and "Column out of bounds");
1717 if (height <= 1 or !(column < width) or !count)
1718 {
1719 return;
1720 }
1721
1722 // fits \p count into [0..height[
1723 count = (count % height + height) % height;
1724 if (count == 0 or (uint) count == height)
1725 {
1726 return;
1727 }
1728
1729 // Algorithm in O(N)
1730 reverseRows(column, 0, count);
1731 reverseRows(column, count, height);
1732 reverseRows(column, 0, height);
1733 markAsModified();
1734}
1735
1736template<class T, class ReadWriteT>
1738 uint column) const
1739{
1740 assert(column < width);
1741 assert(Memory::RawPointer(entry[column]));
1742 return entry[column];
1743}
1744
1745template<class T, class ReadWriteT>
1747{
1748 assert(column < width);
1749 assert(Memory::RawPointer(entry[column]));
1750 return entry[column];
1751}
1752
1753template<class T, class ReadWriteT>
1755{
1756 assert(n < width);
1757 assert(Memory::RawPointer(entry[n]));
1758 return entry[n];
1759}
1760
1761template<class T, class ReadWriteT>
1763{
1764 assert(n < width);
1765 assert(Memory::RawPointer(entry[n]));
1766 return entry[n];
1767}
1768
1769} // namespace Antares
1770
1771#endif // __ANTARES_LIBS_ARRAY_MATRIX_HXX__
A n-by-n matrix.
Definition jit.h:30
JIT::Informations * jit
Just-in-time informations.
Definition matrix.h:447
bool saveToCSVFile(const AnyString &filename, uint precision=6, bool print_dimensions=false, bool saveEvenIfAllZero=false) const
Write the content of a matrix into a single file.
Definition matrix.hxx:446
void swap(MatrixType &rhs) noexcept
Swap contents of Matrix with another.
Definition matrix.hxx:1569
void multiplyColumnBy(uint x, const U &c)
Multiply or divide a column by a given value.
Definition matrix.hxx:1418
void fillUnit()
Make the matrix an unit matrix (identity matrix)
Definition matrix.hxx:362
virtual ~Matrix()
Destructor.
Definition matrix.hxx:276
void reset()
Empty the matrix and mark it as modified.
Definition matrix.hxx:548
ColumnType & operator[](uint column)
operator []
Definition matrix.hxx:1746
void unloadFromMemory() const
Try to remove from memory all data from the matrix.
Definition matrix.hxx:1644
void fill(const T &v)
Fill the matrix with a given value.
Definition matrix.hxx:348
Matrix & operator=(const Matrix &rhs)
Assignement.
Definition matrix.hxx:1580
bool forceReload(bool reload=false) const
Force the Load of data (if not done) for the next save and mark the matrix as modified.
Definition matrix.hxx:375
T findLowerBound() const
Find the lower bound.
Definition matrix.hxx:1468
void pasteToColumn(uint x, const U *data)
Copy values into a given column in the matrix.
Definition matrix.hxx:468
typename Antares::Memory::Stored< double >::Type ColumnType
Definition matrix.h:62
ColumnType * entry
All entries of the matrix (bidimensional array)
Definition matrix.h:445
T findUpperBound() const
Find the upper bound.
Definition matrix.hxx:1486
void print() const
Print the matrix to std::cout (debug)
Definition matrix.hxx:1616
bool empty() const
Get if the matrix is empty.
Definition matrix.hxx:526
void zero()
Make the matrix a zero matrix.
Definition matrix.hxx:293
uint width
Width of the matrix.
Definition matrix.h:441
void markAsModified() const
Mark the matrix as modified.
Definition matrix.hxx:517
ColumnType & column(uint n)
Get the Nth column.
Definition matrix.hxx:1762
uint height
Height of the matrix.
Definition matrix.h:443
void columnToZero(uint x)
Set to zero a entire column.
Definition matrix.hxx:506
virtual bool loadFromCSVFile(const AnyString &filename, uint minWidth, uint maxHeight, uint options=optNone, BufferType *buffer=NULL)
Load entries from a CSV file.
Definition matrix.hxx:425
void fillColumn(uint x, const T &value)
Set a entire column with a given value.
Definition matrix.hxx:492
void copyFrom(const Matrix< U, V > &rhs)
Copy values from another matrix.
Definition matrix.hxx:1505
void makeAllEntriesAbsolute()
Make all entries absolute.
Definition matrix.hxx:1455
bool containsOnlyZero() const
Get if the matrix only contains zero.
Definition matrix.hxx:1150
void circularShiftRows(uint count)
Shift all rows.
Definition matrix.hxx:1681
void resizeWithoutDataLost(uint x, uint y, const T &defVal=T())
Resize the matrix without destroying its content.
Definition matrix.hxx:1316
void averageTimeseries(bool roundValues=true)
Compute the average of all timeseries (derated mode)
Definition matrix.hxx:303
Matrix()
Default Constructor.
Definition matrix.hxx:202
Yuni::Clob BufferType
Definition matrix.h:65
void resize(uint w, uint h, bool fixedSize=false)
Resize the matrix.
Definition matrix.hxx:555
void multiplyAllEntriesBy(const U &c)
Multiply all entries by a given value.
Definition matrix.hxx:1391
void clear()
Empty the matrix.
Definition matrix.hxx:532
void roundAllEntries()
Round all entries.
Definition matrix.hxx:1442
virtual bool openFile(Yuni::IO::File::Stream &file, const AnyString &filename) const
Trying to open a file.
Definition matrix.hxx:1239
static void Release(T *&pointer)
Release a raw pointer.
Definition memory.hxx:32
Definition jit.h:118
unsigned options
The option to the matrix.
Definition jit.h:150
unsigned minWidth
Minimum width expected (for Matrices)
Definition jit.h:156
unsigned maxHeight
Minimum height expected (for Matrices)
Definition jit.h:162
Definition jit.h:66
static Informations * Reset(Informations *jit, const AnyString &filename)
Reset the source filename.
Definition jit.cpp:80
static bool IsReady(Informations *j)
Get if the data has been loaded.
Definition jit.hxx:28
static void Invalidate(Informations *j)
Mark the attached object as modified.
Definition jit.cpp:110
static bool enabled
Flag to enable/disable JIT informations.
Definition jit.h:179
static void MarkAsNotLoaded(Informations *j)
Mark the attached object as not loaded.
Definition jit.cpp:101
Definition matrix.h:450
Definition tests-matrix-save.h:42