ref: c6aa991371c01426c0925b61776f957823425799
parent: 21733d5e5d65afc738084fdb6165480ecd2ab14c
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Jan 28 21:10:34 EST 2025
number->string: support bignums and floats/doubles
--- a/src/string.c
+++ b/src/string.c
@@ -369,22 +369,41 @@
value_t n = args[0];
int neg = 0;
uint64_t num;
+ int radix = 10;
+ if(nargs == 2)
+ radix = get_radix_arg(args[1]);
if(isfixnum(n))
num = numval(n);
- else if(!iscprim(n))
+ else if(iscprim(n)){
+ void *data = ptr(n);
+ if(cp_numtype(data) < T_FLOAT)
+ num = conv_to_uint64(cp_data(data), cp_numtype(data));
+ else if(radix != 10)
+ lerrorf(FL_ArgError, "invalid radix with floating point");
+ else
+ return fn_builtin_string(args, nargs);
+ }else if(iscvalue(n) && cp_numtype(ptr(n)) == T_MPINT){
+ if(radix != 16 && radix != 10 && radix != 8 && radix != 4 && radix != 2)
+ lerrorf(FL_ArgError, "invalid radix with bignum");
+ mpint *i = *(mpint**)cv_data(ptr(n));
+ char *s = mptoa(i, radix, nil, 0);
+ assert(s != nil);
+ if(radix == 16){ /* FFFF → ffff */
+ for(int k = 0; s[k]; k++)
+ s[k] = tolower(s[k]);
+ }
+ n = string_from_cstr(s);
+ MEM_FREE(s);
+ return n;
+ }else{
type_error("integer", n);
- else
- num = conv_to_uint64(cp_data(ptr(n)), cp_numtype(ptr(n)));
+ }
if(numval(fl_compare(args[0], fixnum(0), false)) < 0){
num = -num;
neg = 1;
}
- unsigned long radix = 10;
- if(nargs == 2)
- radix = get_radix_arg(args[1]);
- char buf[128];
- char *str = uint2str(buf, sizeof(buf), num, radix);
- if(neg && str > &buf[0])
+ char buf[128], *str = uint2str(buf, sizeof(buf), num, radix);
+ if(neg && str > buf)
*(--str) = '-';
return string_from_cstr(str);
}
--- a/test/unittest.lsp
+++ b/test/unittest.lsp
@@ -547,5 +547,10 @@
(assert (equal? #f (char-lower-case? #\П)))
(assert (equal? #f (char-lower-case? #\nul)))
+(assert (equal? "1.5" (number->string 1.5)))
+(assert (equal? "-3039" (number->string (int16 -12345) 16)))
+(assert (equal? "111111111111111111111111111111111" (number->string 111111111111111111111111111111111)))
+(assert (equal? "fffffffffffffffffffffffffffffffff" (number->string 0xfffffffffffffffffffffffffffffffff 16)))
+
(princ "all tests pass")
(newline)
--
⑨