prettyprinter, locale independant float printing

db4
Jon Harper 2015-06-16 00:29:02 +02:00 committed by John Benediktsson
parent 3cd2775855
commit 19fadb6c96
6 changed files with 48 additions and 18 deletions

View File

@ -150,7 +150,7 @@ M: timestamp year. ( timestamp -- )
! Should be enough for anyone, allows to not do a fancy
! algorithm to detect infinite decimals (e.g 1/3)
: ss.SSSSSS ( timestamp -- )
second>> >float "%09.6f" format-float write ;
second>> >float "0" 9 6 "f" "C" format-float write ;
: (timestamp>rfc3339) ( timestamp -- )
{

View File

@ -30,8 +30,7 @@ IN: formatting
[ 0 ] [ string>number ] if-empty ;
: format-simple ( x digits string -- string )
[ [ >float ] [ number>string ] bi* "%." ] dip
surround format-float ;
[ >float "" -1 ] 2dip "" format-float ;
: format-scientific ( x digits -- string ) "e" format-simple ;

View File

@ -420,7 +420,7 @@ M: object infer-call* \ call bad-macro-input ;
{ fixnum>float { fixnum } { float } }
! float
{ (format-float) { float byte-array } { byte-array } }
{ (format-float) { float byte-array fixnum fixnum byte-array byte-array } { byte-array } }
{ bits>float { integer } { float } }
{ float* { float float } { float } }
{ float+ { float float } { float } }

View File

@ -476,7 +476,7 @@ tuple
{ "bits>float" "math" "primitive_bits_float" ( n -- x ) }
{ "double>bits" "math" "primitive_double_bits" ( x -- n ) }
{ "float>bits" "math" "primitive_float_bits" ( x -- n ) }
{ "(format-float)" "math.parser.private" "primitive_format_float" ( n format -- byte-array ) }
{ "(format-float)" "math.parser.private" "primitive_format_float" ( n fill width precision format locale -- byte-array ) }
{ "bignum*" "math.private" "primitive_bignum_multiply" ( x y -- z ) }
{ "bignum+" "math.private" "primitive_bignum_add" ( x y -- z ) }
{ "bignum-" "math.private" "primitive_bignum_subtract" ( x y -- z ) }

View File

@ -6,7 +6,7 @@ sequences.private splitting strings strings.private ;
IN: math.parser
<PRIVATE
PRIMITIVE: (format-float) ( n format -- byte-array )
PRIMITIVE: (format-float) ( n fill width precision format locale -- byte-array )
PRIVATE>
: digit> ( ch -- n )
@ -488,12 +488,12 @@ M: ratio >base
<PRIVATE
: fix-float ( str -- newstr )
CHAR: e over index [
cut [ fix-float ] dip append
: fix-float ( str exponent -- newstr )
2dup first swap member? [
[ [ split1 ] keep swap [ fix-float ] dip ] [ glue ] bi
] [
CHAR: . over member? [ ".0" append ] unless
] if* ;
drop CHAR: . over member? [ ".0" append ] unless
] if ;
: mantissa-expt-normalize ( mantissa expt -- mantissa' expt' )
[ dup log2 52 swap - [ shift 52 2^ 1 - bitand ] [ 1022 + neg ] bi ]
@ -548,14 +548,17 @@ M: ratio >base
] 2curry each-integer
] keep ; inline
: format-float ( n format -- string )
format-string (format-float)
dup [ 0 = ] find drop
format-head fix-float ; inline
: format-float ( n fill width precision format locale -- string )
[
[ format-string ] 4dip [ format-string ] bi@ (format-float)
dup [ 0 = ] find drop format-head
] [
"C" = [ [ "G" = ] [ "E" = ] bi or "E" "e" ? fix-float ] [ drop ] if
] 2bi ; inline
: float>base ( n radix -- str )
{
{ 10 [ "%.16g" format-float ] }
{ 10 [ "" -1 16 "" "C" format-float ] }
[ bin-float>base ]
} case ; inline

View File

@ -1,4 +1,6 @@
#include "master.hpp"
#include <sstream>
#include <iomanip>
namespace factor {
@ -211,10 +213,36 @@ void factor_vm::primitive_fixnum_to_float() {
/* Allocates memory */
void factor_vm::primitive_format_float() {
byte_array* array = allot_byte_array(100);
char* locale = alien_offset(ctx->pop());
char* format = alien_offset(ctx->pop());
fixnum precision = untag_fixnum(ctx->pop());
fixnum width = untag_fixnum(ctx->pop());
char* fill = alien_offset(ctx->pop());
double value = untag_float_check(ctx->peek());
SNPRINTF(array->data<char>(), 99, format, value);
std::ostringstream localized_stream;
localized_stream.imbue(std::locale(locale));
switch (format[0]) {
case 'f': localized_stream << std::fixed; break;
case 'e': localized_stream << std::scientific; break;
}
if (isupper(format[0])) {
localized_stream << std::uppercase;
}
if (fill[0] != '\0') {
localized_stream << std::setfill(fill[0]);
}
if (width >= 0) {
localized_stream << std::setw(width);
}
if (precision >= 0) {
localized_stream << std::setprecision(precision);
}
localized_stream << value;
const std::string& tmp = localized_stream.str();
const char* cstr = tmp.c_str();
int size = tmp.length()+1;
byte_array* array = allot_byte_array(size);
memcpy(array->data<char>(), cstr, size);
ctx->replace(tag<byte_array>(array));
}