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

PerezHz / TaylorSeries.jl / 25996768675

17 May 2026 04:45PM UTC coverage: 90.358% (-0.5%) from 90.847%
25996768675

push

github

PerezHz
Fix Fateman tests performance regression; now input-pair product shcedules are built lazily on first use

27 of 54 new or added lines in 3 files covered. (50.0%)

4 existing lines in 1 file now uncovered.

5079 of 5621 relevant lines covered (90.36%)

5426735.3 hits per line

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

87.83
/src/arithmetic.jl
1
# This file is part of the TaylorSeries.jl Julia package, MIT license
2
#
3
# Luis Benet & David P. Sanders
4
# UNAM
5
#
6
# MIT Expat license
7
#
8

9
# Arithmetic operations: +, -, *, /
10
## Addition and subtraction ##
11
for (f, fc) in ((:+, :(add!)), (:-, :(subst!)))
12

13
    for T in (:Taylor1, :TaylorN)
14
        @eval begin
15
            ($f)(a::$T{T}, b::$T{S}) where {T<:Number, S<:Number} =
930✔
16
                ($f)(promote(a, b)...)
17

18
            function ($f)(a::$T{T}, b::$T{T}) where {T<:Number}
557,708✔
19
                if $T == TaylorN
557,708✔
20
                    _check_same_space(a, b)
407,234✔
21
                end
22
                if get_order(a) != get_order(b)
557,688✔
23
                    a, b = fixorder(a, b)
16,520✔
24
                end
25
                c = zero(a)
557,688✔
26
                for k in eachindex(a)
557,688✔
27
                    ($fc)(c, a, b, k)
74,915,119✔
28
                end
7,135,616✔
29
                return c
557,688✔
30
            end
31

32
            function ($f)(a::$T)
6,620✔
33
                c = zero(a)
20,410✔
34
                for k in eachindex(a)
20,410✔
35
                    ($fc)(c, a, k)
228,813✔
36
                end
378,290✔
37
                return c
20,410✔
38
            end
39

40
            function ($f)(a::$T{T}, b::S) where {T<:Number, S<:NumberNotSeries}
11,011✔
41
                if $T == TaylorN
29,571✔
42
                    R = promote_type(T, S)
2,511✔
43
                    aa = convert(TaylorN{R}, a)
2,511✔
44
                    bb = convert(R, b)
2,511✔
45
                    c = TaylorN(aa.coeffs[:], get_order(aa))
4,266✔
46
                    if $(QuoteNode(f)) == :+
2,511✔
47
                        c[0][1] = aa[0][1] + bb
1,181✔
48
                    else
49
                        c[0][1] = aa[0][1] - bb
1,330✔
50
                    end
51
                    return c
2,511✔
52
                end
53
                return ($f)(promote(a, b)...)
27,060✔
54
            end
55

56
            function ($f)(a::$T{T}, b::T) where {T<:Number}
×
57
                c = $T(a.coeffs[:])
×
58
                c[0] = $f(a[0], b)
×
59
                return c
×
60
            end
61

62
            function ($f)(b::S, a::$T{T}) where {T<:Number, S<:NumberNotSeries}
9,866✔
63
                if $T == TaylorN
10,885✔
64
                    R = promote_type(T, S)
2,168✔
65
                    aa = convert(TaylorN{R}, a)
2,168✔
66
                    bb = convert(R, b)
2,168✔
67
                    if $(QuoteNode(f)) == :+
2,168✔
68
                        c = TaylorN(aa.coeffs[:], get_order(aa))
3,239✔
69
                        c[0][1] = bb + aa[0][1]
1,918✔
70
                    else
71
                        c = TaylorN((-aa).coeffs[:], get_order(aa))
1,337✔
72
                        c[0][1] = bb - aa[0][1]
250✔
73
                    end
74
                    return c
2,168✔
75
                end
76
                return ($f)(promote(b, a)...)
8,717✔
77
            end
78

79
            function ($f)(b::T, a::$T{T}) where {T<:Number}
×
80
                c = $T($f(a.coeffs[:]))
×
81
                c[0] = b + a[0]
×
82
                return c
×
83
            end
84

85
            ## add! and subst! ##
86
            function ($fc)(v::$T{T}, a::T, k::Int) where {T<:Number}
80✔
87
                @inbounds v[k] = k==0 ? ($f)(a) : zero(a)
80✔
88
                return nothing
80✔
89
            end
90

91
            if $T == Taylor1
92
                function ($fc)(v::$T{T}, a::$T{T}, k::Int) where {T<:Number}
69,519✔
93
                    @inbounds v[k] = ($f)(a[k])
231,730✔
94
                    return nothing
231,730✔
95
                end
96

97
                function ($fc)(v::$T, a::$T, b::$T, k::Int)
10,943,716✔
98
                    @inbounds v[k] = ($f)(a[k], b[k])
36,538,692✔
99
                    return nothing
36,538,692✔
100
                end
101

102
                function ($fc)(v::$T, a::$T, b::Number, k::Int)
65,382✔
103
                    if k == 0
212,430✔
104
                        v[k] = ($f)(a[k], b)
14,220✔
105
                    else
106
                        v[k] = ($f)(a[k], zero(b))
198,210✔
107
                    end
108
                    return nothing
212,430✔
109
                end
110

111
                function ($fc)(v::$T, a::Number, b::$T, k::Int)
1,112✔
112
                    if k == 0
3,660✔
113
                        v[k] = ($f)(a, b[k])
520✔
114
                    else
115
                        v[k] = ($f)(zero(a), b[k])
3,140✔
116
                    end
117
                    return nothing
3,660✔
118
                end
119

120
                # Nested Taylor1s
121
                function ($fc)(v::$T{$T{T}}, a::$T{$T{T}}, k::Int) where
6,120✔
122
                        {T<:NumberNotSeriesN}
123
                    @inbounds for i in eachindex(v[k])
16,200✔
124
                        v[k][i] = ($f)(a[k][i])
162,000✔
125
                    end
307,800✔
126
                    return nothing
16,200✔
127
                end
128

129
                function ($fc)(v::$T{$T{T}}, a::$T{$T{T}}, b::$T{$T{T}}, k::Int) where
761,510✔
130
                        {T<:NumberNotSeriesN}
131
                    @inbounds for i in eachindex(v[k])
2,448,550✔
132
                        ($fc)(v[k], a[k], b[k], i)
26,829,994✔
133
                    end
46,444,006✔
134
                    return nothing
2,448,550✔
135
                end
136

137
                function ($fc)(v::$T{$T{T}}, a::$T{$T{T}}, b::$T{T}, k::Int) where
×
138
                        {T<:NumberNotSeriesN}
139
                    @inbounds for i in eachindex(v[k])
×
140
                        ($fc)(v[k], a[k], b, i)
×
141
                    end
×
142
                    return nothing
×
143
                end
144

145
                function ($fc)(v::$T{$T{T}}, a::$T{T}, b::$T{$T{T}}, k::Int) where
×
146
                        {T<:NumberNotSeriesN}
147
                    @inbounds for i in eachindex(v[k])
×
148
                        ($fc)(v[k], a, b[k], i)
×
149
                    end
×
150
                    return nothing
×
151
                end
152

153
                function ($fc)(v::$T{$T{T}}, a::$T{$T{T}}, b::T, k::Int) where
760✔
154
                        {T<:NumberNotSeriesN}
155
                    bb = k == 0 ? b : zero(b)
1,320✔
156
                    @inbounds for i in eachindex(v[k])
1,320✔
157
                        ($fc)(v[k], a[k], bb, i)
6,840✔
158
                    end
12,360✔
159
                    return nothing
1,320✔
160
                end
161

162
                function ($fc)(v::$T{$T{T}}, a::T, b::$T{$T{T}}, k::Int) where
520✔
163
                        {T<:NumberNotSeriesN}
164
                    aa = k == 0 ? a : zero(a)
520✔
165
                    @inbounds for i in eachindex(v[k])
520✔
166
                        ($fc)(v[k], aa, b[k], i)
3,640✔
167
                    end
6,760✔
168
                    return nothing
520✔
169
                end
170

171
            else
172
                function ($fc)(v::$T{T}, a::$T{T}, k::Int) where {T<:Number}
3,214✔
173
                    @inbounds for l in eachindex(v[k])
9,920✔
174
                        v[k][l] = ($f)(a[k][l])
71,770✔
175
                    end
133,620✔
176
                    return nothing
9,920✔
177
                end
178

179
                function ($fc)(v::$T, a::$T, b::$T, k::Int)
998,930✔
180
                    _check_same_space(v, a, b)
2,578,826✔
181
                    @inbounds for i in eachindex(v[k])
2,578,826✔
182
                        v[k][i] = ($f)(a[k][i], b[k][i])
117,180,863✔
183
                    end
231,782,900✔
184
                    return nothing
2,578,826✔
185
                end
186

187
                function ($fc)(v::$T, a::$T, b::Number, k::Int)
2,619✔
188
                    bb = k == 0 ? b : zero(b)
8,730✔
189
                    for i in eachindex(v[k])
8,730✔
190
                        v[k][i] = ($f)(a[k][i], bb)
8,730✔
191
                    end
8,730✔
192
                    return nothing
8,730✔
193
                end
194

195
                function ($fc)(v::$T, a::Number, b::$T, k::Int)
×
196
                    aa = k == 0 ? a : zero(a)
×
197
                    for i in eachindex(v[k])
×
198
                        v[k][i] = ($f)(aa, b[k][i])
×
199
                    end
×
200
                    return nothing
×
201
                end
202

203
            end
204
        end
205

206
    end
207

208
    @eval ($f)(a::T, b::S) where {T<:Taylor1, S<:TaylorN} = ($f)(promote(a, b)...)
20✔
209
    @eval ($f)(a::T, b::S) where {T<:TaylorN, S<:Taylor1} = ($f)(promote(a, b)...)
×
210

211
    @eval begin
212
        function ($f)(a::HomogeneousPolynomial{T}, b::HomogeneousPolynomial{S}) where
10✔
213
                {T<:NumberNotSeriesN, S<:NumberNotSeriesN}
214
            _check_same_space(a, b)
10✔
215
            @assert get_order(a) == get_order(b)
10✔
216
            v = ($f)(a.coeffs, b.coeffs)
10✔
217
            return HomogeneousPolynomial(a.space, v, get_order(a))
10✔
218
        end
219

220
        function ($f)(a::HomogeneousPolynomial{T}, b::HomogeneousPolynomial{T}) where
2,085✔
221
                {T<:NumberNotSeriesN}
222
            _check_same_space(a, b)
6,674✔
223
            @assert get_order(a) == get_order(b)
6,674✔
224
            v = ($f)(a.coeffs, b.coeffs)
6,674✔
225
            return HomogeneousPolynomial(a.space, v, get_order(a))
6,674✔
226
        end
227

228
        # NOTE add! and subst! for HomogeneousPolynomial's act as += or -=
229
        function ($fc)(res::HomogeneousPolynomial{T}, a::HomogeneousPolynomial{T},
×
230
                b::HomogeneousPolynomial{T}, k::Int) where {T<:NumberNotSeriesN}
231
            _check_same_space(res, a, b)
×
232
            res[k] += ($f)(a[k], b[k])
×
233
            return nothing
×
234
        end
235

236
        ($f)(a::HomogeneousPolynomial) =
6,381✔
237
            HomogeneousPolynomial(a.space, ($f)(a.coeffs), get_order(a))
238

239
        function ($f)(a::TaylorN{Taylor1{T}}, b::S) where
161✔
240
                {T<:NumberNotSeries, S<:NumberNotSeries}
241
            @inbounds aux = $f(a[0][1], b)
161✔
242
            R = TS.numtype(aux)
161✔
243
            coeffs = FixedSizeVectorDefault{HomogeneousPolynomial{Taylor1{R}}}(
322✔
244
                    undef, get_order(a)+1)
245
            coeffs .= a.coeffs
271✔
246
            @inbounds coeffs[1] = aux
161✔
247
            return TaylorN(coeffs, get_order(a))
161✔
248
        end
249

250
        function ($f)(b::S, a::TaylorN{Taylor1{T}}) where
467✔
251
                {T<:NumberNotSeries, S<:NumberNotSeries}
252
            @inbounds aux = $f(b, a[0][1])
467✔
253
            R = TS.numtype(aux)
467✔
254
            coeffs = FixedSizeVectorDefault{HomogeneousPolynomial{Taylor1{R}}}(
934✔
255
                    undef, get_order(a)+1)
256
            coeffs .= $f.(a.coeffs)
934✔
257
            @inbounds coeffs[1] = aux
467✔
258
            return TaylorN(coeffs, get_order(a))
467✔
259
        end
260

261
        function ($f)(a::TaylorN{Taylor1{T}}, b::Taylor1{S}) where
30✔
262
                {T<:NumberNotSeries, S<:NumberNotSeries}
263
            @inbounds aux = $f(a[0][1], b)
30✔
264
            R = TS.numtype(aux)
30✔
265
            coeffs = FixedSizeVectorDefault{HomogeneousPolynomial{Taylor1{R}}}(undef, get_order(a)+1)
60✔
266
            coeffs .= a.coeffs
47✔
267
            @inbounds coeffs[1] = aux
30✔
268
            return TaylorN(coeffs, get_order(a))
30✔
269
        end
270

271
        function ($f)(b::Taylor1{S}, a::TaylorN{Taylor1{T}}) where
20✔
272
                {T<:NumberNotSeries, S<:NumberNotSeries}
273
            @inbounds aux = $f(b, a[0][1])
20✔
274
            R = TS.numtype(aux)
20✔
275
            coeffs = FixedSizeVectorDefault{HomogeneousPolynomial{Taylor1{R}}}(undef, get_order(a)+1)
40✔
276
            coeffs .= $f.(a.coeffs)
40✔
277
            @inbounds coeffs[1] = aux
20✔
278
            return TaylorN(coeffs, get_order(a))
20✔
279
        end
280

281
        function ($f)(a::Taylor1{TaylorN{T}}, b::S) where
465✔
282
                {T<:NumberNotSeries, S<:NumberNotSeries}
283
            @inbounds aux = ($f)(a[0][0][1], b)
465✔
284
            c = Taylor1( TaylorN(a[0].space, zero(aux), get_order(a[0])), get_order(a))
465✔
285
            for k in eachindex(a)
465✔
286
                ($fc)(c, a, b, k)
2,560✔
287
            end
4,655✔
288
            return c
465✔
289
        end
290

291
        function ($f)(b::S, a::Taylor1{TaylorN{T}}) where
687✔
292
                {T<:NumberNotSeries, S<:NumberNotSeries}
293
            @inbounds aux = ($f)(b, a[0][0][1])
687✔
294
            c = Taylor1( TaylorN(a[0].space, zero(aux), get_order(a[0])), get_order(a))
687✔
295
            for k in eachindex(a)
687✔
296
                ($fc)(c, b, a, k)
3,828✔
297
            end
6,969✔
298
            return c
687✔
299
        end
300

301
        function ($f)(a::Taylor1{TaylorN{T}}, b::TaylorN{S}) where
20✔
302
                {T<:NumberNotSeries, S<:NumberNotSeries}
303
            _check_same_space(a[0], b)
20✔
304
            @inbounds aux = $f(a[0], b)
20✔
305
            c = Taylor1( zero(aux), get_order(a))
20✔
306
            for k in eachindex(a)
20✔
307
                ($fc)(c, a, b, k)
100✔
308
            end
180✔
309
            return c
20✔
310
        end
311

312
        function ($f)(b::TaylorN{S}, a::Taylor1{TaylorN{T}}) where
210✔
313
                {T<:NumberNotSeries,S<:NumberNotSeries}
314
            _check_same_space(b, a[0])
210✔
315
            @inbounds aux = $f(b, a[0])
210✔
316
            c = Taylor1( zero(aux), get_order(a))
210✔
317
            for k in eachindex(a)
210✔
318
                ($fc)(c, a, b, k)
1,260✔
319
            end
2,310✔
320
            return c
210✔
321
        end
322

323
    end
324
end
325

326
for (f, fc) in ((:+, :(add!)), (:-, :(subst!)))
327
    @eval begin
328
        function ($f)(a::Taylor1{TaylorN{T}}, b::Taylor1{TaylorN{T}}) where
1,808✔
329
                {T<:NumberNotSeries}
330
            _check_same_space(a[0], b[0])
1,808✔
331
            if get_order(a) != get_order(b) ||
3,606✔
332
                    any(get_order.(a.coeffs) .!= get_order.(b.coeffs))
333
                a, b = fixorder(a, b)
20✔
334
            end
335
            c = zero(a)
1,808✔
336
            for k in eachindex(a)
1,808✔
337
                ($fc)(c, a, b, k)
9,866✔
338
            end
17,924✔
339
            return c
1,808✔
340
        end
341
        function ($fc)(v::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}},
10,286✔
342
                b::Taylor1{TaylorN{T}}, k::Int) where {T<:NumberNotSeries}
343
            @inbounds for i in eachindex(v[k])
10,286✔
344
                for j in eachindex(v[k][i])
69,088✔
345
                    v[k][i][j] = ($f)(a[k][i][j], b[k][i][j])
274,926✔
346
                end
480,764✔
347
            end
127,890✔
348
            return nothing
10,286✔
349
        end
350
        function ($fc)(v::Taylor1{TaylorN{T}}, a::NumberNotSeries,
3,868✔
351
                b::Taylor1{TaylorN{T}}, k::Int) where {T<:NumberNotSeries}
352
            @inbounds for i in eachindex(v[k])
3,868✔
353
                aaa = ifelse(k == 0 && i == 0, a, zero(a))
22,188✔
354
                for j in eachindex(v[k][i])
22,188✔
355
                    v[k][i][j] = ($f)(aaa, b[k][i][j])
85,668✔
356
                end
149,148✔
357
            end
40,508✔
358
            return nothing
3,868✔
359
        end
360
        function ($fc)(v::Taylor1{TaylorN{T}}, b::Taylor1{TaylorN{T}},
3,010✔
361
                a::NumberNotSeries, k::Int) where {T<:NumberNotSeries}
362
            @inbounds for i in eachindex(v[k])
3,010✔
363
                aaa = ifelse(k == 0 && i == 0, a, zero(a))
18,382✔
364
                for j in eachindex(v[k][i])
18,382✔
365
                    v[k][i][j] = ($f)(b[k][i][j], aaa)
70,764✔
366
                end
123,146✔
367
            end
33,754✔
368
            return nothing
3,010✔
369
        end
370
        function ($fc)(v::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}},
1,470✔
371
                k::Int) where {T<:NumberNotSeries}
372
            @inbounds for l in eachindex(v[k])
1,470✔
373
                for m in eachindex(v[k][l])
10,050✔
374
                    v[k][l][m] = ($f)(a[k][l][m])
40,080✔
375
                end
70,110✔
376
            end
18,630✔
377
            return nothing
1,470✔
378
        end
379
    end
380
end
381

382

383
for T in (:Taylor1, :TaylorN)
384
    @eval begin
385
        function sum!(v::$T{S}, a::AbstractArray{$T{S}}) where {S <: Number}
×
386
            for i in eachindex(a)
×
387
                for k in eachindex(v)
×
388
                    add!(v, v, a[i], k)
×
389
                end
×
390
            end
×
391
            return nothing
×
392
        end
393
    end
394
end
395

396
function sum!(v::TaylorN{S}, a::AbstractArray{HomogeneousPolynomial{S}}) where {S <: Number}
×
397
    for i in eachindex(a)
×
398
        for k in eachindex(v)
×
399
            add!(v, v, a[i], k)
×
400
        end
×
401
    end
×
402
    return nothing
×
403
end
404

405

406

407
## Multiplication ##
408
for T in (:Taylor1, :TaylorN)
409
    @eval begin
410
        function *(a::T, b::$T{S}) where {T<:NumberNotSeries, S<:NumberNotSeries}
7,923✔
411
            v = $T( a * b[0], get_order(b))
16,379✔
412
            @inbounds for k in eachindex(v)
13,067✔
413
                mul!(v, b, a, k)
1,169,417✔
414
            end
158,903✔
415
            return v
13,067✔
416
        end
417
        *(b::$T{S}, a::T) where {T<:NumberNotSeries, S<:NumberNotSeries} = a * b
17,859✔
418
        function *(a::T, b::$T{T}) where {T<:NumberNotSeries}
435,343✔
419
            v = $T( a * b[0], get_order(b))
702,815✔
420
            @inbounds for k in eachindex(v)
459,948✔
421
                mul!(v, b, a, k)
52,177,318✔
422
            end
4,894,702✔
423
            return v
459,948✔
424
        end
425
        *(b::$T{T}, a::T) where {T<:NumberNotSeries} = a * b
147,623✔
426
    end
427
end
428

429
*(a::T, b::HomogeneousPolynomial{S}) where {T<:NumberNotSeries,
23,522✔
430
    S<:NumberNotSeries} = HomogeneousPolynomial(b.space, a * b.coeffs, get_order(b))
431
*(b::HomogeneousPolynomial{S}, a::T) where {T<:NumberNotSeries,
57✔
432
    S<:NumberNotSeries} = a * b
433
*(a::T, b::HomogeneousPolynomial{T}) where {T<:NumberNotSeries} =
428,013✔
434
    HomogeneousPolynomial(b.space, a * b.coeffs, get_order(b))
435
*(b::HomogeneousPolynomial{T}, a::T) where {T<:NumberNotSeries} = a * b
190✔
436

437
for T in (:HomogeneousPolynomial, :TaylorN)
438
    @eval begin
439
        *(a::T, b::$T{Taylor1{S}}) where {T<:NumberNotSeries,
936✔
440
            S<:NumberNotSeries} = $T( a .* b.coeffs, get_order(b))
441
        *(b::$T{Taylor1{S}}, a::T) where {T<:NumberNotSeries,
×
442
            S<:NumberNotSeries} = a * b
443
        *(a::T, b::Taylor1{$T{S}}) where {T<:NumberNotSeries,
697✔
444
            S<:NumberNotSeries} = Taylor1(a .* b.coeffs)
445
        *(b::Taylor1{$T{S}}, a::T) where
31✔
446
            {T<:NumberNotSeries, S<:NumberNotSeries} = a * b
447
        *(a::Taylor1{T}, b::$T{Taylor1{S}}) where
1,346✔
448
            {T<:NumberNotSeries, S<:NumberNotSeries} = $T(a .* b.coeffs, get_order(b))
449
        *(b::$T{Taylor1{R}}, a::Taylor1{T}) where
30✔
450
            {T<:NumberNotSeries, R<:NumberNotSeries} = a * b
451
        *(a::$T{T}, b::Taylor1{$T{S}}) where {T<:NumberNotSeries,
884✔
452
            S<:NumberNotSeries} = Taylor1(a .* b.coeffs)
453
        *(b::Taylor1{$T{S}}, a::$T{T}) where {T<:NumberNotSeries,
10✔
454
            S<:NumberNotSeries} = a * b
455
    end
456
end
457

458
for (T, W) in ((:Taylor1, :Number), (:TaylorN, :NumberNotSeriesN))
459
    @eval function *(a::$T{T}, b::$T{T}) where {T<:$W}
117,197✔
460
        if $T == TaylorN
117,197✔
461
            _check_same_space(a, b)
8,538✔
462
        end
463
        if get_order(a) != get_order(b)
117,187✔
464
            a, b = fixorder(a, b)
44,212✔
465
        end
466
        c = zero(a)
117,187✔
467
        for ord in eachindex(c)
117,187✔
468
            if $T == TaylorN
1,290,857✔
469
                _muladd_unchecked!(c, a, b, ord) # updates c[ord]
351,185✔
470
            else
471
                mul!(c, a, b, ord) # updates c[ord]
8,750,399✔
472
            end
473
        end
2,464,527✔
474
        return c
117,187✔
475
    end
476
end
477

478
function *(a::T, b::Taylor1{Taylor1{T}}) where {T<:NumberNotSeriesN}
40✔
479
    v = Taylor1( a * b[0], get_order(b))
166✔
480
    @inbounds for k in eachindex(v)
40✔
481
        mul!(v, b, a, k)
3,324✔
482
    end
1,400✔
483
    return v
40✔
484
end
485
*(b::Taylor1{Taylor1{T}}, a::T) where {T<:NumberNotSeriesN} = a * b
10✔
486

487
function *(a::Taylor1{T}, b::Taylor1{Taylor1{T}}) where {T<:NumberNotSeriesN}
694✔
488
    v = Taylor1( a * b[0], get_order(b))
694✔
489
    @inbounds for k in eachindex(v)
694✔
490
        mul!(v, b, a, k)
36,948✔
491
    end
13,296✔
492
    return v
694✔
493
end
494
*(b::Taylor1{Taylor1{T}}, a::Taylor1{T}) where {T<:NumberNotSeriesN} = a * b
10✔
495

496

497
*(a::HomogeneousPolynomial{T}, b::HomogeneousPolynomial{S}) where
10✔
498
    {T<:NumberNotSeriesN,S<:NumberNotSeriesN} = *(promote(a,b)...)
499

500
function *(a::HomogeneousPolynomial{T}, b::HomogeneousPolynomial{T}) where
150✔
501
        {T<:NumberNotSeriesN}
502
    _check_same_space(a, b)
150✔
503
    order = get_order(a) + get_order(b)
150✔
504
    # NOTE: the following returns order 0, but could be get_order(), or get_order(a)
505
    order > get_order(a.space) && return HomogeneousPolynomial(a.space, zero(a[1]), get_order(a))
150✔
506
    res = HomogeneousPolynomial(a.space, zero(a[1]), order)
140✔
507
    mul!(res, a, b)
280✔
508
    return res
140✔
509
end
510

511
function *(a::Taylor1{TaylorN{T}}, b::Taylor1{TaylorN{S}}) where
10✔
512
        {T<:NumberNotSeries, S<:NumberNotSeries}
513
    R = promote_type(T,S)
10✔
514
    return *(convert(Taylor1{TaylorN{R}}, a), convert(Taylor1{TaylorN{R}}, b))
10✔
515
end
516

517
function *(a::Taylor1{TaylorN{T}}, b::Taylor1{TaylorN{T}}) where {T<:NumberNotSeries}
945✔
518
    _check_same_space(a[0], b[0])
945✔
519
    if (get_order(a) != get_order(b)) || any(get_order.(a.coeffs) .!= get_order.(b.coeffs))
1,814✔
520
        a, b = fixorder(a, b)
76✔
521
    end
522
    res = zero(a)
945✔
523
    for ordT in eachindex(a)
945✔
524
        _mul_unchecked!(res, a, b, ordT)
4,608✔
525
    end
8,271✔
526
    return res
945✔
527
end
528

529

530
# Internal multiplication functions
531
function mul!(c::Taylor1{T}, a::Taylor1{T}, b::Taylor1{T}, k::Int) where
3,447,787✔
532
        {T<:NumberNotSeries}
533
    zero!(c, k)
11,551,820✔
534
    muladd!(c, a, b, k)
69,060,458✔
535
    return nothing
11,551,820✔
536
end
537
function mul!(v::Taylor1{T}, a::Taylor1{S}, b::NumberNotSeries, k::Int) where
8,066,221✔
538
        {T<:NumberNotSeries, S<:NumberNotSeries}
539
    @inbounds v[k] = a[k] * b
26,886,660✔
540
    return nothing
26,886,660✔
541
end
542
mul!(v::Taylor1{T}, a::NumberNotSeries, b::Taylor1{S}, k::Int) where
9,126,272✔
543
        {T<:NumberNotSeries, S<:NumberNotSeries} = mul!(v, b, a, k)
544
#
545
function muladd!(c::Taylor1{T}, a::Taylor1{T}, b::Taylor1{T}, k::Int) where
33,357,321✔
546
        {T<:NumberNotSeries}
547
    @inbounds for i = 0:k
111,181,872✔
548
        c[k] += a[i] * b[k-i]
616,910,418✔
549
    end
1,122,638,964✔
550
    return nothing
111,181,872✔
551
end
552

553
function muladd!(c::Taylor1{T}, a::Taylor1{T}, b::Taylor1{T}) where
4,080✔
554
        {T<:NumberNotSeries}
555
    for k in eachindex(c)
4,080✔
556
        muladd!(c, a, b, k)
230,880✔
557
    end
72,480✔
558
    return nothing
4,080✔
559
end
560

561
# function muladd!(v::Taylor1{T}, a::Taylor1{T}, b::NumberNotSeries, k::Int) where
562
#         {T<:NumberNotSeries}
563
#     @inbounds v[k] += a[k] * b
564
#     return nothing
565
# end
566
# muladd!(v::Taylor1{T}, a::NumberNotSeries, b::Taylor1{T}, k::Int) where
567
#         {T<:NumberNotSeries} = muladd!(v, b, a, k)
568
# Implements c[k] = scalar \sum_i a[i] b[k-i]
569
function mul_scalar!(c::Taylor1{T}, scalar::NumberNotSeries, a::Taylor1{T},
9,120,092✔
570
        b::Taylor1{T}, k::Int) where {T<:NumberNotSeries}
571
    mul!(c, a, b, k)
37,759,064✔
572
    mul!(c, scalar, c, k)
9,122,612✔
573
    return nothing
9,122,612✔
574
end
575

576
# NOTE: For TaylorN, `mul!` (`muladd!`) *accumulates* the result of a * b in c[k]
577
mul!(c::TaylorN{T}, a::TaylorN{T}, b::TaylorN{T}, k::Int) where
173,002✔
578
        {T<:Number} = muladd!(c, a, b, k)
579
function mul!(v::TaylorN, a::TaylorN, b::NumberNotSeries, k::Int)
3,279,459✔
580
    _check_same_space(v, a)
10,024,304✔
581
    @inbounds for i in eachindex(v[k])
10,024,304✔
582
        v[k][i] = a[k][i] * b
202,245,757✔
583
    end
394,467,210✔
584
    return nothing
10,024,304✔
585
end
586
mul!(v::TaylorN{T}, a::NumberNotSeries, b::TaylorN{T}, k::Int) where
60,633,470✔
587
    {T<:Number} = mul!(v, b, a, k)
588
#
589
function muladd!(c::TaylorN{T}, a::TaylorN{T}, b::TaylorN{T},
173,002✔
590
        k::Int) where {T<:Number}
591
    _check_same_space(c, a, b)
173,002✔
592
    _muladd_unchecked!(c, a, b, k)
734,052✔
593
    return nothing
173,002✔
594
end
595
function muladd!(v::TaylorN, a::TaylorN, b::NumberNotSeries, k::Int)
133,441✔
596
    _check_same_space(v, a)
439,950✔
597
    @inbounds for i in eachindex(v[k])
439,950✔
598
        v[k][i] += a[k][i] * b
4,106,460✔
599
    end
7,772,970✔
600
    return nothing
439,950✔
601
end
602
muladd!(v::TaylorN, a::NumberNotSeries, b::TaylorN, k::Int) = muladd!(v, b, a, k)
3,000,123✔
603
function mul_scalar!(c::TaylorN{T}, scalar::NumberNotSeries, a::TaylorN{T},
110,040✔
604
        b::TaylorN{T}, k::Int) where {T<:Number}
605
    _check_same_space(c, a, b)
110,040✔
606
    _mul_scalar_unchecked!(c, scalar, a, b, k)
345,840✔
607
    return nothing
110,040✔
608
end
609

610
# Nested Taylor1s
611
function mul!(c::Taylor1{Taylor1{T}}, a::Taylor1{Taylor1{T}}, b::Taylor1{Taylor1{T}},
1,740,767✔
612
        k::Int) where {T<:NumberNotSeriesN}
613
    @inbounds for j in eachindex(c[k])
1,740,767✔
614
        zero!(c[k], j)
17,398,964✔
615
        for i = 0:k
17,398,586✔
616
            muladd!(c[k], a[i], b[k-i], j)
526,300,249✔
617
        end
174,040,152✔
618
    end
33,056,405✔
619
    return nothing
1,740,767✔
620
end
621
mul!(v::Taylor1{Taylor1{T}}, a::Taylor1{T}, b::Taylor1{Taylor1{T}}, k::Int) where
×
622
        {T<:NumberNotSeriesN} = mul!(v, b, a, k)
623
function mul!(v::Taylor1{Taylor1{T}}, a::Taylor1{Taylor1{T}}, b::Taylor1{T}, k::Int) where
5,587✔
624
        {T<:NumberNotSeriesN}
625
    @inbounds for i in eachindex(v[k])
6,995✔
626
        mul!(v[k], a[k], b, i)
197,580✔
627
    end
122,497✔
628
    return nothing
6,995✔
629
end
630
mul!(v::Taylor1{Taylor1{T}}, a::NumberNotSeries, b::Taylor1{Taylor1{T}}, k::Int) where
260✔
631
        {T<:NumberNotSeriesN} = mul!(v, b, a, k)
632
function mul!(v::Taylor1{Taylor1{T}}, a::Taylor1{Taylor1{T}}, b::NumberNotSeries,
554✔
633
        k::Int) where {T<:NumberNotSeriesN}
634
    @inbounds for i in eachindex(v[k])
1,240✔
635
        mul!(v[k], a[k], b, i)
8,080✔
636
    end
14,920✔
637
    return nothing
1,240✔
638
end
639
function muladd!(c::Taylor1{Taylor1{T}}, a::Taylor1{Taylor1{T}},
189✔
640
        b::Taylor1{Taylor1{T}}, k::Int) where {T<:NumberNotSeriesN}
641
    @inbounds for j in eachindex(c[k])
189✔
642
        for i = 0:k
756✔
643
            muladd!(c[k], a[i], b[k-i], j)
3,780✔
644
        end
2,268✔
645
    end
1,323✔
646
    return nothing
189✔
647
end
648
# muladd!(v::Taylor1{Taylor1{T}}, a::Taylor1{T}, b::Taylor1{Taylor1{T}}, k::Int) where
649
#         {T<:NumberNotSeriesN} = muladd!(v, b, a, k)
650
# function muladd!(v::Taylor1{Taylor1{T}}, a::Taylor1{Taylor1{T}}, b::Taylor1{T}, k::Int) where
651
#         {T<:NumberNotSeriesN}
652
#     @inbounds for i in eachindex(v[k])
653
#         muladd!(v[k], a[k], b, i)
654
#     end
655
#     return nothing
656
# end
657
# function muladd!(v::Taylor1{Taylor1{T}}, a::Taylor1{Taylor1{T}}, b::T, k::Int) where
658
#         {T<:NumberNotSeriesN}
659
#     @inbounds for i in eachindex(v[k])
660
#         muladd!(v[k], a[k], b, i)
661
#     end
662
#     return nothing
663
# end
664
# muladd!(v::Taylor1{Taylor1{T}}, a::T, b::Taylor1{Taylor1{T}}, k::Int) where
665
#     {T<:NumberNotSeriesN} = muladd!(v, b, a, k)
666
function mul_scalar!(c::Taylor1{Taylor1{T}}, scalar::NumberNotSeries,
515,100✔
667
        a::Taylor1{Taylor1{T}}, b::Taylor1{Taylor1{T}}, k::Int) where {T<:Number}
668
    mul!(c, a, b, k)
1,717,000✔
669
    # c[k] <- scalar * c[k]
670
    for ord in eachindex(c[k])
1,717,000✔
671
        mul!(c[k], c[k], scalar, ord)
17,170,000✔
672
    end
32,623,000✔
673
    return nothing
1,717,000✔
674
end
675

676

677
# for T in (:Taylor1, :TaylorN)
678
#     @eval begin
679
#         function mul!(v::$T{T}, a::$T{T}, b::NumberNotSeries) where {T<:Number}
680
#             for k in eachindex(v)
681
#                 mul!(v, a, b, k)
682
#             end
683
#             return nothing
684
#         end
685
#         mul!(v::$T{T}, a::NumberNotSeries, b::$T{T}) where {T<:Number} = mul!(v, b, a)
686
#     end
687
# end
688

689
# in-place product: `a` <- `a*b`
690
# this method computes the product `a*b` and saves it back into `a`
691
# assumes `a` and `b` are of same order
692
function mul!(a::TaylorN{T}, b::TaylorN{T}) where {T<:Number}
141,194✔
693
    @inbounds for k in reverse(eachindex(a))
282,378✔
694
        mul!(a, a, b[0][1], k)
18,788,561✔
695
        for l in 1:k
2,243,574✔
696
            mul!(a[k], a[k-l], b[l])
23,279,510✔
697
        end
35,070,760✔
698
    end
4,345,954✔
699
    return nothing
141,194✔
700
end
701
function mul!(a::Taylor1{T}, b::Taylor1{T}) where {T<:NumberNotSeries}
90✔
702
    @inbounds for k in reverse(eachindex(a))
180✔
703
        # a[k] <- a[k]*b[0]
704
        mul!(a, a, b[0], k)
890✔
705
        for l in 1:k
890✔
706
            # a[k] <- a[k] + a[k-l] * b[l]
707
            a[k] += a[k-l] * b[l]
4,150✔
708
        end
7,500✔
709
    end
1,690✔
710
    return nothing
90✔
711
end
712
function mul!(a::Taylor1{TaylorN{T}}, b::Taylor1{TaylorN{T}}) where
×
713
        {T<:NumberNotSeries}
714
    @inbounds for k in reverse(eachindex(a))
×
715
        mul!(a, a, b[0], k)
×
716
        for l in 1:k
×
717
            # a[k] += a[k-l] * b[l]
718
            for m in eachindex(a[k])
×
719
                mul!(a[k], a[k-l], b[l], m)
×
720
            end
×
721
        end
×
722
    end
×
723
    return nothing
×
724
end
725
function mul!(a::Taylor1{Taylor1{T}}, b::Taylor1{Taylor1{T}}) where
×
726
        {T<:NumberNotSeriesN}
727
    @inbounds for k in reverse(eachindex(a))
×
728
        # a[k] <- a[k]*b[0]
729
        mul!(a, a, b[0], k)
×
730
        for l in 1:k
×
731
            # a[k] <- a[k] + a[k-l] * b[l]
732
            for m in eachindex(a[k])
×
733
                muladd!(a[k], a[k-l], b[l], m)
×
734
            end
×
735
        end
×
736
    end
×
737
    return nothing
×
738
end
739

740
function _mul_unchecked!(res::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}},
5,268✔
741
        b::Taylor1{TaylorN{T}}, ordT::Int) where {T<:NumberNotSeries}
742
    zero!(res, ordT)
5,268✔
743
    for k in 0:ordT
5,268✔
744
        @inbounds for ordQ in eachindex(a[ordT])
16,883✔
745
            _muladd_unchecked!(res[ordT], a[k], b[ordT-k], ordQ)
344,392✔
746
        end
207,215✔
747
    end
28,498✔
748
    return nothing
5,268✔
749
end
750

751
function mul!(res::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}},
198✔
752
        b::Taylor1{TaylorN{T}}, ordT::Int) where {T<:NumberNotSeries}
753
    _check_same_space(res[0], a[0], b[0])
660✔
754
    _mul_unchecked!(res, a, b, ordT)
660✔
755
    return nothing
660✔
756
end
757

758
function mul!(res::Taylor1{TaylorN{T}}, a::NumberNotSeries,
600✔
759
        b::Taylor1{TaylorN{T}}, k::Int) where {T<:NumberNotSeries}
760
    for l in eachindex(b[k])
600✔
761
        for m in eachindex(b[k][l])
4,200✔
762
            res[k][l][m] = a*b[k][l][m]
16,800✔
763
        end
29,400✔
764
    end
7,800✔
765
    return nothing
600✔
766
end
767
mul!(res::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}}, b::NumberNotSeries,
×
768
    k::Int) where {T<:NumberNotSeries} = mul!(res, b, a, k)
769

770

771
# in-place product (assumes equal order among TaylorNs)
772
# NOTE: the result of the product is *accumulated* in c[k]
773
function mul!(c::Taylor1{T}, a::Taylor1{T}, b::Taylor1{T}) where {T<:Number}
96,250✔
774
    for k in eachindex(c)
96,250✔
775
        mul!(c, a, b, k)
3,952,727✔
776
    end
1,213,496✔
777
end
778

779
function mul!(c::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}},
×
780
        b::Taylor1{TaylorN{T}}) where {T<:NumberNotSeries}
781
    _check_same_space(c[0], a[0], b[0])
×
782
    for k in eachindex(c)
×
783
        _mul_unchecked!(c, a, b, k)
×
784
    end
×
785
    return nothing
×
786
end
787

788
function mul!(c::TaylorN{T}, a::TaylorN{T}, b::TaylorN{T}) where {T<:NumberNotSeriesN}
2,550✔
789
    _check_same_space(c, a, b)
2,550✔
790
    for k in eachindex(c)
2,550✔
791
        _muladd_unchecked!(c, a, b, k)
56,100✔
792
    end
17,850✔
793
end
794

795
# function muladd!(c::Taylor1{T}, a::Taylor1{T}, b::Taylor1{T}) where {T<:Number}
796
#     for k in eachindex(c)
797
#         muladd!(c, a, b, k)
798
#     end
799
# end
800
#
801
# function mul_scalar!(c::Taylor1{T}, scalar::NumberNotSeries, a::Taylor1{T},
802
#         b::Taylor1{T}) where {T<:Number}
803
#     for k in eachindex(c)
804
#         mul_scalar!(c, scalar, a, b, k)
805
#     end
806
# end
807

808
function mul_scalar!(c::TaylorN{T}, scalar::NumberNotSeries, a::TaylorN{T},
3,540✔
809
        b::TaylorN{T}) where {T<:NumberNotSeriesN}
810
    _check_same_space(c, a, b)
3,540✔
811
    for k in eachindex(c)
3,540✔
812
        _mul_scalar_unchecked!(c, scalar, a, b, k)
77,880✔
813
    end
24,780✔
814
end
815

816

817
@doc doc"""
818
    mul!(c, a, b, k::Int) --> nothing
819

820
Update the `k`-th expansion coefficient `c[k]` of `c = a * b`,
821
where all `c`, `a`, and `b` are either `Taylor1` or `TaylorN`.
822
Note that for `TaylorN` the result of `a * b` is accumulated in `c[k]`.
823

824
The coefficients are given by
825

826
```math
827
c_k = \sum_{j=0}^k a_j b_{k-j}.
828
```
829

830
""" mul!
831

832

833
@inline function _check_homogeneous_product_order(c::HomogeneousPolynomial,
9,142,242✔
834
        a::HomogeneousPolynomial, b::HomogeneousPolynomial)
835
    get_order(c) == get_order(a) + get_order(b) ||
30,163,898✔
836
        throw(DimensionMismatch("result homogeneous degree must equal the sum of input degrees"))
837
    return nothing
30,163,898✔
838
end
839

840
@inline function _muladd_scalar_unchecked!(c::HomogeneousPolynomial, scalar,
146,715✔
841
        a::HomogeneousPolynomial)
842
    _isthinzero(scalar) && return nothing
461,911✔
843
    @inbounds for i in eachindex(c)
458,705✔
844
        ai = a[i]
15,180,870✔
845
        _isthinzero(ai) && continue
15,190,923✔
846
        c[i] += scalar * ai
1,952,472✔
847
    end
29,903,035✔
848
    return nothing
458,705✔
849
end
850

851
@inline function _mul_unchecked!(c::HomogeneousPolynomial, a::HomogeneousPolynomial,
492,795✔
852
        b::HomogeneousPolynomial)
853
    (_isthinzero(b) || _isthinzero(a)) && return nothing
1,875,360✔
854
    degree_a = get_order(a)
72,298✔
855
    degree_b = get_order(b)
72,298✔
856
    degree_a == 0 && return _muladd_scalar_unchecked!(c, a[1], b)
72,298✔
857
    degree_b == 0 && return _muladd_scalar_unchecked!(c, b[1], a)
57,045✔
858

859
    order_a = degree_a+1
56,415✔
860
    order_b = degree_b+1
56,415✔
861
    sp = c.space
56,415✔
862
    @inbounds num_coeffs_a = sp.size_table[order_a]
56,415✔
863
    @inbounds num_coeffs_b = sp.size_table[order_b]
56,415✔
864
    input_positions = _product_table(sp, order_a, order_b).input_positions
60,275✔
865
    pair = 1
56,415✔
866
    @inbounds for na in 1:num_coeffs_a
56,415✔
867
        ca = a[na]
2,010,132✔
868
        if _isthinzero(ca)
2,022,970✔
869
            pair += num_coeffs_b
112,344✔
870
            continue
112,344✔
871
        end
872
        @inbounds for nb in 1:num_coeffs_b
1,897,788✔
873
            cb = b[nb]
1,158,383,940✔
874
            if !_isthinzero(cb)
1,158,402,615✔
875
                pos = input_positions[pair]
1,158,200,220✔
876
                c[pos] += ca * cb
1,158,200,220✔
877
            end
878
            pair += 1
1,158,383,940✔
879
        end
1,158,383,940✔
880
    end
3,963,849✔
881
    return nothing
56,415✔
882
end
883

884
@inline function _mul_output_major_unchecked!(c::HomogeneousPolynomial{Float64},
×
885
        a::HomogeneousPolynomial{Float64}, b::HomogeneousPolynomial{Float64})
886
    (_isthinzero(b) || _isthinzero(a)) && return nothing
×
887
    degree_a = get_order(a)
×
888
    degree_b = get_order(b)
×
889
    degree_a == 0 && return _muladd_scalar_unchecked!(c, a[1], b)
×
890
    degree_b == 0 && return _muladd_scalar_unchecked!(c, b[1], a)
×
891

NEW
892
    table = _init_output_major_product_table!(c.space, degree_a+1, degree_b+1)
×
893
    offsets = table.output_offsets
×
894
    output_pairs = table.output_pairs
×
895
    num_right = table.num_right
×
896
    c_coeffs = c.coeffs
×
897
    a_coeffs = a.coeffs
×
898
    b_coeffs = b.coeffs
×
899
    @inbounds for pos in 1:length(offsets)-1
×
900
        acc = c_coeffs[pos]
×
901
        for csr_pos in offsets[pos]:(offsets[pos+1]-1)
×
902
            pair = Int(output_pairs[csr_pos]) - 1
×
903
            na = pair ÷ num_right + 1
×
904
            nb = pair - (na-1) * num_right + 1
×
905
            acc += a_coeffs[na] * b_coeffs[nb]
×
906
        end
×
907
        c_coeffs[pos] = acc
×
908
    end
×
909
    return nothing
×
910
end
911

912
@inline function _mul_unchecked!(c::HomogeneousPolynomial{Float64},
8,783,280✔
913
        a::HomogeneousPolynomial{Float64}, b::HomogeneousPolynomial{Float64})
914
    (_isthinzero(b) || _isthinzero(a)) && return nothing
38,950,069✔
915
    degree_a = get_order(a)
4,835,589✔
916
    degree_b = get_order(b)
4,835,589✔
917
    degree_a == 0 && return _muladd_scalar_unchecked!(c, a[1], b)
4,835,589✔
918
    degree_b == 0 && return _muladd_scalar_unchecked!(c, b[1], a)
4,595,989✔
919

920
    order_a = degree_a+1
4,521,337✔
921
    order_b = degree_b+1
4,521,337✔
922
    sp = c.space
4,521,337✔
923
    @inbounds num_coeffs_a = sp.size_table[order_a]
4,521,337✔
924
    @inbounds num_coeffs_b = sp.size_table[order_b]
4,521,337✔
925
    input_positions = _product_table(sp, order_a, order_b).input_positions
4,521,951✔
926
    pair = 1
4,521,337✔
927
    @inbounds for na in 1:num_coeffs_a
4,521,337✔
928
        ca = a[na]
34,623,624✔
929
        if iszero(ca)
34,623,624✔
930
            pair += num_coeffs_b
29,076,156✔
931
            continue
29,076,156✔
932
        end
933
        @inbounds for nb in 1:num_coeffs_b
5,547,468✔
934
            cb = b[nb]
79,344,380✔
935
            if !iszero(cb)
79,344,380✔
936
                pos = input_positions[pair]
9,855,262✔
937
                c[pos] += ca * cb
9,855,262✔
938
            end
939
            pair += 1
79,344,380✔
940
        end
79,344,380✔
941
    end
64,725,911✔
942
    return nothing
4,521,337✔
943
end
944

945
@inline function _mul_scalar_unchecked!(c::HomogeneousPolynomial,
7,782✔
946
        scalar::NumberNotSeries, a::HomogeneousPolynomial,
947
        b::HomogeneousPolynomial)
948
    (_isthinzero(scalar) || _isthinzero(b) || _isthinzero(a)) && return nothing
48,860✔
949
    degree_a = get_order(a)
6,180✔
950
    degree_b = get_order(b)
6,180✔
951
    degree_a == 0 && return _muladd_scalar_unchecked!(c, scalar * a[1], b)
6,180✔
952
    degree_b == 0 && return _muladd_scalar_unchecked!(c, scalar * b[1], a)
5,760✔
953

954
    order_a = degree_a+1
4,680✔
955
    order_b = degree_b+1
4,680✔
956
    sp = c.space
4,680✔
957
    @inbounds num_coeffs_a = sp.size_table[order_a]
4,680✔
958
    @inbounds num_coeffs_b = sp.size_table[order_b]
4,680✔
959
    input_positions = _product_table(sp, order_a, order_b).input_positions
4,820✔
960
    pair = 1
4,680✔
961
    @inbounds for na in 1:num_coeffs_a
4,680✔
962
        ca = a[na]
14,080✔
963
        if _isthinzero(ca)
16,220✔
964
            pair += num_coeffs_b
4,570✔
965
            continue
4,570✔
966
        end
967
        sca = scalar * ca
10,035✔
968
        @inbounds for nb in 1:num_coeffs_b
9,510✔
969
            cb = b[nb]
35,400✔
970
            if !_isthinzero(cb)
38,880✔
971
                pos = input_positions[pair]
21,430✔
972
                c[pos] += sca * cb
21,430✔
973
            end
974
            pair += 1
35,400✔
975
        end
35,400✔
976
    end
23,480✔
977
    return nothing
4,680✔
978
end
979

980
@inline function _mul_scalar_unchecked!(c::HomogeneousPolynomial{Float64},
565,152✔
981
        scalar::NumberNotSeries, a::HomogeneousPolynomial{Float64},
982
        b::HomogeneousPolynomial{Float64})
983
    (_isthinzero(scalar) || _isthinzero(b) || _isthinzero(a)) && return nothing
3,122,880✔
984
    degree_a = get_order(a)
437,270✔
985
    degree_b = get_order(b)
437,270✔
986
    degree_a == 0 && return _muladd_scalar_unchecked!(c, scalar * a[1], b)
437,270✔
987
    degree_b == 0 && return _muladd_scalar_unchecked!(c, scalar * b[1], a)
404,470✔
988

989
    order_a = degree_a+1
310,200✔
990
    order_b = degree_b+1
310,200✔
991
    sp = c.space
310,200✔
992
    @inbounds num_coeffs_a = sp.size_table[order_a]
310,200✔
993
    @inbounds num_coeffs_b = sp.size_table[order_b]
310,200✔
994
    input_positions = _product_table(sp, order_a, order_b).input_positions
312,061✔
995
    pair = 1
310,200✔
996
    @inbounds for na in 1:num_coeffs_a
310,200✔
997
        ca = a[na]
1,934,930✔
998
        if iszero(ca)
1,934,930✔
999
            pair += num_coeffs_b
443,170✔
1000
            continue
443,170✔
1001
        end
1002
        sca = scalar * ca
1,491,760✔
1003
        @inbounds for nb in 1:num_coeffs_b
1,491,760✔
1004
            cb = b[nb]
37,330,930✔
1005
            if !iszero(cb)
37,330,930✔
1006
                pos = input_positions[pair]
35,775,180✔
1007
                c[pos] += sca * cb
35,775,180✔
1008
            end
1009
            pair += 1
37,330,930✔
1010
        end
37,330,930✔
1011
    end
3,559,660✔
1012
    return nothing
310,200✔
1013
end
1014

1015
@inline function _muladd_unchecked!(c::TaylorN{T}, a::TaylorN{T},
111,624✔
1016
        b::TaylorN{T}, k::Int) where {T<:Number}
1017
    @inbounds _mul_unchecked!(c[k], a[0], b[k])
486,407✔
1018
    @inbounds for i = 1:k
370,169✔
1019
        _mul_unchecked!(c[k], a[i], b[k-i])
2,017,540✔
1020
    end
2,553,316✔
1021
    return nothing
370,169✔
1022
end
1023

1024
@inline function _mul_scalar_unchecked!(c::TaylorN{T}, scalar::NumberNotSeries,
40,446✔
1025
        a::TaylorN{T}, b::TaylorN{T}, k::Int) where {T<:Number}
1026
    @inbounds _mul_scalar_unchecked!(c[k], scalar, a[0], b[k])
269,290✔
1027
    @inbounds for i = 1:k
134,820✔
1028
        _mul_scalar_unchecked!(c[k], scalar, a[i], b[k-i])
807,870✔
1029
    end
693,360✔
1030
    return nothing
134,820✔
1031
end
1032

1033

1034
"""
1035
    mul!(c, a, b) --> nothing
1036

1037
Accumulates in `c` the result of `a*b` with minimum allocation. Arguments
1038
c, a and b are `HomogeneousPolynomial`.
1039

1040
"""
1041
@inline function mul!(c::HomogeneousPolynomial, a::HomogeneousPolynomial,
8,731,092✔
1042
        b::HomogeneousPolynomial)
1043
    _check_same_space(c, a, b)
29,093,398✔
1044
    _check_homogeneous_product_order(c, a, b)
29,093,398✔
1045
    _mul_unchecked!(c, a, b)
38,321,482✔
1046
    return nothing
29,093,398✔
1047
end
1048

1049

1050
"""
1051
    mul_scalar!(c, scalar, a, b) --> nothing
1052

1053
Accumulates in `c` the result of `scalar*a*b` with minimum allocation. Arguments
1054
c, a and b are `HomogeneousPolynomial`; `scalar` is a NumberNotSeries.
1055

1056
"""
1057
@inline function mul_scalar!(c::HomogeneousPolynomial, scalar::NumberNotSeries, a::HomogeneousPolynomial,
411,150✔
1058
        b::HomogeneousPolynomial)
1059
    _check_same_space(c, a, b)
1,070,500✔
1060
    _check_homogeneous_product_order(c, a, b)
1,070,500✔
1061
    _mul_scalar_unchecked!(c, scalar, a, b)
2,094,580✔
1062
    return nothing
1,070,500✔
1063
end
1064

1065

1066

1067
## Division ##
1068
function /(a::Taylor1{Rational{T}}, b::S) where {T<:Integer, S<:NumberNotSeries}
20✔
1069
    R = typeof( a[0] // b)
20✔
1070
    v = FixedSizeVectorDefault{R}(undef, get_order(a)+1)
40✔
1071
    v .= a.coeffs .// b
30✔
1072
    return Taylor1(v, get_order(a))
20✔
1073
end
1074

1075
for T in (:Taylor1, :HomogeneousPolynomial, :TaylorN)
1076
    @eval function /(a::$T{T}, b::S) where {T<:NumberNotSeries, S<:NumberNotSeries}
276,940✔
1077
        @inbounds aux = a.coeffs[1] / b
276,940✔
1078
        v = FixedSizeVectorDefault{typeof(aux)}(undef, length(a.coeffs))
553,880✔
1079
        v .= a.coeffs ./ b
551,820✔
1080
        if $T == HomogeneousPolynomial
276,940✔
1081
            return HomogeneousPolynomial(a.space, v, get_order(a))
23,890✔
1082
        end
1083
        return $T(v, get_order(a))
253,050✔
1084
    end
1085

1086
    # @eval function /(a::$T{T}, b::T) where {T<:Number}
1087
    #     @inbounds aux = a.coeffs[1] / b
1088
    #     c = $T( zero(aux), get_order(a) )
1089
    #     for ord in eachindex(c)
1090
    #         div!(c, a, b, ord) # updates c[ord]
1091
    #     end
1092
    #     return c
1093
    # end
1094
end
1095

1096
for T in (:HomogeneousPolynomial, :TaylorN)
1097
    @eval function /(b::$T{Taylor1{S}}, a::Taylor1{T}) where
200✔
1098
            {T<:NumberNotSeries, S<:NumberNotSeries}
1099
        @inbounds aux = b.coeffs[1] / a
200✔
1100
        R = typeof(aux)
200✔
1101
        coeffs = FixedSizeVectorDefault{R}(undef, length(b.coeffs))
397✔
1102
        coeffs .= b.coeffs ./ a
310✔
1103
        if $T == HomogeneousPolynomial
200✔
1104
            return HomogeneousPolynomial(b.space, coeffs, get_order(b))
190✔
1105
        end
1106
        return $T(coeffs, get_order(b))
10✔
1107
    end
1108

1109
    @eval function /(b::$T{Taylor1{T}}, a::S) where {T<:NumberNotSeries, S<:NumberNotSeries}
80✔
1110
        @inbounds aux = b.coeffs[1] / a
80✔
1111
        R = typeof(aux)
80✔
1112
        coeffs = FixedSizeVectorDefault{R}(undef, length(b.coeffs))
160✔
1113
        coeffs .= b.coeffs ./ a
160✔
1114
        if $T == HomogeneousPolynomial
80✔
1115
            return HomogeneousPolynomial(b.space, coeffs, get_order(b))
80✔
1116
        end
1117
        return $T(coeffs, get_order(b))
×
1118
    end
1119

1120
    @eval function /(b::Taylor1{$T{S}}, a::$T{T}) where
10✔
1121
            {T<:NumberNotSeries, S<:NumberNotSeries}
1122
        @inbounds aux = b[0] / a
10✔
1123
        v = Taylor1(zero(aux), get_order(b))
10✔
1124
        @inbounds for k in eachindex(b)
10✔
1125
            v[k] = b[k] / a
60✔
1126
        end
110✔
1127
        return v
10✔
1128
    end
1129
end
1130

1131
/(a::Taylor1{T}, b::Taylor1{S}) where {T<:Number, S<:Number} = /(promote(a,b)...)
540✔
1132

1133
function /(a::Taylor1{T}, b::Taylor1{T}) where {T<:Number}
148,810✔
1134
    iszero(a) && !iszero(b) && return zero(a)
148,810✔
1135
    if get_order(a) != get_order(b)
139,630✔
1136
        a, b = fixorder(a, b)
3,120✔
1137
    end
1138

1139
    # order and coefficient of first factorized term
1140
    ordfact, cdivfact = divfactorization(a, b)
139,630✔
1141
    R = typeof(cdivfact)
139,600✔
1142
    if R == T
139,600✔
1143
        aa = a
139,430✔
1144
        bb = b
139,430✔
1145
    else
1146
        aa = convert(Taylor1{R}, a)
170✔
1147
        bb = convert(Taylor1{R}, b)
170✔
1148
    end
1149
    c = Taylor1(cdivfact, get_order(a)-ordfact)
139,600✔
1150
    for ord in eachindex(c)
139,600✔
1151
        div!(c, aa, bb, ord) # updates c[ord]
1,243,720✔
1152
    end
2,347,840✔
1153

1154
    return c
139,600✔
1155
end
1156

1157
/(a::TaylorN{T}, b::TaylorN{S}) where
10✔
1158
    {T<:NumberNotSeriesN, S<:NumberNotSeriesN} = /(promote(a,b)...)
1159

1160
function /(a::TaylorN{T}, b::TaylorN{T}) where {T<:NumberNotSeriesN}
310✔
1161
    _check_same_space(a, b)
310✔
1162
    @assert !iszero(constant_term(b))
330✔
1163

1164
    if get_order(a) != get_order(b)
290✔
1165
        a, b = fixorder(a, b)
×
1166
    end
1167

1168
    # first coefficient
1169
    @inbounds cdivfact = a[0] / constant_term(b)
290✔
1170
    c = TaylorN(cdivfact, get_order(a))
493✔
1171
    for ord in eachindex(c)
290✔
1172
        div!(c, a, b, ord) # updates c[ord]
2,710✔
1173
    end
5,130✔
1174

1175
    return c
290✔
1176
end
1177

1178
function /(a::S, b::TaylorN{T}) where {S<:NumberNotSeriesN, T<:NumberNotSeriesN}
50✔
1179
    @assert !iszero(constant_term(b))
60✔
1180
    R = typeof(a / constant_term(b))
40✔
1181
    bb = convert(TaylorN{R}, b)
40✔
1182
    res = TaylorN(b.space, zero(R), get_order(b))
40✔
1183
    iszero(a) && !iszero(b) && return res
40✔
1184
    aa = convert(R, a)
40✔
1185
    for ord in eachindex(res)
40✔
1186
        div!(res, aa, bb, ord)
500✔
1187
    end
960✔
1188
    return res
40✔
1189
end
1190

1191
function /(a::Taylor1{TaylorN{T}}, b::Taylor1{TaylorN{T}}) where {T<:NumberNotSeries}
130✔
1192
    _check_same_space(a[0], b[0])
130✔
1193
    iszero(a) && !iszero(b) && return zero(a)
130✔
1194
    if (get_order(a) != get_order(b)) || any(get_order.(a.coeffs) .!= get_order.(b.coeffs))
250✔
1195
        a, b = fixorder(a, b)
10✔
1196
    end
1197
    # order and coefficient of first factorized term
1198
    ordfact, cdivfact = divfactorization(a, b)
130✔
1199
    R = numtype(cdivfact)
130✔
1200
    if R == T
130✔
1201
        aa = a
130✔
1202
        bb = b
130✔
1203
    else
1204
        aa = convert(Taylor1{TaylorN{R}}, a)
×
1205
        bb = convert(Taylor1{TaylorN{R}}, b)
×
1206
    end
1207
    res = Taylor1(cdivfact, get_order(a)-ordfact)
130✔
1208
    for ordT in eachindex(res)
130✔
1209
        div!(res, aa, bb, ordT)
760✔
1210
    end
1,390✔
1211
    return res
130✔
1212
end
1213

1214
function /(a::S, b::Taylor1{TaylorN{T}}) where {S<:NumberNotSeries, T<:NumberNotSeries}
50✔
1215
    R = promote_type(TaylorN{S}, TaylorN{T})
50✔
1216
    res = convert(Taylor1{R}, zero(b))
50✔
1217
    iszero(a) && !iszero(b) && return res
50✔
1218

1219
    for ordT in eachindex(res)
50✔
1220
        div!(res, a, b, ordT)
540✔
1221
    end
490✔
1222
    return res
50✔
1223
end
1224

1225
function /(a::TaylorN{T}, b::Taylor1{TaylorN{T}}) where {T<:NumberNotSeries}
10✔
1226
    res = zero(b)
10✔
1227
    iszero(a) && !iszero(b) && return res
10✔
1228

1229
    aa = Taylor1(a, get_order(b))
10✔
1230
    for ordT in eachindex(res)
10✔
1231
        div!(res, aa, b, ordT)
50✔
1232
    end
90✔
1233
    return res
10✔
1234
end
1235

1236
# @inline
1237
function divfactorization(a1::Taylor1, b1::Taylor1)
1,604,410✔
1238
    # order of first factorized term; a1 and b1 assumed to be of the same order
1239
    a1nz = findfirst(a1)
3,208,810✔
1240
    b1nz = findfirst(b1)
3,208,810✔
1241
    a1nz = a1nz ≥ 0 ? a1nz : get_order(a1)
1,604,420✔
1242
    b1nz = b1nz ≥ 0 ? b1nz : get_order(a1)
1,604,420✔
1243
    ordfact = min(a1nz, b1nz)
1,604,410✔
1244
    cdivfact = a1[ordfact] / b1[ordfact]
1,604,410✔
1245

1246
    # Is the polynomial factorizable?
1247
    TS._isthinzero(b1[ordfact]) && throw( ArgumentError(
1,604,480✔
1248
        """Division does not define a Taylor1 polynomial;
1249
        order k=$(ordfact) => coeff[$(ordfact)]=$(cdivfact).""") )
1250

1251
    return ordfact, cdivfact
1,604,380✔
1252
end
1253

1254

1255
## TODO: Implement factorization (divfactorization) for TaylorN polynomials
1256

1257

1258
# Homogeneous coefficient for the division
1259
@doc doc"""
1260
    div!(c, a, b, k::Int)
1261

1262
Compute the `k-th` expansion coefficient `c[k]` of `c = a / b`,
1263
where all `c`, `a` and `b` are either `Taylor1` or `TaylorN`.
1264

1265
The coefficients are given by
1266

1267
```math
1268
c_k =  \frac{1}{b_0} \big(a_k - \sum_{j=0}^{k-1} c_j b_{k-j}\big).
1269
```
1270

1271
For `Taylor1` polynomials, a similar formula is implemented which
1272
exploits `k_0`, the order of the first non-zero coefficient of `a`.
1273
""" div!
1274

1275
# @inline
1276
function div!(c::Taylor1{T}, a::Taylor1{T}, b::Taylor1{T}, k::Int) where
2,560,460✔
1277
        {T<:NumberNotSeries}
1278
    zero!(c, k)
2,560,460✔
1279
    iszero(a) && !iszero(b) && return nothing
2,560,460✔
1280
    # order and coefficient of first factorized term
1281
    ordfact, cdivfact = divfactorization(a, b)
1,358,040✔
1282
    if k == 0
1,358,040✔
1283
        @inbounds c[0] = cdivfact
151,570✔
1284
        return nothing
151,570✔
1285
    end
1286
    b_order = get_order(b)
1,206,470✔
1287
    imin = max(0, k+ordfact-b_order)
1,206,470✔
1288
    @inbounds c[k] = c[imin] * b[k+ordfact-imin]
1,206,470✔
1289
    @inbounds for i = imin+1:k-1
1,354,460✔
1290
        c[k] += c[i] * b[k+ordfact-i]
4,523,870✔
1291
    end
7,989,260✔
1292
    if k+ordfact ≤ b_order
1,206,470✔
1293
        @inbounds c[k] = a[k+ordfact] - c[k]
1,206,450✔
1294
    else
1295
        @inbounds c[k] = - c[k]
20✔
1296
    end
1297
    c[k] = c[k] / b[ordfact]
1,206,470✔
1298
    return nothing
1,206,470✔
1299
end
1300

1301
# @inline
1302
function div!(v::Taylor1{T}, a::Taylor1{T}, b::NumberNotSeries,
345,543✔
1303
        k::Int) where {T<:Number}
1304
    @inbounds v[k] = a[k] / b
1,151,180✔
1305
    return nothing
1,151,180✔
1306
end
1307

1308
# @inline
1309
function div!(c::Taylor1{T}, a::NumberNotSeries, b::Taylor1{T}, k::Int) where
80✔
1310
        {T<:NumberNotSeries}
1311
    zero!(c, k)
80✔
1312
    iszero(a) && !iszero(b) && return nothing
80✔
1313
    # order and coefficient of first factorized term
1314
    # In this case, since a[k]=0 for k>0, we can simplify to:
1315
    # ordfact, cdivfact = 0, a/b[0]
1316
    if k == 0
80✔
1317
        @inbounds c[0] = a / b[0]
20✔
1318
        return nothing
20✔
1319
    end
1320
    @inbounds c[k] = c[0] * b[k]
60✔
1321
    @inbounds for i = 1:k-1
60✔
1322
        c[k] += c[i] * b[k-i]
150✔
1323
    end
250✔
1324
    @inbounds c[k] = -c[k] / b[0]
60✔
1325
    return nothing
60✔
1326
end
1327

1328
function div!(c::Taylor1, a::NumberNotSeries, b::Taylor1)
3✔
1329
    @inbounds for k in eachindex(c)
10✔
1330
        div!(c, a, b, k)
70✔
1331
    end
130✔
1332
    return nothing
10✔
1333
end
1334

1335
@inline function div!(c::Taylor1{Taylor1{T}}, a::NumberNotSeries,
260✔
1336
        b::Taylor1{Taylor1{T}}, k::Int) where {T<:NumberNotSeriesN}
1337
    zero!(c, k)
1,820✔
1338
    iszero(a) && !iszero(b) && return nothing
260✔
1339
    # order and coefficient of first factorized term
1340
    # In this case, since a[k]=0 for k>0, we can simplify to:
1341
    # ordfact, cdivfact = 0, a/b[0]
1342
    if k == 0
260✔
1343
        @inbounds div!(c[0], a, b[0])
70✔
1344
        return nothing
10✔
1345
    end
1346
    @inbounds mul!(c[k], c[0], b[k])
700✔
1347
    @inbounds for i = 1:k-1
250✔
1348
        # c[k] += c[i] * b[k-i]
1349
        muladd!(c[k], c[i], b[k-i])
3,000✔
1350
    end
5,760✔
1351
    # @inbounds c[k] = -c[k]/b[0]
1352
    @inbounds div_scalar!(c[k], -1, b[0])
250✔
1353
    return nothing
250✔
1354
end
1355

1356
#
1357
# @inline
1358
function div!(c::Taylor1{Taylor1{T}}, a::Taylor1{Taylor1{T}},
109,600✔
1359
        b::Taylor1{Taylor1{T}}, k::Int) where {T<:NumberNotSeriesN}
1360
    zero!(c, k)
1,089,430✔
1361
    iszero(a) && !iszero(b) && return nothing
109,600✔
1362
    # order and coefficient of first factorized term
1363
    ordfact, aux = divfactorization(a, b)
106,600✔
1364
    if k == 0
106,600✔
1365
        identity!(c, aux, k)
10,600✔
1366
        return nothing
10,600✔
1367
    end
1368
    b_order = get_order(b)
96,000✔
1369
    imin = max(0, k+ordfact-b_order)
96,000✔
1370
    # c[k] = c[imin] * b[k+ordfact-imin]
1371
    mul!(c[k], c[imin], b[k+ordfact-imin])
353,376✔
1372
    for i = imin+1:k-1
106,600✔
1373
        # c[k] += c[i] * b[k+ordfact-i]
1374
        for ord in eachindex(minlength(c[k], c[i], b[k+ordfact-i]))
391,840✔
1375
            muladd!(c[k], c[i], b[k+ordfact-i], ord)
21,143,280✔
1376
        end
7,350,320✔
1377
    end
698,280✔
1378
    zero!(aux)
953,920✔
1379
    if k+ordfact ≤ b_order
96,000✔
1380
        # @inbounds aux <- a[k+ordfact] - c[k]
1381
        for ord in eachindex(minlength(aux, a[k+ordfact]))
191,920✔
1382
            subst!(aux, a[k+ordfact], c[k], ord)
953,920✔
1383
        end
1,811,840✔
1384
    else
1385
        # @inbounds aux <- - c[k]
1386
        for ord in eachindex(minlength(aux, a[k+ordfact]))
×
1387
            subst!(aux, c[k], ord)
×
1388
        end
×
1389
    end
1390
    # c[k] <- aux / b[ordfact]
1391
    for ord in eachindex(c[k])
96,000✔
1392
        div!(c[k], aux, b[ordfact], ord)
953,920✔
1393
    end
1,811,840✔
1394
    return nothing
96,000✔
1395
end
1396

1397
# @inline function div!(v::Taylor1{Taylor1{T}}, a::Taylor1{Taylor1{T}},
1398
#         b::NumberNotSeries, k::Int) where {T<:NumberNotSeriesN}
1399
#     # @inbounds v[k] = a[k] / b
1400
#     for ord in eachindex(v)
1401
#         div!(v, a, b, ord)
1402
#     end
1403
#     return nothing
1404
# end
1405

1406
@inline function div!(c::Taylor1{TaylorN{T}}, a::NumberNotSeries,
81✔
1407
        b::Taylor1{TaylorN{T}}, k::Int) where {T<:NumberNotSeries}
1408
    zero!(c, k)
270✔
1409
    iszero(a) && !iszero(b) && return nothing
270✔
1410
    # order and coefficient of first factorized term
1411
    # In this case, since a[k]=0 for k>0, we can simplify to:
1412
    # ordfact, cdivfact = 0, a/b[0]
1413
    if k == 0
270✔
1414
        @inbounds div!(c[0], a, b[0])
50✔
1415
        return nothing
50✔
1416
    end
1417
    @inbounds mul!(c[k], c[0], b[k])
220✔
1418
    @inbounds for i = 1:k-1
220✔
1419
        # c[k] += c[i] * b[k-i]
1420
        mul!(c[k], c[i], b[k-i])
380✔
1421
    end
590✔
1422
    # @inbounds c[k] = -c[k]/b[0]
1423
    @inbounds div_scalar!(c[k], -1, b[0])
220✔
1424
    return nothing
220✔
1425
end
1426

1427
# TODO: avoid allocations when T isa Taylor1
1428
@inline function div!(v::HomogeneousPolynomial{T}, a::HomogeneousPolynomial{T}, b::NumberNotSeriesN) where {T <: Number}
133,830✔
1429
    _check_same_space(v, a)
326,100✔
1430
    @inbounds for k in eachindex(v)
326,100✔
1431
        v[k] = a[k] / b
15,469,830✔
1432
    end
30,613,560✔
1433
    return nothing
326,100✔
1434
end
1435

1436
# NOTE: Due to the use of `zero!`, this `div!` method does *not* accumulate the result of a / b in c[k] (k > 0)
1437
@inline function div!(c::TaylorN, a::TaylorN, b::TaylorN, k::Int)
5,128✔
1438
    _check_same_space(c, a, b)
17,070✔
1439
    if k==0
17,070✔
1440
        @inbounds c[0][1] = constant_term(a) / constant_term(b)
2,350✔
1441
        return nothing
2,350✔
1442
    end
1443

1444
    zero!(c, k)
81,050✔
1445

1446
    @inbounds for i = 0:k-1
14,720✔
1447
        mul!(c[k], c[i], b[k-i])
81,050✔
1448
    end
99,840✔
1449
    @inbounds for i in eachindex(c[k])
14,720✔
1450
        c[k][i] = (a[k][i] - c[k][i]) / constant_term(b)
81,350✔
1451
    end
147,980✔
1452
    return nothing
14,720✔
1453
end
1454

1455
# In-place division and assignment: c[k] = (c/a)[k]
1456
# NOTE: Here `div!` *accumulates* the result of (c/a)[k] in c[k] (k > 0)
1457
#
1458
# Recursion algorithm:
1459
#
1460
# k = 0: c[0] <- c[0]/a[0]
1461
# k = 1: c[1] <- c[1] - c[0]*a[1]
1462
#        c[1] <- c[1]/a[0]
1463
# k = 2: c[2] <- c[2] - c[0]*a[2] - c[1]*a[1]
1464
#        c[2] <- c[2]/a[0]
1465
# etc.
1466
@inline function div!(c::TaylorN, a::TaylorN, k::Int)
2,289✔
1467
    _check_same_space(c, a)
7,630✔
1468
    if k==0
7,630✔
1469
        @inbounds c[0][1] = constant_term(c) / constant_term(a)
1,090✔
1470
        return nothing
1,090✔
1471
    end
1472

1473
    @inbounds for i = 0:k-1
6,540✔
1474
        mul_scalar!(c[k], -1, c[i], a[k-i])
30,460✔
1475
    end
39,240✔
1476
    @inbounds for i in eachindex(c[k])
6,540✔
1477
        c[k][i] = c[k][i] / constant_term(a)
29,430✔
1478
    end
52,320✔
1479
    return nothing
6,540✔
1480
end
1481

1482
# In-place division and assignment: c[k] <- scalar * (c/a)[k]
1483
# NOTE: Here `div!` *accumulates* the result of scalar * (c/a)[k] in c[k] (k > 0)
1484
#
1485
# Recursion algorithm:
1486
#
1487
# k = 0: c[0] <- scalar*c[0]/a[0]
1488
# k = 1: c[1] <- scalar*c[1] - c[0]*a[1]
1489
#        c[1] <- c[1]/a[0]
1490
# k = 2: c[2] <- scalar*c[2] - c[0]*a[2] - c[1]*a[1]
1491
#        c[2] <- c[2]/a[0]
1492
# etc.
1493
@inline function div_scalar!(c::TaylorN, scalar::NumberNotSeries, a::TaylorN, k::Int)
4,704✔
1494
    _check_same_space(c, a)
15,680✔
1495
    if k==0
15,680✔
1496
        @inbounds c[0][1] = scalar*constant_term(c) / constant_term(a)
2,240✔
1497
        return nothing
2,240✔
1498
    end
1499

1500
    @inbounds mul!(c, scalar, c, k)
46,116✔
1501
    @inbounds for i = 0:k-1
13,440✔
1502
        mul_scalar!(c[k], -1, c[i], a[k-i])
70,070✔
1503
    end
80,640✔
1504
    @inbounds for i in eachindex(c[k])
13,440✔
1505
        c[k][i] = c[k][i] / constant_term(a)
60,480✔
1506
    end
107,520✔
1507
    return nothing
13,440✔
1508
end
1509

1510
@inline function div_scalar!(c::Taylor1{T}, scalar::NumberNotSeries,
525✔
1511
        a::Taylor1{T}, k::Int) where {T <: NumberNotSeries}
1512
    if k==0
1,750✔
1513
        @inbounds c[0] = scalar*constant_term(c) / constant_term(a)
250✔
1514
        return nothing
250✔
1515
    end
1516

1517
    aux = c[k] = scalar * c[k]
1,500✔
1518
    @inbounds zero!(c, k)
1,500✔
1519
    @inbounds for i = 0:k-1
1,500✔
1520
        c[k] -= c[i] * a[k-i]
5,250✔
1521
    end
9,000✔
1522
    c[k] += aux
1,500✔
1523
    @inbounds c[k] = c[k] / constant_term(a)
1,500✔
1524
    return nothing
1,500✔
1525
end
1526

1527
# NOTE: Here `div!` *accumulates* the result of a[k] / b[k] in c[k] (k > 0)
1528
@inline function div!(c::TaylorN, a::NumberNotSeries, b::TaylorN, k::Int)
255✔
1529
    _check_same_space(c, b)
850✔
1530
    if k==0
850✔
1531
        @inbounds c[0][1] = a / constant_term(b)
90✔
1532
        return nothing
90✔
1533
    end
1534

1535
    @inbounds for i = 0:k-1
760✔
1536
        mul!(c[k], c[i], b[k-i])
6,580✔
1537
    end
8,300✔
1538
    @inbounds for i in eachindex(c[k])
760✔
1539
        c[k][i] = ( -c[k][i] ) / constant_term(b)
5,290✔
1540
    end
9,820✔
1541
    return nothing
760✔
1542
end
1543

1544
# in-place division c <- c/a (assumes equal order among TaylorNs)
1545
function div!(c::TaylorN, a::TaylorN)
670✔
1546
    @inbounds for k in eachindex(c)
670✔
1547
        div!(c, a, k)
4,690✔
1548
    end
8,710✔
1549
    return nothing
670✔
1550
end
1551

1552
# in-place division c <- scalar*c/a (assumes equal order among TaylorNs)
1553
function div_scalar!(c::TaylorN, scalar::NumberNotSeries, a::TaylorN)
2,240✔
1554
    @inbounds for k in eachindex(c)
2,240✔
1555
        div_scalar!(c, scalar, a, k)
15,680✔
1556
    end
29,120✔
1557
    return nothing
2,240✔
1558
end
1559

1560
# in-place division c <- scalar*c/a (assumes equal order among TaylorNs)
1561
function div_scalar!(c::Taylor1, scalar::NumberNotSeries, a::Taylor1)
250✔
1562
    @inbounds for k in eachindex(c)
250✔
1563
        div_scalar!(c, scalar, a, k)
1,750✔
1564
    end
3,250✔
1565
    return nothing
250✔
1566
end
1567

1568
# c[k] <- (a/b)[k]
1569
function div!(c::TaylorN, a::TaylorN, b::TaylorN)
140✔
1570
    @inbounds for k in eachindex(c)
140✔
1571
        div!(c, a, b, k)
980✔
1572
    end
1,820✔
1573
    return nothing
140✔
1574
end
1575

1576
# c[k] <- (a/b)[k], where a is a scalar
1577
function div!(c::TaylorN, a::NumberNotSeries, b::TaylorN)
50✔
1578
    @inbounds for k in eachindex(c)
50✔
1579
        div!(c, a, b, k)
350✔
1580
    end
650✔
1581
    return nothing
50✔
1582
end
1583

1584
# # c[k] <- a[k]/b, where b is a scalar
1585
# function div!(c::TaylorN, a::TaylorN, b::NumberNotSeries)
1586
#     @inbounds for k in eachindex(c)
1587
#         div!(c[k], a[k], b)
1588
#     end
1589
#     return nothing
1590
# end
1591

1592
# NOTE: Here `div!` *accumulates* the result of a / b in res[k] (k > 0)
1593
@inline function div!(c::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}},
243✔
1594
        b::Taylor1{TaylorN{T}}, k::Int) where {T<:NumberNotSeriesN}
1595

1596
    # order and coefficient of first factorized term
1597
    # ordfact, cdivfact = divfactorization(a, b)
1598
    anz = findfirst(a)
1,620✔
1599
    bnz = findfirst(b)
1,620✔
1600
    anz = anz ≥ 0 ? anz : get_order(a)
810✔
1601
    bnz = bnz ≥ 0 ? bnz : get_order(a)
810✔
1602
    ordfact = min(anz, bnz)
810✔
1603

1604
    # Is the polynomial factorizable?
1605
    iszero(b[ordfact]) && throw( ArgumentError(
810✔
1606
        """Division does not define a Taylor1 polynomial;
1607
        order k=$(ordfact) => coeff[$(ordfact)]=$(cdivfact).""") )
1608

1609
    zero!(c, k)
810✔
1610

1611
    if k == 0
810✔
1612
        # @inbounds c[0] = a[ordfact]/b[ordfact]
1613
        @inbounds div!(c[0], a[ordfact], b[ordfact])
140✔
1614
        return nothing
140✔
1615
    end
1616
    b_order = get_order(b)
670✔
1617
    imin = max(0, k+ordfact-b_order)
670✔
1618
    @inbounds mul!(c[k], c[imin], b[k+ordfact-imin])
670✔
1619
    @inbounds for i = imin+1:k-1
810✔
1620
        mul!(c[k], c[i], b[k+ordfact-i])
1,280✔
1621
    end
2,030✔
1622
        if k+ordfact ≤ b_order
670✔
1623
        # @inbounds c[k] = (a[k+ordfact]-c[k]) / b[ordfact]
1624
        @inbounds for l in eachindex(c[k])
670✔
1625
            subst!(c[k], a[k+ordfact], c[k], l)
14,539✔
1626
        end
8,710✔
1627
        @inbounds div!(c[k], b[ordfact])
670✔
1628
    else
1629
        # @inbounds c[k] = (-c[k]) / b[ordfact]
1630
        @inbounds div_scalar!(c[k], -1, b[ordfact])
×
1631
    end
1632
    return nothing
670✔
1633
end
1634

1635
@inline function div!(res::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}},
1,635✔
1636
        b::NumberNotSeries, k::Int) where {T<:NumberNotSeries}
1637
    for l in eachindex(a[k])
5,450✔
1638
        for m in eachindex(a[k][l])
38,150✔
1639
            res[k][l][m] = a[k][l][m]/b
152,600✔
1640
        end
267,050✔
1641
    end
70,850✔
1642
    return nothing
5,450✔
1643
end
1644

1645

1646

1647
"""
1648
    mul!(Y, A, B)
1649

1650
Multiply A*B and save the result in Y.
1651
"""
1652
function mul!(y::Vector{Taylor1{T}},
×
1653
        a::Union{Matrix{T},SparseMatrixCSC{T}},
1654
        b::Vector{Taylor1{T}}) where {T<:Number}
1655

1656
    n, k = size(a)
×
1657
    @assert (length(y)== n && length(b)== k)
×
1658

1659
    # determine the maximal order of b
1660
    order = maximum(get_order.(b))
×
1661

1662
    # Use matrices of coefficients (of proper size) and mul!
1663
    # B = zeros(T, k, order+1)
1664
    B = Array{T}(undef, k, order+1)
×
1665
    B = zero.(B)
×
1666
    for i = 1:k
×
1667
        @inbounds ord = get_order(b[i])
×
1668
        @inbounds for j = 1:ord+1
×
1669
            B[i,j] = b[i][j-1]
×
1670
        end
×
1671
    end
×
1672
    Y = Array{T}(undef, n, order+1)
×
1673
    mul!(Y, a, B)
×
1674
    @inbounds for i = 1:n
×
1675
        # y[i] = Taylor1( collect(Y[i,:]), order)
1676
        y[i] = Taylor1( Y[i,:], order)
×
1677
    end
×
1678

1679
    return y
×
1680
end
1681

1682

1683
# Adapted from (Julia v1.2) stdlib/v1.2/LinearAlgebra/src/dense.jl#721-734,
1684
# licensed under MIT "Expat".
1685
# Specialize a method of `inv` for Matrix{Taylor1{T}}. Simply, avoid pivoting,
1686
# since the polynomial field is not an ordered one.
1687
# function Base.inv(A::StridedMatrix{Taylor1{T}}) where T
1688
#     checksquare(A)
1689
#     S = Taylor1{typeof((one(T)*zero(T) + one(T)*zero(T))/one(T))}
1690
#     AA = convert(AbstractArray{S}, A)
1691
#     if istriu(AA)
1692
#         Ai = triu!(parent(inv(UpperTriangular(AA))))
1693
#     elseif istril(AA)
1694
#         Ai = tril!(parent(inv(LowerTriangular(AA))))
1695
#     else
1696
#         # Do not use pivoting !!
1697
#         Ai = inv!(lu(AA, Val(false)))
1698
#         Ai = convert(typeof(parent(Ai)), Ai)
1699
#     end
1700
#     return Ai
1701
# end
1702

1703
# see https://github.com/JuliaLang/julia/pull/40623
1704
const LU_RowMaximum = RowMaximum()
1705
const LU_NoPivot = NoPivot()
1706

1707
# Adapted from (Julia v1.2) stdlib/v1.2/LinearAlgebra/src/lu.jl#240-253
1708
# and (Julia v1.4.0-dev) stdlib/LinearAlgebra/v1.4/src/lu.jl#270-274,
1709
# licensed under MIT "Expat".
1710
# Specialize a method of `lu` for Matrix{Taylor1{T}}, which avoids pivoting,
1711
# since the polynomial field is not an ordered one.
1712
# We can't assume an ordered field so we first try without pivoting
1713
function lu(A::AbstractMatrix{Taylor1{T}}; check::Bool = true) where {T<:Number}
777✔
1714
    S = Taylor1{lutype(T)}
420✔
1715
    F = lu!(copy_oftype(A, S), LU_NoPivot; check = false)
567✔
1716
    if issuccess(F)
420✔
1717
        return F
420✔
1718
    else
1719
        return lu!(copy_oftype(A, S), LU_RowMaximum; check = check)
×
1720
    end
1721
end
1722

1723

1724
# Fast allocation-free matrix multiplication
1725
for T in (:Taylor1, :TaylorN)
1726
    @eval function matmul!(C::Matrix{$T{T}},
40✔
1727
                           A::Matrix{$T{T}}, B::Matrix{$T{T}}) where {T}
1728
        mc, nc = size(C)
40✔
1729
        ma, na = size(A)
40✔
1730
        mb, nb = size(B)
40✔
1731
        @assert (na == mb && mc == ma && nc == nb)
40✔
1732
        for j in axes(C,2)
40✔
1733
            for i in axes(C,1)
120✔
1734
                TS.zero!(C[i,j])
5,760✔
1735
                for k in 1:na
360✔
1736
                    TS.muladd!(C[i,j], A[i,k], B[k,j])
1,080✔
1737
                end
1,800✔
1738
            end
600✔
1739
        end
200✔
1740
        return nothing
40✔
1741
    end
1742
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

© 2026 Coveralls, Inc