On Tue, Oct 04, 2011 at 06:02:21PM -0700, Jeremy Huddleston wrote: > Reviewed-by: Jeremy Huddleston <[email protected]> > > Wow, that's all I missed? Not bad for coding in an email client ;) > > You might want to replace my "crap" comment with something more > descriptive such as "loss of precision, setting to 0"
I thought it was quite expressive as-is but I will amend :) I wonder if we need this path at all though. after all, if d-trunc(d) starts giving us values outside of 0..1 we have other problems. Also, this needs a follow-up patch anyway, I completely forgot to test negative numbers. Cheers, Peter > On Oct 4, 2011, at 4:39 PM, Peter Hutterer wrote: > > > Co-authored by Jeremy Huddleston <[email protected]> > > Signed-off-by: Peter Hutterer <[email protected]> > > --- > > Jeremy, these are your functions fixed up to pass the tests (a few bitshifts > > where wrong). > > Changes to your version: > > - use trunc instad of (double)(int)(double_value) > > - use rint(trunc()) instead of (int) to silence gcc > > - fix a few wrong bitshifts/masks > > - fix < 0 to < 1 for fabs(frac) > > > > dix/inpututils.c | 68 ++++++++++++++++++++++++++++ > > include/inpututils.h | 6 +++ > > test/input.c | 120 > > ++++++++++++++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 194 insertions(+), 0 deletions(-) > > > > diff --git a/dix/inpututils.c b/dix/inpututils.c > > index 582135e..c27e16c 100644 > > --- a/dix/inpututils.c > > +++ b/dix/inpututils.c > > @@ -821,3 +821,71 @@ input_option_set_value(InputOption *opt, const char > > *value) > > if (value) > > opt->value = strdup(value); > > } > > + > > + > > +/* FP1616/FP3232 conversion functions */ > > +double > > +fp1616_to_double(FP1616 in) > > +{ > > + double ret; > > + ret = (double)(in >> 16); > > + ret += ldexp((double)(in & 0xffff), -16); > > + return ret; > > +} > > + > > +double > > +fp3232_to_double(FP3232 in) > > +{ > > + double ret; > > + ret = (double)in.integral; > > + ret += ldexp((double)in.frac, -32); > > + return ret; > > +} > > + > > + > > +FP1616 > > +double_to_fp1616(double in) > > +{ > > + FP1616 ret; > > + int32_t integral; > > + double frac_f; > > + uint32_t frac_d; > > + > > + integral = (int32_t)in << 16; > > + frac_f = in - trunc(in); > > + > > + if (fabs(frac_f) < 1) { > > + frac_d = rint(trunc(ldexp(frac_f, 16))); > > + } else { > > + /* crap */ > > + frac_d = 0; > > + } > > + > > + ret = integral; > > + ret |= frac_d & 0xffff; > > + return ret; > > +} > > + > > +FP3232 > > +double_to_fp3232(double in) > > +{ > > + FP3232 ret; > > + int32_t integral; > > + double frac_f; > > + uint32_t frac_d; > > + > > + integral = (int32_t)in; > > + frac_f = in - trunc(in); > > + > > + if (fabs(frac_f) < 1) { > > + frac_d = rint(trunc(ldexp(frac_f,32))); > > + } else { > > + /* crap */ > > + frac_d = 0; > > + } > > + > > + ret.integral = integral; > > + ret.frac = frac_d; > > + return ret; > > +} > > + > > diff --git a/include/inpututils.h b/include/inpututils.h > > index 47e242d..2832ed5 100644 > > --- a/include/inpututils.h > > +++ b/include/inpututils.h > > @@ -30,6 +30,7 @@ > > #define INPUTUTILS_H > > > > #include "input.h" > > +#include <X11/extensions/XI2proto.h> > > > > struct _ValuatorMask { > > int8_t last_bit; /* highest bit set in mask */ > > @@ -40,4 +41,9 @@ struct _ValuatorMask { > > extern void verify_internal_event(const InternalEvent *ev); > > extern void init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time > > ms); > > > > +FP3232 double_to_fp3232(double in); > > +FP1616 double_to_fp1616(double in); > > +double fp1616_to_double(FP1616 in); > > +double fp3232_to_double(FP3232 in); > > + > > #endif > > diff --git a/test/input.c b/test/input.c > > index 5fb9a90..05ef3ac 100644 > > --- a/test/input.c > > +++ b/test/input.c > > @@ -1476,8 +1476,128 @@ static void input_option_test(void) > > } > > > > > > +static void > > +_test_double_fp16_values(double d) > > +{ > > + FP1616 fp16; > > + double re; > > + uint32_t frac; > > + int32_t integral; > > + > > + if (d > 0x7FFF) { > > + printf("Test out of range\n"); > > + assert(0); > > + } > > + > > + frac = rint(trunc(ldexp(d - trunc(d), 16))); > > + integral = ((int16_t)d) << 16; > > + > > + fp16 = double_to_fp1616(d); > > + re = fp1616_to_double(fp16); > > + > > + /* printf("FP16: double: %f fp16: %u int: %u frac: %u re:%f\n", d, > > fp16, integral, frac, re); */ > > + > > + assert((fp16 & 0xFFFF0000) == integral); > > + assert((fp16 & 0x0000FFFF) == frac); > > + > > + re = fp1616_to_double(fp16); > > + /* since we lose precision, we only do rough range testing */ > > + assert(re > d - 0.1); > > + assert(re < d + 0.1); > > + > > +} > > + > > +static void > > +_test_double_fp32_values(double d) > > +{ > > + FP3232 fp32; > > + double re; > > + uint32_t frac; > > + int32_t integral; > > + > > + if (d > 0x7FFFFFFF) { > > + printf("Test out of range\n"); > > + assert(0); > > + } > > + > > + frac = rint(trunc(ldexp(d - trunc(d), 32))); > > + integral = ((int32_t)d); > > + > > + fp32 = double_to_fp3232(d); > > + re = fp3232_to_double(fp32); > > + > > + /* printf("FP32: double: %f fp32: %u.%u int: %u frac: %u re:%f\n", d, > > fp32.integral, fp32.frac, integral, frac, re); */ > > + > > + assert(fp32.integral == integral); > > + assert(fp32.frac == frac); > > + > > + re = fp3232_to_double(fp32); > > + /* since we lose precision, we only do rough range testing */ > > + assert(re > d - 0.1); > > + assert(re < d + 0.1); > > +} > > + > > +static void > > +dix_double_fp_conversion(void) > > +{ > > + long i; > > + printf("Testing double to FP1616/FP3232 conversions\n"); > > + > > + _test_double_fp16_values(0); > > + for (i = 1; i < 0x7FFF; i <<= 1) { > > + double val; > > + > > + val = i; > > + _test_double_fp16_values(val); > > + _test_double_fp32_values(val); > > + > > + /* and some pseudo-random floating points */ > > + val = i + 0.00382; > > + _test_double_fp16_values(val); > > + _test_double_fp32_values(val); > > + > > + val = i + 0.05234; > > + _test_double_fp16_values(val); > > + _test_double_fp32_values(val); > > + > > + val = i + 0.12342; > > + _test_double_fp16_values(val); > > + _test_double_fp32_values(val); > > + > > + val = i + 0.27583; > > + _test_double_fp16_values(val); > > + _test_double_fp32_values(val); > > + > > + val = i + 0.50535; > > + _test_double_fp16_values(val); > > + _test_double_fp32_values(val); > > + > > + val = i + 0.72342; > > + _test_double_fp16_values(val); > > + _test_double_fp32_values(val); > > + > > + val = i + 0.80408; > > + _test_double_fp16_values(val); > > + _test_double_fp32_values(val); > > + } > > + > > + for (i = 0x7FFFF; i < 0x7FFFFFFF; i <<= 1) { > > + _test_double_fp32_values(i); > > + /* and a few more random floating points, obtained > > + * by faceplanting into the numpad repeatedly */ > > + _test_double_fp32_values(i + 0.010177); > > + _test_double_fp32_values(i + 0.213841); > > + _test_double_fp32_values(i + 0.348720); > > + _test_double_fp32_values(i + 0.472020); > > + _test_double_fp32_values(i + 0.572020); > > + _test_double_fp32_values(i + 0.892929); > > + } > > + > > +} > > + > > int main(int argc, char** argv) > > { > > + dix_double_fp_conversion(); > > dix_input_valuator_masks(); > > dix_input_attributes(); > > dix_init_valuators(); > > -- > > 1.7.6.4 > > > > _______________________________________________ > > [email protected]: X.Org development > > Archives: http://lists.x.org/archives/xorg-devel > > Info: http://lists.x.org/mailman/listinfo/xorg-devel > > > > _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
