Skip to content

Instantly share code, notes, and snippets.

@2bbb
Created January 8, 2016 06:55
Show Gist options
  • Select an option

  • Save 2bbb/29e71d773bab751c572e to your computer and use it in GitHub Desktop.

Select an option

Save 2bbb/29e71d773bab751c572e to your computer and use it in GitHub Desktop.
vector
#include <iostream>
#include <type_traits>
#include <array>
#include <cmath>
#if 201402L <= __cplusplus
# define constexpr_14 constexpr
#else
# define constexpr_14
#endif
template <std::size_t s, typename value_t = double>
struct base_vec {
static_assert(std::is_arithmetic<value_t>::value, "required: value_t is arithmetic type");
using value_type = value_t;
base_vec()
: data() {}
base_vec(const base_vec &v)
: data(v.data) {}
template <typename argument, typename ... arguments, typename std::enable_if<std::is_arithmetic<argument>::value>::type *_ = nullptr>
base_vec(argument arg, arguments ... args)
: data({static_cast<value_t>(arg), static_cast<value_t>(args) ...}) {}
template <std::size_t s_, typename value_t_>
base_vec(const base_vec<s_, value_t_> &v) {
for(std::size_t i = 0, end = std::min(s, s_); i < end; i++) data[i] = v[i];
}
constexpr std::size_t size() { return s; }
value_t &operator[](std::size_t index) { return data[index]; }
constexpr const value_t &operator[](std::size_t index) const { return data[index]; }
value_t &at(std::size_t index) { return data.at(index); }
constexpr const value_t &at(std::size_t index) const { return data.at(index); }
base_vec &operator=(const base_vec &v) { data = v.data; }
base_vec &operator=(const std::array<value_t, s> &v) { data = v; }
template <std::size_t s_, typename value_t_>
base_vec &operator=(const base_vec<s_, value_t_> &v) {
for(std::size_t i = 0, end = std::min(s, s_); i < end; i++) data[i] = v.data[i];
return *this;
}
constexpr const base_vec &operator+() const { return *this; }
constexpr_14 base_vec operator-() const {
base_vec v0;
for(std::size_t i = 0; i < size(); i++) v0 = -data[i];
return v0;
}
constexpr_14 base_vec operator+(const base_vec &v) const {
base_vec v0;
for(std::size_t i = 0; i < size(); i++) v0 = data[i] + v[i];
return v0;
}
base_vec &operator+=(const base_vec &v) {
for(std::size_t i = 0; i < size(); i++) data[i] += v[i];
return *this;
}
constexpr_14 base_vec operator-(const base_vec &v) const {
base_vec v0;
for(std::size_t i = 0; i < size(); i++) v0 = data[i] - v[i];
return v0;
}
base_vec &operator-=(const base_vec &v) {
for(std::size_t i = 0; i < size(); i++) data[i] -= v[i];
return *this;
}
constexpr_14 value_t operator*(const base_vec &v) const {
value_t sum{0.0};
for(std::size_t i = 0; i < size(); i++) sum += data[i] * v[i];
return sum;
}
constexpr_14 value_t dot(const base_vec &v) const {
return *this * v;
}
constexpr_14 base_vec operator*(value_t scale) const {
base_vec v0;
for(std::size_t i = 0; i < size(); i++) v0[i] = data[i] * scale;
return v0;
}
base_vec &operator*=(value_t scale) {
for(std::size_t i = 0; i < size(); i++) data[i] *= scale;
return *this;
}
operator std::array<value_t, s> &() { return data; }
constexpr operator const std::array<value_t, s> &() const { return data; }
constexpr bool operator==(const base_vec &v) const { return data == v.data; }
constexpr bool operator!=(const base_vec &v) const { return data != v.data; }
constexpr bool operator<(const base_vec &v) const { return data < v.data; }
constexpr bool operator<=(const base_vec &v) const { return data <= v.data; }
constexpr bool operator>(const base_vec &v) const { return data > v.data; }
constexpr bool operator>=(const base_vec &v) const { return data >= v.data; }
void swap(base_vec &v) { std::swap(data, v.data); }
using iterator = typename std::array<value_t, s>::iterator;
using const_iterator = typename std::array<value_t, s>::const_iterator;
using reverse_iterator = typename std::array<value_t, s>::reverse_iterator;
using const_reverse_iterator = typename std::array<value_t, s>::const_reverse_iterator;
iterator begin() { return data.begin(); }
iterator end() { return data.end(); }
const_iterator begin() const { return data.cbegin(); }
const_iterator end() const { return data.cend(); }
const_iterator cbegin() const { return data.cbegin(); }
const_iterator cend() const { return data.cend(); }
reverse_iterator rbegin() { return data.rbegin(); }
reverse_iterator rend() { return data.rend(); }
const_reverse_iterator rbegin() const { return data.crbegin(); }
const_reverse_iterator rend() const { return data.crend(); }
const_reverse_iterator crbegin() const { return data.crbegin(); }
const_reverse_iterator crend() const { return data.crend(); }
friend base_vec operator*(value_t scale, const base_vec &v);
protected:
std::array<value_t, s> data;
};
template <std::size_t s, typename value_t = double>
base_vec<s, value_t> operator*(value_t scale, const base_vec<s, value_t> &v) {
return v * s;
}
template <std::size_t s, typename value_t = double>
struct vec : base_vec<s, value_t> {
vec() : base_vec<s, value_t>() {};
template <typename ... arguments>
vec(arguments ... args) : base_vec<s, value_t>(args ...) {};
};
template <typename value_t>
struct vec<2, value_t> : base_vec<2, value_t> {
value_t &x, &y;
vec(value_t x = 0, value_t y = 0)
: base_vec<2, value_t>(x, y)
, x(data[0])
, y(data[1]) {};
template <std::size_t s_, typename value_t_>
vec(const vec<s_, value_t_> &v)
: base_vec<2, value_t>(static_cast<base_vec<s_, value_t>>(v))
, x(data[0])
, y(data[1]) {};
private:
using base_vec<2, value_t>::data;
};
template <typename value_t>
struct vec<3, value_t> : base_vec<3, value_t> {
value_t &x, &y, &z;
vec(value_t x = 0, value_t y = 0, value_t z = 0)
: base_vec<3, value_t>(x, y, z)
, x(data[0])
, y(data[1])
, z(data[2]) {}
operator base_vec<3, value_t> &() { return *this; }
operator const base_vec<3, value_t> &() const { return *this; }
template <std::size_t s_, typename value_t_>
vec(const vec<s_, value_t_> &v)
: base_vec<3, value_t>(static_cast<base_vec<s_, value_t>>(v))
, x(data[0])
, y(data[1])
, z(data[2]) {};
private:
using base_vec<3, value_t>::data;
};
template <typename value_t>
struct vec<4, value_t> : base_vec<4, value_t> {
value_t &x, &y, &z, &w;
vec(value_t x = 0, value_t y = 0, value_t z = 0, value_t w = 0)
: base_vec<4, value_t>(x, y, z, w)
, x(data[0])
, y(data[1])
, z(data[2])
, w(data[3]) {}
template <std::size_t s_, typename value_t_>
vec(const vec<s_, value_t_> &v)
: base_vec<4, value_t>(static_cast<base_vec<s_, value_t>>(v))
, x(data[0])
, y(data[1])
, z(data[2])
, w(data[3]) {};
private:
using base_vec<4, value_t>::data;
};
int main(int argc, char *argv[]) {
vec<4, float> u{1, 2, 3, 4}, v{1, 2, 3, 4};
vec<5, float> w{1.0, 2.0, 3.0, 4.0};
vec<2, float> v2 = u;
vec<5, float> v5 = u;
std::array<float, 4> f = v;
u += v;
std::cout << u.x << ", " << u.y << ", " << u.z << ", " << u.w << std::endl;
std::cout << (u * v) << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment