Commit a61b80fc authored by Philip Trettner's avatar Philip Trettner
Browse files

more work on vector, type and detail

parent 770c41fe
......@@ -27,3 +27,7 @@ Why not `tm::vec3`?
## Dependencies
None.
## TODO
* Benchmark how compile times are affected by includes
......@@ -2,8 +2,6 @@
#include <limits>
#include "types.hh"
namespace tg
{
template <class T>
......@@ -15,4 +13,4 @@ constexpr T min = std::numeric_limits<T>::min();
template <class T>
constexpr T max = std::numeric_limits<T>::max();
}
} // namespace tg
#pragma once
#include <iostream>
#include "../types/types.hh"
namespace tg
{
}
\ No newline at end of file
#pragma once
// ================= OPERATORS =================
// ================= TRAITS =================
#define TG_DEFINE_BOOL_TRAIT(trait, default_val) \
template <class T> \
struct trait##_t \
{ \
static constexpr bool value = default_val; \
}; \
template <class T> \
constexpr bool trait = trait##_t<T>::value // enforce ;
#define TG_DEFINE_TYPE_TRAIT(trait, default_type) \
template <class T> \
struct trait##_t \
{ \
using type = default_type; \
}; \
template <class T> \
using trait = typename trait##_t<T>::type // enforce ;
#define TG_ADD_BOOL_TRAIT(trait, type, val) \
template <> \
struct trait##_t<type> \
{ \
static constexpr bool value = val; \
} // enforce ;
#define TG_ADD_TYPE_TRAIT(trait, ttype, result_type) \
template <> \
struct trait##_t<ttype> \
{ \
using type = result_type; \
} // enforce ;
#define TG_INHERIT_TRAITS_D(ttype) \
template <int D, class ScalarT> \
struct is_integer_t<ttype<D, ScalarT>> \
{ \
static constexpr bool value = is_integer<ScalarT>; \
}; \
template <int D, class ScalarT> \
struct is_signed_integer_t<ttype<D, ScalarT>> \
{ \
static constexpr bool value = is_signed_integer<ScalarT>; \
}; \
template <int D, class ScalarT> \
struct is_unsigned_integer_t<ttype<D, ScalarT>> \
{ \
static constexpr bool value = is_unsigned_integer<ScalarT>; \
}; \
template <int D, class ScalarT> \
struct is_floating_point_t<ttype<D, ScalarT>> \
{ \
static constexpr bool value = is_floating_point<ScalarT>; \
}; \
template <int D, class ScalarT> \
struct fractional_result_t<ttype<D, ScalarT>> \
{ \
using type = ttype<D, fractional_result<ScalarT>>; \
} // enforce ;
#define TG_INHERIT_TRAITS_FIELD_D(ttype) \
TG_INHERIT_TRAITS_D(ttype); \
template <int D, class ScalarT> \
struct has_multiplication_t<ttype<D, ScalarT>> \
{ \
static constexpr bool value = has_multiplication<ScalarT>; \
}; // enforce ;
#pragma once
namespace tg
{
namespace detail
{
template <class ScalarT>
constexpr ScalarT add(ScalarT a, ScalarT b)
{
return a + b;
}
template <class ScalarT>
constexpr ScalarT sub(ScalarT a, ScalarT b)
{
return a - b;
}
template <class ScalarT>
constexpr ScalarT neg(ScalarT a)
{
return -a;
}
template <class ScalarT>
constexpr ScalarT mul(ScalarT a, ScalarT b)
{
return a * b;
}
template <class ScalarT>
constexpr bool eq(ScalarT a, ScalarT b)
{
return a == b;
}
constexpr bool logic_and(bool a, bool b) { return a && b; }
constexpr bool logic_or(bool a, bool b) { return a || b; }
constexpr bool logic_not(bool a) { return !a; }
template <class A, class B, class C, class F>
constexpr void apply(vec<1, A>& r, vec<1, B> const& a, vec<1, C> const& b, F&& f)
{
r.x = f(a.x, b.x);
}
template <class A, class B, class C, class F>
constexpr void apply(vec<2, A>& r, vec<2, B> const& a, vec<2, C> const& b, F&& f)
{
r.x = f(a.x, b.x);
r.y = f(a.y, b.y);
}
template <class A, class B, class C, class F>
constexpr void apply(vec<3, A>& r, vec<3, B> const& a, vec<3, C> const& b, F&& f)
{
r.x = f(a.x, b.x);
r.y = f(a.y, b.y);
r.z = f(a.z, b.z);
}
template <class A, class B, class C, class F>
constexpr void apply(vec<4, A>& r, vec<4, B> const& a, vec<4, C> const& b, F&& f)
{
r.x = f(a.x, b.x);
r.y = f(a.y, b.y);
r.z = f(a.z, b.z);
r.w = f(a.w, b.w);
}
template <class A, class B, class C, class F>
constexpr void apply(vec<1, A>& r, vec<1, B> const& a, F&& f)
{
r.x = f(a.x);
}
template <class A, class B, class C, class F>
constexpr void apply(vec<2, A>& r, vec<2, B> const& a, F&& f)
{
r.x = f(a.x);
r.y = f(a.y);
}
template <class A, class B, class C, class F>
constexpr void apply(vec<3, A>& r, vec<3, B> const& a, F&& f)
{
r.x = f(a.x);
r.y = f(a.y);
r.z = f(a.z);
}
template <class A, class B, class C, class F>
constexpr void apply(vec<4, A>& r, vec<4, B> const& a, F&& f)
{
r.x = f(a.x);
r.y = f(a.y);
r.z = f(a.z);
r.w = f(a.w);
}
template <class R, int D, class A, class B, class F>
constexpr vec<D, R> compwise(vec<D, A> const& a, vec<D, B> const& b, F&& f)
{
vec<D, R> r;
apply(r, a, b, f);
return r;
}
template <class R, int D, class A, class B, class F>
constexpr vec<D, R> compwise(vec<D, A> const& a, B b, F&& f)
{
vec<D, R> r;
apply(r, a, vec<D, B>(b), f);
return r;
}
template <class R, int D, class A, class F>
constexpr vec<D, R> compwise(vec<D, A> const& a, F&& f)
{
vec<D, R> r;
apply(r, a, f);
return r;
}
template <class ScalarT, class F>
constexpr ScalarT reduce(vec<1, ScalarT> const& v, F&& f)
{
return v.x;
}
template <class ScalarT, class F>
constexpr ScalarT reduce(vec<2, ScalarT> const& v, F&& f)
{
return f(v.x, v.y);
}
template <class ScalarT, class F>
constexpr ScalarT reduce(vec<3, ScalarT> const& v, F&& f)
{
return f(f(v.x, v.y), v.z);
}
template <class ScalarT, class F>
constexpr ScalarT reduce(vec<4, ScalarT> const& v, F&& f)
{
return f(f(v.x, v.y), f(v.z, v.w));
}
} // namespace detail
} // namespace tg
#pragma once
#include <cmath>
#include <type_traits>
#include "types.hh"
#include "../detail/traits.hh"
#include "../types/scalar.hh"
// TODO:
// proper f8, f16
......@@ -26,17 +28,39 @@ constexpr f32 abs(f32 v) { return v < 0 ? -v : v; }
constexpr f64 abs(f64 v) { return v < 0 ? -v : v; }
f32 sin(f32 v) { return std::sin(v); }
f64 sin(f64 v) { return std::sin(v); }
inline f32 sin(f32 v) { return std::sin(v); }
inline f64 sin(f64 v) { return std::sin(v); }
f32 cos(f32 v) { return std::cos(v); }
f64 cos(f64 v) { return std::cos(v); }
inline f32 cos(f32 v) { return std::cos(v); }
inline f64 cos(f64 v) { return std::cos(v); }
f32 sqrt(f32 v) { return std::sqrt(v); }
f64 sqrt(f64 v) { return std::sqrt(v); }
inline f32 sqrt(f32 v) { return std::sqrt(v); }
inline f64 sqrt(f64 v) { return std::sqrt(v); }
inline f32 pow(f32 b, f32 e) { return std::pow(b, e); }
inline f32 pow(f32 b, i32 e) { return std::pow(b, e); }
inline f64 pow(f64 b, f64 e) { return std::pow(b, e); }
inline f64 pow(f64 b, i32 e) { return std::pow(b, e); }
template <class T, class = std::enable_if_t<has_multiplication<T>>>
constexpr T pow2(T const& v)
{
return v * v;
}
template <class T, class = std::enable_if_t<has_multiplication<T>>>
constexpr T pow3(T const& v)
{
return v * v * v;
}
template <class T, class = std::enable_if_t<has_multiplication<T>>>
constexpr T pow4(T const& v)
{
return (v * v) * (v * v);
}
template <class T, class = std::enable_if_t<has_multiplication<T>>>
constexpr T pow5(T const& v)
{
return (v * v) * (v * v) * v;
}
f32 pow(f32 b, f32 e) { return std::pow(b, e); }
f32 pow(f32 b, i32 e) { return std::pow(b, e); }
f64 pow(f64 b, f64 e) { return std::pow(b, e); }
f64 pow(f64 b, i32 e) { return std::pow(b, e); }
} // namespace tg
#pragma once
#include "types.hh"
#include "../types/types.hh"
namespace tg
{
......@@ -11,14 +11,65 @@ namespace tg
static constexpr bool value = default_val; \
}; \
template <class T> \
constexpr bool trait = trait##_t<T>::value
constexpr bool trait = trait##_t<T>::value // enforce ;
#define TG_DEFINE_TYPE_TRAIT(trait, default_type) \
template <class T> \
struct trait##_t \
{ \
using type = default_type; \
}; \
template <class T> \
using trait = typename trait##_t<T>::type // enforce ;
#define TG_ADD_BOOL_TRAIT(trait, type, val) \
template <> \
struct trait##_t<type> \
{ \
static constexpr bool value = val; \
}
} // enforce ;
#define TG_ADD_TYPE_TRAIT(trait, ttype, result_type) \
template <> \
struct trait##_t<ttype> \
{ \
using type = result_type; \
} // enforce ;
#define TG_INHERIT_TRAITS_D(ttype) \
template <int D, class ScalarT> \
struct is_integer_t<ttype<D, ScalarT>> \
{ \
static constexpr bool value = is_integer<ScalarT>; \
}; \
template <int D, class ScalarT> \
struct is_signed_integer_t<ttype<D, ScalarT>> \
{ \
static constexpr bool value = is_signed_integer<ScalarT>; \
}; \
template <int D, class ScalarT> \
struct is_unsigned_integer_t<ttype<D, ScalarT>> \
{ \
static constexpr bool value = is_unsigned_integer<ScalarT>; \
}; \
template <int D, class ScalarT> \
struct is_floating_point_t<ttype<D, ScalarT>> \
{ \
static constexpr bool value = is_floating_point<ScalarT>; \
}; \
template <int D, class ScalarT> \
struct fractional_result_t<ttype<D, ScalarT>> \
{ \
using type = ttype<D, fractional_result<ScalarT>>; \
} // enforce ;
#define TG_INHERIT_TRAITS_FIELD_D(ttype) \
TG_INHERIT_TRAITS_D(ttype); \
template <int D, class ScalarT> \
struct has_multiplication_t<ttype<D, ScalarT>> \
{ \
static constexpr bool value = has_multiplication<ScalarT>; \
}; // enforce ;
// shape traits
TG_DEFINE_BOOL_TRAIT(is_scalar, false);
......@@ -31,6 +82,7 @@ TG_DEFINE_BOOL_TRAIT(is_integer, false);
TG_DEFINE_BOOL_TRAIT(is_floating_point, false);
TG_DEFINE_BOOL_TRAIT(is_signed_integer, false);
TG_DEFINE_BOOL_TRAIT(is_unsigned_integer, false);
TG_DEFINE_BOOL_TRAIT(has_multiplication, true);
// scalars
TG_ADD_BOOL_TRAIT(is_scalar, i8, true);
......@@ -73,33 +125,26 @@ TG_ADD_BOOL_TRAIT(is_floating_point, f16, true);
TG_ADD_BOOL_TRAIT(is_floating_point, f32, true);
TG_ADD_BOOL_TRAIT(is_floating_point, f64, true);
TG_ADD_BOOL_TRAIT(has_multiplication, bool, false);
// type mapping
TG_DEFINE_TYPE_TRAIT(fractional_result, float);
TG_ADD_TYPE_TRAIT(fractional_result, f64, f64);
TG_ADD_TYPE_TRAIT(fractional_result, i64, f64);
TG_ADD_TYPE_TRAIT(fractional_result, u64, f64);
// vectors
template <int D, class ScalarT>
struct is_vector_t<vec<D, ScalarT>>
{
static constexpr bool value = true;
};
template <int D, class ScalarT>
struct is_integer_t<vec<D, ScalarT>>
{
static constexpr bool value = is_integer<ScalarT>;
};
template <int D, class ScalarT>
struct is_signed_integer_t<vec<D, ScalarT>>
{
static constexpr bool value = is_signed_integer<ScalarT>;
};
template <int D, class ScalarT>
struct is_unsigned_integer_t<vec<D, ScalarT>>
{
static constexpr bool value = is_unsigned_integer<ScalarT>;
};
template <int D, class ScalarT>
struct is_floating_point_t<vec<D, ScalarT>>
{
static constexpr bool value = is_floating_point<ScalarT>;
};
TG_INHERIT_TRAITS_D(vec);
#undef TG_DEFINE_BOOL_TRAIT
#undef TG_DEFINE_TYPE_TRAIT
#undef TG_ADD_BOOL_TRAIT
#undef TG_ADD_TYPE_TRAIT
#undef TG_INHERIT_TRAITS_D
#undef TG_INHERIT_TRAITS_FIELDS_D
} // namespace tg
#pragma once
#include <cstdint>
#include "half.hh"
#include "quarter.hh"
#include "vec.hh"
namespace tg
{
// Scalar types
using i8 = std::int8_t;
using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using f8 = quarter;
using f16 = half;
using f32 = float;
using f64 = double;
// Common vector types
using vec1 = vec<1, f32>;
using vec2 = vec<2, f32>;
using vec3 = vec<3, f32>;
using vec4 = vec<4, f32>;
using bvec1 = vec<1, bool>;
using bvec2 = vec<2, bool>;
using bvec3 = vec<3, bool>;
using bvec4 = vec<4, bool>;
using fvec1 = vec<1, f32>;
using fvec2 = vec<2, f32>;
using fvec3 = vec<3, f32>;
using fvec4 = vec<4, f32>;
using dvec1 = vec<1, f64>;
using dvec2 = vec<2, f64>;
using dvec3 = vec<3, f64>;
using dvec4 = vec<4, f64>;
using ivec1 = vec<1, i32>;
using ivec2 = vec<2, i32>;
using ivec3 = vec<3, i32>;
using ivec4 = vec<4, i32>;
using uvec1 = vec<1, u32>;
using uvec2 = vec<2, u32>;
using uvec3 = vec<3, u32>;
using uvec4 = vec<4, u32>;
// Sized vector types
using i8vec1 = vec<1, i8>;
using i8vec2 = vec<2, i8>;
using i8vec3 = vec<3, i8>;
using i8vec4 = vec<4, i8>;
using i16vec1 = vec<1, i16>;
using i16vec2 = vec<2, i16>;
using i16vec3 = vec<3, i16>;
using i16vec4 = vec<4, i16>;
using i32vec1 = vec<1, i32>;
using i32vec2 = vec<2, i32>;
using i32vec3 = vec<3, i32>;
using i32vec4 = vec<4, i32>;
using i64vec1 = vec<1, i64>;
using i64vec2 = vec<2, i64>;
using i64vec3 = vec<3, i64>;
using i64vec4 = vec<4, i64>;
using u8vec1 = vec<1, u8>;
using u8vec2 = vec<2, u8>;
using u8vec3 = vec<3, u8>;
using u8vec4 = vec<4, u8>;
using u16vec1 = vec<1, u16>;
using u16vec2 = vec<2, u16>;
using u16vec3 = vec<3, u16>;
using u16vec4 = vec<4, u16>;
using u32vec1 = vec<1, u32>;
using u32vec2 = vec<2, u32>;
using u32vec3 = vec<3, u32>;
using u32vec4 = vec<4, u32>;
using u64vec1 = vec<1, u64>;
using u64vec2 = vec<2, u64>;
using u64vec3 = vec<3, u64>;
using u64vec4 = vec<4, u64>;
using f8vec1 = vec<1, f8>;
using f8vec2 = vec<2, f8>;
using f8vec3 = vec<3, f8>;
using f8vec4 = vec<4, f8>;
using f16vec1 = vec<1, f16>;
using f16vec2 = vec<2, f16>;
using f16vec3 = vec<3, f16>;
using f16vec4 = vec<4, f16>;
using f32vec1 = vec<1, f32>;
using f32vec2 = vec<2, f32>;
using f32vec3 = vec<3, f32>;
using f32vec4 = vec<4, f32>;
using f64vec1 = vec<1, f64>;
using f64vec2 = vec<2, f64>;
using f64vec3 = vec<3, f64>;
using f64vec4 = vec<4, f64>;
// Quaternion types
// TODO
// Matrix types
// TODO
} // namespace tg
#pragma once
#include "vec.hh"
#include "op_helper.hh"
#include "../types/vec.hh"
namespace tg
{
......@@ -15,14 +17,136 @@ constexpr ScalarT* data_ptr(vec<D, ScalarT>& v)
return &v.x;
}
// -- operator@ --
template <int D, class ScalarT>
constexpr vec<D, ScalarT> operator+(vec<D, ScalarT> const& a, vec<D, ScalarT> const& b)
{
return detail::compwise<ScalarT>(a, b, detail::add<ScalarT>);
}
template <int D, class ScalarT>
constexpr vec<D, ScalarT> operator+(vec<D, ScalarT> const& a, ScalarT b)
{
return detail::compwise<ScalarT>(a, b, detail::add<ScalarT>);
}
template <int D, class ScalarT>
constexpr vec<D, ScalarT> operator-(vec<D, ScalarT> const& a, vec<D, ScalarT> const& b)
{
return detail::compwise<ScalarT>(a, b, detail::sub<ScalarT>);
}
template <int D, class ScalarT>
constexpr vec<D, ScalarT> operator-(vec<D, ScalarT> const& a, ScalarT b)
{