static gpointer matrix_setup (void) { MatrixBench *res = g_new0 (MatrixBench, 1); int i; res->a = alloc_n_matrix (N_ROUNDS); res->b = alloc_n_matrix (N_ROUNDS); res->c = alloc_n_matrix (N_ROUNDS); res->pa = alloc_n_vec (N_ROUNDS); res->qa = alloc_n_vec (N_ROUNDS); res->ra = alloc_n_vec (N_ROUNDS); for (i = 0; i < N_ROUNDS; i++) { graphene_simd4f_t p, q; p = graphene_simd4f_init (i, i, i, i); q = graphene_simd4f_init (N_ROUNDS - i, N_ROUNDS - i, N_ROUNDS - i, N_ROUNDS - i); res->a[i] = graphene_simd4x4f_init (p, p, p, p); res->b[i] = graphene_simd4x4f_init (q, q, q, q); res->pa[i] = graphene_simd4f_init (i, i, 0.f, 0.f); res->qa[i] = graphene_simd4f_init (N_ROUNDS - i, N_ROUNDS - 1, 1.f, 0.f); } return res; }
/** * graphene_quaternion_slerp: * @a: a #graphene_quaternion_t * @b: a #graphene_quaternion_t * @factor: the linear interpolation factor * @res: (out caller-allocates): return location for the interpolated * quaternion * * Interpolates between the two given quaternions using a spherical * linear interpolation, or [SLERP](http://en.wikipedia.org/wiki/Slerp), * using the given interpolation @factor. * * Since: 1.0 */ void graphene_quaternion_slerp (const graphene_quaternion_t *a, const graphene_quaternion_t *b, float factor, graphene_quaternion_t *res) { float theta, r_sin_theta, right_v, left_v, dot; graphene_simd4f_t v_a, v_b, left, right, sum; v_a = graphene_simd4f_init (a->x, a->y, a->z, a->w); v_b = graphene_simd4f_init (b->x, b->y, b->z, b->w); dot = CLAMP (graphene_simd4f_get_x (graphene_simd4f_dot4 (v_a, v_b)), -1.f, 1.f); if (dot == 1.f) { *res = *a; return; } theta = acos (dot); r_sin_theta = 1.f / sqrtf (1.f - dot * dot); right_v = sinf (factor * theta) * r_sin_theta; left_v = cosf (factor * theta) - dot * right_v; left = graphene_simd4f_init (a->x, a->y, a->z, a->w); right = graphene_simd4f_init (b->x, b->y, b->z, b->w); left = graphene_simd4f_mul (left, graphene_simd4f_splat (left_v)); right = graphene_simd4f_mul (right, graphene_simd4f_splat (right_v)); sum = graphene_simd4f_add (left, right); graphene_quaternion_init_from_simd4f (res, sum); }
static void init_static_vec2_once (void) { static_vec2[VEC2_ZERO].value = graphene_simd4f_init_zero (); static_vec2[VEC2_ONE].value = graphene_simd4f_init (1.f, 1.f, 0.f, 0.f); static_vec2[VEC2_X_AXIS].value = graphene_simd4f_init (1.f, 0.f, 0.f, 0.f); static_vec2[VEC2_Y_AXIS].value = graphene_simd4f_init (0.f, 1.f, 0.f, 0.f); }
static void init_static_vec4_once (void) { static_vec4[VEC4_ZERO].value = graphene_simd4f_init_zero (); static_vec4[VEC4_ONE].value = graphene_simd4f_splat (1.f); static_vec4[VEC4_X_AXIS].value = graphene_simd4f_init (1.f, 0.f, 0.f, 0.f); static_vec4[VEC4_Y_AXIS].value = graphene_simd4f_init (0.f, 1.f, 0.f, 0.f); static_vec4[VEC4_Z_AXIS].value = graphene_simd4f_init (0.f, 0.f, 1.f, 0.f); static_vec4[VEC4_W_AXIS].value = graphene_simd4f_init (0.f, 0.f, 0.f, 1.f); }
/** * graphene_quaternion_dot: * @a: a #graphene_quaternion_t * @b: a #graphene_quaternion_t * * Computes the dot product of two #graphene_quaternion_t. * * Returns: the value of the dot products * * Since: 1.0 */ float graphene_quaternion_dot (const graphene_quaternion_t *a, const graphene_quaternion_t *b) { graphene_simd4f_t v_a, v_b; v_a = graphene_simd4f_init (a->x, a->y, a->z, a->w); v_b = graphene_simd4f_init (b->x, b->y, b->z, b->w); return graphene_simd4f_get_x (graphene_simd4f_dot4 (v_a, v_b)); }
/** * graphene_matrix_init_translate: * @m: a #graphene_matrix_t * @p: the translation coordinates * * Initializes a #graphene_matrix_t with a translation to the * given coordinates. * * Returns: (transfer none): the initialized matrix * * Since: 1.0 */ graphene_matrix_t * graphene_matrix_init_translate (graphene_matrix_t *m, const graphene_point3d_t *p) { m->value = graphene_simd4x4f_init (graphene_simd4f_init (1.0f, 0.0f, 0.0f, 0.0f), graphene_simd4f_init (0.0f, 1.0f, 0.0f, 0.0f), graphene_simd4f_init (0.0f, 0.0f, 1.0f, 0.0f), graphene_simd4f_init (p->x, p->y, p->z, 1.0f)); return m; }
/** * graphene_matrix_init_scale: * @m: a #graphene_matrix_t * @x: the scale factor on the X axis * @y: the scale factor on the Y axis * @z: the scale factor on the Z axis * * Initializes a #graphene_matrix_t with the given scaling factors. * * Returns: (transfer none): the initialized matrix * * Since: 1.0 */ graphene_matrix_t * graphene_matrix_init_scale (graphene_matrix_t *m, float x, float y, float z) { m->value = graphene_simd4x4f_init (graphene_simd4f_init ( x, 0.0f, 0.0f, 0.0f), graphene_simd4f_init (0.0f, y, 0.0f, 0.0f), graphene_simd4f_init (0.0f, 0.0f, z, 0.0f), graphene_simd4f_init (0.0f, 0.0f, 0.0f, 1.0f)); return m; }
graphene_matrix_t * graphene_matrix_init_translate (graphene_matrix_t *m, const graphene_point3d_t *p) { g_return_val_if_fail (m != NULL, NULL); g_return_val_if_fail (p != NULL, m); m->value = graphene_simd4x4f_init (graphene_simd4f_init (1.0f, 0.0f, 0.0f, 0.0f), graphene_simd4f_init (0.0f, 1.0f, 0.0f, 0.0f), graphene_simd4f_init (0.0f, 0.0f, 1.0f, 0.0f), graphene_simd4f_init (p->x, p->y, p->z, 1.0f)); return m; }
/** * graphene_vec3_get_xyz1: * @v: a #graphene_vec3_t * @res: (out caller-allocates): return location for the vector * * Converts a #graphene_vec3_t in a #graphene_vec4_t using 1.0 * as the value for the fourth component of the resulting vector. * * Since: 1.0 */ void graphene_vec3_get_xyz1 (const graphene_vec3_t *v, graphene_vec4_t *res) { res->value = graphene_simd4f_add (graphene_simd4f_zero_w (v->value), graphene_simd4f_init (0.f, 0.f, 0.f, 1.f)); }
graphene_matrix_t * graphene_matrix_init_scale (graphene_matrix_t *m, float x, float y, float z) { g_return_val_if_fail (m != NULL, NULL); m->value = graphene_simd4x4f_init (graphene_simd4f_init ( x, 0.0f, 0.0f, 0.0f), graphene_simd4f_init (0.0f, y, 0.0f, 0.0f), graphene_simd4f_init (0.0f, 0.0f, z, 0.0f), graphene_simd4f_init (0.0f, 0.0f, 0.0f, 1.0f)); return m; }
/** * graphene_matrix_init_from_2d: * @m: a #graphene_matrix_t * @xx: the xx member * @yx: the yx member * @xy: the xy member * @yy: the yy member * @x_0: the x0 member * @y_0: the y0 member * * Initializes a #graphene_matrix_t from the values of an affine * transformation matrix. * * The arguments map to the following matrix layout: * * |[ * | xx yx | | a b 0 | * | xy yy | = | c d 0 | * | x0 y0 | | tx ty 1 | * ]| * * This function can be used to convert between a matrix type from * other libraries and a #graphene_matrix_t. * * Returns: (transfer none): the initialized matrix * * Since: 1.0 */ graphene_matrix_t * graphene_matrix_init_from_2d (graphene_matrix_t *m, double xx, double yx, double xy, double yy, double x_0, double y_0) { m->value = graphene_simd4x4f_init (graphene_simd4f_init ( xx, yx, 0.f, 0.f), graphene_simd4f_init ( yx, yy, 0.f, 0.f), graphene_simd4f_init (0.f, 0.f, 1.f, 0.f), graphene_simd4f_init (x_0, y_0, 0.f, 1.f)); return m; }
/** * graphene_quaternion_equal: * @a: a #graphene_quaternion_t * @b: a #graphene_quaternion_t * * Checks whether the given quaternions are equal. * * Returns: `true` if the quaternions are equal * * Since: 1.0 */ bool graphene_quaternion_equal (const graphene_quaternion_t *a, const graphene_quaternion_t *b) { graphene_simd4f_t v_a, v_b; if (a == b) return true; if (a == NULL || b == NULL) return false; v_a = graphene_simd4f_init (a->x, a->y, a->z, a->w); v_b = graphene_simd4f_init (b->x, b->y, b->z, b->w); return graphene_simd4f_cmp_eq (v_a, v_b); }
/** * graphene_point_near: * @a: a #graphene_point_t * @b: a #graphene_point_t * @epsilon: threshold between the two points * * Checks whether the two points @a and @b are within * the threshold of @epsilon. * * Returns: `true` if the distance is within @epsilon * * Since: 1.0 */ bool graphene_point_near (const graphene_point_t *a, const graphene_point_t *b, float epsilon) { graphene_simd4f_t s_a, s_b, res; if (a == b) return true; s_a = graphene_simd4f_init (a->x, a->y, 0.f, 0.f); s_b = graphene_simd4f_init (b->x, b->y, 0.f, 0.f); res = graphene_simd4f_sub (s_a, s_b); return fabsf (graphene_simd4f_get_x (res)) < epsilon && fabsf (graphene_simd4f_get_y (res)) < epsilon; }
/** * graphene_simd4f_init: * @x: the first component of the vector * @y: the second component of the vector * @z: the third component of the vector * @w: the fourth component of the vector * * Initializes a #graphene_simd4f_t with the given values. * * Returns: the initialized #graphene_simd4f_t * * Since: 1.0 */ graphene_simd4f_t (graphene_simd4f_init) (float x, float y, float z, float w) { return graphene_simd4f_init (x, y, z, w); }
/** * graphene_matrix_init_skew: * @m: a #graphene_matrix_t * @x_skew: skew factor on the X axis * @y_skew: skew factor on the Y axis * * Initializes a #graphene_matrix_t with a skew transformation * with the given factors. * * Returns: (transfer none): the initialized matrix * * Since: 1.0 */ graphene_matrix_t * graphene_matrix_init_skew (graphene_matrix_t *m, float x_skew, float y_skew) { float t_x, t_y; t_x = tanf (x_skew); t_y = tanf (y_skew); m->value = graphene_simd4x4f_init (graphene_simd4f_init (1.0f, t_y, 0.0f, 0.0f), graphene_simd4f_init ( t_x, 1.0f, 0.0f, 0.0f), graphene_simd4f_init (0.0f, 0.0f, 1.0f, 0.0f), graphene_simd4f_init (0.0f, 0.0f, 0.0f, 1.0f)); return m; }
graphene_simd4f_t (graphene_simd4f_cross3) (const graphene_simd4f_t a, const graphene_simd4f_t b) { return graphene_simd4f_init (a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x, 0.f); }
graphene_simd4f_t (graphene_simd4f_min) (const graphene_simd4f_t a, const graphene_simd4f_t b) { return graphene_simd4f_init (a.x < b.x ? a.x : b.x, a.y < b.y ? a.y : b.y, a.z < b.z ? a.z : b.z, a.w < b.w ? a.w : b.w); }
graphene_simd4f_t (graphene_simd4f_max) (const graphene_simd4f_t a, const graphene_simd4f_t b) { return graphene_simd4f_init (a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y, a.z > b.z ? a.z : b.z, a.w > b.w ? a.w : b.w); }
/** * graphene_vec2_init: * @v: a #graphene_vec2_t * @x: the X field of the vector * @y: the Y field of the vector * * Initializes a #graphene_vec2_t using the given values. * * This function can be called multiple times. * * Returns: (transfer none): the initialized vector * * Since: 1.0 */ graphene_vec2_t * graphene_vec2_init (graphene_vec2_t *v, float x, float y) { v->value = graphene_simd4f_init (x, y, 0.f, 0.f); return v; }
/** * graphene_vec4_init_from_vec2: * @v: a #graphene_vec4_t * @src: a #graphene_vec2_t * @z: the value for the third component of @v * @w: the value for the fourth component of @v * * Initializes a #graphene_vec4_t using the components of a * #graphene_vec2_t and the values of @z and @w. * * Returns: (transfer none): the initialized vector * * Since: 1.0 */ graphene_vec4_t * graphene_vec4_init_from_vec2 (graphene_vec4_t *v, const graphene_vec2_t *src, float z, float w) { v->value = graphene_simd4f_merge_low (src->value, graphene_simd4f_init (z, w, 0, 0)); return v; }
/** * graphene_vec3_init: * @v: a #graphene_vec3_t * @x: the X field of the vector * @y: the Y field of the vector * @z: the Z field of the vector * * Initializes a #graphene_vec3_t using the given values. * * This function can be called multiple times. * * Returns: (transfer none): a pointer to the initialized * vector * * Since: 1.0 */ graphene_vec3_t * graphene_vec3_init (graphene_vec3_t *v, float x, float y, float z) { v->value = graphene_simd4f_init (x, y, z, 0.f); return v; }
/** * graphene_quaternion_normalize: * @q: a #graphene_quaternion_t * @res: (out caller-allocates): return location for the normalized * quaternion * * Normalizes a #graphene_quaternion_t. * * Since: 1.0 */ void graphene_quaternion_normalize (const graphene_quaternion_t *q, graphene_quaternion_t *res) { graphene_simd4f_t v_q; v_q = graphene_simd4f_init (q->x, q->y, q->z, q->w); v_q = graphene_simd4f_normalize4 (v_q); graphene_quaternion_init_from_simd4f (res, v_q); }
/** * graphene_vec4_init: * @v: a #graphene_vec4_t * @x: the X field of the vector * @y: the Y field of the vector * @z: the Z field of the vector * @w: the W field of the vector * * Initializes a #graphene_vec4_t using the given values. * * This function can be called multiple times. * * Returns: (transfer none): a pointer to the initialized * vector * * Since: 1.0 */ graphene_vec4_t * graphene_vec4_init (graphene_vec4_t *v, float x, float y, float z, float w) { v->value = graphene_simd4f_init (x, y, z, w); return v; }
/** * graphene_matrix_transform_point: * @m: a #graphene_matrix_t * @p: a #graphene_point_t * @res: (out caller-allocates): return location for the * transformed #graphene_point_t * * Transforms the given #graphene_point_t using the matrix @m. * * Since: 1.0 */ void graphene_matrix_transform_point (const graphene_matrix_t *m, const graphene_point_t *p, graphene_point_t *res) { graphene_simd4f_t vec3; vec3 = graphene_simd4f_init (p->x, p->y, 0.0f, 0.0f); graphene_simd4x4f_vec3_mul (&m->value, &vec3, &vec3); res->x = graphene_simd4f_get_x (vec3); res->y = graphene_simd4f_get_y (vec3); }
/** * graphene_quaternion_to_matrix: * @q: a #graphene_quaternion_t * @m: (out caller-allocates): a #graphene_matrix_t * * Converts a quaternion into a transformation matrix expressing * the rotation defined by the #graphene_quaternion_t. * * Since: 1.0 */ void graphene_quaternion_to_matrix (const graphene_quaternion_t *q, graphene_matrix_t *m) { graphene_simd4f_t m_x, m_y, m_z, m_w; m_x = graphene_simd4f_init (1.f - 2.f * (q->y * q->y + q->z * q->z), 2.f * (q->x * q->y + q->w * q->z), 2.f * (q->x * q->z - q->w * q->y), 0.f); m_y = graphene_simd4f_init ( 2.f * (q->x * q->y - q->w * q->z), 1.f - 2.f * (q->x * q->x + q->z * q->z), 2.f * (q->y * q->z + q->w * q->x), 0.f); m_z = graphene_simd4f_init ( 2.f * (q->x * q->z + q->w * q->y), 2.f * (q->y * q->z - q->w * q->x), 1.f - 2.f * (q->x * q->x + q->y * q->y), 0.f); m_w = graphene_simd4f_init (0.f, 0.f, 0.f, 1.f); m->value = graphene_simd4x4f_init (m_x, m_y, m_z, m_w); }
/** * graphene_point_distance: * @a: a #graphene_point_t * @b: a #graphene_point_t * @d_x: (out) (optional): distance component on the X axis * @d_y: (out) (optional): distance component on the Y axis * * Computes the distance between @a and @b. * * Returns: the distance between the two points * * Since: 1.0 */ float graphene_point_distance (const graphene_point_t *a, const graphene_point_t *b, float *d_x, float *d_y) { graphene_simd4f_t s_a, s_b, res; if (a == b) return 0.f; s_a = graphene_simd4f_init (a->x, a->y, 0.f, 0.f); s_b = graphene_simd4f_init (b->x, b->y, 0.f, 0.f); res = graphene_simd4f_sub (s_a, s_b); if (d_x != NULL) *d_x = fabsf (graphene_simd4f_get_x (res)); if (d_y != NULL) *d_y = fabsf (graphene_simd4f_get_y (res)); return graphene_simd4f_get_x (graphene_simd4f_length2 (res)); }
static void matrix_project (gpointer data_) { MatrixBench *data = data_; int i; for (i = 0; i < N_ROUNDS; i++) { graphene_simd4f_t pback, qback, uback; float t, x, y; graphene_simd4x4f_vec3_mul (&(data->a[i]), &(data->pa[i]), &pback); graphene_simd4x4f_vec3_mul (&(data->a[i]), &(data->qa[i]), &qback); uback = graphene_simd4f_sub (data->pa[i], pback); t = -1.0f * graphene_simd4f_get_z (pback) / graphene_simd4f_get_z (uback); x = graphene_simd4f_get_x (pback) + t * graphene_simd4f_get_x (uback); y = graphene_simd4f_get_y (pback) + t * graphene_simd4f_get_y (uback); data->ra[i] = graphene_simd4f_init (x, y, 0.f, 0.f); } }
graphene_simd4f_t (graphene_simd4f_neg) (const graphene_simd4f_t s) { return graphene_simd4f_init (-s.x, -s.y, -s.z, -s.w); }
graphene_simd4f_t (graphene_simd4f_flip_sign_1010) (const graphene_simd4f_t s) { return graphene_simd4f_init (-s.x, s.y, -s.z, s.w); }
graphene_simd4f_t (graphene_simd4f_flip_sign_0101) (const graphene_simd4f_t s) { return graphene_simd4f_init (s.x, -s.y, s.z, -s.w); }