From 1021344aef1e92a79e9949954468ccb6875c87e4 Mon Sep 17 00:00:00 2001 From: Alex Shinn Date: Sat, 28 Dec 2013 09:21:14 +0900 Subject: [PATCH] Switching to Karatsuba for bignum multiplication. Fixing potential memory issue in bignum copying. --- bignum.c | 79 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/bignum.c b/bignum.c index 2409e730..27d706b5 100644 --- a/bignum.c +++ b/bignum.c @@ -1,5 +1,5 @@ /* bignum.c -- bignum support */ -/* Copyright (c) 2009-2012 Alex Shinn. All rights reserved. */ +/* Copyright (c) 2009-2013 Alex Shinn. All rights reserved. */ /* BSD-style license: http://synthcode.com/license.txt */ #include "chibi/sexp.h" @@ -85,14 +85,13 @@ sexp sexp_copy_bignum (sexp ctx, sexp dst, sexp a, sexp_uint_t len0) { size = sexp_sizeof(bignum) + len*sizeof(sexp_uint_t); if (! dst || sexp_bignum_length(dst) < len) { dst = sexp_alloc_tagged(ctx, size, SEXP_BIGNUM); - memmove(dst, a, size); sexp_bignum_length(dst) = len; - } else { - memset(dst->value.bignum.data, 0, - sexp_bignum_length(dst)*sizeof(sexp_uint_t)); - memmove(dst->value.bignum.data, a->value.bignum.data, - sexp_bignum_length(a)*sizeof(sexp_uint_t)); } + sexp_bignum_sign(dst) = sexp_bignum_sign(a); + memset(sexp_bignum_data(dst), 0, + sexp_bignum_length(dst)*sizeof(sexp_uint_t)); + memmove(sexp_bignum_data(dst), sexp_bignum_data(a), + sexp_bignum_length(a)*sizeof(sexp_uint_t)); return dst; } @@ -389,22 +388,64 @@ sexp sexp_bignum_sub (sexp ctx, sexp dst, sexp a, sexp b) { return res; } +static void sexp_bignum_split (sexp ctx, sexp a, sexp_uint_t k, sexp* lo, sexp* hi) { + sexp_uint_t alen=sexp_bignum_hi(a), i, *adata=sexp_bignum_data(a), + *lodata, *hidata; + *lo = sexp_make_bignum(ctx, k); /* must be gc protected by caller */ + *hi = sexp_make_bignum(ctx, alen-k+1); + lodata = sexp_bignum_data(*lo); + hidata = sexp_bignum_data(*hi); + for (i=0; i