Files
Flux/include/utils/vector.h
T

239 lines
6.9 KiB
C++

#ifndef _vector_n_
#define _vector_n_
#include "iostream"
#include <vector>
#include <random>
namespace utils{
//######################################
//# VECTOR TYPE #
//# Backed by std::vector<T> #
//######################################
template<typename T>
class Vector{
public:
using value_type = T;
std::vector<T> v;
// Default construtor utils::Vd vector;
Vector() = default;
// Construtor utils::Vd vector(2, 3.15);
// Prevent implicit conversions like Vector<double> v = 5;
explicit Vector(uint64_t size, T value = T()) {
v.resize(size, value);
}
//##########################################################
//# VECTOR: --- basic properties --- #
//##########################################################
// vector.clear();
void clear() noexcept {v.clear();}
// vector.push_back(2);
void push_back(const T& val) { v.push_back(val); }
// vector[2] = 2;
T& operator[](uint64_t idx) { return v[idx]; }
// a = vector[2];
const T& operator[](uint64_t idx) const { return v[idx]; }
// vector.size();
uint64_t size() const noexcept { return v.size(); }
//###########################################
//# VECTOR: == and != #
//###########################################
bool operator==(const Vector<T>& a) const {
if (v.size() != a.size()) {
return false;
}
for (uint64_t i = 0; i < v.size(); ++i) {
if (v[i] != a[i]) {
return false;
}
}
return true;
}
bool operator!=(const Vector<T>& a) const { return !(*this == a); }
//##################################################
//# VECTOR: Scalar Addition #
//##################################################
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
void inplace_add(const U a){
const uint64_t n = v.size();
for (uint64_t i = 0; i < n; ++i){
v[i] += a;
}
}
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
Vector<T> add(const U a) const{
Vector<T> result = *this;
result.inplace_add(a);
return result;
}
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
Vector<T> operator+(const U a) const {
return add(a);
}
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
Vector<T>& operator+=(const U a) {
inplace_add(a);
return *this;
}
//##################################################
//# VECTOR: Vector Addition #
//##################################################
void inplace_add(const Vector<T>& a){
if (a.size() != v.size()){
throw std::runtime_error("utill:Vector.inplace_add -> Dimensions does not fit");
}
const uint64_t n = v.size();
for (uint64_t i = 0; i < n; ++i){
v[i] += a[i];
}
}
Vector<T> add(const Vector<T>& a) const{
Vector<T> result = *this;
result.inplace_add(a);
return result;
}
Vector<T> operator+(const Vector<T>& a) const {
return add(a);
}
Vector<T>& operator+=(const Vector<T>& a) {
inplace_add(a);
return *this;
}
//##################################################
//# VECTOR: Vector Subtract #
//##################################################
void inplace_vec_subtract(const Vector<T>& a){
if (a.size() != v.size()){
throw std::runtime_error("utill:Vector.inplace_vec_subtract -> Dimensions does not fit");
}
uint64_t n = a.size();
for (uint64_t i = 0; i < n; ++i){
v[i] -= a[i];
}
}
Vector<T> vec_subtract(const Vector<T>& a) const{
Vector<T> result = *this;
result.inplace_vec_subtract(a);
return result;
}
Vector<T> operator-(const Vector<T>& a) const {
return vec_subtract(a);
}
Vector<T>& operator-=(const Vector<T>& a) {
inplace_vec_subtract(a);
return *this;
}
//##################################################
//# VECTOR: Vector Multiply #
//##################################################
void inplace_vec_multiply(const Vector<T>& a){
if (a.size() != v.size()){
throw std::runtime_error("utill:Vector.inplace_vec_multiply -> Dimensions does not fit");
}
uint64_t n = a.size();
for (uint64_t i = 0; i < n; ++i){
v[i] *= a[i];
}
}
Vector<T> vec_multiply(const Vector<T>& a) const{
Vector<T> result = *this;
result.inplace_vec_multiply(a);
return result;
}
Vector<T> operator*(const Vector<T>& a) const {
return vec_multiply(a);
}
Vector<T>& operator*=(const Vector<T>& a) {
inplace_vec_multiply(a);
return *this;
}
//##################################################
//# VECTOR: Vector Divide #
//##################################################
void inplace_vec_divide(const Vector<T>& a){
if (a.size() != v.size()){
throw std::runtime_error("utill:Vector.inplace_vec_divide -> Dimensions does not fit");
}
uint64_t n = a.size();
for (uint64_t i = 0; i < n; ++i){
v[i] /= a[i];
}
}
Vector<T> vec_divide(const Vector<T>& a) const{
Vector<T> result = *this;
result.inplace_vec_divide(a);
return result;
}
Vector<T> operator/(const Vector<T>& a) const {
return vec_divide(a);
}
Vector<T>& operator/=(const Vector<T>& a) {
inplace_vec_divide(a);
return *this;
}
//######################################################
//# VECTOR: Support Functions #
//######################################################
inline friend std::ostream& operator << (std::ostream& out, const Vector& vec){
out << "[";
for (uint64_t i = 0; i < vec.v.size(); i++){
out << vec.v[i];
if (i != vec.v.size() - 1) {
out << ", ";
}
}
out << "]";
return out;
}
void print() const{
std::cout << *this << std::endl;
}
/*
void linspace(const T start, const T stop, const T num){
v.clear();
if (num > 1){
double delta = (stop - start)/(num - 1);
for (uint64_t i = 0; i < num; i++){
v.push_back(static_cast<T>(start + delta * i));
}
//v.push_back(static_cast<T>(stop));
}
}*/
};
typedef Vector<int> Vi;
typedef Vector<float> Vf;
typedef Vector<double> Vd;
} // namespace utils
#endif // _vector_n_