diff options
| author | Paul Eggert | 2018-08-31 00:25:07 -0700 |
|---|---|---|
| committer | Paul Eggert | 2018-08-31 00:28:58 -0700 |
| commit | db2fed3bdfb351c3283e481829ce687931d27a3d (patch) | |
| tree | 4f2674ec4f4fe450fd483132b9ddcca48f9eaf81 /src/bignum.c | |
| parent | a451c6ec12b7b024f347364becb10c49807513ed (diff) | |
| download | emacs-db2fed3bdfb351c3283e481829ce687931d27a3d.tar.gz emacs-db2fed3bdfb351c3283e481829ce687931d27a3d.zip | |
Several fixes for formatting bignums
* src/bignum.c: Include stdlib.h, for abs.
(bignum_bufsize, bignum_to_c_string): New functions.
* src/bignum.c (bignum_to_string):
* src/print.c (print_vectorlike): Use them.
* src/editfns.c (styled_format): Instead of having a separate
buffer for sprintf (which does not work for bignums), just append
to the main buffer. When formatting bignums, add support for the
standard integer flags -, #, 0, + and space. Fix some comments.
Capitalize properly when formatting bignums with %X. Use
functions like c_isdigit rather than reinventing the wheel.
Simplify computation of excess precision.
* src/print.c: Do not include bignum.h; no longer needed.
(print_vectorlike): Avoid recalculating string length.
* test/src/editfns-tests.el (format-bignum):
Test some of the above fixes.
Diffstat (limited to 'src/bignum.c')
| -rw-r--r-- | src/bignum.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/src/bignum.c b/src/bignum.c index 5dbfdb9319a..b18ceccb59d 100644 --- a/src/bignum.c +++ b/src/bignum.c | |||
| @@ -23,6 +23,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 23 | 23 | ||
| 24 | #include "lisp.h" | 24 | #include "lisp.h" |
| 25 | 25 | ||
| 26 | #include <stdlib.h> | ||
| 27 | |||
| 26 | /* Return the value of the Lisp bignum N, as a double. */ | 28 | /* Return the value of the Lisp bignum N, as a double. */ |
| 27 | double | 29 | double |
| 28 | bignum_to_double (Lisp_Object n) | 30 | bignum_to_double (Lisp_Object n) |
| @@ -223,18 +225,39 @@ bignum_to_uintmax (Lisp_Object x) | |||
| 223 | return v; | 225 | return v; |
| 224 | } | 226 | } |
| 225 | 227 | ||
| 226 | /* Convert NUM to a base-BASE Lisp string. */ | 228 | /* Yield an upper bound on the buffer size needed to contain a C |
| 229 | string representing the bignum NUM in base BASE. This includes any | ||
| 230 | preceding '-' and the terminating null. */ | ||
| 231 | ptrdiff_t | ||
| 232 | bignum_bufsize (Lisp_Object num, int base) | ||
| 233 | { | ||
| 234 | return mpz_sizeinbase (XBIGNUM (num)->value, base) + 2; | ||
| 235 | } | ||
| 236 | |||
| 237 | /* Store into BUF (of size SIZE) the value of NUM as a base-BASE string. | ||
| 238 | If BASE is negative, use upper-case digits in base -BASE. | ||
| 239 | Return the string's length. | ||
| 240 | SIZE must equal bignum_bufsize (NUM, abs (BASE)). */ | ||
| 241 | ptrdiff_t | ||
| 242 | bignum_to_c_string (char *buf, ptrdiff_t size, Lisp_Object num, int base) | ||
| 243 | { | ||
| 244 | eassert (bignum_bufsize (num, abs (base)) == size); | ||
| 245 | mpz_get_str (buf, base, XBIGNUM (num)->value); | ||
| 246 | ptrdiff_t n = size - 2; | ||
| 247 | return !buf[n - 1] ? n - 1 : n + !!buf[n]; | ||
| 248 | } | ||
| 249 | |||
| 250 | /* Convert NUM to a base-BASE Lisp string. | ||
| 251 | If BASE is negative, use upper-case digits in base -BASE. */ | ||
| 227 | 252 | ||
| 228 | Lisp_Object | 253 | Lisp_Object |
| 229 | bignum_to_string (Lisp_Object num, int base) | 254 | bignum_to_string (Lisp_Object num, int base) |
| 230 | { | 255 | { |
| 231 | ptrdiff_t n = mpz_sizeinbase (XBIGNUM (num)->value, base) - 1; | 256 | ptrdiff_t size = bignum_bufsize (num, abs (base)); |
| 232 | USE_SAFE_ALLOCA; | 257 | USE_SAFE_ALLOCA; |
| 233 | char *str = SAFE_ALLOCA (n + 3); | 258 | char *str = SAFE_ALLOCA (size); |
| 234 | mpz_get_str (str, base, XBIGNUM (num)->value); | 259 | ptrdiff_t len = bignum_to_c_string (str, size, num, base); |
| 235 | while (str[n]) | 260 | Lisp_Object result = make_unibyte_string (str, len); |
| 236 | n++; | ||
| 237 | Lisp_Object result = make_unibyte_string (str, n); | ||
| 238 | SAFE_FREE (); | 261 | SAFE_FREE (); |
| 239 | return result; | 262 | return result; |
| 240 | } | 263 | } |