aboutsummaryrefslogtreecommitdiffstats
path: root/src/fns.c
diff options
context:
space:
mode:
authorPaul Eggert2018-09-03 18:37:40 -0700
committerPaul Eggert2018-09-03 18:50:34 -0700
commitfe042e9d15da7863b5beb4c2cc326a62d2c7fccb (patch)
tree84fac8f99c678667e01d69d5e2ef17f4c8e8e275 /src/fns.c
parent40f8ade7c81ab6f99537691ae00d2d42069bdb20 (diff)
downloademacs-fe042e9d15da7863b5beb4c2cc326a62d2c7fccb.tar.gz
emacs-fe042e9d15da7863b5beb4c2cc326a62d2c7fccb.zip
Speed up (+ 2 2) by a factor of 10
Improve arithmetic performance by avoiding bignums until needed. Also, simplify bignum memory management, fixing some unlikely leaks. This patch improved the performance of (+ 2 2) by a factor of ten on a simple microbenchmark computing (+ x 2), byte-compiled, with x a local variable initialized to 2 via means the byte compiler could not predict: performance improved from 135 to 13 ns. The platform was Fedora 28 x86-64, AMD Phenom II X4 910e. Performance also improved 0.6% on ‘make compile-always’. * src/bignum.c (init_bignum_once): New function. * src/emacs.c (main): Use it. * src/bignum.c (mpz): New global var. (make_integer_mpz): Rename from make_integer. All uses changed. * src/bignum.c (double_to_bignum, make_bignum_bits) (make_bignum, make_bigint, make_biguint, make_integer_mpz): * src/data.c (bignum_arith_driver, Frem, Flogcount, Fash) (expt_integer, Fadd1, Fsub1, Flognot): * src/floatfns.c (Fabs, rounding_driver, rounddiv_q): * src/fns.c (Fnthcdr): Use mpz rather than mpz_initting and mpz_clearing private temporaries. * src/bignum.h (bignum_integer): New function. * src/data.c (Frem, Fmod, Fash, expt_integer): * src/floatfns.c (rounding_driver): Use it to simplify code. * src/data.c (FIXNUMS_FIT_IN_LONG, free_mpz_value): Remove. All uses removed. (floating_point_op): New function. (floatop_arith_driver): New function, with much of the guts of the old float_arith_driver. (float_arith_driver): Use it. (floatop_arith_driver, arith_driver): Simplify by assuming NARGS is at least 2. All callers changed. (float_arith_driver): New arg, containing the partly converted value of the next arg. Reorder args for consistency. All uses changed. (bignum_arith_driver): New function. (arith_driver): Use it. Do fixnum-only integer calculations in intmax_t instead of mpz_t, when they fit. Break out mpz_t calculations into bignum_arith_driver. (Fquo): Use floatop_arith_driver instead of float_arith_driver, since the op is known to be valid. (Flogcount, Fash): Simplify by coalescing bignum and fixnum code. (Fadd1, Fsub1): Simplify by using make_int.
Diffstat (limited to 'src/fns.c')
-rw-r--r--src/fns.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/src/fns.c b/src/fns.c
index 17a869e1abc..8b25492eaeb 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1468,19 +1468,17 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
1468 /* Undo any error introduced when LARGE_NUM was substituted for 1468 /* Undo any error introduced when LARGE_NUM was substituted for
1469 N, by adding N - LARGE_NUM to NUM, using arithmetic modulo 1469 N, by adding N - LARGE_NUM to NUM, using arithmetic modulo
1470 CYCLE_LENGTH. */ 1470 CYCLE_LENGTH. */
1471 mpz_t z; /* N mod CYCLE_LENGTH. */ 1471 /* Add N mod CYCLE_LENGTH to NUM. */
1472 mpz_init (z);
1473 if (cycle_length <= ULONG_MAX) 1472 if (cycle_length <= ULONG_MAX)
1474 num += mpz_mod_ui (z, XBIGNUM (n)->value, cycle_length); 1473 num += mpz_mod_ui (mpz[0], XBIGNUM (n)->value, cycle_length);
1475 else 1474 else
1476 { 1475 {
1477 mpz_set_intmax (z, cycle_length); 1476 mpz_set_intmax (mpz[0], cycle_length);
1478 mpz_mod (z, XBIGNUM (n)->value, z); 1477 mpz_mod (mpz[0], XBIGNUM (n)->value, mpz[0]);
1479 intptr_t iz; 1478 intptr_t iz;
1480 mpz_export (&iz, NULL, -1, sizeof iz, 0, 0, z); 1479 mpz_export (&iz, NULL, -1, sizeof iz, 0, 0, mpz[0]);
1481 num += iz; 1480 num += iz;
1482 } 1481 }
1483 mpz_clear (z);
1484 num += cycle_length - large_num % cycle_length; 1482 num += cycle_length - large_num % cycle_length;
1485 } 1483 }
1486 num %= cycle_length; 1484 num %= cycle_length;