Skip to content

Commit

Permalink
disable on wasm32
Browse files Browse the repository at this point in the history
  • Loading branch information
HertzDevil committed Dec 7, 2023
1 parent a5c0a0a commit ca5447e
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 58 deletions.
2 changes: 2 additions & 0 deletions spec/std/float_printer/ryu_printf_spec.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{% skip_file if flag?(:wasm32) %}

# This file contains test cases derived from:
#
# * https://github.com/ulfjack/ryu
Expand Down
2 changes: 2 additions & 0 deletions src/float/printer/ryu_printf.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{% skip_file if flag?(:wasm32) %}

require "./ryu_printf_table"

# Source port of Ryu Printf's reference implementation in C.
Expand Down
2 changes: 2 additions & 0 deletions src/float/printer/ryu_printf_table.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{% skip_file if flag?(:wasm32) %}

module Float::Printer::RyuPrintf
{% begin %}
# A table of all two-digit numbers. This is used to speed up decimal digit
Expand Down
125 changes: 67 additions & 58 deletions src/string/formatter.cr
Original file line number Diff line number Diff line change
Expand Up @@ -307,18 +307,25 @@ struct String::Formatter(A)
elsif float.nan?
float_special("nan", 1, flags)
else
case flags.type
when 'f'
float_fixed(float, flags)
when 'e', 'E'
float_scientific(float, flags)
when 'g', 'G'
float_general(float, flags)
when 'a', 'A'
float_hex(float, flags)
else
raise "BUG: Unknown format type '#{flags.type}'"
end
# FIXME: wasm32 appears to run out of memory if we use Ryu Printf, which
# initializes very large lookup tables, so we always fall back to
# `LibC.snprintf` (#13918)
{% if flag?(:wasm32) %}
float_fallback(float, flags)
{% else %}
case flags.type
when 'f'
float_fixed(float, flags)
when 'e', 'E'
float_scientific(float, flags)
when 'g', 'G'
float_general(float, flags)
when 'a', 'A'
float_hex(float, flags)
else
raise "BUG: Unknown format type '#{flags.type}'"
end
{% end %}
end
else
raise ArgumentError.new("Expected a float, not #{arg.inspect}")
Expand All @@ -339,61 +346,63 @@ struct String::Formatter(A)
pad(str_size, flags) if flags.right_padding?
end

# Formats floats with `%f`
private def float_fixed(float, flags)
# the longest string possible is due to `Float64::MIN_SUBNORMAL`, which
# produces `0.` followed by 1074 nonzero digits; there is also no need
# for any precision > 1074 because all trailing digits will be zeros
if precision = flags.precision
printf_precision = {precision.to_u32, 1074_u32}.min
trailing_zeros = {precision - printf_precision, 0}.max
else
# default precision for C's `%f`
printf_precision = 6_u32
trailing_zeros = 0
end
{% unless flag?(:wasm32) %}
# Formats floats with `%f`
private def float_fixed(float, flags)
# the longest string possible is due to `Float64::MIN_SUBNORMAL`, which
# produces `0.` followed by 1074 nonzero digits; there is also no need
# for any precision > 1074 because all trailing digits will be zeros
if precision = flags.precision
printf_precision = {precision.to_u32, 1074_u32}.min
trailing_zeros = {precision - printf_precision, 0}.max
else
# default precision for C's `%f`
printf_precision = 6_u32
trailing_zeros = 0
end

printf_buf = uninitialized UInt8[1076]
printf_size = Float::Printer::RyuPrintf.d2fixed_buffered_n(float, printf_precision, printf_buf.to_unsafe)
printf_slice = printf_buf.to_slice[0, printf_size]
dot_index = printf_slice.index('.'.ord)
sign = Math.copysign(1.0, float)
printf_buf = uninitialized UInt8[1076]
printf_size = Float::Printer::RyuPrintf.d2fixed_buffered_n(float, printf_precision, printf_buf.to_unsafe)
printf_slice = printf_buf.to_slice[0, printf_size]
dot_index = printf_slice.index('.'.ord)
sign = Math.copysign(1.0, float)

str_size = printf_size + trailing_zeros
str_size += 1 if sign < 0 || flags.plus || flags.space
str_size += 1 if flags.sharp && dot_index.nil?
str_size = printf_size + trailing_zeros
str_size += 1 if sign < 0 || flags.plus || flags.space
str_size += 1 if flags.sharp && dot_index.nil?

pad(str_size, flags) if flags.left_padding? && flags.padding_char != '0'
pad(str_size, flags) if flags.left_padding? && flags.padding_char != '0'

# this preserves -0.0's sign correctly
write_plus_or_space(sign, flags)
@io << '-' if sign < 0
# this preserves -0.0's sign correctly
write_plus_or_space(sign, flags)
@io << '-' if sign < 0

pad(str_size, flags) if flags.left_padding? && flags.padding_char == '0'
@io.write_string(printf_slice)
trailing_zeros.times { @io << '0' }
@io << '.' if flags.sharp && dot_index.nil?
pad(str_size, flags) if flags.left_padding? && flags.padding_char == '0'
@io.write_string(printf_slice)
trailing_zeros.times { @io << '0' }
@io << '.' if flags.sharp && dot_index.nil?

pad(str_size, flags) if flags.right_padding?
end
pad(str_size, flags) if flags.right_padding?
end

# Formats floats with `%e` or `%E`
private def float_scientific(float, flags)
# TODO: implement using `Float::Printer::RyuPrintf`
float_fallback(float, flags)
end
# Formats floats with `%e` or `%E`
private def float_scientific(float, flags)
# TODO: implement using `Float::Printer::RyuPrintf`
float_fallback(float, flags)
end

# Formats floats with `%g` or `%G`
private def float_general(float, flags)
# TODO: implement using `Float::Printer::RyuPrintf`
float_fallback(float, flags)
end
# Formats floats with `%g` or `%G`
private def float_general(float, flags)
# TODO: implement using `Float::Printer::RyuPrintf`
float_fallback(float, flags)
end

# Formats floats with `%a` or `%A`
private def float_hex(float, flags)
# TODO: implement using `Float::Printer::Hexfloat`
float_fallback(float, flags)
end
# Formats floats with `%a` or `%A`
private def float_hex(float, flags)
# TODO: implement using `Float::Printer::Hexfloat`
float_fallback(float, flags)
end
{% end %}

# Delegate to `LibC.snprintf` for float formats not yet ported to Crystal
private def float_fallback(float, flags)
Expand Down

0 comments on commit ca5447e

Please sign in to comment.