MCL
A C++ library mirroring some of the most common Matlab functions.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
vectorop.h
Go to the documentation of this file.
1 /*
2  MCL
3  Copyright (c) 2012-18, Enzo De Sena
4  All rights reserved.
5 
6  Authors: Enzo De Sena, enzodesena@gmail.com
7  */
8 
9 #ifndef MCL_VECTOROP_H
10 #define MCL_VECTOROP_H
11 
12 
13 #include "mcltypes.h"
14 #include "elementaryop.h"
15 #include "basicop.h"
16 #include "matrixop.h"
17 #include <vector>
18 #include <iostream>
19 
20 namespace mcl {
21 
22 
23 
25 template<class T>
26 Int Length(const std::vector<T>& input) noexcept {
27  return (UInt) input.size();
28 }
29 
30 
32 template <class T>
33 std::vector<T> Zeros(Int length) noexcept {
34  //TODO: check if this returns zeros for all types
35  return std::vector<T>(length);
36 }
37 
38 template <class T>
39 std::vector<T> EmptyVector() noexcept {
40  return std::vector<T>();
41 }
42 
48 template<class T>
49 std::vector<T> ZeroPad(const std::vector<T>& input,
50  const Int total_length) noexcept {
51  std::vector<T> output = Zeros<T>(total_length);
52  Int M = ((Int)input.size() < total_length) ? input.size() : total_length;
53  for (Int i=0; i<M; ++i) { output[i] = input[i]; }
54  return output;
55 }
56 
57 
58 
63 template<class T>
64 std::vector<T> Multiply(const std::vector<T>& vector,
65  const T gain) noexcept {
66  std::vector<T> output(vector.size());
67  for (Int i=0; i<(Int)vector.size(); ++i) {
68  output[i] = vector[i]*gain;
69  }
70  return output;
71 }
72 
73 
74 void Multiply(const Real* input_data,
75  const Int num_samples,
76  const Real gain,
77  Real* output_data) noexcept;
78 
79 template<>
80 inline std::vector<Real> Multiply(const std::vector<Real>& input,
81  const Real gain) noexcept {
82  std::vector<Real> output(input.size());
83  Multiply(input.data(), input.size(), gain, output.data());
84  return output;
85 }
86 
90 void MultiplyAdd(const Real* input_data_mult,
91  const Real gain,
92  const Real* input_data_add,
93  const Int num_samples,
94  Real* output_data) noexcept;
95 
96 
101 template<class T>
102 std::vector<T> Add(const std::vector<T>& vector_a,
103  const T scalar) noexcept {
104  std::vector<T> output((Int)vector_a.size());
105  for (Int i=0; i<(Int)vector_a.size(); ++i) {
106  output[i] = vector_a[i]+scalar;
107  }
108  return output;
109 }
110 
111 
112 Real Add(const Real* input_data, const Int num_samples) noexcept;
113 
114 
120 template<class T>
121 std::vector<T> Subset(const std::vector<T>& vector,
122  const Int from_index, const Int to_index) noexcept {
123  ASSERT(from_index < (Int)vector.size());
124  ASSERT(to_index < (Int)vector.size());
125  ASSERT(from_index <= to_index);
126 
127  return std::vector<T>(vector.begin() + from_index,
128  vector.begin() + to_index + 1);
129 }
130 
131 
136 template<class T>
137 std::vector<T> Concatenate(std::vector<T> vector_a,
138  const std::vector<T>& vector_b) noexcept {
139  std::vector<T> output = Zeros<T>((Int)vector_a.size()+(Int)vector_b.size());
140  vector_a.insert(vector_a.end(), vector_b.begin(), vector_b.end());
141  return vector_a;
142 }
143 
144 
146 template<class T>
147 std::vector<T> UnaryVector(const T& element) noexcept {
148  std::vector<T> output(1, element);
149  return output;
150 }
151 
153 template<class T>
154 std::vector<T> BinaryVector(const T& element_a, const T& element_b) noexcept {
155  std::vector<T> output(2);
156  output[0] = element_a;
157  output[1] = element_b;
158  return output;
159 }
160 
165 template<class T>
166 std::vector<T> Flip(std::vector<T> vector) noexcept {
167  if (vector.size() <= 1) { return vector; }
168  Int N(Length(vector));
169  for (Int i=0; i<=((Int) (floor(N/2)-1)); ++i) {
170  T temp_value = vector[i];
171  vector[i] = vector[N-i-1];
172  vector[N-i-1] = temp_value;
173  }
174  return vector;
175 }
176 
181 template<class T>
182 std::vector<T> CircShift(const std::vector<T>& vector,
183  Int num_positions) noexcept {
184  Int N = vector.size();
185  std::vector<T> output(N);
186  for (Int i=0; i<N; ++i) {
187  Int index = (UInt) Mod(((Int) i) - num_positions, (Int) N);
188  output[i] = vector[index];
189  }
190 
191  return output;
192 }
193 
195 template<class T>
196 std::vector<T> Conv(const std::vector<T>& vector_a,
197  const std::vector<T>& vector_b) noexcept {
198  Int N_a = (Int)vector_a.size();
199  Int N_b = (Int)vector_b.size();
200  Int out_length = N_a+N_b-1;
201 
202  std::vector<T> moving_vector_temp = Concatenate(Zeros<T>(N_b-1),
203  Flip(vector_a));
204  std::vector<T> moving_vector_a = Concatenate(moving_vector_temp,
205  Zeros<T>(N_b-1));
206 
207  std::vector<T> output = Zeros<T>(out_length);
208  for (Int n=0; n<out_length; ++n) {
209  for (Int m=0; m<N_b; ++m) {
210  output[out_length-n-1] += moving_vector_a[n+m]*vector_b[m];
211  }
212  }
213  return output;
214 }
215 
216 
221 template<class T>
222 std::vector<T>
223 AddVectors(const std::vector<std::vector<T> >& vectors) noexcept {
224  // Get maximum length
225  std::vector<Int> vector_lengths(vectors.size());
226  for (Int i=0; i<(Int)vectors.size(); ++i) {
227  vector_lengths[i] = (Int)vectors[i].size();
228  }
229  Int max_length(Max(vector_lengths));
230 
231  std::vector<T> output = Zeros<T>(max_length);
232  for (Int i=0; i<(Int)vectors.size(); ++i) {
233  output = Add(output, ZeroPad(vectors[i], max_length));
234  }
235 
236  return output;
237 }
238 
243 template<class T>
244 std::vector<T> AddVectors(const std::vector<T>& vector_a,
245  const std::vector<T>& vector_b) noexcept {
246  // Get maximum length
247  Int max_length(Max((Int)vector_a.size(), (Int)vector_b.size()));
248 
249  std::vector<T> output = Zeros<T>(max_length);
250  output = Add(output, ZeroPad(vector_a, max_length));
251  output = Add(output, ZeroPad(vector_b, max_length));
252 
253  return output;
254 }
255 
256 
259 template<class T>
260 std::vector<T> Interleave(const std::vector<T>& vector_a,
261  const std::vector<T>& vector_b) noexcept {
262  ASSERT(vector_a.size() == vector_b.size());
263 
264  std::vector<T> output;
265  for (Int i=0; i<(Int)vector_a.size(); ++i) {
266  output.push_back(vector_a[i]);
267  output.push_back(vector_b[i]);
268  }
269  return output;
270 }
271 
274 template<class T>
275 std::vector<T> Downsample(const std::vector<T>& vector,
276  const Int downsampling_factor) noexcept {
277  ASSERT(downsampling_factor >= 1);
278  std::vector<T> output;
279  for (Int i=0; i<(Int)vector.size(); i += downsampling_factor) {
280  output.push_back(vector[i]);
281  }
282  return output;
283 }
284 
289 template<class T>
290 std::vector<T> ColonOperator(const Int from, const Int to) noexcept {
291  if ((to-from) < 0) { return EmptyVector<T>(); }
292  const Int vector_length = (UInt) (to-from+1);
293  std::vector<T> output(vector_length);
294  for (Int i=0; i<vector_length; ++i) {
295  output[i] = ((T) i) + ((T) from);
296  }
297  return output;
298 }
299 
304 // TODO: implement negative step and fractional input.
305 std::vector<Real>
306 ColonOperator(const Real from, const Real step, const Real to) noexcept;
307 
308 
313 template<class T>
314 std::vector<T> Elements(const std::vector<T>& vector,
315  const Int from_id,
316  const Int to_id) noexcept {
317  return std::vector<T>(vector.begin() + ((Int)from_id),
318  vector.begin() + ((Int)to_id)+1);
319 }
320 
321 
322 template<class T>
323 std::vector<T> GetSegment(const std::vector<T>& vector,
324  const Int subset_id,
325  const Int subset_length,
326  bool zeropad_if_shorter = false) noexcept {
327  const Int size = vector.size();
328 
329  const Int from_sample = subset_id * subset_length;
330  if (from_sample >= size) {
331  if (zeropad_if_shorter) {
332  return Zeros<T>(subset_length);
333  } else {
334  return std::vector<T>(); // Return empty vector
335  }
336  }
337 
338  const Int to_sample = Min(from_sample + subset_length - 1,
339  size - 1);
340 
341  const Int actual_length = to_sample - from_sample + 1;
342  if (zeropad_if_shorter && actual_length < subset_length) {
343  return ZeroPad(Elements(vector, from_sample, to_sample), subset_length);
344  } else {
345  return Elements(vector, from_sample, to_sample);
346  }
347 }
348 
353 template<class T>
354 T Prod(const std::vector<T>& vector) noexcept {
355  const Int num_elements = vector.size();
356  T output = (T) 1.0;
357  for (Int i=0; i<num_elements; ++i) { output *= vector[i]; }
358  return output;
359 }
360 
362 template<class T>
363 T Dot(const std::vector<T>& vector_a,
364  const std::vector<T>& vector_b) noexcept {
365  const Int num_elements = (Int)vector_a.size();
366  ASSERT(num_elements == (Int)vector_b.size());
367 
368  T output = (T) 0.0;
369  for (Int i=0; i<num_elements; ++i) {
370  output += vector_a[i]*vector_b[i];
371  }
372  return output;
373 }
374 
375 Real Norm(const std::vector<Real>& vector,
376  Real l_norm = 2.0) noexcept;
377 
378 template<class T>
379 void Print(const T* vector, const Int num_elements) noexcept {
380  std::cout<<"\n------------\n";
381  for (Int i=0; i<num_elements; ++i) {
382  std::cout<<vector[i]<<std::endl;
383  }
384  std::cout<<"------------\n";
385 }
386 
387 template<class T>
388 void Print(const std::vector<T>& vector) noexcept {
389  Print(vector.data(), vector.size());
390 }
391 
393 std::vector<Real> Ones(Int length) noexcept;
394 
395 
396 std::vector<Real> Hann(const Int length) noexcept;
397 
399 std::vector<Real> Hamming(const Int length) noexcept;
400 
401 std::vector<Real> TukeyWin(const Int length,
402  const Real ratio) noexcept;
403 
404 
406 std::vector<Real> LinSpace(Real min, Real max,
407  Int num_elements) noexcept;
408 
409 
410 Real Sum(const std::vector<Real>& input) noexcept;
411 
413 Real Mean(const std::vector<Real>& input) noexcept;
414 
419 Real Geomean(const std::vector<Real>& input) noexcept;
420 
426 Real Mean(const std::vector<Real>& input,
427  const std::vector<Real>& weigths) noexcept;
428 
433 Real Std(const std::vector<Real>& input) noexcept;
434 
436 Real Var(const std::vector<Real>& input) noexcept;
437 
439 Real Var(const std::vector<Real>& input,
440  const std::vector<Real>& weights) noexcept;
441 
443 std::vector<std::string> Split(const std::string& string,
444  char delim) noexcept;
445 
447 std::vector<Complex> Poly(const std::vector<Complex> roots) noexcept;
448 std::vector<Complex> Poly(const std::vector<Real> roots) noexcept;
449 
451 bool IsNonNegative(const std::vector<Real>& input) noexcept;
452 
454 bool VectorOpTest();
455 
456 Matrix<Real> Cov(const std::vector<Real>& x,
457  const std::vector<Real>& y) noexcept;
458 
459 Matrix<Real> Cov(const std::vector<std::vector<Real> >& input) noexcept;
460 
461 Real CovElement(const std::vector<Real>& x,
462  const std::vector<Real>& y) noexcept;
463 
468 std::vector<Real> CumSum(const std::vector<Real>& input) noexcept;
469 
471 std::vector<std::vector<Real> > Enframe(const std::vector<Real>& input,
472  const std::vector<Real>& window,
473  const Int frame_increment) noexcept;
474 
475 std::vector<Real> OverlapAdd(const std::vector<std::vector<Real> >& frames,
476  const std::vector<Real>& window,
477  const Int frame_increment) noexcept;
478 
479 std::vector<Complex> ConvertToComplex(std::vector<Real> input) noexcept;
480 
481 }
483 #endif