diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 0d2b4a8a4..e257412d6 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -112,6 +112,8 @@ extern exprtype_t cexpr_uint; extern exprtype_t cexpr_size_t; extern exprtype_t cexpr_float; extern exprtype_t cexpr_double; +extern exprtype_t cexpr_vector; +extern exprtype_t cexpr_quaternion; extern exprtype_t cexpr_exprval; extern exprtype_t cexpr_field; diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index e2e09c341..997127a94 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -99,8 +99,8 @@ qvmulf (vec4f_t q, vec4f_t v) // zero the scalar of the quaternion. Results in an extra operation, but // avoids adding precision issues. q = _mm_insert_ps (q, q, 0xf8); - vec4f_t c = crossf (q, v); // q.w is 0 so v.w is irrelevant - vec4f_t qv = dotf (q, v); + vec4f_t c = crossf (q, v); + vec4f_t qv = dotf (q, v); // q.w is 0 so v.w is irrelevant vec4f_t qq = dotf (q, q); return (s * s - qq) * v + 2 * (qv * q + s * c); diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index c1dbbafb0..81fc212cd 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -30,6 +30,8 @@ #include #include "QF/cexpr.h" +#include "QF/mathlib.h" +#include "QF/simd/vec4f.h" #include "libs/util/cexpr-parse.h" @@ -232,7 +234,7 @@ static void float_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, exprctx_t *ctx) { - // implement true modulo for integers: + // implement true modulo for floats: // 5 mod 3 = 2 // -5 mod 3 = 1 // 5 mod -3 = -1 @@ -242,6 +244,26 @@ float_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, *(float *) result->value = a - b * floorf (a / b); } +static void +float_mul_vec4f (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ + float s = *(float *) val1->value; + __auto_type v = (vec4f_t *) val2->value; + __auto_type r = (vec4f_t *) result->value; + *r = s * *v; +} + +static void +float_div_quat (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ + float a = *(float *) val1->value; + vec4f_t b = *(vec4f_t *) val2->value; + __auto_type c = (vec4f_t *) result->value; + *c = a * qconjf (b) / dotf (b, b); +} + UNOP(float, pos, float, +) UNOP(float, neg, float, -) UNOP(float, tnot, float, !) @@ -250,7 +272,10 @@ binop_t float_binops[] = { { '+', &cexpr_float, &cexpr_float, float_add }, { '-', &cexpr_float, &cexpr_float, float_sub }, { '*', &cexpr_float, &cexpr_float, float_mul }, + { '*', &cexpr_vector, &cexpr_vector, float_mul_vec4f }, + { '*', &cexpr_quaternion, &cexpr_quaternion, float_mul_vec4f }, { '/', &cexpr_float, &cexpr_float, float_div }, + { '/', &cexpr_quaternion, &cexpr_quaternion, float_div_quat }, { '%', &cexpr_float, &cexpr_float, float_rem }, { MOD, &cexpr_float, &cexpr_float, float_mod }, {} @@ -288,7 +313,7 @@ static void double_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, exprctx_t *ctx) { - // implement true modulo for integers: + // implement true modulo for doubles: // 5 mod 3 = 2 // -5 mod 3 = 1 // 5 mod -3 = -1 @@ -326,6 +351,102 @@ exprtype_t cexpr_double = { double_unops, }; +BINOP(vector, add, vec4f_t, +) +BINOP(vector, sub, vec4f_t, -) +BINOP(vector, mul, vec4f_t, *) +BINOP(vector, div, vec4f_t, /) + +static void +vector_rem (const exprval_t *val1, const exprval_t *val2, exprval_t *result, + exprctx_t *ctx) +{ + vec4f_t a = *(vec4f_t *) val1->value; + vec4f_t b = *(vec4f_t *) val2->value; + __auto_type c = (vec4f_t *) result->value; + *c = a - b * vtruncf (a / b); +} + +static void +vector_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, + exprctx_t *ctx) +{ + // implement true modulo for doubles: + // 5 mod 3 = 2 + // -5 mod 3 = 1 + // 5 mod -3 = -1 + // -5 mod -3 = -2 + vec4f_t a = *(vec4f_t *) val1->value; + vec4f_t b = *(vec4f_t *) val2->value; + __auto_type c = (vec4f_t *) result->value; + *c = a - b * vfloorf (a / b); +} + +UNOP(vector, pos, vec4f_t, +) +UNOP(vector, neg, vec4f_t, -) + +static void +vector_tnot (const exprval_t *val, exprval_t *result, exprctx_t *ctx) +{ + vec4f_t v = *(vec4f_t *) val->value; + __auto_type c = (vec4i_t *) result->value; + *c = v != 0; +} + +binop_t vector_binops[] = { + { '+', &cexpr_vector, &cexpr_vector, vector_add }, + { '-', &cexpr_vector, &cexpr_vector, vector_sub }, + { '*', &cexpr_vector, &cexpr_vector, vector_mul }, + { '/', &cexpr_vector, &cexpr_vector, vector_div }, + { '%', &cexpr_vector, &cexpr_vector, vector_rem }, + { MOD, &cexpr_vector, &cexpr_vector, vector_mod }, + {} +}; + +unop_t vector_unops[] = { + { '+', &cexpr_vector, vector_pos }, + { '-', &cexpr_vector, vector_neg }, + { '!', &cexpr_vector, vector_tnot }, + {} +}; + +exprtype_t cexpr_vector = { + "vector", + sizeof (vec4f_t), + vector_binops, + vector_unops, +}; + +static void +quaternion_mul (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ + vec4f_t a = *(vec4f_t *) val1->value; + vec4f_t b = *(vec4f_t *) val2->value; + __auto_type c = (vec4f_t *) result->value; + *c = qmulf (a, b); +} + +binop_t quaternion_binops[] = { + { '+', &cexpr_quaternion, &cexpr_quaternion, vector_add }, + { '-', &cexpr_quaternion, &cexpr_quaternion, vector_sub }, + { '*', &cexpr_quaternion, &cexpr_quaternion, quaternion_mul }, + {} +}; + +unop_t quaternion_unops[] = { + { '+', &cexpr_vector, vector_pos }, + { '-', &cexpr_vector, vector_neg }, + { '!', &cexpr_vector, vector_tnot }, + {} +}; + +exprtype_t cexpr_quaternion = { + "quaterion", + sizeof (vec4f_t), + quaternion_binops, + quaternion_unops, +}; + exprtype_t cexpr_exprval = { "exprval", sizeof (exprval_t *),