NumCpp  1.0
A C++ implementation of the Python Numpy library
average.hpp
Go to the documentation of this file.
1 #pragma once
30 
31 #include "NumCpp/Core/Shape.hpp"
32 #include "NumCpp/Core/Types.hpp"
39 #include "NumCpp/NdArray.hpp"
40 
41 #include <complex>
42 #include <string>
43 
44 namespace nc
45 {
46  //============================================================================
47  // Method Description:
57  template<typename dtype>
58  auto average(const NdArray<dtype>& inArray, Axis inAxis = Axis::NONE)
59  {
60  return mean(inArray, inAxis);
61  }
62 
63  //============================================================================
64  // Method Description:
75  template<typename dtype>
76  NdArray<double> average(const NdArray<dtype>& inArray, const NdArray<dtype>& inWeights, Axis inAxis = Axis::NONE)
77  {
79 
80  switch (inAxis)
81  {
82  case Axis::NONE:
83  {
84  if (inWeights.shape() != inArray.shape())
85  {
86  THROW_INVALID_ARGUMENT_ERROR("input array and weight values are not consistant.");
87  }
88 
89  NdArray<double> weightedArray(inArray.shape());
90  stl_algorithms::transform(inArray.cbegin(), inArray.cend(), inWeights.cbegin(),
91  weightedArray.begin(), std::multiplies<double>());
92 
93  double sum = std::accumulate(weightedArray.begin(), weightedArray.end(), 0.0);
94  NdArray<double> returnArray = { sum /= inWeights.template astype<double>().sum().item() };
95 
96  return returnArray;
97  }
98  case Axis::COL:
99  {
100  const Shape arrayShape = inArray.shape();
101  if (inWeights.size() != arrayShape.cols)
102  {
103  THROW_INVALID_ARGUMENT_ERROR("input array and weights value are not consistant.");
104  }
105 
106  double weightSum = inWeights.template astype<double>().sum().item();
107  NdArray<double> returnArray(1, arrayShape.rows);
108  for (uint32 row = 0; row < arrayShape.rows; ++row)
109  {
110  NdArray<double> weightedArray(1, arrayShape.cols);
111  stl_algorithms::transform(inArray.cbegin(row), inArray.cend(row), inWeights.cbegin(),
112  weightedArray.begin(), std::multiplies<double>());
113 
114  double sum = std::accumulate(weightedArray.begin(), weightedArray.end(), 0.0);
115  returnArray(0, row) = sum / weightSum;
116  }
117 
118  return returnArray;
119  }
120  case Axis::ROW:
121  {
122  if (inWeights.size() != inArray.shape().rows)
123  {
124  THROW_INVALID_ARGUMENT_ERROR("input array and weight values are not consistant.");
125  }
126 
127  NdArray<dtype> transposedArray = inArray.transpose();
128 
129  const Shape transShape = transposedArray.shape();
130  double weightSum = inWeights.template astype<double>().sum().item();
131  NdArray<double> returnArray(1, transShape.rows);
132  for (uint32 row = 0; row < transShape.rows; ++row)
133  {
134  NdArray<double> weightedArray(1, transShape.cols);
135  stl_algorithms::transform(transposedArray.cbegin(row), transposedArray.cend(row), inWeights.cbegin(),
136  weightedArray.begin(), std::multiplies<double>());
137 
138  double sum = std::accumulate(weightedArray.begin(), weightedArray.end(), 0.0);
139  returnArray(0, row) = sum / weightSum;
140  }
141 
142  return returnArray;
143  }
144  default:
145  {
146  // this isn't actually possible, just putting this here to get rid
147  // of the compiler warning.
148  return NdArray<double>(0);
149  }
150  }
151  }
152 
153  //============================================================================
154  // Method Description:
165  template<typename dtype>
166  NdArray<std::complex<double>> average(const NdArray<std::complex<dtype>>& inArray,
167  const NdArray<dtype>& inWeights, Axis inAxis = Axis::NONE)
168  {
170 
171  const auto multiplies = [](const std::complex<dtype>& lhs, dtype rhs) -> std::complex<double>
172  {
173  return complex_cast<double>(lhs) * static_cast<double>(rhs);
174  };
175 
176  switch (inAxis)
177  {
178  case Axis::NONE:
179  {
180  if (inWeights.shape() != inArray.shape())
181  {
182  THROW_INVALID_ARGUMENT_ERROR("input array and weight values are not consistant.");
183  }
184 
185  NdArray<std::complex<double>> weightedArray(inArray.shape());
186  stl_algorithms::transform(inArray.cbegin(), inArray.cend(), inWeights.cbegin(),
187  weightedArray.begin(), multiplies);
188 
189  std::complex<double> sum = std::accumulate(weightedArray.begin(), weightedArray.end(), std::complex<double>(0.0));
190  NdArray<std::complex<double>> returnArray = { sum /= inWeights.template astype<double>().sum().item() };
191 
192  return returnArray;
193  }
194  case Axis::COL:
195  {
196  const Shape arrayShape = inArray.shape();
197  if (inWeights.size() != arrayShape.cols)
198  {
199  THROW_INVALID_ARGUMENT_ERROR("input array and weights value are not consistant.");
200  }
201 
202  double weightSum = inWeights.template astype<double>().sum().item();
203  NdArray<std::complex<double>> returnArray(1, arrayShape.rows);
204  for (uint32 row = 0; row < arrayShape.rows; ++row)
205  {
206  NdArray<std::complex<double>> weightedArray(1, arrayShape.cols);
207  stl_algorithms::transform(inArray.cbegin(row), inArray.cend(row), inWeights.cbegin(),
208  weightedArray.begin(), multiplies);
209 
210  const std::complex<double> sum = std::accumulate(weightedArray.begin(), weightedArray.end(),
211  std::complex<double>(0.0));
212  returnArray(0, row) = sum / weightSum;
213  }
214 
215  return returnArray;
216  }
217  case Axis::ROW:
218  {
219  if (inWeights.size() != inArray.shape().rows)
220  {
221  THROW_INVALID_ARGUMENT_ERROR("input array and weight values are not consistant.");
222  }
223 
224  NdArray<std::complex<dtype>> transposedArray = inArray.transpose();
225 
226  const Shape transShape = transposedArray.shape();
227  double weightSum = inWeights.template astype<double>().sum().item();
228  NdArray<std::complex<double>> returnArray(1, transShape.rows);
229  for (uint32 row = 0; row < transShape.rows; ++row)
230  {
231  NdArray<std::complex<double>> weightedArray(1, transShape.cols);
232  stl_algorithms::transform(transposedArray.cbegin(row), transposedArray.cend(row), inWeights.cbegin(),
233  weightedArray.begin(), multiplies);
234 
235  const std::complex<double> sum = std::accumulate(weightedArray.begin(), weightedArray.end(),
236  std::complex<double>(0.0));
237  returnArray(0, row) = sum / weightSum;
238  }
239 
240  return returnArray;
241  }
242  default:
243  {
244  // this isn't actually possible, just putting this here to get rid
245  // of the compiler warning.
246  return NdArray<std::complex<double>>(0);
247  }
248  }
249  }
250 }
StaticAsserts.hpp
nc::NdArray::item
value_type item() const
Definition: NdArrayCore.hpp:2950
nc::NdArray::shape
Shape shape() const noexcept
Definition: NdArrayCore.hpp:4296
nc::Axis::NONE
@ NONE
Error.hpp
STATIC_ASSERT_ARITHMETIC
#define STATIC_ASSERT_ARITHMETIC(dtype)
Definition: StaticAsserts.hpp:38
nc::Axis::ROW
@ ROW
StdComplexOperators.hpp
nc::mean
NdArray< double > mean(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition: mean.hpp:54
nc::NdArray::transpose
NdArray< dtype > transpose() const
Definition: NdArrayCore.hpp:4591
nc::NdArray< dtype >
nc::uint32
std::uint32_t uint32
Definition: Types.hpp:41
NdArray.hpp
nc::Shape
A Shape Class for NdArrays.
Definition: Core/Shape.hpp:41
nc::NdArray::end
iterator end() noexcept
Definition: NdArrayCore.hpp:1435
nc::NdArray::size
size_type size() const noexcept
Definition: NdArrayCore.hpp:4310
nc::Shape::cols
uint32 cols
Definition: Core/Shape.hpp:46
nc::NdArray::sum
NdArray< dtype > sum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:4411
nc::sum
NdArray< dtype > sum(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition: sum.hpp:48
nc::NdArray::cend
const_iterator cend() const noexcept
Definition: NdArrayCore.hpp:1491
nc::Axis
Axis
Enum To describe an axis.
Definition: Types.hpp:47
Shape.hpp
nc
Definition: Coordinate.hpp:45
nc::Shape::rows
uint32 rows
Definition: Core/Shape.hpp:45
THROW_INVALID_ARGUMENT_ERROR
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:37
nc::stl_algorithms::transform
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction) noexcept
Definition: StlAlgorithms.hpp:703
nc::NdArray::cbegin
const_iterator cbegin() const noexcept
Definition: NdArrayCore.hpp:1147
StlAlgorithms.hpp
Types.hpp
nc::NdArray::begin
iterator begin() noexcept
Definition: NdArrayCore.hpp:1091
nc::Axis::COL
@ COL
TypeTraits.hpp
mean.hpp
nc::average
auto average(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition: average.hpp:58