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 
29 namespace ns3
30 {
31 
78 template <class T>
79 class 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;
159  ValArray<T>& operator=(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;
269  ValArray<T>& operator+=(const ValArray<T>& rhs);
275  ValArray<T>& operator-=(const ValArray<T>& rhs);
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 
380 template <class T>
381 inline uint16_t
383 {
384  return m_numRows;
385 };
386 
387 template <class T>
388 inline uint16_t
390 {
391  return m_numCols;
392 };
393 
394 template <class T>
395 inline uint16_t
397 {
398  return m_numPages;
399 };
400 
401 template <class T>
402 inline size_t
404 {
405  return m_values.size();
406 }
407 
408 template <class T>
409 inline T&
410 ValArray<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 
419 template <class T>
420 inline const T&
421 ValArray<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 
430 template <class T>
431 inline T&
432 ValArray<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 
438 template <class T>
439 inline const T&
440 ValArray<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 
446 template <class T>
447 inline T&
448 ValArray<T>::operator()(uint16_t index)
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 
459 template <class T>
460 inline const T&
461 ValArray<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 
472 template <class T>
473 inline ValArray<T>
474 ValArray<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 
482 template <class T>
483 inline ValArray<T>
485 {
486  AssertEqualDims(rhs);
487  return ValArray<T>(m_numRows, m_numCols, m_numPages, m_values + rhs.m_values);
488 }
489 
490 template <class T>
491 inline ValArray<T>
493 {
494  AssertEqualDims(rhs);
495  return ValArray<T>(m_numRows, m_numCols, m_numPages, m_values - rhs.m_values);
496 }
497 
498 template <class T>
499 inline ValArray<T>
501 {
502  return ValArray<T>(m_numRows, m_numCols, m_numPages, -m_values);
503 }
504 
505 template <class T>
506 inline ValArray<T>&
508 {
509  AssertEqualDims(rhs);
510  m_values += rhs.m_values;
511  return *this;
512 }
513 
514 template <class T>
515 inline ValArray<T>&
517 {
518  AssertEqualDims(rhs);
519  m_values -= rhs.m_values;
520  return *this;
521 }
522 
523 template <class T>
524 inline T*
525 ValArray<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 
531 template <class T>
532 inline const T*
533 ValArray<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 
539 template <class T>
540 inline bool
542 {
543  return (m_numRows == rhs.m_numRows) && (m_numCols == rhs.m_numCols) &&
544  (m_numPages == rhs.m_numPages);
545 }
546 
547 template <class T>
548 inline T&
550 {
551  return (*this)(index);
552 }
553 
554 template <class T>
555 inline const T&
556 ValArray<T>::operator[](size_t index) const
557 {
558  return (*this)(index);
559 }
560 
561 template <class T>
562 inline const std::valarray<T>&
564 {
565  return m_values;
566 }
567 
568 template <class T>
569 inline T&
570 ValArray<T>::Elem(size_t row, size_t col, size_t page)
571 {
572  return (*this)(row, col, page);
573 };
574 
575 template <class T>
576 inline const T&
577 ValArray<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 
586 template <class T>
587 ValArray<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 
595 template <class T>
596 ValArray<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 
604 template <class T>
605 ValArray<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 
613 template <class T>
614 ValArray<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 
623 template <class T>
624 ValArray<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 
634 template <class T>
635 ValArray<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 
645 template <class T>
646 ValArray<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 
659 template <class T>
660 ValArray<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 
673 template <class T>
674 bool
676 {
677  return EqualDims(rhs) &&
678  std::equal(std::begin(m_values), std::end(m_values), std::begin(rhs.m_values));
679 }
680 
681 template <class T>
682 bool
684 {
685  return !((*this) == rhs);
686 }
687 
688 template <class T>
689 bool
690 ValArray<T>::IsAlmostEqual(const ValArray<T>& rhs, T tol) const
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 
701 template <class T>
702 void
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 
721 template <class T>
722 std::ostream&
723 operator<<(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
ValArray< T > & operator=(ValArray< T > &&)=default
Move assignment operator.
uint16_t GetNumRows() const
Definition: val-array.h:382
ValArray< T > & operator=(const ValArray< T > &)=default
Copy assignment operator.
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
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
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