[PATCH libinput 06/11] util: add a couple of 3x3 matrix helper functions

Hans de Goede hdegoede at redhat.com
Fri Aug 29 06:00:10 PDT 2014


Hi,

On 08/29/2014 01:51 AM, Peter Hutterer wrote:
> On Thu, Aug 28, 2014 at 03:04:30PM +0200, Hans de Goede wrote:
>> Hi,
>>
>> On 08/27/2014 06:31 AM, Peter Hutterer wrote:
>>> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
>>> ---
>>>  src/libinput-util.h | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>>  test/misc.c         |  78 ++++++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 178 insertions(+)
>>>
>>> diff --git a/src/libinput-util.h b/src/libinput-util.h
>>> index 5d366b0..925b86e 100644
>>> --- a/src/libinput-util.h
>>> +++ b/src/libinput-util.h
>>> @@ -25,6 +25,7 @@
>>>  
>>>  #include <unistd.h>
>>>  #include <math.h>
>>> +#include <string.h>
>>>  
>>>  #include "libinput.h"
>>>  
>>> @@ -179,4 +180,103 @@ long_set_bit_state(unsigned long *array, int bit, int state)
>>>  		long_clear_bit(array, bit);
>>>  }
>>>  
>>> +struct matrix {
>>> +	float val[3][3]; /* [row][col] */
>>> +};
>>> +
>>> +static inline void
>>> +matrix_init_identity(struct matrix *m)
>>> +{
>>> +	memset(m, 0, sizeof(*m));
>>> +	m->val[0][0] = 1;
>>> +	m->val[1][1] = 1;
>>> +	m->val[2][2] = 1;
>>> +}
>>> +
>>> +static inline void
>>> +matrix_from_farray6(struct matrix *m, const float values[6])
>>> +{
>>> +	matrix_init_identity(m);
>>> +	m->val[0][0] = values[0];
>>> +	m->val[0][1] = values[1];
>>> +	m->val[0][2] = values[2];
>>> +	m->val[1][0] = values[3];
>>> +	m->val[1][1] = values[4];
>>> +	m->val[1][2] = values[5];
>>> +}
>>> +
>>> +static inline void
>>> +matrix_init_scale(struct matrix *m, float sx, float sy)
>>> +{
>>> +	matrix_init_identity(m);
>>> +	m->val[0][0] = sx;
>>> +	m->val[1][1] = sy;
>>> +}
>>> +
>>> +static inline void
>>> +matrix_init_translate(struct matrix *m, float x, float y)
>>> +{
>>> +	matrix_init_identity(m);
>>> +	m->val[0][2] = x;
>>> +	m->val[1][2] = y;
>>> +}
>>> +
>>> +static inline int
>>> +matrix_is_identity(struct matrix *m)
>>> +{
>>> +	return (m->val[0][0] == 1 &&
>>> +		m->val[0][1] == 0 &&
>>> +		m->val[0][2] == 0 &&
>>> +		m->val[1][0] == 0 &&
>>> +		m->val[1][1] == 1 &&
>>> +		m->val[1][2] == 0 &&
>>> +		m->val[2][0] == 0 &&
>>> +		m->val[2][1] == 0 &&
>>> +		m->val[2][2] == 1);
>>> +}
>>> +
>>> +static inline void
>>> +matrix_mult(struct matrix *dest,
>>> +	    const struct matrix *m1,
>>> +	    const struct matrix *m2)
>>> +{
>>> +	struct matrix m;
>>> +	int row, col, i;
>>> +
>>> +	for (row = 0; row < 3; row++) {
>>> +		for (col = 0; col < 3; col++) {
>>> +			double v = 0;
>>> +			for (i = 0; i < 3; i++) {
>>> +				v += m1->val[row][i] * m2->val[i][col];
>>> +			}
>>> +			m.val[row][col] = v;
>>> +		}
>>> +	}
>>> +
>>> +	memcpy(dest, &m, sizeof(m));
>>
>> Why are you storing things in a local matrix first, and not
>> directly into dest ?
> 
> I'll add that to the commit message but: it allows for dest == m1 or 
> dest == m2.

Ah, maybe put a comment in the code about this too?

Reviewed-by: Hans de Goede <hdegoede at redhat.com>

Regards,

Hans

> 
> Cheers,
>    Peter
> 
> 
>>
>>
>>> +}
>>> +
>>> +static inline void
>>> +matrix_mult_vec(struct matrix *m, int *x, int *y)
>>> +{
>>> +	int tx, ty;
>>> +
>>> +	tx = *x * m->val[0][0] + *y * m->val[0][1] + m->val[0][2];
>>> +	ty = *x * m->val[1][0] + *y * m->val[1][1] + m->val[1][2];
>>> +
>>> +	*x = tx;
>>> +	*y = ty;
>>> +}
>>
>> Idem comment as for patch 5/11.
>>
>> Otherwise looks good.
>>
>> Regards,
>>
>> Hans
>>
>>> +
>>> +static inline void
>>> +matrix_to_farray6(const struct matrix *m, float out[6])
>>> +{
>>> +	out[0] = m->val[0][0];
>>> +	out[1] = m->val[0][1];
>>> +	out[2] = m->val[0][2];
>>> +	out[3] = m->val[1][0];
>>> +	out[4] = m->val[1][1];
>>> +	out[5] = m->val[1][2];
>>> +}
>>> +
>>>  #endif /* LIBINPUT_UTIL_H */
>>> diff --git a/test/misc.c b/test/misc.c
>>> index 983c3f9..1512180 100644
>>> --- a/test/misc.c
>>> +++ b/test/misc.c
>>> @@ -431,6 +431,83 @@ START_TEST(config_status_string)
>>>  }
>>>  END_TEST
>>>  
>>> +START_TEST(matrix_helpers)
>>> +{
>>> +	struct matrix m1, m2, m3;
>>> +	float f[6] = { 1, 2, 3, 4, 5, 6 };
>>> +	int x, y;
>>> +	int row, col;
>>> +
>>> +	matrix_init_identity(&m1);
>>> +
>>> +	for (row = 0; row < 3; row++) {
>>> +		for (col = 0; col < 3; col++) {
>>> +			ck_assert_int_eq(m1.val[row][col],
>>> +					 (row == col) ? 1 : 0);
>>> +		}
>>> +	}
>>> +	ck_assert(matrix_is_identity(&m1));
>>> +
>>> +	matrix_from_farray6(&m2, f);
>>> +	ck_assert_int_eq(m2.val[0][0], 1);
>>> +	ck_assert_int_eq(m2.val[0][1], 2);
>>> +	ck_assert_int_eq(m2.val[0][2], 3);
>>> +	ck_assert_int_eq(m2.val[1][0], 4);
>>> +	ck_assert_int_eq(m2.val[1][1], 5);
>>> +	ck_assert_int_eq(m2.val[1][2], 6);
>>> +	ck_assert_int_eq(m2.val[2][0], 0);
>>> +	ck_assert_int_eq(m2.val[2][1], 0);
>>> +	ck_assert_int_eq(m2.val[2][2], 1);
>>> +
>>> +	x = 100;
>>> +	y = 5;
>>> +	matrix_mult_vec(&m1, &x, &y);
>>> +	ck_assert_int_eq(x, 100);
>>> +	ck_assert_int_eq(y, 5);
>>> +
>>> +	matrix_mult(&m3, &m1, &m1);
>>> +	ck_assert(matrix_is_identity(&m3));
>>> +
>>> +	matrix_init_scale(&m2, 2, 4);
>>> +	ck_assert_int_eq(m2.val[0][0], 2);
>>> +	ck_assert_int_eq(m2.val[0][1], 0);
>>> +	ck_assert_int_eq(m2.val[0][2], 0);
>>> +	ck_assert_int_eq(m2.val[1][0], 0);
>>> +	ck_assert_int_eq(m2.val[1][1], 4);
>>> +	ck_assert_int_eq(m2.val[1][2], 0);
>>> +	ck_assert_int_eq(m2.val[2][0], 0);
>>> +	ck_assert_int_eq(m2.val[2][1], 0);
>>> +	ck_assert_int_eq(m2.val[2][2], 1);
>>> +
>>> +	matrix_mult_vec(&m2, &x, &y);
>>> +	ck_assert_int_eq(x, 200);
>>> +	ck_assert_int_eq(y, 20);
>>> +
>>> +	matrix_init_translate(&m2, 10, 100);
>>> +	ck_assert_int_eq(m2.val[0][0], 1);
>>> +	ck_assert_int_eq(m2.val[0][1], 0);
>>> +	ck_assert_int_eq(m2.val[0][2], 10);
>>> +	ck_assert_int_eq(m2.val[1][0], 0);
>>> +	ck_assert_int_eq(m2.val[1][1], 1);
>>> +	ck_assert_int_eq(m2.val[1][2], 100);
>>> +	ck_assert_int_eq(m2.val[2][0], 0);
>>> +	ck_assert_int_eq(m2.val[2][1], 0);
>>> +	ck_assert_int_eq(m2.val[2][2], 1);
>>> +
>>> +	matrix_mult_vec(&m2, &x, &y);
>>> +	ck_assert_int_eq(x, 210);
>>> +	ck_assert_int_eq(y, 120);
>>> +
>>> +	matrix_to_farray6(&m2, f);
>>> +	ck_assert_int_eq(f[0], 1);
>>> +	ck_assert_int_eq(f[1], 0);
>>> +	ck_assert_int_eq(f[2], 10);
>>> +	ck_assert_int_eq(f[3], 0);
>>> +	ck_assert_int_eq(f[4], 1);
>>> +	ck_assert_int_eq(f[5], 100);
>>> +}
>>> +END_TEST
>>> +
>>>  int main (int argc, char **argv) {
>>>  	litest_add_no_device("events:conversion", event_conversion_device_notify);
>>>  	litest_add_no_device("events:conversion", event_conversion_pointer);
>>> @@ -441,5 +518,6 @@ int main (int argc, char **argv) {
>>>  	litest_add("device:id", device_ids, LITEST_ANY, LITEST_ANY);
>>>  	litest_add_no_device("config:status string", config_status_string);
>>>  
>>> +	litest_add_no_device("misc:matrix", matrix_helpers);
>>>  	return litest_run(argc, argv);
>>>  }
>>>


More information about the wayland-devel mailing list