audio_wm/vector.h

340 lines
11 KiB
C
Raw Permalink Normal View History

2025-02-10 23:13:41 +08:00
#ifndef VECTOR_H
#define VECTOR_H
#include <algorithm>
#include <cmath>
#include <functional>
#include <iomanip>
#include <numeric>
#include <ostream>
#include <vector>
namespace Vector {
//===========================================================================
// This header contains a definition for all the most common mathematical
// operations on vectors implemented as overlading of standard operators.
//===========================================================================
//===========================================================================
// Binary vector-vector operations
//===========================================================================
// Element-wise vector addition (vector1+vector2)
template<typename T>
std::vector<T> operator+(std::vector<T> vector1, const std::vector<T>& vector2) {
if(vector1.size() != vector2.size()) {
throw std::invalid_argument("std::vector operator+");
}
// This is actually implemented as vector1 += vector2, so the first
// parameter is passed by copy and then overwritten with the result
std::transform(vector1.begin(), vector1.end(), vector2.begin(), vector1.begin(), std::plus<T>());
return vector1;
}
// Element-wise vector addition and assignment (vector1+=vector2)
template<typename T>
std::vector<T>& operator+=(std::vector<T>& vector1, const std::vector<T>& vector2) {
if(vector1.size() != vector2.size()) {
throw std::invalid_argument("std::vector operator+=");
}
// The first parameter is passed by reference, modified and returned
std::transform(vector1.begin(), vector1.end(), vector2.begin(), vector1.begin(), std::plus<T>());
return vector1;
}
// Element-wise vector subtraction (vector1-vector2)
template<typename T>
std::vector<T> operator-(std::vector<T> vector1, const std::vector<T>& vector2) {
if(vector1.size() != vector2.size()) {
throw std::invalid_argument("std::vector operator-");
}
std::transform(vector1.begin(), vector1.end(), vector2.begin(), vector1.begin(), std::minus<T>());
return vector1;
}
// Element-wise vector subtraction and assignment (vector1-=vector2)
template<typename T>
std::vector<T>& operator-=(std::vector<T>& vector1, const std::vector<T>& vector2) {
if(vector1.size()!=vector2.size()) {
throw std::invalid_argument("std::vector operator-=");
}
std::transform(vector1.begin(), vector1.end(), vector2.begin(), vector1.begin(), std::minus<T>());
return vector1;
}
// Element-wise vector multiplication (vector1*vector2)
template<typename T>
std::vector<T> operator*(std::vector<T> vector1, const std::vector<T>& vector2) {
if(vector1.size() != vector2.size()) {
throw std::invalid_argument("std::vector operator*");
}
std::transform(vector1.begin(), vector1.end(), vector2.begin(), vector1.begin(), std::multiplies<T>());
return vector1;
}
// Element-wise vector multiplication and assignment (vector1*=vector2)
template<typename T>
std::vector<T>& operator*=(std::vector<T>& vector1, const std::vector<T>& vector2) {
if(vector1.size() != vector2.size()) {
throw std::invalid_argument("std::vector operator*=");
}
std::transform(vector1.begin(), vector1.end(), vector2.begin(), vector1.begin(), std::multiplies<T>());
return vector1;
}
// Element-wise vector division (vector1/vector2)
template<typename T>
std::vector<T> operator/(std::vector<T> vector1, const std::vector<T>& vector2) {
if(vector1.size() != vector2.size()) {
throw std::invalid_argument("std::vector operator/");
}
std::transform(vector1.begin(), vector1.end(), vector2.begin(), vector1.begin(), std::divides<T>());
return vector1;
}
// Element-wise vector division and assignment (vector1/=vector2)
template<typename T>
std::vector<T>& operator/=(std::vector<T>& vector1, const std::vector<T>& vector2) {
if(vector1.size() != vector2.size()) {
throw std::invalid_argument("std::vector operator/=");
}
std::transform(vector1.begin(), vector1.end(), vector2.begin(), vector1.begin(), std::divides<T>());
return vector1;
}
//===========================================================================
// Unary vector operations
//===========================================================================
// Element-wise vector negation (-vector)
template<typename T>
std::vector<T> operator-(std::vector<T> vector) {
std::transform(vector.begin(), vector.end(), vector.begin(), std::negate<T>());
return vector;
}
//===========================================================================
// Binary vector-scalar operations
//===========================================================================
// Right scalar vector addition (vector+scalar)
template<typename T>
std::vector<T> operator+(std::vector<T> vector, T scalar) {
std::transform(vector.begin(), vector.end(), vector.begin(), [&scalar](T value) {
return scalar + value;
});
return vector;
}
// Left scalar vector addition (scalar+vector)
template<typename T>
std::vector<T> operator+(T scalar, std::vector<T> vector) {
return vector + scalar;
}
// Right scalar vector subtraction (vector-scalar)
template<typename T>
std::vector<T> operator-(std::vector<T> vector, T scalar) {
std::transform(vector.begin(), vector.end(), vector.begin(), [&scalar](T value) {
return value - scalar;
});
return vector;
}
// Left scalar vector subtraction (scalar-vector)
template<typename T>
std::vector<T> operator-(T scalar, std::vector<T> vector) {
std::transform(vector.begin(), vector.end(), vector.begin(), [&scalar](T value) {
return scalar - value;
});
return vector;
}
// Right scalar vector multiplication (vector*scalar)
template<typename T>
std::vector<T> operator*(std::vector<T> vector, T scalar) {
std::transform(vector.begin(), vector.end(), vector.begin(), [&scalar](T value) {
return value * scalar;
});
return vector;
}
// Left scalar vector multiplication (scalar*vector)
template<typename T>
std::vector<T> operator*(T scalar, std::vector<T> vector) {
return vector * scalar;
}
// Right scalar vector division (vector/scalar)
template<typename T>
std::vector<T> operator/(std::vector<T> vector, T scalar) {
std::transform(vector.begin(), vector.end(), vector.begin(), [&scalar](T value) {
return value / scalar;
});
return vector;
}
// Left scalar vector division (scalar/vector)
template<typename T>
std::vector<T> operator/(T scalar, std::vector<T> vector) {
std::transform(vector.begin(), vector.end(), vector.begin(), [&scalar](T value) {
return scalar / value;
});
return vector;
}
// Vector power to the given scalar (vector^scalar)
template<typename T>
std::vector<T> operator^(std::vector<T> vector, T scalar) {
std::transform(vector.begin(), vector.end(), vector.begin(), [&scalar](T value) {
return std::pow(value, scalar);
});
return vector;
}
//===========================================================================
// Utils
//===========================================================================
// Element-wise round of vector
template<typename T>
void Round(std::vector<T>& vector) {
std::transform(vector.begin(), vector.end(), vector.begin(), [](T value) {
return std::round(value);
});
}
// Element-wise floor of vector
template<typename T>
void Floor(std::vector<T>& vector) {
std::transform(vector.begin(), vector.end(), vector.begin(), [](T value) {
return std::floor(value);
});
}
// Element-wise ceil of vector
template<typename T>
void Ceil(std::vector<T>& vector) {
std::transform(vector.begin(), vector.end(), vector.begin(), [](T value) {
return std::ceil(value);
});
}
// Element-wise clamp of vector
template<typename T>
void Clamp(std::vector<T>& vector, T min_value, T max_value) {
std::transform(vector.begin(), vector.end(), vector.begin(), [&min_value, &max_value](T value) {
return std::min(std::max(value, min_value), max_value);
});
}
// Get maximum value of vector
template<typename T>
T Max(const std::vector<T>& vector) {
return *std::max_element(vector.begin(), vector.end());
}
// Get minimum value of vector
template<typename T>
T Min(const std::vector<T>& vector) {
return *std::min_element(vector.begin(), vector.end());
}
// Sum of elements in vector
template<typename T>
T Sum(const std::vector<T>& vector) {
T val = 0;
val = std::accumulate(vector.begin(), vector.end(), val);
return val;
}
// Product of elements in vector
template<typename T>
T Prod(const std::vector<T>& vector) {
T val = 1;
val = std::accumulate(vector.begin(), vector.end(), val, std::multiplies<T>());
return val;
}
// Dot-product between vectors
template<typename T>
T Dot(const std::vector<T>& vector1, const std::vector<T>& vector2) {
return Sum(vector1 * vector2);
}
// Lp-norm of vector
template<typename T>
T LpNorm(const std::vector<T>& vector, T p) {
return Sum(vector ^ p) ^ (static_cast<T>(1) / p);
}
// L2-norm of vector
template<typename T>
T Norm(const std::vector<T>& vector) {
return std::sqrt(Dot(vector, vector));
}
// Normalise vector
template<typename T>
std::vector<T> Normalise(const std::vector<T>& vector) {
return vector / Norm(vector);
}
// Convolution types
enum ConvolutionType {
kFullConvolution = 0,
kSameConvolution,
kValidConvolution
};
// Convolution of vector with given filter
template<typename T>
std::vector<T> Conv(const std::vector<T>& vector, const std::vector<T>& filter, ConvolutionType convolutionType = kFullConvolution) {
const size_t vector_size = vector.size();
const size_t filter_size = filter.size();
if (filter_size > vector_size) {
throw std::invalid_argument("Conv");
}
// Compute convolution
size_t minI = 0;
size_t maxI = vector_size + filter_size - 1;
if (convolutionType == kSameConvolution) {
minI = filter_size / 2;
maxI = minI + vector_size;
}
else if (convolutionType == kValidConvolution) {
minI = filter_size - 1;
maxI = vector_size;
}
std::vector<T> output;
output.reserve(maxI - minI);
for (size_t i = minI; i < maxI; i++) {
const size_t minJ = (i < filter_size - 1) ? 0 : i - filter_size + 1;
const size_t maxJ = (i >= vector_size - 1) ? vector_size : i + 1;
T value = static_cast<T>(0);
for (size_t j = minJ; j < maxJ; j++) {
value += vector[j] * filter[i - j];
}
output.push_back(value);
}
return output;
}
} // namespace Vector
//=============================================================================
// Output to std::ostream
//=============================================================================
// Overloaded operator<< for std::vector<T>
template<typename T>
inline std::ostream& operator<<(std::ostream& out, const std::vector<T>& vector) {
for(size_t i = 0, endI = vector.size(); i < endI; i++) {
out << std::setw(8) << std::setprecision(4) << std::left << vector.at(i);
}
return out;
}
#endif // VECTOR_H