mirror of
https://github.com/X11Libre/xf86-input-libinput.git
synced 2026-04-14 10:54:17 +00:00
Caused by different results in -O0 vs -O2. The resulting array differs only
slightly but the initial sequence has one extra zero. That triggers our
assert, no other compiler flag seem to be affecting this.
Compiled with -O0:
Breakpoint 1, test_nonzero_x_linear () at test-bezier.c:157
157 assert(bezier[x] > bezier[x-1]);
(gdb) p bezier
$6 = {0 <repeats 409 times>, 1, 2, 4, 5, 7, 9, 10, 12, 14, 15, 17, 19, 21, 22,
Compiled with -O2:
(gdb) p bezier
$1 = {0 <repeats 410 times>, 1, 3, 5, 7, 9, 10, 12, 14, 15, 17, 19, 20, 22,
Printing of the temporary numbers in the decasteljau function shows that a few
of them are off by one, e.g.
408.530612/0.836735 with O0, but
409.510204/0.836735 with O2
Note: these are not rounding errors caused by the code, the cast to int
happens afterwards.
Hack around this by allowing for one extra zero before we check that the rest
of the curve is ascending again.
https://bugs.freedesktop.org/show_bug.cgi?id=99992
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
207 lines
4.2 KiB
C
207 lines
4.2 KiB
C
/*
|
|
* Copyright © 2016 Red Hat, Inc.
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software
|
|
* and its documentation for any purpose is hereby granted without
|
|
* fee, provided that the above copyright notice appear in all copies
|
|
* and that both that copyright notice and this permission notice
|
|
* appear in supporting documentation, and that the name of Red Hat
|
|
* not be used in advertising or publicity pertaining to distribution
|
|
* of the software without specific, written prior permission. Red
|
|
* Hat makes no representations about the suitability of this software
|
|
* for any purpose. It is provided "as is" without express or implied
|
|
* warranty.
|
|
*
|
|
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
|
* NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include "bezier.h"
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
static inline void
|
|
print_curve(int *bezier, size_t size)
|
|
{
|
|
/* look at it with gnuplot, "plot 'output-file.txt'" */
|
|
for (int i = 0; i < size; i++)
|
|
printf("%d %d\n", i, bezier[i]);
|
|
}
|
|
|
|
static void
|
|
test_linear(void)
|
|
{
|
|
const int size = 2048;
|
|
int bezier[size];
|
|
|
|
struct bezier_control_point controls[] = {
|
|
{ 0.0, 0.0 },
|
|
{ 0.0, 0.0 },
|
|
{ 1.0, 1.0 },
|
|
{ 1.0, 1.0 }
|
|
};
|
|
|
|
cubic_bezier(controls, bezier, size);
|
|
|
|
assert(bezier[0] == 0);
|
|
assert(bezier[size - 1] == size - 1);
|
|
|
|
for (int x = 1; x < size; x++)
|
|
assert(bezier[x] == x);
|
|
}
|
|
|
|
/* Center point pulled down towards X axis */
|
|
static void
|
|
test_flattened(void)
|
|
{
|
|
const int size = 2048;
|
|
int bezier[size];
|
|
|
|
struct bezier_control_point controls[] = {
|
|
{ 0.0, 0.0 },
|
|
{ 0.1, 0.0 },
|
|
{ 1.0, 0.9 },
|
|
{ 1.0, 1.0 }
|
|
};
|
|
|
|
cubic_bezier(controls, bezier, size);
|
|
|
|
assert(bezier[0] == 0);
|
|
assert(bezier[size - 1] == size - 1);
|
|
|
|
for (int x = 1; x < size - 1; x++) {
|
|
assert(bezier[x] < x);
|
|
}
|
|
}
|
|
|
|
/* Center point pulled up from X axis */
|
|
static void
|
|
test_raised(void)
|
|
{
|
|
const int size = 2048;
|
|
int bezier[size];
|
|
|
|
struct bezier_control_point controls[] = {
|
|
{ 0.0, 0.0 },
|
|
{ 0.1, 0.4 },
|
|
{ 0.4, 1.0 },
|
|
{ 1.0, 1.0 }
|
|
};
|
|
|
|
cubic_bezier(controls, bezier, size);
|
|
|
|
assert(bezier[0] == 0);
|
|
assert(bezier[size - 1] == size - 1);
|
|
|
|
for (int x = 1; x < size; x++)
|
|
assert(bezier[x] >= x);
|
|
|
|
for (int x = 10; x < size - 10; x++)
|
|
assert(bezier[x] > x);
|
|
}
|
|
|
|
static void
|
|
test_windy(void)
|
|
{
|
|
const int size = 2048;
|
|
int bezier[size];
|
|
|
|
struct bezier_control_point controls[] = {
|
|
{ 0.0, 0.0 },
|
|
{ 0.0, 0.3 },
|
|
{ 1.0, 0.7 },
|
|
{ 1.0, 1.0 }
|
|
};
|
|
|
|
cubic_bezier(controls, bezier, size);
|
|
|
|
assert(bezier[0] == 0);
|
|
assert(bezier[size - 1] == size - 1);
|
|
|
|
for (int x = 1; x < size/2 - 20; x++)
|
|
assert(bezier[x] > x);
|
|
|
|
for (int x = size/2 + 20; x < size - 1; x++)
|
|
assert(bezier[x] < x);
|
|
}
|
|
|
|
static void
|
|
test_nonzero_x_linear(void)
|
|
{
|
|
const int size = 2048;
|
|
int bezier[size];
|
|
int x;
|
|
|
|
struct bezier_control_point controls[] = {
|
|
{ 0.2, 0.0 },
|
|
{ 0.2, 0.0 },
|
|
{ 0.8, 1.0 },
|
|
{ 0.8, 1.0 }
|
|
};
|
|
|
|
cubic_bezier(controls, bezier, size);
|
|
|
|
x = 0;
|
|
do {
|
|
assert(bezier[x] == 0);
|
|
} while (++x < size * 0.2 - 1);
|
|
|
|
/* ppc64le, ppc64, aarch64 have different math results at -O2,
|
|
resulting in one extra zero at the beginning of the array.
|
|
some other numbers are different too but within the error
|
|
margin (#99992) */
|
|
if (bezier[x] == 0)
|
|
x++;
|
|
|
|
do {
|
|
assert(bezier[x] > bezier[x-1]);
|
|
} while (++x < size * 0.8 - 1);
|
|
|
|
do {
|
|
assert(bezier[x] == size - 1);
|
|
} while (++x < size);
|
|
}
|
|
|
|
static void
|
|
test_nonzero_y_linear(void)
|
|
{
|
|
const int size = 2048;
|
|
int bezier[size];
|
|
|
|
struct bezier_control_point controls[] = {
|
|
{ 0.0, 0.2 },
|
|
{ 0.0, 0.2 },
|
|
{ 1.0, 0.8 },
|
|
{ 1.0, 0.8 }
|
|
};
|
|
|
|
cubic_bezier(controls, bezier, size);
|
|
|
|
assert(bezier[0] == (int)(size * 0.2));
|
|
|
|
for (int x = 1; x < size; x++) {
|
|
assert(bezier[x - 1] <= bezier[x]);
|
|
assert(bezier[x] >= (int)(size * 0.2));
|
|
}
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
test_linear();
|
|
test_flattened();
|
|
test_raised();
|
|
test_windy();
|
|
test_nonzero_x_linear();
|
|
test_nonzero_y_linear();
|
|
|
|
return 0;
|
|
}
|