4848#include < functional>
4949#include < limits>
5050#include < numeric>
51+ #include < cstdalign>
5152
52- static constexpr inline bool VM_ISPOW2 (uintmax_t x) { return (x && (!(x & (x-1 )))); }
53-
54- template <typename T>
55- static constexpr inline int VM_BIT_SCAN_REVERSE_CONST (const T n) noexcept {
56- if (n == 0 ) return -1 ;
57- if (VM_ISPOW2 (n)) return n;
58- T a = n, b = 0 , j = std::numeric_limits<T>::digits, k = 0 ;
59- do {
60- j >>= 1 ;
61- k = (T)1 << j;
62- if (a >= k) {
63- a >>= j;
64- b += j;
65- }
66- } while (j > 0 );
67- return int (b);
68- }
53+ #ifndef __alignas_is_defined
54+ #if _MSVC_LANG > 201402
55+ #define alignas (n ) __declspec(align(n))
56+ #elif (__GNUC__ >= 3 || defined(__clang__))
57+ #define alignas (n ) __attribute__((aligned(n)))
58+ #else
59+ #define alignas (n )
60+ #endif
61+ #endif
6962
70- template <typename T>
71- static constexpr inline T VM_BIT_CEIL (T x) noexcept { return T (1 ) << (VM_BIT_SCAN_REVERSE_CONST ((T)x-1 ) + 1 ); };
63+ #define BITOP_RUP01__ (x ) ( (x) | ( (x) >> 1 ))
64+ #define BITOP_RUP02__ (x ) (BITOP_RUP01__(x) | (BITOP_RUP01__(x) >> 2 ))
65+ #define BITOP_RUP04__ (x ) (BITOP_RUP02__(x) | (BITOP_RUP02__(x) >> 4 ))
66+ #define BITOP_RUP08__ (x ) (BITOP_RUP04__(x) | (BITOP_RUP04__(x) >> 8 ))
67+ #define BITOP_RUP16__ (x ) (BITOP_RUP08__(x) | (BITOP_RUP08__(x) >> 16 ))
68+ #define BITOP_RUP32__ (x ) (BITOP_RUP16__(x) | (BITOP_RUP16__(x) >> 32 ))
69+ #define BITOP_RUP64__ (x ) (BITOP_RUP32__(x) | (BITOP_RUP32__(x) >> 64 ))
7270
73- template <typename T>
74- static constexpr inline T VM_BIT_FLOOR (T x) noexcept { return x == 0 || VM_ISPOW2 (x) ? x : ((VM_BIT_FLOOR (x >> 1 )) << 1 ); }
71+ constexpr static inline uintmax_t VM_BIT_CEIL (uintmax_t x) {
72+ switch (std::numeric_limits<uintmax_t >::digits)
73+ {
74+ case 8 : return (BITOP_RUP04__ (uint8_t (x) - 1 ) + 1 );
75+ case 16 : return (BITOP_RUP08__ (uint16_t (x) - 1 ) + 1 );
76+ default :
77+ case 32 : return (BITOP_RUP16__ (uint32_t (x) - 1 ) + 1 );
78+ case 64 : return (BITOP_RUP32__ (uint64_t (x) - 1 ) + 1 );
79+ }
80+ }
7581
76- #ifdef _MSVC_LANG
77- #define VM_ALIGN (n ) __declspec(align(n))
78- #else
79- #define VM_ALIGN (n ) __attribute__((aligned(n)))
80- #endif
82+ constexpr static inline bool VM_ISPOW2 (uintmax_t x) { return x && (!(x & (x-1 ))); }
83+ constexpr static inline uintmax_t VM_BIT_FLOOR (uintmax_t x) { return ((x == 0 ) || VM_ISPOW2 (x) ? x : ((VM_BIT_FLOOR (x >> 1 )) << 1 )); }
8184
8285enum class align
8386{
8487 none = 0 << 0 ,
85- scalar = 1 << 1 ,
86- vector = 2 << 1 ,
87- matrix = 3 << 1 ,
88- adaptive = 4 << 1 ,
88+ scalar = 1 << 0 ,
89+ linear = 1 << 1 ,
90+ matrix = 1 << 2 ,
91+ adaptive = 1 << 3 ,
8992};
9093
91- template <typename T, size_t N, enum align A = align::adaptive, size_t N_POW2 = VM_BIT_CEIL(N)>
92- struct alignas (N== N_POW2 && A != align::scalar || A == align::vector ? alignof (T) * N_POW2 : alignof (T) ) vec : std::array<T,N> {
94+ template <typename T, size_t N, enum align A = align::adaptive, size_t N_POW2 = VM_BIT_CEIL(N), size_t T_S = std::max< size_t >( alignof (T), sizeof (T)) >
95+ struct alignas ((((N == N_POW2) && ( A != align::scalar)) || (( A == align::linear) || (A == align::matrix))) ? N_POW2 * T_S : T_S ) vec : std::array<T,N> {
9396
9497template <size_t N_DST = N, enum align A_DST = align::adaptive>
9598operator vec<T,N_DST,A_DST>() { return *reinterpret_cast <vec<T,N_DST,A_DST>*>(this ); }
@@ -287,8 +290,8 @@ constexpr static inline scalar dot(const vec<T,N_A,A_A> &a, const vec<T,N_B,A_B>
287290template <size_t N_A = 3 , size_t N_B = 3 , enum align A_A = align::adaptive, enum align A_B = align::adaptive>
288291constexpr static inline vec<T,3 > cross3 (const vec<T,N_A,A_A> &a, const vec<T,N_B,A_B> &b)
289292{
290- return vec<T,3 ,align::vector >{a.y ()*b.z (), a.z ()*b.x (), a.x ()*b.y ()}
291- - vec<T,3 ,align::vector >{b.y ()*a.z (), b.z ()*a.x (), b.x ()*a.y ()};
293+ return vec<T,3 ,align::linear >{a.y ()*b.z (), a.z ()*b.x (), a.x ()*b.y ()}
294+ - vec<T,3 ,align::linear >{b.y ()*a.z (), b.z ()*a.x (), b.x ()*a.y ()};
292295}
293296constexpr inline scalar mag () const { return (scalar)sqrt (dot ((*this ),(*this ))); }
294297
@@ -300,17 +303,17 @@ static constexpr inline scalar distance(const vec<T,N_A,A_A> &a, const vec<T,N_B
300303
301304using vector = vec<scalar,3 >;
302305using vector_array = vector;
303- using aligned_vector = vec<scalar,3 ,align::vector >;
306+ using aligned_vector = vec<scalar,3 ,align::linear >;
304307using aligned_vector_array = aligned_vector;
305308
306309using vector4 = vec<scalar,4 >;
307310using vector4_array = vector4;
308- using aligned_vector4 = vec<scalar,4 ,align::vector >;
311+ using aligned_vector4 = vec<scalar,4 ,align::linear >;
309312using aligned_vector4_array = aligned_vector4;
310313
311314using angvec = vec<angle,3 >;
312315using angvec_array = angvec;
313- using aligned_angvec = vec<angle,3 ,align::vector >;
316+ using aligned_angvec = vec<angle,3 ,align::linear >;
314317using aligned_angvec_array = aligned_angvec;
315318
316319// Set an angvec to {0,0,0}
@@ -339,9 +342,31 @@ constexpr static inline const matrix ne()
339342{
340343 return matrix{ vector{}, vector{}, vector{} };
341344}
345+ constexpr inline void set_col (size_t i, const vector v)
346+ {
347+ a2d[0 ][i % 3 ] = v[0 ];
348+ a2d[1 ][i % 3 ] = v[1 ];
349+ a2d[2 ][i % 3 ] = v[2 ];
350+ }
351+ constexpr inline vector col (size_t i) const
352+ {
353+ return vector{ a2d[0 ][i % 3 ], a2d[1 ][i % 3 ], a2d[2 ][i % 3 ] };
354+ }
355+ constexpr inline matrix transposed () const
356+ {
357+ return matrix{ col (0 ), col (1 ), col (2 ) };
358+ }
359+ constexpr inline scalar det () const
360+ {
361+ scalar dst = scalar (0 );
362+ for (size_t i = 0 ; i < 3 ; i++)
363+ dst += a2d[0 ][i] * (a2d[1 ][(i+1 ) % 3 ] * a2d[2 ][(i+2 ) % 3 ]
364+ - a2d[1 ][(i+2 ) % 3 ] * a2d[2 ][(i+1 ) % 3 ]);
365+ return dst;
366+ }
342367};
343368
344- constexpr matrix IDENTITY_MATRIX = matrix ::id() ;
369+ constexpr matrix IDENTITY_MATRIX = { vector ::id (0 ), vector::id ( 1 ), vector::id ( 2 ) } ;
345370
346371struct alignas (alignof (vector4) * 4 ) matrix4 {
347372constexpr static const size_t RIGHT_HAND = 0 ;
@@ -366,6 +391,21 @@ constexpr static inline const matrix4 ne()
366391{
367392 return matrix4{ vector4{}, vector4{}, vector4{}, vector4{} };
368393}
394+ constexpr inline void set_col (size_t i, const vector4 v)
395+ {
396+ a2d[0 ][i % 4 ] = v[0 ];
397+ a2d[1 ][i % 4 ] = v[1 ];
398+ a2d[2 ][i % 4 ] = v[2 ];
399+ a2d[3 ][i % 4 ] = v[3 ];
400+ }
401+ constexpr inline vector4 col (size_t i) const
402+ {
403+ return vector4{ a2d[0 ][i % 4 ], a2d[1 ][i % 4 ], a2d[2 ][i % 4 ], a2d[2 ][i % 4 ] };
404+ }
405+ constexpr inline matrix4 transposed () const
406+ {
407+ return matrix4{ col (0 ), col (1 ), col (2 ), col (3 ) };
408+ }
369409};
370410
371411// Adds 2 matrices
@@ -436,19 +476,7 @@ static inline matrix operator/=(matrix &src, float n) { return (src = src / n);
436476
437477// Matrix transpose
438478static inline matrix operator ~(matrix m) {
439- float t;
440-
441- t = m.uvec .x ();
442- m.uvec .x () = m.rvec .y ();
443- m.rvec .y () = t;
444- t = m.fvec .x ();
445- m.fvec .x () = m.rvec .z ();
446- m.rvec .z () = t;
447- t = m.fvec .y ();
448- m.fvec .y () = m.uvec .z ();
449- m.uvec .z () = t;
450-
451- return m;
479+ return m.transposed ();
452480}
453481
454482// Apply a matrix to a vector
0 commit comments