NumCpp  2.1.0
A C++ implementation of the Python Numpy library
average.hpp
Go to the documentation of this file.
1 #pragma once
30 
36 #include "NumCpp/Core/Shape.hpp"
37 #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  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
147  return {};
148  }
149  }
150  }
151 
152  //============================================================================
153  // Method Description:
164  template<typename dtype>
165  NdArray<std::complex<double>> average(const NdArray<std::complex<dtype>>& inArray,
166  const NdArray<dtype>& inWeights, Axis inAxis = Axis::NONE)
167  {
169 
170  const auto multiplies = [](const std::complex<dtype>& lhs, dtype rhs) -> std::complex<double>
171  {
172  return complex_cast<double>(lhs) * static_cast<double>(rhs);
173  };
174 
175  switch (inAxis)
176  {
177  case Axis::NONE:
178  {
179  if (inWeights.shape() != inArray.shape())
180  {
181  THROW_INVALID_ARGUMENT_ERROR("input array and weight values are not consistant.");
182  }
183 
184  NdArray<std::complex<double>> weightedArray(inArray.shape());
185  stl_algorithms::transform(inArray.cbegin(), inArray.cend(), inWeights.cbegin(),
186  weightedArray.begin(), multiplies);
187 
188  std::complex<double> sum = std::accumulate(weightedArray.begin(), weightedArray.end(), std::complex<double>(0.0));
189  NdArray<std::complex<double>> returnArray = { sum /= inWeights.template astype<double>().sum().item() };
190 
191  return returnArray;
192  }
193  case Axis::COL:
194  {
195  const Shape arrayShape = inArray.shape();
196  if (inWeights.size() != arrayShape.cols)
197  {
198  THROW_INVALID_ARGUMENT_ERROR("input array and weights value are not consistant.");
199  }
200 
201  double weightSum = inWeights.template astype<double>().sum().item();
202  NdArray<std::complex<double>> returnArray(1, arrayShape.rows);
203  for (uint32 row = 0; row < arrayShape.rows; ++row)
204  {
205  NdArray<std::complex<double>> weightedArray(1, arrayShape.cols);
206  stl_algorithms::transform(inArray.cbegin(row), inArray.cend(row), inWeights.cbegin(),
207  weightedArray.begin(), multiplies);
208 
209  const std::complex<double> sum = std::accumulate(weightedArray.begin(), weightedArray.end(),
210  std::complex<double>(0.0));
211  returnArray(0, row) = sum / weightSum;
212  }
213 
214  return returnArray;
215  }
216  case Axis::ROW:
217  {
218  if (inWeights.size() != inArray.shape().rows)
219  {
220  THROW_INVALID_ARGUMENT_ERROR("input array and weight values are not consistant.");
221  }
222 
223  NdArray<std::complex<dtype>> transposedArray = inArray.transpose();
224 
225  const Shape transShape = transposedArray.shape();
226  double weightSum = inWeights.template astype<double>().sum().item();
227  NdArray<std::complex<double>> returnArray(1, transShape.rows);
228  for (uint32 row = 0; row < transShape.rows; ++row)
229  {
230  NdArray<std::complex<double>> weightedArray(1, transShape.cols);
231  stl_algorithms::transform(transposedArray.cbegin(row), transposedArray.cend(row), inWeights.cbegin(),
232  weightedArray.begin(), multiplies);
233 
234  const std::complex<double> sum = std::accumulate(weightedArray.begin(), weightedArray.end(),
235  std::complex<double>(0.0));
236  returnArray(0, row) = sum / weightSum;
237  }
238 
239  return returnArray;
240  }
241  default:
242  {
243  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
244  return {}; // get rid of compiler warning
245  }
246  }
247  }
248 } // namespace nc
StaticAsserts.hpp
nc::NdArray::item
value_type item() const
Definition: NdArrayCore.hpp:2958
nc::NdArray::shape
Shape shape() const noexcept
Definition: NdArrayCore.hpp:4312
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:4608
nc::NdArray< dtype >
nc::stl_algorithms::transform
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction)
Definition: StlAlgorithms.hpp:703
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:4326
nc::Shape::cols
uint32 cols
Definition: Core/Shape.hpp:46
nc::NdArray::sum
NdArray< dtype > sum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:4427
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::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