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

Reply via email to