summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-12-10 10:12:37 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-12-10 10:12:37 -0800
commitb2a9e9235656317a5608c2ef837ed0d7a4fd43ae (patch)
tree1523228c1d50d05b019362df8907bcf6ead5baa9
parentc97acc792a69cbcabfa05150b639ef6b11f877f9 (diff)
downloadtxr-b2a9e9235656317a5608c2ef837ed0d7a4fd43ae.tar.gz
txr-b2a9e9235656317a5608c2ef837ed0d7a4fd43ae.tar.bz2
txr-b2a9e9235656317a5608c2ef837ed0d7a4fd43ae.zip
* arith.c: File is now generated using TXR.
(NOOP): New macro. (plus): Use NOOP macro. (minus, neg): Function moved here from lib.c and rewritten for bignum support. * lib.c (minus, neg): Functions removed. * arith.txr: New file.
-rw-r--r--ChangeLog12
-rw-r--r--arith.c83
-rw-r--r--arith.txr163
-rw-r--r--lib.c18
4 files changed, 257 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 695ff973..8b219237 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2011-12-10 Kaz Kylheku <kaz@kylheku.com>
+
+ * arith.c: File is now generated using TXR.
+ (NOOP): New macro.
+ (plus): Use NOOP macro.
+ (minus, neg): Function moved here from lib.c and rewritten
+ for bignum support.
+
+ * lib.c (minus, neg): Functions removed.
+
+ * arith.txr: New file.
+
2011-12-09 Kaz Kylheku <kaz@kylheku.com>
* configure: Fix patching without quilt.
diff --git a/arith.c b/arith.c
index a1026b37..f13d067e 100644
--- a/arith.c
+++ b/arith.c
@@ -1,4 +1,6 @@
-/* Copyright 2011
+/* This file is generated using txr arith.txr > arith.c!
+ *
+ * Copyright 2011
* Kaz Kylheku <kaz@kylheku.com>
* Vancouver, Canada
* All rights reserved.
@@ -42,6 +44,7 @@
#include "arith.h"
#define TAG_PAIR(A, B) ((A) << TAG_SHIFT | (B))
+#define NOOP(A, B)
static mp_int NUM_MAX_MP;
@@ -95,6 +98,7 @@ val plus(val anum, val bnum)
n = make_bignum();
if (sizeof (int_ptr_t) <= sizeof (mp_digit)) {
mp_add_d(mp(bnum), c_num(anum), mp(n));
+ NOOP(mp(n), mp(n));
} else {
mp_int tmp;
mp_init(&tmp);
@@ -132,6 +136,83 @@ val plus(val anum, val bnum)
abort();
}
+val minus(val anum, val bnum)
+{
+ int tag_a = tag(anum);
+ int tag_b = tag(bnum);
+
+ switch (TAG_PAIR(tag_a, tag_b)) {
+ case TAG_PAIR(TAG_NUM, TAG_NUM):
+ {
+ cnum a = c_num(anum);
+ cnum b = c_num(bnum);
+ cnum sum = a - b;
+
+ if (sum < NUM_MIN || sum > NUM_MAX) {
+ val n = make_bignum();
+ mp_set_intptr(mp(n), sum);
+ return n;
+ }
+
+ return num(sum);
+ }
+ case TAG_PAIR(TAG_NUM, TAG_PTR):
+ {
+ val n;
+ type_check(bnum, BGNUM);
+ n = make_bignum();
+ if (sizeof (int_ptr_t) <= sizeof (mp_digit)) {
+ mp_sub_d(mp(bnum), c_num(anum), mp(n));
+ mp_neg(mp(n), mp(n));
+ } else {
+ mp_int tmp;
+ mp_init(&tmp);
+ mp_set_intptr(&tmp, c_num(anum));
+ mp_sub(mp(bnum), &tmp, mp(n));
+ }
+ return normalize(n);
+ }
+ case TAG_PAIR(TAG_PTR, TAG_NUM):
+ {
+ val n;
+ type_check(anum, BGNUM);
+ n = make_bignum();
+ if (sizeof (int_ptr_t) <= sizeof (mp_digit)) {
+ mp_sub_d(mp(anum), c_num(bnum), mp(n));
+ } else {
+ mp_int tmp;
+ mp_init(&tmp);
+ mp_set_intptr(&tmp, c_num(bnum));
+ mp_sub(mp(anum), &tmp, mp(n));
+ }
+ return normalize(n);
+ }
+ case TAG_PAIR(TAG_PTR, TAG_PTR):
+ {
+ val n;
+ type_check(anum, BGNUM);
+ type_check(bnum, BGNUM);
+ n = make_bignum();
+ mp_sub(mp(anum), mp(bnum), mp(n));
+ return normalize(n);
+ }
+ }
+ uw_throwf(error_s, lit("minus: invalid operands ~s ~s"), anum, bnum, nao);
+ abort();
+}
+
+val neg(val anum)
+{
+ if (bignump(anum)) {
+ val n = make_bignum();
+ mp_neg(mp(anum), mp(n));
+ return n;
+ } else {
+ cnum n = c_num(anum);
+ return num(-n);
+ }
+}
+
void arith_init(void)
{
mp_init(&NUM_MAX_MP);
diff --git a/arith.txr b/arith.txr
new file mode 100644
index 00000000..9c746802
--- /dev/null
+++ b/arith.txr
@@ -0,0 +1,163 @@
+@(bind add-fname ("plus" "minus"))
+@(bind add-mp-op ("add" "sub"))
+@(bind add-mp-neg ("NOOP" "mp_neg"))
+@(bind add-c-op ("+" "-"))
+@(output)
+/* This file is generated using txr arith.txr > arith.c!
+ *
+ * Copyright 2011
+ * Kaz Kylheku <kaz@@kylheku.com>
+ * Vancouver, Canada
+ * All rights reserved.
+ *
+ * BSD License:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wctype.h>
+#include <assert.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <dirent.h>
+#include <setjmp.h>
+#include <wchar.h>
+#include "config.h"
+#include "lib.h"
+#include "unwind.h"
+#include "gc.h"
+#include "arith.h"
+
+#define TAG_PAIR(A, B) ((A) << TAG_SHIFT | (B))
+#define NOOP(A, B)
+
+static mp_int NUM_MAX_MP;
+
+val make_bignum(void)
+{
+ val n = make_obj();
+ n->bn.type = BGNUM;
+ mp_init(&n->bn.mp);
+ return n;
+}
+
+static val normalize(val bignum)
+{
+ switch (mp_cmp_mag(mp(bignum), &NUM_MAX_MP)) {
+ case MP_EQ:
+ case MP_GT:
+ return bignum;
+ default:
+ {
+ cnum fixnum;
+ mp_get_intptr(mp(bignum), &fixnum);
+ return num(fixnum);
+ }
+ }
+}
+
+@(repeat)
+val @{add-fname}(val anum, val bnum)
+{
+ int tag_a = tag(anum);
+ int tag_b = tag(bnum);
+
+ switch (TAG_PAIR(tag_a, tag_b)) {
+ case TAG_PAIR(TAG_NUM, TAG_NUM):
+ {
+ cnum a = c_num(anum);
+ cnum b = c_num(bnum);
+ cnum sum = a @{add-c-op} b;
+
+ if (sum < NUM_MIN || sum > NUM_MAX) {
+ val n = make_bignum();
+ mp_set_intptr(mp(n), sum);
+ return n;
+ }
+
+ return num(sum);
+ }
+ case TAG_PAIR(TAG_NUM, TAG_PTR):
+ {
+ val n;
+ type_check(bnum, BGNUM);
+ n = make_bignum();
+ if (sizeof (int_ptr_t) <= sizeof (mp_digit)) {
+ mp_@{add-mp-op}_d(mp(bnum), c_num(anum), mp(n));
+ @{add-mp-neg}(mp(n), mp(n));
+ } else {
+ mp_int tmp;
+ mp_init(&tmp);
+ mp_set_intptr(&tmp, c_num(anum));
+ mp_@{add-mp-op}(mp(bnum), &tmp, mp(n));
+ }
+ return normalize(n);
+ }
+ case TAG_PAIR(TAG_PTR, TAG_NUM):
+ {
+ val n;
+ type_check(anum, BGNUM);
+ n = make_bignum();
+ if (sizeof (int_ptr_t) <= sizeof (mp_digit)) {
+ mp_@{add-mp-op}_d(mp(anum), c_num(bnum), mp(n));
+ } else {
+ mp_int tmp;
+ mp_init(&tmp);
+ mp_set_intptr(&tmp, c_num(bnum));
+ mp_@{add-mp-op}(mp(anum), &tmp, mp(n));
+ }
+ return normalize(n);
+ }
+ case TAG_PAIR(TAG_PTR, TAG_PTR):
+ {
+ val n;
+ type_check(anum, BGNUM);
+ type_check(bnum, BGNUM);
+ n = make_bignum();
+ mp_@{add-mp-op}(mp(anum), mp(bnum), mp(n));
+ return normalize(n);
+ }
+ }
+ uw_throwf(error_s, lit("@{add-fname}: invalid operands ~s ~s"), anum, bnum, nao);
+ abort();
+}
+
+@(end)
+val neg(val anum)
+{
+ if (bignump(anum)) {
+ val n = make_bignum();
+ mp_neg(mp(anum), mp(n));
+ return n;
+ } else {
+ cnum n = c_num(anum);
+ return num(-n);
+ }
+}
+
+void arith_init(void)
+{
+ mp_init(&NUM_MAX_MP);
+ mp_set_intptr(&NUM_MAX_MP, NUM_MAX);
+}
+@(end)
diff --git a/lib.c b/lib.c
index d99d16e2..acd7d643 100644
--- a/lib.c
+++ b/lib.c
@@ -837,24 +837,6 @@ val plusv(val nlist)
return reduce_left(func_n2(plus), nlist, num(0), nil);
}
-val minus(val anum, val bnum)
-{
- cnum a = c_num(anum);
- cnum b = c_num(bnum);
-
- numeric_assert (b != NUM_MIN || NUM_MIN == -NUM_MAX);
- numeric_assert (a <= 0 || -b <= 0 || NUM_MAX + b >= a);
- numeric_assert (a >= 0 || -b >= 0 || NUM_MIN + b <= a);
-
- return num(a - b);
-}
-
-val neg(val anum)
-{
- cnum n = c_num(anum);
- return num(-n);
-}
-
val minusv(val minuend, val nlist)
{
if (nlist)