• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #38182

15 Aug 2025 03:55AM UTC coverage: 77.87% (-0.4%) from 78.28%
#38182

push

local

web-flow
🤖 [master] Bump the SparseArrays stdlib from 30201ab to bb5ecc0 (#59263)

Stdlib: SparseArrays
URL: https://github.com/JuliaSparse/SparseArrays.jl.git
Stdlib branch: main
Julia branch: master
Old commit: 30201ab
New commit: bb5ecc0
Julia version: 1.13.0-DEV
SparseArrays version: 1.13.0
Bump invoked by: @ViralBShah
Powered by:
[BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl)

Diff:
https://github.com/JuliaSparse/SparseArrays.jl/compare/30201abcb...bb5ecc091

```
$ git log --oneline 30201ab..bb5ecc0
bb5ecc0 fast quadratic form for dense matrix, sparse vectors (#640)
34ece87 Extend 3-arg `dot` to generic `HermOrSym` sparse matrices (#643)
095b685 Exclude unintended complex symmetric sparse matrices from 3-arg `dot` (#642)
8049287 Fix signature for 2-arg matrix-matrix `dot` (#641)
cff971d Make cond(::SparseMatrix, 1 / Inf) discoverable from 2-norm error (#629)
```

Co-authored-by: ViralBShah <744411+ViralBShah@users.noreply.github.com>

48274 of 61993 relevant lines covered (77.87%)

9571166.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.81
/base/ryu/utils.jl
1
const MANTISSA_MASK = Base.significand_mask(Float64)
2
const EXP_MASK = Base.exponent_mask(Float64) >> Base.significand_bits(Float64)
3

4
# Note: these are smaller than the values given in Figure 4 from the paper
5
# see https://github.com/ulfjack/ryu/issues/119
6
pow5_bitcount(::Type{Float16}) = 30
×
7
pow5_bitcount(::Type{Float32}) = 61
×
8
pow5_bitcount(::Type{Float64}) = 121
×
9

10
pow5_inv_bitcount(::Type{Float16}) = 30
×
11
pow5_inv_bitcount(::Type{Float32}) = 59
×
12
pow5_inv_bitcount(::Type{Float64}) = 122
×
13

14
qinvbound(::Type{Float16}) = 4
×
15
qinvbound(::Type{Float32}) = 9
×
16
qinvbound(::Type{Float64}) = 21
×
17

18
qbound(::Type{Float16}) = 15
×
19
qbound(::Type{Float32}) = 31
×
20
qbound(::Type{Float64}) = 63
×
21

22
"""
23
    Ryu.log10pow2(e::Integer)
24

25
Computes `floor(log10(2^e))`. This is valid for all `e < 1651`.
26
"""
27
log10pow2(e) = (e * 78913) >> 18
1✔
28

29

30
"""
31
    Ryu.log10pow5(e::Integer)
32

33
Computes `floor(log10(5^e))`. This is valid for all `e < 2621`.
34
"""
35
log10pow5(e) = (e * 732923) >> 20
162,173✔
36

37
"""
38
    Ryu.pow5bits(e)
39

40
Computes `e == 0 ? 1 : ceil(log2(5^e))`. This is valid for `e < 3529` (if performend in `Int32` arithmetic).
41
"""
42
pow5bits(e) = ((e * 1217359) >> 19) + 1
162,175✔
43

44
""""
45
     Ryu.mulshift(m::U, mula, j) where {U<:Unsigned}
46

47
Compute `(m * mul) >> j`, where `j >= 8*sizeof(U)`. The type of the results is the larger of `U` or `UInt32`.
48
"""
49
function mulshift(m::U, mul, j) where {U<:Unsigned}
50
    W = widen(U)
486,519✔
51
    nbits = 8*sizeof(U)
486,519✔
52
    return ((((W(m) * (mul % U)) >> nbits) + W(m) * (mul >> nbits)) >> (j - nbits)) % promote_type(U,UInt32)
486,523✔
53
end
54

55
indexforexp(e) = div(e + 15, 16)
29✔
56
pow10bitsforindex(idx) = 16 * idx + 120
1,084✔
57
lengthforindex(idx) = div(((Int64(16 * idx) * 1292913986) >> 32) + 1 + 16 + 8, 9)
1,084✔
58

59
"""
60
    Ryu.pow5(x, p)
61

62
Return `true` if `5^p` is a divisor of `x`.
63
"""
64
pow5(x, p) = x % (UInt64(5)^p) == 0
5✔
65

66
"""
67
    Ryu.pow2(x, p)
68

69
Return `true` if `2^p` is a divisor of `x`. In other words, if the trailing `p` bits of `x` are zero.
70
"""
71
pow2(x, p) = (x & ((Int64(1) << p) - 1)) == 0
162,319✔
72

73
"""
74
    Ryu.decimallength(v)
75

76
The number of decimal digits of the integer `v`.
77
"""
78
function decimallength(v)
79
    v >= 10000000000000000 && return 17
162,406✔
80
    v >= 1000000000000000 && return 16
162,406✔
81
    v >= 100000000000000 && return 15
17,585✔
82
    v >= 10000000000000 && return 14
3,892✔
83
    v >= 1000000000000 && return 13
2,710✔
84
    v >= 100000000000 && return 12
2,504✔
85
    v >= 10000000000 && return 11
2,500✔
86
    v >= 1000000000 && return 10
2,500✔
87
    v >= 100000000 && return 9
2,500✔
88
    v >= 10000000 && return 8
2,500✔
89
    v >= 1000000 && return 7
2,500✔
90
    v >= 100000 && return 6
2,499✔
91
    v >= 10000 && return 5
2,492✔
92
    v >= 1000 && return 4
2,440✔
93
    v >= 100 && return 3
2,433✔
94
    v >= 10 && return 2
1,814✔
95
    return 1
1,205✔
96
end
97
function decimallength(v::UInt32)
98
    v >= 100000000 && return 9
1,128✔
99
    v >= 10000000 && return 8
1,102✔
100
    v >= 1000000 && return 7
1,079✔
101
    v >= 100000 && return 6
1,073✔
102
    v >= 10000 && return 5
1,070✔
103
    v >= 1000 && return 4
1,040✔
104
    v >= 100 && return 3
773✔
105
    v >= 10 && return 2
574✔
106
    return 1
448✔
107
end
108
function decimallength(v::UInt16)
×
109
    v >= 10000 && return 5
×
110
    v >= 1000 && return 4
×
111
    v >= 100 && return 3
×
112
    v >= 10 && return 2
×
113
    return 1
×
114
end
115

116
function mulshiftinvsplit(::Type{T}, mv, mp, mm, i, j) where {T}
117
    mul = pow5invsplit_lookup(T, i)
1✔
118
    vr = mulshift(mv, mul, j)
1✔
119
    vp = mulshift(mp, mul, j)
1✔
120
    vm = mulshift(mm, mul, j)
1✔
121
    return vr, vp, vm
×
122
end
123

124
function mulshiftsplit(::Type{T}, mv, mp, mm, i, j) where {T}
125
    mul = pow5split_lookup(T, i)
162,173✔
126
    vr = mulshift(mv, mul, j)
162,173✔
127
    vp = mulshift(mp, mul, j)
162,173✔
128
    vm = mulshift(mm, mul, j)
162,173✔
129
    return vr, vp, vm
162,173✔
130
end
131

132
"""
133
    Ryu.umul256(a::UInt128, bHi::UInt64, bLo::UInt64)::Tuple{UInt128, UInt128}
134

135
Compute `p = a*b` where `b = bLo + bHi<<64`, returning the result as `pLo, pHi` where `p = pLo + pHi<<128`.
136
"""
137
function umul256(a::UInt128, bHi::UInt64, bLo::UInt64)
138
    aLo = a % UInt64
3,709✔
139
    aHi = (a >> 64) % UInt64
3,709✔
140

141
    b00 = UInt128(aLo) * bLo
3,709✔
142
    b01 = UInt128(aLo) * bHi
3,709✔
143
    b10 = UInt128(aHi) * bLo
3,709✔
144
    b11 = UInt128(aHi) * bHi
3,709✔
145

146
    b00Lo = b00 % UInt64
2,429✔
147
    b00Hi = (b00 >> 64) % UInt64
3,709✔
148

149
    mid1 = b10 + b00Hi
3,709✔
150
    mid1Lo = mid1 % UInt64
3,709✔
151
    mid1Hi = (mid1 >> 64) % UInt64
3,709✔
152

153
    mid2 = b01 + mid1Lo
3,709✔
154
    mid2Lo = mid2 % UInt64
2,429✔
155
    mid2Hi = (mid2 >> 64) % UInt64
3,709✔
156

157
    pHi = b11 + mid1Hi + mid2Hi
3,709✔
158
    pLo = (UInt128(mid2Lo) << 64) | b00Lo
2,429✔
159
    return pLo, pHi
2,429✔
160
end
161

162
"""
163
    Ryu.umul256_hi(a::UInt128, bHi::UInt64, bLo::UInt64)::UInt128
164

165
Compute `pHi = (a*b)>>128` where `b = bLo + bHi<<64`.
166
"""
167
umul256_hi(a::UInt128, bHi::UInt64, bLo::UInt64) = umul256(a, bHi, bLo)[2]
3,709✔
168

169
"""
170
    Ryu.mulshiftmod1e9(m, mula, mulb, mulc, j)::UInt32
171

172
Compute `(m * mul) >> j % 10^9` where `mul = mula + mulb<<64 + mulc<<128`, and `j >= 128`.
173
"""
174
function mulshiftmod1e9(m, mula, mulb, mulc, j)
175
    b0 = UInt128(m) * mula
3,709✔
176
    b1 = UInt128(m) * mulb
3,709✔
177
    b2 = UInt128(m) * mulc
3,709✔
178
    mid = b1 + ((b0 >> 64) % UInt64)
3,709✔
179
    s1 = b2 + ((mid >> 64) % UInt64)
3,709✔
180
    v = s1 >> (j - 128)
3,709✔
181
    multiplied = umul256_hi(v, 0x89705F4136B4A597, 0x31680A88F8953031)
3,709✔
182
    shifted = (multiplied >> 29) % UInt32
3,709✔
183
    return (v % UInt32) - UInt32(1000000000) * shifted
3,709✔
184
end
185

186
function append_sign(x, plus::Bool, space::Bool, buf, pos::Int)
187
    if signbit(x) && !isnan(x)  # suppress minus sign for signaling NaNs
324,360✔
188
        buf[pos] = UInt8('-')
59✔
189
        pos += 1
59✔
190
    elseif plus
324,301✔
191
        buf[pos] = UInt8('+')
34✔
192
        pos += 1
34✔
193
    elseif space
324,267✔
194
        buf[pos] = UInt8(' ')
30✔
195
        pos += 1
30✔
196
    end
197
    return pos
324,360✔
198
end
199

200

201
import Base: append_c_digits_fast as append_c_digits, append_nine_digits
202

203
function append_d_digits(olength::Int, digits::Unsigned, buf, pos::Int, decchar)
204
    newpos = append_c_digits(olength, digits, buf, pos + 1)
319✔
205
    @inbounds buf[pos] = buf[pos + 1]
319✔
206
    @inbounds buf[pos + 1] = decchar
319✔
207
    return newpos # == pos + olength + 1
319✔
208
end
209

210
const BIG_MASK = (big(1) << 64) - 1
211

212
const POW10_SPLIT = collect(Iterators.flatten(map(0:63) do idx
213
    pow10bits = pow10bitsforindex(idx)
×
214
    map(0:lengthforindex(idx)-1) do i
×
215
        v = (div(big(1) << pow10bits, big(10)^(9 * i)) + 1) % ((big(10)^9) << 136)
×
216
        return (UInt64(v & BIG_MASK), UInt64((v >> 64) & BIG_MASK), UInt64((v >> 128) & BIG_MASK))
×
217
    end
218
end))
219

220
function generateinversetables()
×
221
    POW10_OFFSET_2 = Vector{UInt16}(undef, 68 + 1)
×
222
    MIN_BLOCK_2 = fill(0xff, 68 + 1)
×
223
    POW10_SPLIT_2 = Tuple{UInt64, UInt64, UInt64}[]
×
224
    lowerCutoff = big(1) << (54 + 8)
×
225
    for idx = 0:67
×
226
        POW10_OFFSET_2[idx + 1] = length(POW10_SPLIT_2)
×
227
        i = 0
×
228
        while true
×
229
            v = ((big(10)^(9 * (i + 1)) >> (-(120 - 16 * idx))) % (big(10)^9) << (120 + 16))
×
230
            if MIN_BLOCK_2[idx + 1] == 0xff && ((v * lowerCutoff) >> 128) == 0
×
231
                i += 1
×
232
                continue
×
233
            end
234
            if MIN_BLOCK_2[idx + 1] == 0xff
×
235
                MIN_BLOCK_2[idx + 1] = i
×
236
            end
237
            v == 0 && break
×
238
            push!(POW10_SPLIT_2, ((v & BIG_MASK) % UInt64, ((v >> 64) & BIG_MASK) % UInt64, ((v >> 128) & BIG_MASK) % UInt64))
×
239
            i += 1
×
240
        end
×
241
    end
×
242
    POW10_OFFSET_2[end] = length(POW10_SPLIT_2)
×
243
    MIN_BLOCK_2[end] = 0x00
×
244

245
    return POW10_OFFSET_2, MIN_BLOCK_2, POW10_SPLIT_2
×
246
end
247

248
const POW10_OFFSET_2, MIN_BLOCK_2, POW10_SPLIT_2 = generateinversetables()
249

250
"""
251
    Ryu.pow5invsplit(T, i)
252

253
Compute `floor(2^k/5^i)+1`, where `k = pow5bits(i) - 1 + pow5_inv_bitcount(T)`. The result
254
is an unsigned integer twice as wide as `T` (i.e. a `UInt128` if `T == Float64`), with
255
`pow5_inv_bitcount(T)` significant bits.
256
"""
257
function pow5invsplit(::Type{T}, i) where {T<:AbstractFloat}
×
258
    W = widen(uinttype(T))
×
259
    pow = big(5)^i
×
260
    inv = div(big(1) << (ndigits(pow, base=2) - 1 + pow5_inv_bitcount(T)), pow) + 1
×
261
    return W(inv)
×
262
end
263

264
"""
265
    Ryu.pow5invsplit_lookup(T, i)
266

267
[`pow5invsplit`](@ref) computed via lookup table.
268
"""
269
function pow5invsplit_lookup end
270
for T in (Float64, Float32, Float16)
271
    e2_max = exponent_max(T) - precision(T) - 1
272
    i_max = log10pow2(e2_max)
273
    table_sym = Symbol("pow5invsplit_table_", string(T))
274
    @eval const $table_sym = Tuple(Any[pow5invsplit($T, i) for i = 0:$i_max])
275
    @eval pow5invsplit_lookup(::Type{$T}, i) = @inbounds($table_sym[i+1])
2✔
276
end
277

278

279
"""
280
    Ryu.pow5split(T, i)
281

282
Compute `floor(5^i/2^k)`, where `k = pow5bits(i) - pow5_bitcount(T)`. The result is an
283
unsigned integer twice as wide as `T` (i.e. a `UInt128` if `T == Float64`), with
284
`pow5_bitcount(T)` significant bits.
285
"""
286
function pow5split(::Type{T}, i) where {T<:AbstractFloat}
×
287
    W = widen(uinttype(T))
×
288
    pow = big(5)^i
×
289
    return W(pow >> (ndigits(pow, base=2) - pow5_bitcount(T)))
×
290
end
291

292
"""
293
    Ryu.pow5split_lookup(T, i)
294

295
[`pow5split`](@ref) computed via lookup table.
296
"""
297
function pow5split_lookup end
298
for T in (Float64, Float32, Float16)
299
    e2_min = 1 - exponent_bias(T) - significand_bits(T) - 2
300
    i_max = 1 - e2_min - log10pow5(-e2_min)
301
    table_sym = Symbol("pow5split_table_", string(T))
302
    @eval const $table_sym = Tuple(Any[pow5split($T, i) for i = 0:$i_max])
303
    @eval pow5split_lookup(::Type{$T}, i) = @inbounds($table_sym[i+1])
162,173✔
304
end
305

306
const DIGIT_TABLE16 = Base._dec_d100
307

308
const POW10_OFFSET = UInt16[
309
  0, 2, 5, 8, 12, 16, 21, 26, 32, 39,
310
  46, 54, 62, 71, 80, 90, 100, 111, 122, 134,
311
  146, 159, 173, 187, 202, 217, 233, 249, 266, 283,
312
  301, 319, 338, 357, 377, 397, 418, 440, 462, 485,
313
  508, 532, 556, 581, 606, 632, 658, 685, 712, 740,
314
  769, 798, 828, 858, 889, 920, 952, 984, 1017, 1050,
315
  1084, 1118, 1153, 1188
316
]
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc