Hi,
The bsqrt_stop() function can be merged into bsqrt(), making the code
simpler. As a result, the `v' command becomes about 20% faster.
$ jot -rw %uv 262144 16777216 >script
$ time dc script
0m01.56s real 0m01.53s user 0m00.02s system
$ time ./dc script
0m01.20s real 0m01.17s user 0m00.02s system
Index: bcode.c
===================================================================
RCS file: /cvs/src/usr.bin/dc/bcode.c,v
retrieving revision 1.51
diff -u -p -r1.51 bcode.c
--- bcode.c 26 Feb 2017 11:29:55 -0000 1.51
+++ bcode.c 17 Nov 2017 02:38:12 -0000
@@ -95,18 +95,14 @@ static void bdiv(void);
static void bmod(void);
static void bdivmod(void);
static void bexp(void);
-static bool bsqrt_stop(const BIGNUM *, const BIGNUM *, u_int *);
static void bsqrt(void);
static void not(void);
static void equal_numbers(void);
@@ -1262,28 +1274,12 @@ bexp(void)
free_number(p);
}
-static bool
-bsqrt_stop(const BIGNUM *x, const BIGNUM *y, u_int *onecount)
-{
- BIGNUM *r;
- bool ret;
-
- r = BN_new();
- bn_checkp(r);
- bn_check(BN_sub(r, x, y));
- if (BN_is_one(r))
- (*onecount)++;
- ret = BN_is_zero(r);
- BN_free(r);
- return ret || *onecount > 1;
-}
-
static void
bsqrt(void)
{
struct number *n;
struct number *r;
- BIGNUM *x, *y;
+ BIGNUM *x, *y, *t;
u_int scale, onecount;
BN_CTX *ctx;
@@ -1306,14 +1302,16 @@ bsqrt(void)
bn_checkp(y);
ctx = BN_CTX_new();
bn_checkp(ctx);
- for (;;) {
- bn_checkp(BN_copy(y, x));
- bn_check(BN_div(x, NULL, n->number, x, ctx));
- bn_check(BN_add(x, x, y));
- bn_check(BN_rshift1(x, x));
- if (bsqrt_stop(x, y, &onecount))
- break;
- }
+ do {
+ bn_check(BN_div(y, NULL, n->number, x, ctx));
+ bn_check(BN_add(y, x, y));
+ bn_check(BN_rshift1(y, y));
+ bn_check(BN_sub(x, y, x));
+ t = x;
+ x = y;
+ y = t;
+ } while (!BN_is_zero(y) && (onecount += BN_is_one(y)) < 2);
+ bn_check(BN_sub(y, x, y));
r = bmalloc(sizeof(*r));
r->scale = scale;
r->number = y;
Regards,
kshe