A Discrete-Event Network Simulator
API
val-array.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Biljana Bojovic <bbojovic@cttc.es>
18 */
19#ifndef VAL_ARRAY_H
20#define VAL_ARRAY_H
21
22#include <ns3/assert.h>
23#include <ns3/simple-ref-count.h>
24
25#include <complex>
26#include <valarray>
27#include <vector>
28
29namespace ns3
30{
31
78template <class T>
79class ValArray : public SimpleRefCount<ValArray<T>>
80{
81 public:
82 // instruct the compiler to generate the default constructor
83 ValArray<T>() = default;
92 ValArray<T>(uint16_t numRows, uint16_t numCols = 1, uint16_t numPages = 1);
98 explicit ValArray<T>(const std::valarray<T>& values);
104 ValArray<T>(std::valarray<T>&& values);
110 explicit ValArray<T>(const std::vector<T>& values);
118 ValArray<T>(uint16_t numRows, uint16_t numCols, const std::valarray<T>& values);
126 ValArray<T>(uint16_t numRows, uint16_t numCols, std::valarray<T>&& values);
136 ValArray<T>(uint16_t numRows,
137 uint16_t numCols,
138 uint16_t numPages,
139 const std::valarray<T>& values);
149 ValArray<T>(uint16_t numRows, uint16_t numCols, uint16_t numPages, std::valarray<T>&& values);
151 virtual ~ValArray<T>() = default;
153 ValArray<T>(const ValArray<T>&) = default;
161 ValArray<T>(ValArray<T>&&) = default;
171 uint16_t GetNumRows() const;
175 uint16_t GetNumCols() const;
179 uint16_t GetNumPages() const;
183 size_t GetSize() const;
191 T& operator()(uint16_t rowIndex, uint16_t colIndex, uint16_t pageIndex);
199 const T& operator()(uint16_t rowIndex, uint16_t colIndex, uint16_t pageIndex) const;
212 T& operator()(uint16_t rowIndex, uint16_t colIndex);
221 const T& operator()(uint16_t rowIndex, uint16_t colIndex) const;
233 T& operator()(uint16_t index);
239 const T& operator()(uint16_t index) const;
246 ValArray<T> operator*(const T& rhs) const;
252 ValArray<T> operator+(const ValArray<T>& rhs) const;
258 ValArray<T> operator-(const ValArray<T>& rhs) const;
263 ValArray<T> operator-() const;
281 bool operator==(const ValArray<T>& rhs) const;
287 bool operator!=(const ValArray<T>& rhs) const;
298 bool IsAlmostEqual(const ValArray<T>& rhs, T tol) const;
305 T* GetPagePtr(uint16_t pageIndex);
312 const T* GetPagePtr(uint16_t pageIndex) const;
318 bool EqualDims(const ValArray<T>& rhs) const;
324 void AssertEqualDims(const ValArray<T>& rhs) const;
335 T& operator[](size_t index);
343 const T& operator[](size_t index) const;
349 const std::valarray<T>& GetValues() const;
357 T& Elem(size_t row, size_t col, size_t page);
365 const T& Elem(size_t row, size_t col, size_t page) const;
366
367 protected:
368 uint16_t m_numRows =
369 0;
370 uint16_t m_numCols =
371 0;
372 uint16_t m_numPages = 0;
373 std::valarray<T> m_values;
374};
375
376/*************************************************
377 ** Class ValArray inline implementations
378 ************************************************/
379
380template <class T>
381inline uint16_t
383{
384 return m_numRows;
385};
386
387template <class T>
388inline uint16_t
390{
391 return m_numCols;
392};
393
394template <class T>
395inline uint16_t
397{
398 return m_numPages;
399};
400
401template <class T>
402inline size_t
404{
405 return m_values.size();
406}
407
408template <class T>
409inline T&
410ValArray<T>::operator()(uint16_t rowIndex, uint16_t colIndex, uint16_t pageIndex)
411{
412 NS_ASSERT_MSG(rowIndex < m_numRows, "Row index out of bounds");
413 NS_ASSERT_MSG(colIndex < m_numCols, "Column index out of bounds");
414 NS_ASSERT_MSG(pageIndex < m_numPages, "Pages index out of bounds");
415 size_t index = (rowIndex + m_numRows * (colIndex + m_numCols * pageIndex));
416 return m_values[index];
417};
418
419template <class T>
420inline const T&
421ValArray<T>::operator()(uint16_t rowIndex, uint16_t colIndex, uint16_t pageIndex) const
422{
423 NS_ASSERT_MSG(rowIndex < m_numRows, "Row index out of bounds");
424 NS_ASSERT_MSG(colIndex < m_numCols, "Column index out of bounds");
425 NS_ASSERT_MSG(pageIndex < m_numPages, "Pages index out of bounds");
426 size_t index = (rowIndex + m_numRows * (colIndex + m_numCols * pageIndex));
427 return m_values[index];
428};
429
430template <class T>
431inline T&
432ValArray<T>::operator()(uint16_t rowIndex, uint16_t colIndex)
433{
434 NS_ASSERT_MSG(m_numPages == 1, "Cannot use 2D access operator for 3D ValArray.");
435 return (*this)(rowIndex, colIndex, 0);
436};
437
438template <class T>
439inline const T&
440ValArray<T>::operator()(uint16_t rowIndex, uint16_t colIndex) const
441{
442 NS_ASSERT_MSG(m_numPages == 1, "Cannot use 2D access operator for 3D ValArray.");
443 return (*this)(rowIndex, colIndex, 0);
444};
445
446template <class T>
447inline T&
449{
450 NS_ASSERT_MSG(index < m_values.size(),
451 "Invalid index to 1D ValArray. The size of the array should be set through "
452 "constructor.");
453 NS_ASSERT_MSG(((m_numRows == 1 || m_numCols == 1) && (m_numPages == 1)) ||
454 (m_numRows == 1 && m_numCols == 1),
455 "Access operator allowed only for 1D ValArray.");
456 return m_values[index];
457};
458
459template <class T>
460inline const T&
461ValArray<T>::operator()(uint16_t index) const
462{
463 NS_ASSERT_MSG(index < m_values.size(),
464 "Invalid index to 1D ValArray.The size of the array should be set through "
465 "constructor.");
466 NS_ASSERT_MSG(((m_numRows == 1 || m_numCols == 1) && (m_numPages == 1)) ||
467 (m_numRows == 1 && m_numCols == 1),
468 "Access operator allowed only for 1D ValArray.");
469 return m_values[index];
470};
471
472template <class T>
473inline ValArray<T>
474ValArray<T>::operator*(const T& rhs) const
475{
476 return ValArray<T>(m_numRows,
477 m_numCols,
478 m_numPages,
479 m_values * std::valarray<T>(rhs, m_numRows * m_numCols * m_numPages));
480}
481
482template <class T>
483inline ValArray<T>
485{
486 AssertEqualDims(rhs);
487 return ValArray<T>(m_numRows, m_numCols, m_numPages, m_values + rhs.m_values);
488}
489
490template <class T>
491inline ValArray<T>
493{
494 AssertEqualDims(rhs);
495 return ValArray<T>(m_numRows, m_numCols, m_numPages, m_values - rhs.m_values);
496}
497
498template <class T>
499inline ValArray<T>
501{
502 return ValArray<T>(m_numRows, m_numCols, m_numPages, -m_values);
503}
504
505template <class T>
506inline ValArray<T>&
508{
509 AssertEqualDims(rhs);
510 m_values += rhs.m_values;
511 return *this;
512}
513
514template <class T>
515inline ValArray<T>&
517{
518 AssertEqualDims(rhs);
519 m_values -= rhs.m_values;
520 return *this;
521}
522
523template <class T>
524inline T*
525ValArray<T>::GetPagePtr(uint16_t pageIndex)
526{
527 NS_ASSERT_MSG(pageIndex < m_numPages, "Invalid page index.");
528 return &(m_values[m_numRows * m_numCols * pageIndex]);
529};
530
531template <class T>
532inline const T*
533ValArray<T>::GetPagePtr(uint16_t pageIndex) const
534{
535 NS_ASSERT_MSG(pageIndex < m_numPages, "Invalid page index.");
536 return &(m_values[m_numRows * m_numCols * pageIndex]);
537};
538
539template <class T>
540inline bool
542{
543 return (m_numRows == rhs.m_numRows) && (m_numCols == rhs.m_numCols) &&
544 (m_numPages == rhs.m_numPages);
545}
546
547template <class T>
548inline T&
550{
551 return (*this)(index);
552}
553
554template <class T>
555inline const T&
556ValArray<T>::operator[](size_t index) const
557{
558 return (*this)(index);
559}
560
561template <class T>
562inline const std::valarray<T>&
564{
565 return m_values;
566}
567
568template <class T>
569inline T&
570ValArray<T>::Elem(size_t row, size_t col, size_t page)
571{
572 return (*this)(row, col, page);
573};
574
575template <class T>
576inline const T&
577ValArray<T>::Elem(size_t row, size_t col, size_t page) const
578{
579 return (*this)(row, col, page);
580};
581
582/*************************************************
583 ** Class ValArray non-inline implementations
584 ************************************************/
585
586template <class T>
587ValArray<T>::ValArray(uint16_t numRows, uint16_t numCols, uint16_t numPages)
588 : m_numRows{numRows},
589 m_numCols{numCols},
590 m_numPages{numPages}
591{
593};
594
595template <class T>
596ValArray<T>::ValArray(const std::valarray<T>& values)
597 : m_numRows{(uint16_t)values.size()},
598 m_numCols{1},
599 m_numPages{1},
600 m_values{values}
601{
602}
603
604template <class T>
605ValArray<T>::ValArray(std::valarray<T>&& values)
606 : m_numRows{(uint16_t)values.size()},
607 m_numCols{1},
608 m_numPages{1},
609 m_values{std::move(values)}
610{
611}
612
613template <class T>
614ValArray<T>::ValArray(const std::vector<T>& values)
615 : m_numRows{(uint16_t)values.size()},
616 m_numCols{1},
617 m_numPages{1}
618{
619 m_values.resize(values.size());
620 std::copy(values.begin(), values.end(), std::begin(m_values));
621}
622
623template <class T>
624ValArray<T>::ValArray(uint16_t numRows, uint16_t numCols, const std::valarray<T>& values)
625 : m_numRows{numRows},
626 m_numCols{numCols},
627 m_numPages{1},
628 m_values{values}
629{
630 NS_ASSERT_MSG(m_numRows * m_numCols == values.size(),
631 "Dimensions and the initialization array size do not match.");
632};
633
634template <class T>
635ValArray<T>::ValArray(uint16_t numRows, uint16_t numCols, std::valarray<T>&& values)
636 : m_numRows{numRows},
637 m_numCols{numCols},
638 m_numPages{1}
639{
640 NS_ASSERT_MSG(m_numRows * m_numCols == values.size(),
641 "Dimensions and the initialization array size do not match.");
642 m_values = std::move(values);
643};
644
645template <class T>
646ValArray<T>::ValArray(uint16_t numRows,
647 uint16_t numCols,
648 uint16_t numPages,
649 const std::valarray<T>& values)
650 : m_numRows{numRows},
651 m_numCols{numCols},
652 m_numPages{numPages},
653 m_values{values}
654{
655 NS_ASSERT_MSG(m_numRows * m_numCols * m_numPages == values.size(),
656 "Dimensions and the initialization array size do not match.");
657};
658
659template <class T>
660ValArray<T>::ValArray(uint16_t numRows,
661 uint16_t numCols,
662 uint16_t numPages,
663 std::valarray<T>&& values)
664 : m_numRows{numRows},
665 m_numCols{numCols},
666 m_numPages{numPages}
667{
668 NS_ASSERT_MSG(m_numRows * m_numCols * m_numPages == values.size(),
669 "Dimensions and the initialization array size do not match.");
670 m_values = std::move(values);
671};
672
673template <class T>
674bool
676{
677 return EqualDims(rhs) &&
678 std::equal(std::begin(m_values), std::end(m_values), std::begin(rhs.m_values));
679}
680
681template <class T>
682bool
684{
685 return !((*this) == rhs);
686}
687
688template <class T>
689bool
691{
692 return EqualDims(rhs) && std::equal(std::begin(m_values),
693 std::end(m_values),
694 std::begin(rhs.m_values),
695 [tol](T lhsValue, T rhsValue) {
696 return lhsValue == rhsValue ||
697 std::abs(lhsValue - rhsValue) <= std::abs(tol);
698 });
699}
700
701template <class T>
702void
704{
705 NS_ASSERT_MSG(EqualDims(rhs),
706 "Dimensions mismatch: "
707 "lhs (rows, cols, pages) = ("
708 << m_numRows << ", " << m_numCols << ", " << m_numPages
709 << ") and "
710 "rhs (rows, cols, pages) = ("
711 << rhs.m_numRows << ", " << rhs.m_numCols << ", " << rhs.m_numPages << ")");
712}
713
721template <class T>
722std::ostream&
723operator<<(std::ostream& os, const ValArray<T>& a)
724{
725 os << "\n";
726 for (auto p = 0; p != a.GetNumPages(); ++p)
727 {
728 os << "Page " << p << ":\n";
729 for (auto i = 0; i != a.GetNumRows(); ++i)
730 {
731 for (auto j = 0; j != a.GetNumCols(); ++j)
732 {
733 os << "\t" << a(i, j, p);
734 }
735 os << "\n";
736 }
737 }
738 return os;
739}
740
741} // namespace ns3
742
743#endif // VAL_ARRAY_H
A template-based reference counting class.
ValArray is a class to efficiently store 3D array.
Definition: val-array.h:80
uint16_t m_numRows
The size of the first dimension, i.e., the number of rows of each 2D array.
Definition: val-array.h:368
void AssertEqualDims(const ValArray< T > &rhs) const
Function that asserts if the dimensions of lhs and rhs ValArray are not equal and prints a message wi...
Definition: val-array.h:703
T * GetPagePtr(uint16_t pageIndex)
Get a data pointer to a specific 2D array for use in linear algebra libraries.
Definition: val-array.h:525
uint16_t GetNumRows() const
Definition: val-array.h:382
uint16_t GetNumCols() const
Definition: val-array.h:389
T & Elem(size_t row, size_t col, size_t page)
Alternative access operator to access a specific element.
Definition: val-array.h:570
ValArray< T > operator+(const ValArray< T > &rhs) const
operator+ definition for ValArray<T>.
Definition: val-array.h:484
const std::valarray< T > & GetValues() const
Returns underlying values.
Definition: val-array.h:563
ValArray< T > & operator+=(const ValArray< T > &rhs)
operator+= definition for ValArray<T>.
Definition: val-array.h:507
bool IsAlmostEqual(const ValArray< T > &rhs, T tol) const
Compare Valarray up to a given absolute tolerance.
Definition: val-array.h:690
bool operator!=(const ValArray< T > &rhs) const
operator!= definition for ValArray<T>.
Definition: val-array.h:683
ValArray< T > & operator=(ValArray< T > &&)=default
Move assignment operator.
T & operator[](size_t index)
Single-element access operator[] that can be used to access a specific element of 1D ValArray.
Definition: val-array.h:549
T & operator()(uint16_t rowIndex, uint16_t colIndex, uint16_t pageIndex)
Access operator, with bound-checking in debug profile.
Definition: val-array.h:410
bool operator==(const ValArray< T > &rhs) const
operator== definition for ValArray<T>.
Definition: val-array.h:675
uint16_t m_numPages
The size of the third dimension, i.e., the number of 2D arrays.
Definition: val-array.h:372
size_t GetSize() const
Definition: val-array.h:403
std::valarray< T > m_values
The data values.
Definition: val-array.h:373
ValArray< T > & operator-=(const ValArray< T > &rhs)
operator-= definition for ValArray<T>.
Definition: val-array.h:516
ValArray()=default
uint16_t GetNumPages() const
Definition: val-array.h:396
ValArray< T > & operator=(const ValArray< T > &)=default
Copy assignment operator.
uint16_t m_numCols
The size of the second dimension, i.e., the number of columns of each 2D array.
Definition: val-array.h:370
bool EqualDims(const ValArray< T > &rhs) const
Checks whether rhs and lhs ValArray objects have the same dimensions.
Definition: val-array.h:541
ValArray< T > operator*(const T &rhs) const
Element-wise multiplication with a scalar value.
Definition: val-array.h:474
ValArray< T > operator-() const
unary operator- definition for ValArray<T>.
Definition: val-array.h:500
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:129
STL namespace.