@@ -24,39 +24,39 @@ const EMPTY_DICT_T = typeof(EMPTY_DICT)
24
24
const ENABLE_HASHCONSING = Ref (true )
25
25
26
26
@compactify show_methods= false begin
27
- @abstract struct BasicSymbolic{T} <: Symbolic{T}
27
+ @abstract mutable struct BasicSymbolic{T} <: Symbolic{T}
28
28
metadata:: Metadata = NO_METADATA
29
29
end
30
- struct Sym{T} <: BasicSymbolic{T}
30
+ mutable struct Sym{T} <: BasicSymbolic{T}
31
31
name:: Symbol = :OOF
32
32
end
33
- struct Term{T} <: BasicSymbolic{T}
33
+ mutable struct Term{T} <: BasicSymbolic{T}
34
34
f:: Any = identity # base/num if Pow; issorted if Add/Dict
35
35
arguments:: SmallV{Any} = EMPTY_ARGS
36
36
hash:: RefValue{UInt} = EMPTY_HASH
37
37
hash2:: RefValue{UInt} = EMPTY_HASH
38
38
end
39
- struct Mul{T} <: BasicSymbolic{T}
39
+ mutable struct Mul{T} <: BasicSymbolic{T}
40
40
coeff:: Any = 0 # exp/den if Pow
41
41
dict:: EMPTY_DICT_T = EMPTY_DICT
42
42
hash:: RefValue{UInt} = EMPTY_HASH
43
43
hash2:: RefValue{UInt} = EMPTY_HASH
44
44
arguments:: SmallV{Any} = EMPTY_ARGS
45
45
end
46
- struct Add{T} <: BasicSymbolic{T}
46
+ mutable struct Add{T} <: BasicSymbolic{T}
47
47
coeff:: Any = 0 # exp/den if Pow
48
48
dict:: EMPTY_DICT_T = EMPTY_DICT
49
49
hash:: RefValue{UInt} = EMPTY_HASH
50
50
hash2:: RefValue{UInt} = EMPTY_HASH
51
51
arguments:: SmallV{Any} = EMPTY_ARGS
52
52
end
53
- struct Div{T} <: BasicSymbolic{T}
53
+ mutable struct Div{T} <: BasicSymbolic{T}
54
54
num:: Any = 1
55
55
den:: Any = 1
56
56
simplified:: Bool = false
57
57
arguments:: SmallV{Any} = EMPTY_ARGS
58
58
end
59
- struct Pow{T} <: BasicSymbolic{T}
59
+ mutable struct Pow{T} <: BasicSymbolic{T}
60
60
base:: Any = 1
61
61
exp:: Any = 1
62
62
arguments:: SmallV{Any} = EMPTY_ARGS
@@ -87,15 +87,7 @@ function exprtype(x::BasicSymbolic)
87
87
end
88
88
end
89
89
90
- mutable struct HashConsingWrapper
91
- bs:: BasicSymbolic
92
- end
93
-
94
- Base. hash (x:: HashConsingWrapper , h:: UInt ) = hash2 (x. bs, h)
95
-
96
- Base. isequal (x:: HashConsingWrapper , y:: HashConsingWrapper ) = isequal_with_metadata (x. bs, y. bs)
97
-
98
- const wkd = TaskLocalValue {WeakKeyDict{HashConsingWrapper, Nothing}} (WeakKeyDict{HashConsingWrapper, Nothing})
90
+ const wvd = TaskLocalValue {WeakValueDict{UInt, BasicSymbolic}} (WeakValueDict{UInt, BasicSymbolic})
99
91
100
92
# Same but different error messages
101
93
@noinline error_on_type () = error (" Internal error: unreachable reached!" )
@@ -531,15 +523,15 @@ Implements hash consing (flyweight design pattern) for `BasicSymbolic` objects.
531
523
532
524
This function checks if an equivalent `BasicSymbolic` object already exists. It uses a
533
525
custom hash function (`hash2`) incorporating metadata and symtypes to search for existing
534
- objects in a `WeakKeyDict ` (`wkd `). Due to the possibility of hash collisions (where
526
+ objects in a `WeakValueDict ` (`wvd `). Due to the possibility of hash collisions (where
535
527
different objects produce the same hash), a custom equality check (`isequal_with_metadata`)
536
528
which includes metadata comparison, is used to confirm the equivalence of objects with
537
529
matching hashes. If an equivalent object is found, the existing object is returned;
538
530
otherwise, the input `s` is returned. This reduces memory usage, improves compilation time
539
531
for runtime code generation, and supports built-in common subexpression elimination,
540
532
particularly when working with symbolic objects with metadata.
541
533
542
- Using a `WeakKeyDict ` ensures that only weak references to `BasicSymbolic` objects are
534
+ Using a `WeakValueDict ` ensures that only weak references to `BasicSymbolic` objects are
543
535
stored, allowing objects that are no longer strongly referenced to be garbage collected.
544
536
Custom functions `hash2` and `isequal_with_metadata` are used instead of `Base.hash` and
545
537
`Base.isequal` to accommodate metadata without disrupting existing tests reliant on the
@@ -549,14 +541,13 @@ function BasicSymbolic(s::BasicSymbolic)::BasicSymbolic
549
541
if ! ENABLE_HASHCONSING[]
550
542
return s
551
543
end
552
- cache = wkd[]
553
- hcw = HashConsingWrapper (s)
554
- k = getkey (cache, hcw, nothing )
555
- if isnothing (k)
556
- cache[hcw] = nothing
557
- return s
544
+ cache = wvd[]
545
+ h = hash2 (s)
546
+ k = get! (cache, h, s)
547
+ if isequal_with_metadata (k, s)
548
+ return k
558
549
else
559
- return k . bs
550
+ return s
560
551
end
561
552
end
562
553
0 commit comments