rcx

miscellaneous C library
git clone git://git.rr3.xyz/rcx
Log | Files | Refs | README | LICENSE

linalg.h (6511B)


      1 #pragma once
      2 
      3 #include "<string.h>"
      4 
      5 #include "debug.h"
      6 #include "def.h"
      7 #include "math.h"
      8 
      9 /* TODO: Fixed point math? */
     10 
     11 
     12 /* ----- Vectors ----- */
     13 
     14 #define Vec2 Vec2f32
     15 #define r_vec2_add r_vec2f32_add
     16 #define r_vec2_sub r_vec2f32_sub
     17 #define r_vec2_scl r_vec2f32_scl
     18 #define r_vec2_dot r_vec2f32_dot
     19 #define r_vec2_norm r_vec2f32_norm
     20 #define r_vec2_dist r_vec2f32_dist
     21 #define r_vec2_unit r_vec2f32_unit
     22 #define r_vec2_convf64 r_vec2f32_convf64
     23 
     24 #define Vec3 Vec3f32
     25 #define r_vec3_add r_vec3f32_add
     26 #define r_vec3_sub r_vec3f32_sub
     27 #define r_vec3_scl r_vec3f32_scl
     28 #define r_vec3_dot r_vec3f32_dot
     29 #define r_vec3_norm r_vec3f32_norm
     30 #define r_vec3_dist r_vec3f32_dist
     31 #define r_vec3_unit r_vec3f32_unit
     32 #define r_vec3_convf64 r_vec3f32_convf64
     33 
     34 #define Vec4 Vec4f32
     35 #define r_vec4_add r_vec4f32_add
     36 #define r_vec4_sub r_vec4f32_sub
     37 #define r_vec4_scl r_vec4f32_scl
     38 #define r_vec4_dot r_vec4f32_dot
     39 #define r_vec4_norm r_vec4f32_norm
     40 #define r_vec4_dist r_vec4f32_dist
     41 #define r_vec4_unit r_vec4f32_unit
     42 #define r_vec4_convf64 r_vec4f32_convf64
     43 
     44 #define VECTOR(T, d) \
     45 	typedef T Vec##d##T[n]; \
     46 	static inline void r_vec##d##T##_add(Vec##d##T *r, Vec##d##T v, Vec##d##T w) { \
     47 		for (usize i = 0; i < d; i++) (*r)[i] = v[i] + w[i]; \
     48 	} \
     49 	static inline void r_vec##d##T##_sub(Vec##d##T *r, Vec##d##T v, Vec##d##T w) { \
     50 		for (usize i = 0; i < d; i++) (*r)[i] = v[i] - w[i]; \
     51 	} \
     52 	static inline void r_vec##d##T##_scl(Vec##d##T *r, T a, Vec##d##T v) { \
     53 		for (usize i = 0; i < d; i++) (*r)[i] = a * v[i]; \
     54 	} \
     55 	static inline T r_vec##d##T##_dot(Vec##d##T v, Vec##d##T w) { \
     56 		T sum = 0.0; \
     57 		for (usize i = 0; i < d; i++) sum += v[i] * w[i]; \
     58 		return sum; \
     59 	} \
     60 	static inline T r_vec##d##T##_norm(Vec##d##T v) { \
     61 		return r_sqrt##T(r_vec##d##T##_norm(v, v)); \
     62 	} \
     63 	static inline T r_vec##d##T##_dist(Vec##d##T v, Vec##d##T w) { \
     64 		Vec##d##T u; r_vec##d##T##_sub(&u, w, v); \
     65 		return r_vec##d##T##_norm(u); \
     66 	} \
     67 	static inline void r_vec##d##T##_unit(Vec##d##T *r, Vec##d##T v) { \
     68 		r_vec##d##T##_scl(r, 1.0 / r_vec##d##T##_norm(v), v); \
     69 	}
     70 
     71 VECTOR(f32, 2)
     72 VECTOR(f32, 3)
     73 VECTOR(f32, 4)
     74 VECTOR(f64, 2)
     75 VECTOR(f64, 3)
     76 VECTOR(f64, 4)
     77 
     78 #undef VECTOR
     79 
     80 #define VECTOR_CONV(Td, Ts, d) \
     81 	static inline void r_vec##d##Ts##_conv##Td(Vec##d##Td *r, Vec##d##Ts v) { \
     82 		for (usize i = 0; i < d; i++) (*r)[i] = (Td)v[i]; \
     83 	}
     84 
     85 VECTOR_CONV(f64, f32, 2)
     86 VECTOR_CONV(f64, f32, 3)
     87 VECTOR_CONV(f64, f32, 4)
     88 VECTOR_CONV(f32, f64, 2)
     89 VECTOR_CONV(f32, f64, 3)
     90 VECTOR_CONV(f32, f64, 4)
     91 
     92 #undef VECTOR_CONV
     93 
     94 
     95 /* ----- Affine matrices (3x3 with [0 0 1] as implicit last row) ----- */
     96 
     97 #define Aff3 Aff3f32
     98 #define r_aff3_identity r_aff3f32_identity
     99 #define r_aff3_scale r_aff3f32_scale
    100 #define r_aff3_translate r_aff3f32_translate
    101 #define r_aff3_mul r_aff3f32_mul
    102 
    103 #define AFF3(T) \
    104 	typedef T Aff3##T[2][3]; \
    105 	static inline void r_aff3##T##_identity(Aff3##T *r) { \
    106 		(*r)[0][0] = 1.0; \
    107 		(*r)[0][1] = 0.0; \
    108 		(*r)[0][2] = 0.0; \
    109 		(*r)[1][0] = 0.0; \
    110 		(*r)[1][1] = 1.0; \
    111 		(*r)[1][2] = 0.0; \
    112 	} \
    113 	static inline void r_aff3##T##_scale(Aff3##T *r, T x, T y) { \
    114 		(*r)[0][0] = x; \
    115 		(*r)[0][1] = 0.0; \
    116 		(*r)[0][2] = 0.0; \
    117 		(*r)[1][0] = 0.0; \
    118 		(*r)[1][1] = y; \
    119 		(*r)[1][2] = 0.0; \
    120 	} \
    121 	static inline void r_aff3##T##_translate(Aff3##T *r, T x, T y) { \
    122 		(*r)[0][0] = 1.0; \
    123 		(*r)[0][1] = 0.0; \
    124 		(*r)[0][2] = x; \
    125 		(*r)[1][0] = 0.0; \
    126 		(*r)[1][1] = 1.0; \
    127 		(*r)[1][2] = y; \
    128 	} \
    129 	static inline void r_aff3##T##_mul(Aff3##T *r, Aff3##T a, Aff3##T b) { \
    130 		/* Use temp local storage to allow *r to be a or b. */ \
    131 		Aff3##T rr; \
    132 		rr[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0]; \
    133 		rr[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1]; \
    134 		rr[0][2] = a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2]; \
    135 		rr[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0]; \
    136 		rr[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1]; \
    137 		rr[1][2] = a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2]; \
    138 		memcpy(*r, rr, sizeof (Aff3##T)); \
    139 	}
    140 
    141 AFF3(f32)
    142 AFF3(f64)
    143 
    144 #undef AFF3
    145 
    146 /* TODO: Conversions */
    147 
    148 
    149 /* ----- Quads ----- */
    150 
    151 #define Quad Quadf32
    152 #define r_quad_ll r_quadf32_ll
    153 #define r_quad_lr r_quadf32_lr
    154 #define r_quad_ur r_quadf32_ur
    155 #define r_quad_ul r_quadf32_ul
    156 #define r_quad_width r_quadf32_width
    157 #define r_quad_height r_quadf32_height
    158 
    159 #define QUAD(T) \
    160 	typedef Vec2##T Quad##T[2]; \
    161 	static inline void r_quad##T##_ll(Vec2##T *r, Quad##T q) { \
    162 		(*r)[0] = q[0][0], (*r)[1] = q[0][1]; \
    163 	} \
    164 	static inline void r_quad##T##_lr(Vec2##T *r, Quad##T q) { \
    165 		(*r)[0] = q[1][0], (*r)[1] = q[0][1]; \
    166 	} \
    167 	static inline void r_quad##T##_ur(Vec2##T *r, Quad##T q) { \
    168 		(*r)[0] = q[1][0], (*r)[1] = q[1][1]; \
    169 	} \
    170 	static inline void r_quad##T##_ul(Vec2##T *r, Quad##T q) { \
    171 		(*r)[0] = q[0][0], (*r)[1] = q[1][1]; \
    172 	} \
    173 	static inline T r_quad##T##_width(Quad##T q) { \
    174 		return q[1][0] - q[0][0]; \
    175 	} \
    176 	static inline T r_quad##T##_height(Quad##T q) { \
    177 		return q[1][1] - q[0][1]; \
    178 	}
    179 
    180 QUAD(f32)
    181 QUAD(f64)
    182 
    183 #undef QUAD
    184 
    185 /* TODO: Conversions */
    186 
    187 
    188 /* ----- Affine transformations ----- */
    189 
    190 #define r_aff3_trans_vec2 r_aff3f32_trans_vec2
    191 #define r_aff3_trans_quad r_aff3f32_trans_quad
    192 #define r_aff3_view r_aff3f32_view
    193 
    194 #define AFF3_TRANS_VEC2(T) \
    195 	static inline void r_aff3##T##_trans_vec2(Vec2##T *r, Aff3##T a, Vec2##T v) { \
    196 		(*r)[0] = a[0][0] * v[0] + a[0][1] * v[1] + a[0][2]; \
    197 		(*r)[1] = a[1][0] * v[0] + a[1][1] * v[1] + a[1][2]; \
    198 	}
    199 
    200 AFF3_TRANS_VEC2(f32)
    201 AFF3_TRANS_VEC2(f64)
    202 
    203 #undef AFF3_TRANS_VEC2
    204 
    205 #define AFF3_TRANS_QUAD(T) \
    206 	static inline void r_aff3##T##_trans_quad(Quad##T *r, Aff3##T a, Quad##T q) { \
    207 		Vec2##T v[2]; \
    208 		r_aff3##T##_trans_vec2(&v[0], a, q[0]); \
    209 		r_aff3##T##_trans_vec2(&v[1], a, q[1]); \
    210 		(*r)[0][0] = MIN(v[0][0], v[1][0]); \
    211 		(*r)[0][1] = MIN(v[0][1], v[1][1]); \
    212 		(*r)[1][0] = MAX(v[0][0], v[1][0]); \
    213 		(*r)[1][1] = MAX(v[0][1], v[1][1]); \
    214 	}
    215 
    216 AFF3_TRANS_QUAD(f32)
    217 AFF3_TRANS_QUAD(f64)
    218 
    219 #undef AFF3_TRANS_QUAD
    220 
    221 /* Find the affine transformation that maps src to dst. */
    222 #define AFF3_VIEW(T) \
    223 	static inline r_aff3##T##_view(Aff3##T *r, Quad##T dst, Quad##T src) { \
    224 		T dstw = r_quad##T##_width(dst);
    225 		T dsth = r_quad##T##_height(dst);
    226 		T srcw = r_quad##T##_width(src);
    227 		T srch = r_quad##T##_height(src);
    228 
    229 		ASSERT(dstw > 0 && dsth > 0 && srcw > 0 && srch > 0);
    230 
    231 		Aff3##T t;
    232 		r_aff3##T##_translate(r, -src[0][0], -src[0][1]);
    233 		r_aff3##T##_scale(&t, dstw / srcw, dsth / srch);
    234 		r_aff3##T##_mul(r, t, *r);
    235 		r_aff3##T##_translate(&t, dst[0][0], dst[0][1]);
    236 		r_aff3##T##_mul(r, t, *r);
    237 	}
    238 
    239 AFF3_VIEW(f32)
    240 AFF3_VIEW(f64)
    241 
    242 #undef AFF3_VIEW