Hi,

Basic arithmetic on relatively small numbers can be made much cheaper by
leveraging BN_add(3), BN_sub(3) and BN_mul(3)'s ability to store the
calculation's result in one of their operands, thus reducing allocation
overhead.  For example, with this simplification, incrementing a counter
becomes almost twice as fast.

        $ echo 0 >script
        $ jot -b 1+ 16777216 >>script

        $ time dc script
            0m18.03s real     0m18.05s user     0m00.00s system
        $ time ./dc script
            0m09.92s real     0m09.91s user     0m00.01s system

Combined with the previous one regarding BN_CTX, this diff also makes
multiplication at least 60% faster than it originally was.

        $ echo 1 >script
        $ jot -b '1*' 16777216 >>script

        $ time dc script
            0m27.88s real     0m27.88s user     0m00.00s system
        $ time ./dc script
            0m10.51s real     0m10.51s user     0m00.00s system

Index: bcode.c
===================================================================
RCS file: /cvs/src/usr.bin/dc/bcode.c,v
retrieving revision 1.59
diff -u -p -r1.59 bcode.c
--- bcode.c     5 Dec 2017 14:05:22 -0000       1.59
+++ bcode.c     7 Dec 2017 04:31:38 -0000
@@ -978,7 +978,6 @@ static void
 badd(void)
 {
        struct number   *a, *b;
-       struct number   *r;
 
        a = pop_number();
        if (a == NULL)
@@ -989,23 +988,19 @@ badd(void)
                return;
        }
 
-       r = new_number();
-       r->scale = max(a->scale, b->scale);
-       if (r->scale > a->scale)
-               normalize(a, r->scale);
-       else if (r->scale > b->scale)
-               normalize(b, r->scale);
-       bn_check(BN_add(r->number, a->number, b->number));
-       push_number(r);
+       if (a->scale < b->scale)
+               normalize(a, b->scale);
+       else if (a->scale > b->scale)
+               normalize(b, a->scale);
+       bn_check(BN_add(b->number, a->number, b->number));
        free_number(a);
-       free_number(b);
+       push_number(b);
 }
 
 static void
 bsub(void)
 {
        struct number   *a, *b;
-       struct number   *r;
 
        a = pop_number();
        if (a == NULL)
@@ -1016,17 +1011,13 @@ bsub(void)
                return;
        }
 
-       r = new_number();
-
-       r->scale = max(a->scale, b->scale);
-       if (r->scale > a->scale)
-               normalize(a, r->scale);
-       else if (r->scale > b->scale)
-               normalize(b, r->scale);
-       bn_check(BN_sub(r->number, b->number, a->number));
-       push_number(r);
+       if (a->scale < b->scale)
+               normalize(a, b->scale);
+       else if (a->scale > b->scale)
+               normalize(b, a->scale);
+       bn_check(BN_sub(b->number, b->number, a->number));
        free_number(a);
-       free_number(b);
+       push_number(b);
 }
 
 void
@@ -1048,7 +1039,6 @@ static void
 bmul(void)
 {
        struct number   *a, *b;
-       struct number   *r;
 
        a = pop_number();
        if (a == NULL)
@@ -1059,12 +1049,9 @@ bmul(void)
                return;
        }
 
-       r = new_number();
-       bmul_number(r, a, b, bmachine.scale);
-
-       push_number(r);
+       bmul_number(b, a, b, bmachine.scale);
        free_number(a);
-       free_number(b);
+       push_number(b);
 }
 
 static void

Regards,

kshe

Reply via email to