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 "assert.h"
23 #include "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() = default;
92  ValArray(size_t numRows, size_t numCols = 1, size_t numPages = 1);
98  explicit ValArray(const std::valarray<T>& values);
104  ValArray(std::valarray<T>&& values);
110  explicit ValArray(const std::vector<T>& values);
118  ValArray(size_t numRows, size_t numCols, const std::valarray<T>& values);
126  ValArray(size_t numRows, size_t numCols, std::valarray<T>&& values);
136  ValArray(size_t numRows, size_t numCols, size_t numPages, const std::valarray<T>& values);
146  ValArray(size_t numRows, size_t numCols, size_t numPages, std::valarray<T>&& values);
148  virtual ~ValArray() = default;
150  ValArray(const ValArray<T>&) = default;
156  ValArray& operator=(const ValArray<T>&) = default;
158  ValArray(ValArray<T>&&) = default;
168  size_t GetNumRows() const;
172  size_t GetNumCols() const;
176  size_t GetNumPages() const;
180  size_t GetSize() const;
188  T& operator()(size_t rowIndex, size_t colIndex, size_t pageIndex);
196  const T& operator()(size_t rowIndex, size_t colIndex, size_t pageIndex) const;
209  T& operator()(size_t rowIndex, size_t colIndex);
218  const T& operator()(size_t rowIndex, size_t colIndex) const;
230  T& operator()(size_t index);
236  const T& operator()(size_t index) const;
243  ValArray operator*(const T& rhs) const;
249  ValArray operator+(const ValArray<T>& rhs) const;
255  ValArray operator-(const ValArray<T>& rhs) const;
260  ValArray operator-() const;
266  ValArray<T>& operator+=(const ValArray<T>& rhs);
272  ValArray<T>& operator-=(const ValArray<T>& rhs);
278  bool operator==(const ValArray<T>& rhs) const;
284  bool operator!=(const ValArray<T>& rhs) const;
295  bool IsAlmostEqual(const ValArray<T>& rhs, T tol) const;
302  T* GetPagePtr(size_t pageIndex);
309  const T* GetPagePtr(size_t pageIndex) const;
315  bool EqualDims(const ValArray<T>& rhs) const;
321  void AssertEqualDims(const ValArray<T>& rhs) const;
332  T& operator[](size_t index);
340  const T& operator[](size_t index) const;
346  const std::valarray<T>& GetValues() const;
354  T& Elem(size_t row, size_t col, size_t page);
362  const T& Elem(size_t row, size_t col, size_t page) const;
363 
364  protected:
365  size_t m_numRows =
366  0;
367  size_t m_numCols =
368  0;
369  size_t m_numPages = 0;
370  std::valarray<T> m_values;
371 };
372 
373 /*************************************************
374  ** Class ValArray inline implementations
375  ************************************************/
376 
377 template <class T>
378 inline size_t
380 {
381  return m_numRows;
382 }
383 
384 template <class T>
385 inline size_t
387 {
388  return m_numCols;
389 }
390 
391 template <class T>
392 inline size_t
394 {
395  return m_numPages;
396 }
397 
398 template <class T>
399 inline size_t
401 {
402  return m_values.size();
403 }
404 
405 template <class T>
406 inline T&
407 ValArray<T>::operator()(size_t rowIndex, size_t colIndex, size_t pageIndex)
408 {
409  NS_ASSERT_MSG(rowIndex < m_numRows, "Row index out of bounds");
410  NS_ASSERT_MSG(colIndex < m_numCols, "Column index out of bounds");
411  NS_ASSERT_MSG(pageIndex < m_numPages, "Pages index out of bounds");
412  size_t index = (rowIndex + m_numRows * (colIndex + m_numCols * pageIndex));
413  return m_values[index];
414 }
415 
416 template <class T>
417 inline const T&
418 ValArray<T>::operator()(size_t rowIndex, size_t colIndex, size_t pageIndex) const
419 {
420  NS_ASSERT_MSG(rowIndex < m_numRows, "Row index out of bounds");
421  NS_ASSERT_MSG(colIndex < m_numCols, "Column index out of bounds");
422  NS_ASSERT_MSG(pageIndex < m_numPages, "Pages index out of bounds");
423  size_t index = (rowIndex + m_numRows * (colIndex + m_numCols * pageIndex));
424  return m_values[index];
425 }
426 
427 template <class T>
428 inline T&
429 ValArray<T>::operator()(size_t rowIndex, size_t colIndex)
430 {
431  NS_ASSERT_MSG(m_numPages == 1, "Cannot use 2D access operator for 3D ValArray.");
432  return (*this)(rowIndex, colIndex, 0);
433 }
434 
435 template <class T>
436 inline const T&
437 ValArray<T>::operator()(size_t rowIndex, size_t colIndex) const
438 {
439  NS_ASSERT_MSG(m_numPages == 1, "Cannot use 2D access operator for 3D ValArray.");
440  return (*this)(rowIndex, colIndex, 0);
441 }
442 
443 template <class T>
444 inline T&
446 {
447  NS_ASSERT_MSG(index < m_values.size(),
448  "Invalid index to 1D ValArray. The size of the array should be set through "
449  "constructor.");
450  NS_ASSERT_MSG(((m_numRows == 1 || m_numCols == 1) && (m_numPages == 1)) ||
451  (m_numRows == 1 && m_numCols == 1),
452  "Access operator allowed only for 1D ValArray.");
453  return m_values[index];
454 }
455 
456 template <class T>
457 inline const T&
458 ValArray<T>::operator()(size_t index) const
459 {
460  NS_ASSERT_MSG(index < m_values.size(),
461  "Invalid index to 1D ValArray.The size of the array should be set through "
462  "constructor.");
463  NS_ASSERT_MSG(((m_numRows == 1 || m_numCols == 1) && (m_numPages == 1)) ||
464  (m_numRows == 1 && m_numCols == 1),
465  "Access operator allowed only for 1D ValArray.");
466  return m_values[index];
467 }
468 
469 template <class T>
470 inline ValArray<T>
471 ValArray<T>::operator*(const T& rhs) const
472 {
473  return ValArray<T>(m_numRows,
474  m_numCols,
475  m_numPages,
476  m_values * std::valarray<T>(rhs, m_numRows * m_numCols * m_numPages));
477 }
478 
479 template <class T>
480 inline ValArray<T>
482 {
483  AssertEqualDims(rhs);
484  return ValArray<T>(m_numRows, m_numCols, m_numPages, m_values + rhs.m_values);
485 }
486 
487 template <class T>
488 inline ValArray<T>
490 {
491  AssertEqualDims(rhs);
492  return ValArray<T>(m_numRows, m_numCols, m_numPages, m_values - rhs.m_values);
493 }
494 
495 template <class T>
496 inline ValArray<T>
498 {
499  return ValArray<T>(m_numRows, m_numCols, m_numPages, -m_values);
500 }
501 
502 template <class T>
503 inline ValArray<T>&
505 {
506  AssertEqualDims(rhs);
507  m_values += rhs.m_values;
508  return *this;
509 }
510 
511 template <class T>
512 inline ValArray<T>&
514 {
515  AssertEqualDims(rhs);
516  m_values -= rhs.m_values;
517  return *this;
518 }
519 
520 template <class T>
521 inline T*
522 ValArray<T>::GetPagePtr(size_t pageIndex)
523 {
524  NS_ASSERT_MSG(pageIndex < m_numPages, "Invalid page index.");
525  return &(m_values[m_numRows * m_numCols * pageIndex]);
526 }
527 
528 template <class T>
529 inline const T*
530 ValArray<T>::GetPagePtr(size_t pageIndex) const
531 {
532  NS_ASSERT_MSG(pageIndex < m_numPages, "Invalid page index.");
533  return &(m_values[m_numRows * m_numCols * pageIndex]);
534 }
535 
536 template <class T>
537 inline bool
539 {
540  return (m_numRows == rhs.m_numRows) && (m_numCols == rhs.m_numCols) &&
541  (m_numPages == rhs.m_numPages);
542 }
543 
544 template <class T>
545 inline T&
547 {
548  return (*this)(index);
549 }
550 
551 template <class T>
552 inline const T&
553 ValArray<T>::operator[](size_t index) const
554 {
555  return (*this)(index);
556 }
557 
558 template <class T>
559 inline const std::valarray<T>&
561 {
562  return m_values;
563 }
564 
565 template <class T>
566 inline T&
567 ValArray<T>::Elem(size_t row, size_t col, size_t page)
568 {
569  return (*this)(row, col, page);
570 }
571 
572 template <class T>
573 inline const T&
574 ValArray<T>::Elem(size_t row, size_t col, size_t page) const
575 {
576  return (*this)(row, col, page);
577 }
578 
579 /*************************************************
580  ** Class ValArray non-inline implementations
581  ************************************************/
582 
583 template <class T>
584 ValArray<T>::ValArray(size_t numRows, size_t numCols, size_t numPages)
585  : m_numRows{numRows},
586  m_numCols{numCols},
587  m_numPages{numPages}
588 {
590 }
591 
592 template <class T>
593 ValArray<T>::ValArray(const std::valarray<T>& values)
594  : m_numRows{values.size()},
595  m_numCols{1},
596  m_numPages{1},
597  m_values{values}
598 {
599 }
600 
601 template <class T>
602 ValArray<T>::ValArray(std::valarray<T>&& values)
603  : m_numRows{values.size()},
604  m_numCols{1},
605  m_numPages{1},
606  m_values{std::move(values)}
607 {
608 }
609 
610 template <class T>
611 ValArray<T>::ValArray(const std::vector<T>& values)
612  : m_numRows{values.size()},
613  m_numCols{1},
614  m_numPages{1}
615 {
616  m_values.resize(values.size());
617  std::copy(values.begin(), values.end(), std::begin(m_values));
618 }
619 
620 template <class T>
621 ValArray<T>::ValArray(size_t numRows, size_t numCols, const std::valarray<T>& values)
622  : m_numRows{numRows},
623  m_numCols{numCols},
624  m_numPages{1},
625  m_values{values}
626 {
627  NS_ASSERT_MSG(m_numRows * m_numCols == values.size(),
628  "Dimensions and the initialization array size do not match.");
629 }
630 
631 template <class T>
632 ValArray<T>::ValArray(size_t numRows, size_t numCols, std::valarray<T>&& values)
633  : m_numRows{numRows},
634  m_numCols{numCols},
635  m_numPages{1}
636 {
637  NS_ASSERT_MSG(m_numRows * m_numCols == values.size(),
638  "Dimensions and the initialization array size do not match.");
639  m_values = std::move(values);
640 }
641 
642 template <class T>
643 ValArray<T>::ValArray(size_t numRows,
644  size_t numCols,
645  size_t numPages,
646  const std::valarray<T>& values)
647  : m_numRows{numRows},
648  m_numCols{numCols},
649  m_numPages{numPages},
650  m_values{values}
651 {
652  NS_ASSERT_MSG(m_numRows * m_numCols * m_numPages == values.size(),
653  "Dimensions and the initialization array size do not match.");
654 }
655 
656 template <class T>
657 ValArray<T>::ValArray(size_t numRows, size_t numCols, size_t numPages, std::valarray<T>&& values)
658  : m_numRows{numRows},
659  m_numCols{numCols},
660  m_numPages{numPages}
661 {
662  NS_ASSERT_MSG(m_numRows * m_numCols * m_numPages == values.size(),
663  "Dimensions and the initialization array size do not match.");
664  m_values = std::move(values);
665 }
666 
667 template <class T>
668 bool
670 {
671  return EqualDims(rhs) &&
672  std::equal(std::begin(m_values), std::end(m_values), std::begin(rhs.m_values));
673 }
674 
675 template <class T>
676 bool
678 {
679  return !((*this) == rhs);
680 }
681 
682 template <class T>
683 bool
684 ValArray<T>::IsAlmostEqual(const ValArray<T>& rhs, T tol) const
685 {
686  return EqualDims(rhs) && std::equal(std::begin(m_values),
687  std::end(m_values),
688  std::begin(rhs.m_values),
689  [tol](T lhsValue, T rhsValue) {
690  return lhsValue == rhsValue ||
691  std::abs(lhsValue - rhsValue) <= std::abs(tol);
692  });
693 }
694 
695 template <class T>
696 void
698 {
699  NS_ASSERT_MSG(EqualDims(rhs),
700  "Dimensions mismatch: "
701  "lhs (rows, cols, pages) = ("
702  << m_numRows << ", " << m_numCols << ", " << m_numPages
703  << ") and "
704  "rhs (rows, cols, pages) = ("
705  << rhs.m_numRows << ", " << rhs.m_numCols << ", " << rhs.m_numPages << ")");
706 }
707 
715 template <class T>
716 std::ostream&
717 operator<<(std::ostream& os, const ValArray<T>& a)
718 {
719  os << "\n";
720  for (size_t p = 0; p != a.GetNumPages(); ++p)
721  {
722  os << "Page " << p << ":\n";
723  for (size_t i = 0; i != a.GetNumRows(); ++i)
724  {
725  for (size_t j = 0; j != a.GetNumCols(); ++j)
726  {
727  os << "\t" << a(i, j, p);
728  }
729  os << "\n";
730  }
731  }
732  return os;
733 }
734 
735 } // namespace ns3
736 
737 #endif // VAL_ARRAY_H
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
A template-based reference counting class.
ValArray is a class to efficiently store 3D array.
Definition: val-array.h:80
T * GetPagePtr(size_t pageIndex)
Get a data pointer to a specific 2D array for use in linear algebra libraries.
Definition: val-array.h:522
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:697
ValArray< T > & operator=(ValArray< T > &&)=default
Move assignment operator.
T & operator()(size_t rowIndex, size_t colIndex, size_t pageIndex)
Access operator, with bound-checking in debug profile.
Definition: val-array.h:407
T & Elem(size_t row, size_t col, size_t page)
Alternative access operator to access a specific element.
Definition: val-array.h:567
ValArray operator+(const ValArray< T > &rhs) const
operator+ definition for ValArray<T>.
Definition: val-array.h:481
ValArray(const ValArray< T > &)=default
instruct the compiler to generate the implicitly declared copy constructor
ValArray(ValArray< T > &&)=default
instruct the compiler to generate the implicitly declared move constructor
const std::valarray< T > & GetValues() const
Returns underlying values.
Definition: val-array.h:560
ValArray< T > & operator+=(const ValArray< T > &rhs)
operator+= definition for ValArray<T>.
Definition: val-array.h:504
bool IsAlmostEqual(const ValArray< T > &rhs, T tol) const
Compare Valarray up to a given absolute tolerance.
Definition: val-array.h:684
bool operator!=(const ValArray< T > &rhs) const
operator!= definition for ValArray<T>.
Definition: val-array.h:677
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:546
ValArray & operator=(const ValArray< T > &)=default
Copy assignment operator.
bool operator==(const ValArray< T > &rhs) const
operator== definition for ValArray<T>.
Definition: val-array.h:669
size_t GetNumPages() const
Definition: val-array.h:393
size_t GetSize() const
Definition: val-array.h:400
size_t m_numCols
The size of the second dimension, i.e., the number of columns of each 2D array.
Definition: val-array.h:367
std::valarray< T > m_values
The data values.
Definition: val-array.h:370
ValArray< T > & operator-=(const ValArray< T > &rhs)
operator-= definition for ValArray<T>.
Definition: val-array.h:513
ValArray()=default
size_t GetNumRows() const
Definition: val-array.h:379
size_t m_numRows
The size of the first dimension, i.e., the number of rows of each 2D array.
Definition: val-array.h:365
bool EqualDims(const ValArray< T > &rhs) const
Checks whether rhs and lhs ValArray objects have the same dimensions.
Definition: val-array.h:538
size_t GetNumCols() const
Definition: val-array.h:386
size_t m_numPages
The size of the third dimension, i.e., the number of 2D arrays.
Definition: val-array.h:369
ValArray operator*(const T &rhs) const
Element-wise multiplication with a scalar value.
Definition: val-array.h:471
ValArray operator-() const
unary operator- definition for ValArray<T>.
Definition: val-array.h:497
virtual ~ValArray()=default
instruct the compiler to generate the implicitly declared destructor
#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:159
ns3::SimpleRefCount declaration and template implementation.