From cd4e900e89cd7d05b9bd90a175720ab1dc4dd803 Mon Sep 17 00:00:00 2001 From: demotomohiro Date: Thu, 24 Jul 2025 08:11:31 +0900 Subject: [PATCH 1/2] fixes #1321; `lib/bitabs.nim` distinguish `0.0` and `-0.0` --- src/lib/bitabs.nim | 15 ++++++++++++--- tests/nimony/nosystem/tfloatliterals.nif | 4 +++- tests/nimony/nosystem/tfloatliterals.nim | 4 ++++ tests/nimony/nosystem/tfloatliterals0.nif | 4 ++++ tests/nimony/nosystem/tfloatliterals0.nim | 3 +++ 5 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 tests/nimony/nosystem/tfloatliterals0.nif create mode 100644 tests/nimony/nosystem/tfloatliterals0.nim diff --git a/src/lib/bitabs.nim b/src/lib/bitabs.nim index 13f845050..06f91e812 100644 --- a/src/lib/bitabs.nim +++ b/src/lib/bitabs.nim @@ -7,7 +7,7 @@ ## A BiTable is a table that can be seen as an optimized pair ## of `(Table[Id, Val], Table[Val, Id])`. -import std/hashes +import std/[hashes, math] when defined(nimPreviewSlimSystem): import std/assertions @@ -53,6 +53,15 @@ proc enlarge[Id, T](t: var BiTable[Id, T]) = j = nextTry(j, maxHash(t)) t.keys[j] = move n[i] +proc equal[T, U](x: T, y: U): bool {.inline.} = + when T is SomeFloat: + # we need to distinguish `0.0` and `-0.0` even if `0.0 == -0.0`. + # Their bit patterns are different. + # signbit and copySign procs returns the different value. + x == y and signbit(x) == signbit(y) + else: + x == y + proc getKeyId*[Id, T](t: BiTable[Id, T]; v: T): Id = let origH = hash(v) var h = origH and maxHash(t) @@ -60,7 +69,7 @@ proc getKeyId*[Id, T](t: BiTable[Id, T]; v: T): Id = while true: let litId = t.keys[h] if not isFilled(litId): break - if v == t.vals[idToIdx t.keys[h]]: return litId + if equal(v, t.vals[idToIdx t.keys[h]]): return litId h = nextTry(h, maxHash(t)) return Id(0) @@ -71,7 +80,7 @@ template getOrInclImpl() {.dirty.} = while true: let litId = t.keys[h] if not isFilled(litId): break - if v == t.vals[idToIdx t.keys[h]]: return litId + if equal(v, t.vals[idToIdx t.keys[h]]): return litId h = nextTry(h, maxHash(t)) # not found, we need to insert it: if mustRehash(t.keys.len, t.vals.len): diff --git a/tests/nimony/nosystem/tfloatliterals.nif b/tests/nimony/nosystem/tfloatliterals.nif index 98a319412..d5a7c305d 100644 --- a/tests/nimony/nosystem/tfloatliterals.nif +++ b/tests/nimony/nosystem/tfloatliterals.nif @@ -17,4 +17,6 @@ (discard 8 +1E+18) ,18 (discard 8 -1E+18) ,20 (discard 8 +1.23E+19) ,21 - (discard 8 -1.23E+19)) \ No newline at end of file + (discard 8 -1.23E+19) ,24 + (discard 8 +0.0) ,25 + (discard 8 -0.0)) \ No newline at end of file diff --git a/tests/nimony/nosystem/tfloatliterals.nim b/tests/nimony/nosystem/tfloatliterals.nim index c7869960d..fe5168045 100644 --- a/tests/nimony/nosystem/tfloatliterals.nim +++ b/tests/nimony/nosystem/tfloatliterals.nim @@ -20,3 +20,7 @@ discard -1e18 discard 123e17 discard -123e17 + +# issue #1321 +discard 0.0 +discard -0.0 diff --git a/tests/nimony/nosystem/tfloatliterals0.nif b/tests/nimony/nosystem/tfloatliterals0.nif new file mode 100644 index 000000000..63ce5690a --- /dev/null +++ b/tests/nimony/nosystem/tfloatliterals0.nif @@ -0,0 +1,4 @@ +(.nif24) +0,2,tests/nimony/nosystem/tfloatliterals0.nim(stmts + (discard 8 -0.0) ,1 + (discard 8 +0.0)) \ No newline at end of file diff --git a/tests/nimony/nosystem/tfloatliterals0.nim b/tests/nimony/nosystem/tfloatliterals0.nim new file mode 100644 index 000000000..8911bdb81 --- /dev/null +++ b/tests/nimony/nosystem/tfloatliterals0.nim @@ -0,0 +1,3 @@ +# issue #1321 +discard -0.0 +discard 0.0 From 1262973f67c99fbe4a1b439386ba0c907a77fc8e Mon Sep 17 00:00:00 2001 From: demotomohiro Date: Thu, 24 Jul 2025 21:09:50 +0900 Subject: [PATCH 2/2] adds BitTableFloat --- src/lib/bitabs.nim | 26 ++++++++++++++------------ src/lib/nifstreams.nim | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/lib/bitabs.nim b/src/lib/bitabs.nim index 06f91e812..2987c5655 100644 --- a/src/lib/bitabs.nim +++ b/src/lib/bitabs.nim @@ -7,7 +7,7 @@ ## A BiTable is a table that can be seen as an optimized pair ## of `(Table[Id, Val], Table[Val, Id])`. -import std/[hashes, math] +import std/hashes when defined(nimPreviewSlimSystem): import std/assertions @@ -53,15 +53,6 @@ proc enlarge[Id, T](t: var BiTable[Id, T]) = j = nextTry(j, maxHash(t)) t.keys[j] = move n[i] -proc equal[T, U](x: T, y: U): bool {.inline.} = - when T is SomeFloat: - # we need to distinguish `0.0` and `-0.0` even if `0.0 == -0.0`. - # Their bit patterns are different. - # signbit and copySign procs returns the different value. - x == y and signbit(x) == signbit(y) - else: - x == y - proc getKeyId*[Id, T](t: BiTable[Id, T]; v: T): Id = let origH = hash(v) var h = origH and maxHash(t) @@ -69,7 +60,7 @@ proc getKeyId*[Id, T](t: BiTable[Id, T]; v: T): Id = while true: let litId = t.keys[h] if not isFilled(litId): break - if equal(v, t.vals[idToIdx t.keys[h]]): return litId + if v == t.vals[idToIdx t.keys[h]]: return litId h = nextTry(h, maxHash(t)) return Id(0) @@ -80,7 +71,7 @@ template getOrInclImpl() {.dirty.} = while true: let litId = t.keys[h] if not isFilled(litId): break - if equal(v, t.vals[idToIdx t.keys[h]]): return litId + if v == t.vals[idToIdx t.keys[h]]: return litId h = nextTry(h, maxHash(t)) # not found, we need to insert it: if mustRehash(t.keys.len, t.vals.len): @@ -138,6 +129,17 @@ proc memSize*[Id, T](t: BiTable[Id, T]): int = else: t.vals.len * sizeof(T) + t.keys.len * sizeof(Id) +type + # we need to distinguish `0.0` and `-0.0` even if `0.0 == -0.0` + # as signbit and copySign procs returns the different value. + BiTableFloat*[Id] = distinct BiTable[Id, uint64] + +proc getOrIncl*[Id](t: var BiTableFloat[Id]; v: float64): Id {.inline .} = + BiTable[Id, uint64](t).getOrIncl(cast[uint64](v)) + +proc `[]`*[Id](t: BiTableFloat[Id]; litId: Id): float64 {.inline.} = + cast[float64](BiTable[Id, uint64](t)[litId]) + when isMainModule: var t: BiTable[uint32, string] diff --git a/src/lib/nifstreams.nim b/src/lib/nifstreams.nim index bb9e2ced8..3eea441aa 100644 --- a/src/lib/nifstreams.nim +++ b/src/lib/nifstreams.nim @@ -77,7 +77,7 @@ type strings*: BiTable[StrId, string] integers*: BiTable[IntId, int64] uintegers*: BiTable[UIntId, uint64] - floats*: BiTable[FloatId, float64] + floats*: BiTableFloat[FloatId] proc `==`*(a, b: SymId): bool {.borrow.} proc `==`*(a, b: StrId): bool {.borrow.}