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