summaryrefslogtreecommitdiff
path: root/libtwin/twin_fixed.c
diff options
context:
space:
mode:
Diffstat (limited to 'libtwin/twin_fixed.c')
-rw-r--r--libtwin/twin_fixed.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/libtwin/twin_fixed.c b/libtwin/twin_fixed.c
new file mode 100644
index 0000000..060fb08
--- /dev/null
+++ b/libtwin/twin_fixed.c
@@ -0,0 +1,142 @@
+/*
+ * Twin - A Tiny Window System
+ * Copyright © 2004 Keith Packard <keithp@keithp.com>
+ * All rights reserved.
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Twin Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "twinint.h"
+
+#if 0
+#include <stdio.h>
+#define F(f) twin_fixed_to_double(f)
+#define DBGMSG(x) printf x
+#else
+#define DBGMSG(x)
+#endif
+
+#define uint32_lo(i) ((i) & 0xffff)
+#define uint32_hi(i) ((i) >> 16)
+#define uint32_carry16 ((1) << 16)
+
+#if 0
+twin_fixed_t
+twin_fixed_mul (twin_fixed_t af, twin_fixed_t bf)
+{
+ uint32_t a;
+ uint32_t b;
+ uint16_t ah, al, bh, bl;
+ uint32_t r0, r1, r2, r3;
+ uint32_t hi, lo;
+ twin_fixed_t r;
+ twin_bool_t negative = TWIN_FALSE;
+
+ a = (uint32_t) af;
+ b = (uint32_t) bf;
+ if (af < 0)
+ {
+ negative = !negative;
+ a = -a;
+ }
+ if (bf < 0)
+ {
+ negative = !negative;
+ b = -b;
+ }
+
+ al = uint32_lo (a);
+ ah = uint32_hi (a);
+ bl = uint32_lo (b);
+ bh = uint32_hi (b);
+
+ r0 = (uint32_t) al * bl;
+ r1 = (uint32_t) al * bh;
+ r2 = (uint32_t) ah * bl;
+ r3 = (uint32_t) ah * bh;
+
+ r1 += uint32_hi(r0); /* no carry possible */
+ r1 += r2; /* but this can carry */
+ if (r1 < r2) /* check */
+ r3 += uint32_carry16;
+
+ hi = r3 + uint32_hi(r1);
+ lo = (uint32_lo (r1) << 16) + uint32_lo (r0);
+
+ DBGMSG (("0x%x * 0x%x = 0x%x%08x\n", a, b, hi, lo));
+
+ r = (twin_fixed_t) ((hi << 16) | (lo >> 16));
+ if (negative)
+ r = -r;
+ DBGMSG (("%9.4f * %9.4f = %9.4f\n",
+ twin_fixed_to_double(af), twin_fixed_to_double(bf),
+ twin_fixed_to_double (r)));
+ return r;
+}
+#endif
+
+#if 0
+twin_fixed_t
+twin_fixed_div (twin_fixed_t a, twin_fixed_t b)
+{
+ twin_fixed_t q;
+ q = (twin_fixed_t) ((((int64_t) a) << 16) / b);
+ return q;
+}
+#endif
+
+twin_fixed_t
+twin_fixed_sqrt (twin_fixed_t a)
+{
+ twin_fixed_t max, min, mid;
+ twin_fixed_t sqr;
+
+ max = a;
+ min = 0;
+ while (max > min)
+ {
+ mid = (max + min) >> 1;
+ sqr = twin_fixed_mul (mid, mid);
+ if (sqr == a)
+ return mid;
+ if (sqr < a)
+ min = mid + 1;
+ else
+ max = mid - 1;
+ }
+ return (max + min) >> 1;
+}
+
+twin_sfixed_t
+_twin_sfixed_sqrt (twin_sfixed_t as)
+{
+ twin_dfixed_t max = as, min = 0, mid;
+ twin_dfixed_t a = twin_sfixed_to_dfixed (as);
+ twin_dfixed_t sqr;
+
+ while (max > min)
+ {
+ mid = (max + min) >> 1;
+ sqr = mid * mid;
+ if (sqr == a)
+ return (twin_sfixed_t) mid;
+ if (sqr < a)
+ min = mid + 1;
+ else
+ max = mid - 1;
+ }
+ return (twin_sfixed_t) ((max + min) >> 1);
+}