Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 84 additions & 39 deletions src/float/fast_float/bigint.cr
Original file line number Diff line number Diff line change
Expand Up @@ -339,47 +339,92 @@ module Float::FastFloat
module Pow5Tables
LARGE_STEP = 135_u32

SMALL_POWER_OF_5 = [
1_u64,
5_u64,
25_u64,
125_u64,
625_u64,
3125_u64,
15625_u64,
78125_u64,
390625_u64,
1953125_u64,
9765625_u64,
48828125_u64,
244140625_u64,
1220703125_u64,
6103515625_u64,
30517578125_u64,
152587890625_u64,
762939453125_u64,
3814697265625_u64,
19073486328125_u64,
95367431640625_u64,
476837158203125_u64,
2384185791015625_u64,
11920928955078125_u64,
59604644775390625_u64,
298023223876953125_u64,
1490116119384765625_u64,
7450580596923828125_u64,
]

{% if Limb == UInt64 %}
LARGE_POWER_OF_5 = Slice[
1414648277510068013_u64, 9180637584431281687_u64, 4539964771860779200_u64,
10482974169319127550_u64, 198276706040285095_u64,
{% if compare_versions(Crystal::VERSION, "1.16.0") < 0 %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: The value lists are identical between both types. We could reduce code duplication by making only the outer layer conditional:

{% begin %}
  {% if compare_versions(Crystal::VERSION, "1.16.0") < 0 %}
    [
  {% else %}
    Slice(UInt64).literal(
  {% end %}
  1_u64,
  # ...
  7450580596923828125_u64,
  {% if compare_versions(Crystal::VERSION, "1.16.0") < 0 %}
    ]
  {% else %}
    )
  {% end %}
{% end %}

The added overhead won't make this much appealing for very short slices. But it might be a good idea for the bigger ones? WDYT?

SMALL_POWER_OF_5 = [
1_u64,
5_u64,
25_u64,
125_u64,
625_u64,
3125_u64,
15625_u64,
78125_u64,
390625_u64,
1953125_u64,
9765625_u64,
48828125_u64,
244140625_u64,
1220703125_u64,
6103515625_u64,
30517578125_u64,
152587890625_u64,
762939453125_u64,
3814697265625_u64,
19073486328125_u64,
95367431640625_u64,
476837158203125_u64,
2384185791015625_u64,
11920928955078125_u64,
59604644775390625_u64,
298023223876953125_u64,
1490116119384765625_u64,
7450580596923828125_u64,
]

{% if Limb == UInt64 %}
LARGE_POWER_OF_5 = Slice[
1414648277510068013_u64, 9180637584431281687_u64, 4539964771860779200_u64,
10482974169319127550_u64, 198276706040285095_u64,
]
{% else %}
LARGE_POWER_OF_5 = Slice[
4279965485_u32, 329373468_u32, 4020270615_u32, 2137533757_u32, 4287402176_u32,
1057042919_u32, 1071430142_u32, 2440757623_u32, 381945767_u32, 46164893_u32,
]
{% end %}
{% else %}
LARGE_POWER_OF_5 = Slice[
4279965485_u32, 329373468_u32, 4020270615_u32, 2137533757_u32, 4287402176_u32,
1057042919_u32, 1071430142_u32, 2440757623_u32, 381945767_u32, 46164893_u32,
]
SMALL_POWER_OF_5 = Slice(UInt64).literal(
1_u64,
5_u64,
25_u64,
125_u64,
625_u64,
3125_u64,
15625_u64,
78125_u64,
390625_u64,
1953125_u64,
9765625_u64,
48828125_u64,
244140625_u64,
1220703125_u64,
6103515625_u64,
30517578125_u64,
152587890625_u64,
762939453125_u64,
3814697265625_u64,
19073486328125_u64,
95367431640625_u64,
476837158203125_u64,
2384185791015625_u64,
11920928955078125_u64,
59604644775390625_u64,
298023223876953125_u64,
1490116119384765625_u64,
7450580596923828125_u64,
)

{% if Limb == UInt64 %}
LARGE_POWER_OF_5 = Slice(UInt64).literal(
1414648277510068013_u64, 9180637584431281687_u64, 4539964771860779200_u64,
10482974169319127550_u64, 198276706040285095_u64,
)
{% else %}
LARGE_POWER_OF_5 = Slice(UInt32).literal(
4279965485_u32, 329373468_u32, 4020270615_u32, 2137533757_u32, 4287402176_u32,
1057042919_u32, 1071430142_u32, 2440757623_u32, 381945767_u32, 46164893_u32,
)
{% end %}
{% end %}
end

Expand Down
69 changes: 47 additions & 22 deletions src/float/fast_float/digit_comparison.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,53 @@ require "./ascii_number"

module Float::FastFloat
# 1e0 to 1e19
POWERS_OF_TEN_UINT64 = [
1_u64,
10_u64,
100_u64,
1000_u64,
10000_u64,
100000_u64,
1000000_u64,
10000000_u64,
100000000_u64,
1000000000_u64,
10000000000_u64,
100000000000_u64,
1000000000000_u64,
10000000000000_u64,
100000000000000_u64,
1000000000000000_u64,
10000000000000000_u64,
100000000000000000_u64,
1000000000000000000_u64,
10000000000000000000_u64,
]
{% if compare_versions(Crystal::VERSION, "1.16.0") < 0 %}
POWERS_OF_TEN_UINT64 = [
1_u64,
10_u64,
100_u64,
1000_u64,
10000_u64,
100000_u64,
1000000_u64,
10000000_u64,
100000000_u64,
1000000000_u64,
10000000000_u64,
100000000000_u64,
1000000000000_u64,
10000000000000_u64,
100000000000000_u64,
1000000000000000_u64,
10000000000000000_u64,
100000000000000000_u64,
1000000000000000000_u64,
10000000000000000000_u64,
]
{% else %}
POWERS_OF_TEN_UINT64 = Slice(UInt64).literal(
1_u64,
10_u64,
100_u64,
1000_u64,
10000_u64,
100000_u64,
1000000_u64,
10000000_u64,
100000000_u64,
1000000000_u64,
10000000000_u64,
100000000000_u64,
1000000000000_u64,
10000000000000_u64,
100000000000000_u64,
1000000000000000_u64,
10000000000000000_u64,
100000000000000000_u64,
1000000000000000000_u64,
10000000000000000000_u64,
)
{% end %}

# calculate the exponent, in scientific notation, of the number.
# this algorithm is not even close to optimized, but it has no practical
Expand Down
165 changes: 112 additions & 53 deletions src/float/fast_float/float_common.cr
Original file line number Diff line number Diff line change
Expand Up @@ -67,39 +67,75 @@ module Float::FastFloat
struct BinaryFormat_Float64
include BinaryFormat(Float64, UInt64)

POWERS_OF_TEN = [
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22,
]

# Largest integer value v so that (5**index * v) <= 1<<53.
# 0x20000000000000 == 1 << 53
MAX_MANTISSA = [
0x20000000000000_u64,
0x20000000000000_u64.unsafe_div(5),
0x20000000000000_u64.unsafe_div(5 * 5),
0x20000000000000_u64.unsafe_div(5 * 5 * 5),
0x20000000000000_u64.unsafe_div(5 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5 * 5),
]
{% if compare_versions(Crystal::VERSION, "1.16.0") < 0 %}
POWERS_OF_TEN = [
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22,
]

# Largest integer value v so that (5**index * v) <= 1<<53.
# 0x20000000000000 == 1 << 53
MAX_MANTISSA = [
0x20000000000000_u64,
0x20000000000000_u64.unsafe_div(5),
0x20000000000000_u64.unsafe_div(5 * 5),
0x20000000000000_u64.unsafe_div(5 * 5 * 5),
0x20000000000000_u64.unsafe_div(5 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5),
0x20000000000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5 * 5),
]
{% else %}
POWERS_OF_TEN = Slice(Float64).literal(
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22,
)

# Largest integer value v so that (5**index * v) <= 1<<53.
# 0x20000000000000 == 1 << 53
MAX_MANTISSA = Slice(UInt64).literal(
{{ 0x20000000000000_u64 }},
{{ 0x20000000000000_u64 // (5) }},
{{ 0x20000000000000_u64 // (5 * 5) }},
{{ 0x20000000000000_u64 // (5 * 5 * 5) }},
{{ 0x20000000000000_u64 // (5 * 5 * 5 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * 5 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * 5 * 5 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * 5 * 5 * 5 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * 5 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5) }},
{{ 0x20000000000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * CONSTANT_55555 * 5 * 5 * 5 * 5) }},
)
{% end %}

def min_exponent_fast_path : Int32
-22
Expand Down Expand Up @@ -175,26 +211,49 @@ module Float::FastFloat
struct BinaryFormat_Float32
include BinaryFormat(Float32, UInt32)

POWERS_OF_TEN = [
1e0f32, 1e1f32, 1e2f32, 1e3f32, 1e4f32, 1e5f32, 1e6f32, 1e7f32, 1e8f32, 1e9f32, 1e10f32,
]

# Largest integer value v so that (5**index * v) <= 1<<24.
# 0x1000000 == 1<<24
MAX_MANTISSA = [
0x1000000_u64,
0x1000000_u64.unsafe_div(5),
0x1000000_u64.unsafe_div(5 * 5),
0x1000000_u64.unsafe_div(5 * 5 * 5),
0x1000000_u64.unsafe_div(5 * 5 * 5 * 5),
0x1000000_u64.unsafe_div(CONSTANT_55555),
0x1000000_u64.unsafe_div(CONSTANT_55555 * 5),
0x1000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5),
0x1000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5 * 5),
0x1000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5 * 5 * 5),
0x1000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555),
0x1000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * 5),
]
{% if compare_versions(Crystal::VERSION, "1.16.0") < 0 %}
POWERS_OF_TEN = [
1e0f32, 1e1f32, 1e2f32, 1e3f32, 1e4f32, 1e5f32, 1e6f32, 1e7f32, 1e8f32, 1e9f32, 1e10f32,
]

# Largest integer value v so that (5**index * v) <= 1<<24.
# 0x1000000 == 1<<24
MAX_MANTISSA = [
0x1000000_u64,
0x1000000_u64.unsafe_div(5),
0x1000000_u64.unsafe_div(5 * 5),
0x1000000_u64.unsafe_div(5 * 5 * 5),
0x1000000_u64.unsafe_div(5 * 5 * 5 * 5),
0x1000000_u64.unsafe_div(CONSTANT_55555),
0x1000000_u64.unsafe_div(CONSTANT_55555 * 5),
0x1000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5),
0x1000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5 * 5),
0x1000000_u64.unsafe_div(CONSTANT_55555 * 5 * 5 * 5 * 5),
0x1000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555),
0x1000000_u64.unsafe_div(CONSTANT_55555 * CONSTANT_55555 * 5),
]
{% else %}
POWERS_OF_TEN = Slice(Float32).literal(
1e0f32, 1e1f32, 1e2f32, 1e3f32, 1e4f32, 1e5f32, 1e6f32, 1e7f32, 1e8f32, 1e9f32, 1e10f32,
)

# Largest integer value v so that (5**index * v) <= 1<<24.
# 0x1000000 == 1<<24
MAX_MANTISSA = Slice(UInt64).literal(
{{ 0x1000000_u64 }},
{{ 0x1000000_u64 // (5) }},
{{ 0x1000000_u64 // (5 * 5) }},
{{ 0x1000000_u64 // (5 * 5 * 5) }},
{{ 0x1000000_u64 // (5 * 5 * 5 * 5) }},
{{ 0x1000000_u64 // (CONSTANT_55555) }},
{{ 0x1000000_u64 // (CONSTANT_55555 * 5) }},
{{ 0x1000000_u64 // (CONSTANT_55555 * 5 * 5) }},
{{ 0x1000000_u64 // (CONSTANT_55555 * 5 * 5 * 5) }},
{{ 0x1000000_u64 // (CONSTANT_55555 * 5 * 5 * 5 * 5) }},
{{ 0x1000000_u64 // (CONSTANT_55555 * CONSTANT_55555) }},
{{ 0x1000000_u64 // (CONSTANT_55555 * CONSTANT_55555 * 5) }},
)
{% end %}

def min_exponent_fast_path : Int32
-10
Expand Down