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

JuliaLang / julia / #37728

26 Mar 2024 03:46AM UTC coverage: 80.612% (-0.8%) from 81.423%
#37728

push

local

web-flow
Update zlib to 1.3.1 (#53841)

Released January 22, 2024

69920 of 86737 relevant lines covered (80.61%)

14456248.65 hits per line

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

18.1
/base/ryu/shortest.jl
1
"""
2
    b, e10 = reduce_shortest(f[, maxsignif])
3

4
Reduce to shortest decimal representation where `abs(f) == b * 10^e10` and `b` is an
5
integer. If a `maxsignif` argument is provided, then `b < maxsignif`.
6
"""
7
@inline function reduce_shortest(f::T, maxsignif=nothing) where {T}
8
    U = uinttype(T)
2,367✔
9
    uf = reinterpret(U, f)
446,305✔
10
    m = uf & significand_mask(T)
488,062✔
11
    e = ((uf & exponent_mask(T)) >> significand_bits(T)) % Int
883,917✔
12

13
    ## Step 1
14
    #  mf * 2^ef == f
15
    mf = (one(U) << significand_bits(T)) | m
1,276,037✔
16
    ef = e - exponent_bias(T) - significand_bits(T)
837,730✔
17
    f_isinteger = mf & ((one(U) << -ef) - one(U)) == 0
1,459,782✔
18

19
    if ef > 0 || ef < -Base.significand_bits(T) || !f_isinteger
1,294,969✔
20
        # fixup subnormals
21
        if e == 0
1,699,101✔
22
            ef = 1 - exponent_bias(T) - significand_bits(T)
1,380,706✔
23
            mf = m
38,494✔
24
        end
25

26
        ## Step 2
27
        #  u * 2^e2 == (f + prevfloat(f))/2
28
        #  v * 2^e2 == f
29
        #  w * 2^e2 == (f + nextfloat(f))/2
30
        e2 = ef - 2
872,419✔
31
        mf_iseven = iseven(mf) # trailing bit of significand is zero
905,814✔
32

33
        v = U(4) * mf
867,320✔
34
        w = v + U(2)
433,656✔
35
        u_shift_half = m == 0 && e > 1 # if first element of binade, other than first normal one
1,655,275✔
36
        u = v - U(2) + u_shift_half
1,183,121✔
37

38
        ## Step 3
39
        #  a == floor(u * 2^e2 / 10^e10), exact if a_allzero
40
        #  b == floor(v * 2^e2 / 10^e10), exact if b_allzero
41
        #  c == floor(w * 2^e2 / 10^e10)
42
        a_allzero = false
395,158✔
43
        b_allzero = false
×
44
        b_lastdigit = 0x00
568,135✔
45
        if e2 >= 0
1,070,931✔
46
            q = log10pow2(e2) - (T == Float64 ? (e2 > 3) : 0)
3,374,154✔
47
            e10 = q
288,768✔
48
            k = pow5_inv_bitcount(T) + pow5bits(q) - 1
1,656,602✔
49
            i = -e2 + q + k
1,652,883✔
50
            a, b, c = mulshiftinvsplit(T, u, v, w, q, i)
2,042,172✔
51
            if T == Float32 || T == Float16
446,332✔
52
                if q != 0 && div(c - 1, 10) <= div(a, 10)
344,780✔
53
                    l = pow5_inv_bitcount(T) + pow5bits(q - 1) - 1
553,391✔
54
                    mul = pow5invsplit_lookup(T, q-1)
×
55
                    b_lastdigit = (mulshift(v, mul, -e2 + q - 1 + l) % 10) % UInt8
41,436✔
56
                end
57
            end
58
            if q <= qinvbound(T)
×
59
                if ((v % UInt32) - 5 * div(v, 5)) == 0
×
60
                    b_allzero = pow5(v, q)
×
61
                elseif mf_iseven
×
62
                    a_allzero = pow5(u, q)
×
63
                else
64
                    c -= pow5(w, q)
×
65
                end
66
            end
67
        else
68
            q = log10pow5(-e2) - (T == Float64 ? (-e2 > 1) : 0)
×
69
            e10 = q + e2
×
70
            i = -e2 - q
×
71
            k = pow5bits(i) - pow5_bitcount(T)
×
72
            j = q - k
×
73
            a, b, c = mulshiftsplit(T, u, v, w, i, j)
×
74
            if T == Float32 || T == Float16
×
75
                if q != 0 && div(c - 1, 10) <= div(a, 10)
×
76
                    j = q - 1 - (pow5bits(i + 1) - pow5_bitcount(T))
×
77
                    mul = pow5split_lookup(T, i+1)
×
78
                    b_lastdigit = (mulshift(v, mul, j) % 10) % UInt8
×
79
                end
80
            end
81
            if q <= 1
×
82
                b_allzero = true
×
83
                if mf_iseven
×
84
                    a_allzero = !u_shift_half
×
85
                else
86
                    c -= 1
×
87
                end
88
            elseif q < qbound(T)
×
89
                b_allzero = pow2(v, q - (T != Float64))
×
90
            end
91
        end
92

93
        ## Step 4: reduction
94
        if a_allzero || b_allzero
×
95
            # a) slow loop
96
            while true
×
97
                c_div10 = div(c, 10)
×
98
                a_div10 = div(a, 10)
×
99
                if c_div10 <= a_div10
×
100
                    break
×
101
                end
102
                a_mod10 = (a % UInt32) - UInt32(10) * (a_div10 % UInt32)
×
103
                b_div10 = div(b, 10)
×
104
                b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32)
×
105
                a_allzero &= a_mod10 == 0
×
106
                b_allzero &= b_lastdigit == 0
×
107
                b_lastdigit = b_mod10 % UInt8
×
108
                b = b_div10
×
109
                c = c_div10
×
110
                a = a_div10
×
111
                e10 += 1
×
112
            end
×
113
            if a_allzero
×
114
                while true
×
115
                    a_div10 = div(a, 10)
×
116
                    a_mod10 = (a % UInt32) - UInt32(10) * (a_div10 % UInt32)
×
117
                    if a_mod10 != 0 && (maxsignif === nothing || b < maxsignif)
×
118
                        break
×
119
                    end
120
                    c_div10 = div(c, 10)
×
121
                    b_div10 = div(b, 10)
×
122
                    b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32)
×
123
                    b_allzero &= b_lastdigit == 0
×
124
                    b_lastdigit = b_mod10 % UInt8
×
125
                    b = b_div10
×
126
                    c = c_div10
×
127
                    a = a_div10
×
128
                    e10 += 1
×
129
                end
×
130
            end
131
            if b_allzero && b_lastdigit == 5 && iseven(b)
×
132
                b_lastdigit = UInt8(4)
×
133
            end
134
            roundup = (b == a && (!mf_iseven || !a_allzero)) || b_lastdigit >= 5
×
135
        else
136
            # b) specialized for common case (99% Float64, 96% Float32)
137
            roundup = b_lastdigit >= 5
×
138
            c_div100 = div(c, 100)
×
139
            a_div100 = div(a, 100)
×
140
            if c_div100 > a_div100
×
141
                b_div100 = div(b, 100)
×
142
                b_mod100 = (b % UInt32) - UInt32(100) * (b_div100 % UInt32)
×
143
                roundup = b_mod100 >= 50
×
144
                b = b_div100
×
145
                c = c_div100
×
146
                a = a_div100
×
147
                e10 += 2
×
148
            end
149
            while true
×
150
                c_div10 = div(c, 10)
×
151
                a_div10 = div(a, 10)
×
152
                if c_div10 <= a_div10
×
153
                    break
×
154
                end
155
                b_div10 = div(b, 10)
×
156
                b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32)
×
157
                roundup = b_mod10 >= 5
×
158
                b = b_div10
×
159
                c = c_div10
×
160
                a = a_div10
×
161
                e10 += 1
×
162
            end
×
163
            roundup = (b == a || roundup)
×
164
        end
165
        if maxsignif !== nothing && b > maxsignif
×
166
            # reduce to max significant digits
167
            while true
×
168
                b_div10 = div(b, 10)
×
169
                b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32)
×
170
                if b <= maxsignif
×
171
                    break
×
172
                end
173
                b = b_div10
×
174
                roundup = (b_allzero && iseven(b)) ? b_mod10 > 5 : b_mod10 >= 5
×
175
                b_allzero &= b_mod10 == 0
×
176
                e10 += 1
×
177
            end
×
178
            b = b + roundup
×
179

180
            # remove trailing zeros
181
            while true
×
182
                b_div10 = div(b, 10)
×
183
                b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32)
×
184
                if b_mod10 != 0
×
185
                    break
×
186
                end
187
                b = b_div10
×
188
                e10 += 1
×
189
            end
×
190
        else
191
            b = b + roundup
×
192
        end
193
    else
194
        # c) specialized f an integer < 2^53
195
        b = mf >> -ef
×
196
        e10 = 0
×
197

198
        if maxsignif !== nothing && b > maxsignif
×
199
            b_allzero = true
×
200
            # reduce to max significant digits
201
            while true
×
202
                b_div10 = div(b, 10)
×
203
                b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32)
×
204
                if b <= maxsignif
×
205
                    break
×
206
                end
207
                b = b_div10
×
208
                roundup = (b_allzero && iseven(b)) ? b_mod10 > 5 : b_mod10 >= 5
×
209
                b_allzero &= b_mod10 == 0
×
210
                e10 += 1
×
211
            end
×
212
            b = b + roundup
×
213
        end
214
        while true
×
215
            b_div10 = div(b, 10)
×
216
            b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32)
×
217
            if b_mod10 != 0
×
218
                break
×
219
            end
220
            b = b_div10
×
221
            e10 += 1
×
222
        end
×
223
    end
224
    return b, e10
×
225
end
226

227
function writeshortest(buf::Vector{UInt8}, pos, x::T,
1,356,437✔
228
                       plus=false, space=false, hash=true,
229
                       precision=-1, expchar=UInt8('e'), padexp=false, decchar=UInt8('.'),
230
                       typed=false, compact=false) where {T}
231
    @assert 0 < pos <= length(buf)
2,860,646✔
232
    # special cases
233
    if x == 0
1,796,661✔
234
        if typed && x isa Float16
1,351,992✔
235
            @inbounds buf[pos] = UInt8('F')
440,213✔
236
            @inbounds buf[pos + 1] = UInt8('l')
92,906✔
237
            @inbounds buf[pos + 2] = UInt8('o')
47,861✔
238
            @inbounds buf[pos + 3] = UInt8('a')
440,961✔
239
            @inbounds buf[pos + 4] = UInt8('t')
791,996✔
240
            @inbounds buf[pos + 5] = UInt8('1')
349,999✔
241
            @inbounds buf[pos + 6] = UInt8('6')
349,999✔
242
            @inbounds buf[pos + 7] = UInt8('(')
98,299✔
243
            pos += 8
5,455✔
244
        end
245
        pos = append_sign(x, plus, space, buf, pos)
997,128✔
246
        @inbounds buf[pos] = UInt8('0')
1,156,857✔
247
        pos += 1
911,783✔
248
        if hash
1,351,990✔
249
            @inbounds buf[pos] = decchar
1,354,825✔
250
            pos += 1
1,259,123✔
251
        end
252
        if precision == -1
1,256,317✔
253
            @inbounds buf[pos] = UInt8('0')
1,004,680✔
254
            pos += 1
911,790✔
255
            if typed && x isa Float32
956,847✔
256
                @inbounds buf[pos] = UInt8('f')
48,059✔
257
                @inbounds buf[pos + 1] = UInt8('0')
3,408✔
258
                pos += 2
3,413✔
259
            end
260
            if typed && x isa Float16
1,352,507✔
261
                @inbounds buf[pos] = UInt8(')')
444,294✔
262
                pos += 1
440,209✔
263
            end
264
            return pos
956,824✔
265
        end
266
        while hash && precision > 1
47,859✔
267
            @inbounds buf[pos] = UInt8('0')
2,806✔
268
            pos += 1
×
269
            precision -= 1
×
270
        end
×
271
        if typed && x isa Float32
×
272
            @inbounds buf[pos] = UInt8('f')
×
273
            @inbounds buf[pos + 1] = UInt8('0')
×
274
            pos += 2
×
275
        end
276
        if typed && x isa Float16
×
277
            @inbounds buf[pos] = UInt8(')')
×
278
            pos += 1
×
279
        end
280
        return pos
×
281
    elseif isnan(x)
×
282
        pos = append_sign(x, plus, space, buf, pos)
×
283
        @inbounds buf[pos] = UInt8('N')
×
284
        @inbounds buf[pos + 1] = UInt8('a')
×
285
        @inbounds buf[pos + 2] = UInt8('N')
×
286
        if typed
×
287
            if x isa Float32
×
288
                @inbounds buf[pos + 3] = UInt8('3')
×
289
                @inbounds buf[pos + 4] = UInt8('2')
×
290
            elseif x isa Float16
×
291
                @inbounds buf[pos + 3] = UInt8('1')
×
292
                @inbounds buf[pos + 4] = UInt8('6')
×
293
            end
294
        end
295
        return pos + 3 + (typed && x isa Union{Float32, Float16} ? 2 : 0)
×
296
    elseif !isfinite(x)
×
297
        pos = append_sign(x, plus, space, buf, pos)
×
298
        @inbounds buf[pos] = UInt8('I')
×
299
        @inbounds buf[pos + 1] = UInt8('n')
×
300
        @inbounds buf[pos + 2] = UInt8('f')
×
301
        if typed
×
302
            if x isa Float32
×
303
                @inbounds buf[pos + 3] = UInt8('3')
×
304
                @inbounds buf[pos + 4] = UInt8('2')
×
305
            elseif x isa Float16
×
306
                @inbounds buf[pos + 3] = UInt8('1')
×
307
                @inbounds buf[pos + 4] = UInt8('6')
×
308
            end
309
        end
310
        return pos + 3 + (typed && x isa Union{Float32, Float16} ? 2 : 0)
×
311
    end
312

313
    output, nexp = reduce_shortest(x, compact ? 999_999 : nothing)
×
314

315
    if typed && x isa Float16
×
316
        @inbounds buf[pos] = UInt8('F')
×
317
        @inbounds buf[pos + 1] = UInt8('l')
×
318
        @inbounds buf[pos + 2] = UInt8('o')
×
319
        @inbounds buf[pos + 3] = UInt8('a')
×
320
        @inbounds buf[pos + 4] = UInt8('t')
×
321
        @inbounds buf[pos + 5] = UInt8('1')
×
322
        @inbounds buf[pos + 6] = UInt8('6')
×
323
        @inbounds buf[pos + 7] = UInt8('(')
×
324
        pos += 8
×
325
    end
326
    pos = append_sign(x, plus, space, buf, pos)
×
327

328
    olength = decimallength(output)
×
329
    exp_form = true
×
330
    pt = nexp + olength
×
331
    if -4 < pt <= (precision == -1 ? (T == Float16 ? 3 : 6) : precision) &&
×
332
        !(pt >= olength && abs(mod(x + 0.05, 10^(pt - olength)) - 0.05) > 0.05)
333
        exp_form = false
×
334
        if pt <= 0
×
335
            @inbounds buf[pos] = UInt8('0')
×
336
            pos += 1
×
337
            @inbounds buf[pos] = decchar
×
338
            pos += 1
×
339
            for _ = 1:abs(pt)
×
340
                @inbounds buf[pos] = UInt8('0')
×
341
                pos += 1
×
342
            end
×
343
        # elseif pt >= olength
344
            # nothing to do at this point
345
        # else
346
            # nothing to do at this point
347
        end
348
    else
349
        # make space for decchar
350
        pos += 1
×
351
    end
352

353
    append_c_digits(olength, output, buf, pos)
×
354

355
    if !exp_form
×
356
        if pt <= 0
×
357
            pos += olength
×
358
            precision -= olength
×
359
        elseif pt >= olength
×
360
            pos += olength
×
361
            precision -= olength
×
362
            for _ = 1:nexp
×
363
                @inbounds buf[pos] = UInt8('0')
×
364
                pos += 1
×
365
                precision -= 1
×
366
            end
×
367
            if hash
×
368
                @inbounds buf[pos] = decchar
×
369
                pos += 1
×
370
                if precision < 0
×
371
                    @inbounds buf[pos] = UInt8('0')
×
372
                    pos += 1
×
373
                end
374
            end
375
        else
376
            pointoff = olength - abs(nexp)
×
377
            # shift bytes after pointoff to make room for decchar
378
            ptr = pointer(buf)
×
379
            memmove(ptr + pos + pointoff, ptr + pos + pointoff - 1, olength - pointoff + 1)
×
380
            @inbounds buf[pos + pointoff] = decchar
×
381
            pos += olength + 1
×
382
            precision -= olength
×
383
        end
384
        if hash
×
385
            while precision > 0
×
386
                @inbounds buf[pos] = UInt8('0')
×
387
                pos += 1
×
388
                precision -= 1
×
389
            end
×
390
        end
391
        if typed && x isa Float32
×
392
            @inbounds buf[pos] = UInt8('f')
×
393
            @inbounds buf[pos + 1] = UInt8('0')
×
394
            pos += 2
×
395
        end
396
    else
397
        # move leading digit into place
398
        @inbounds buf[pos - 1] = buf[pos]
×
399
        if olength > 1 || hash
×
400
            @inbounds buf[pos] = decchar
×
401
            pos += olength
×
402
            precision -= olength
×
403
        end
404
        if hash
×
405
            if olength == 1
×
406
                @inbounds buf[pos] = UInt8('0')
×
407
                pos += 1
×
408
            end
409
            while precision > 0
×
410
                @inbounds buf[pos] = UInt8('0')
×
411
                pos += 1
×
412
                precision -= 1
×
413
            end
×
414
        end
415

416
        @inbounds buf[pos] = expchar
×
417
        pos += 1
×
418
        exp2 = nexp + olength - 1
×
419
        if exp2 < 0
×
420
            @inbounds buf[pos] = UInt8('-')
×
421
            pos += 1
×
422
            exp2 = -exp2
×
423
        elseif padexp
×
424
            @inbounds buf[pos] = UInt8('+')
×
425
            pos += 1
×
426
        end
427

428
        if exp2 >= 100
×
429
            c = exp2 % 10
×
430
            @inbounds d100 = DIGIT_TABLE16[(div(exp2, 10) % Int) + 1]
×
431
            @inbounds buf[pos] = d100 % UInt8
×
432
            @inbounds buf[pos + 1] = (d100 >> 0x8) % UInt8
×
433
            @inbounds buf[pos + 2] = UInt8('0') + (c % UInt8)
×
434
            pos += 3
×
435
        elseif exp2 >= 10
×
436
            @inbounds d100 = DIGIT_TABLE16[(exp2 % Int) + 1]
×
437
            @inbounds buf[pos] = d100 % UInt8
×
438
            @inbounds buf[pos + 1] = (d100 >> 0x8) % UInt8
×
439
            pos += 2
×
440
        else
441
            if padexp
×
442
                @inbounds buf[pos] = UInt8('0')
×
443
                pos += 1
×
444
            end
445
            @inbounds buf[pos] = UInt8('0') + (exp2 % UInt8)
×
446
            pos += 1
×
447
        end
448
    end
449
    if typed && x isa Float16
×
450
        @inbounds buf[pos] = UInt8(')')
×
451
        pos += 1
×
452
    end
453

454
    return pos
×
455
end
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

© 2025 Coveralls, Inc