@@ -109,11 +109,12 @@ end
109
109
blocksize (A:: Operator ,k) = k== 1 ? length (blocklengths (rangespace (A))) : length (blocklengths (domainspace (A)))
110
110
blocksize (A:: Operator ) = (blocksize (A,1 ),blocksize (A,2 ))
111
111
112
-
112
+ # operators need to define size(A, k::Integer)
113
113
size (A:: Operator ) = (size (A,1 ),size (A,2 ))
114
- size (A:: Operator ,k:: Integer ) = k== 1 ? dimension (rangespace (A)) : dimension (domainspace (A))
115
114
length (A:: Operator ) = size (A,1 ) * size (A,2 )
116
115
116
+ size (A:: Operator ,k:: Integer ) = opsize (A, k)
117
+
117
118
118
119
# used to compute "end" for last index
119
120
function lastindex (A:: Operator , n:: Integer )
@@ -139,50 +140,25 @@ Base.ndims(::Operator) = 2
139
140
# # bandrange and indexrange
140
141
isbandedbelow (A:: Operator ) = isfinite (bandwidth (A,1 )):: Bool
141
142
isbandedabove (A:: Operator ) = isfinite (bandwidth (A,2 )):: Bool
142
- isbanded (A:: Operator ) = all (isfinite, bandwidths (A)) :: Bool
143
+ isbanded (A:: Operator ) = opisbanded (A)
143
144
144
145
145
146
isbandedblockbandedbelow (_) = false
146
147
isbandedblockbandedabove (_) = false
147
148
148
- isbandedblockbanded (A:: Operator ) = isbandedblockbandedabove (A) && isbandedblockbandedbelow (A )
149
+ isbandedblockbanded (A:: Operator ) = opisbandedblockbanded (A :: Operator )
149
150
150
151
151
- # this should be determinable at compile time
152
- # TODO : I think it can be generalized to the case when the domainspace
153
- # blocklengths == rangespace blocklengths, in which case replace the definition
154
- # of p with maximum(blocklength(domainspace(A)))
155
- function blockbandwidths (A:: Operator )
156
- hastrivialblocks (A) && return bandwidths (A)
157
-
158
- if hasconstblocks (A)
159
- a,b = bandwidths (A)
160
- p = getindex_value (blocklengths (domainspace (A)))
161
- return (- fld (- a,p),- fld (- b,p))
162
- end
163
-
164
- # TODO : Generalize to finite dimensional
165
- if size (A,2 ) == 1
166
- rs = rangespace (A)
167
-
168
- if hasconstblocks (rs)
169
- a = bandwidth (A,1 )
170
- p = getindex_value (blocklengths (rs))
171
- return (- fld (- a,p),0 )
172
- end
173
- end
174
-
175
- return (length (blocklengths (rangespace (A)))- 1 ,length (blocklengths (domainspace (A)))- 1 )
176
- end
152
+ blockbandwidths (A:: Operator ) = opblockbandwidths (A:: Operator )
177
153
178
154
# assume dense blocks
179
- subblockbandwidths (K:: Operator ) = maximum ( blocklengths ( rangespace (K))) - 1 , maximum ( blocklengths ( domainspace (K))) - 1
155
+ subblockbandwidths (K:: Operator ) = opsubblockbandwidths (K :: Operator )
180
156
181
157
isblockbandedbelow (A:: Operator ) = isfinite (blockbandwidth (A,1 )):: Bool
182
158
isblockbandedabove (A:: Operator ) = isfinite (blockbandwidth (A,2 )):: Bool
183
- isblockbanded (A:: Operator ) = all (isfinite, blockbandwidths (A)) :: Bool
159
+ isblockbanded (A:: Operator ) = opisblockbanded (A :: Operator )
184
160
185
- israggedbelow (A:: Operator ) = isbandedbelow (A):: Bool || isbandedblockbanded (A) :: Bool || isblockbandedbelow (A) :: Bool
161
+ israggedbelow (A:: Operator ) = opisraggedbelow (A)
186
162
187
163
188
164
blockbandwidth (K:: Operator , k:: Integer ) = blockbandwidths (K)[k]
@@ -197,9 +173,7 @@ bandwidth(A::Operator, k::Integer) = bandwidths(A)[k]
197
173
Return the bandwidth of `op` in the form `(l,u)`, where `l ≥ 0` represents
198
174
the number of subdiagonals and `u ≥ 0` represents the number of superdiagonals.
199
175
"""
200
- bandwidths (A:: Operator ) = (size (A,1 )- 1 ,size (A,2 )- 1 )
201
- bandwidths (A:: Operator , k:: Integer ) = bandwidths (A)[k]
202
-
176
+ bandwidths (A:: Operator ) = opbandwidths (A)
203
177
204
178
205
179
# # Strides
@@ -208,8 +182,7 @@ bandwidths(A::Operator, k::Integer) = bandwidths(A)[k]
208
182
# A diagonal operator has essentially infinite stride
209
183
# which we represent by a factorial, so that
210
184
# the gcd with any number < 10 is the number
211
- stride (A:: Operator ) =
212
- isdiag (A) ? factorial (10 ) : 1
185
+ stride (A:: Operator ) = opstride (A:: Operator )
213
186
214
187
isdiag (A:: Operator ) = bandwidths (A)== (0 ,0 )
215
188
istriu (A:: Operator ) = bandwidth (A, 1 ) <= 0
@@ -486,36 +459,105 @@ end
486
459
# Convenience for wrapper ops
487
460
unwrap_axpy! (α,P,A) = axpy! (α,view (parent (P). op,P. indexes[1 ],P. indexes[2 ]),A)
488
461
iswrapper (_) = false
489
- haswrapperstructure (_) = false
462
+
463
+ haswrapperstructure (@nospecialize (:: Type )) = false
464
+ haswrapperstructure (x:: Operator ) = haswrapperstructure (typeof (x))
465
+
466
+ @traitdef HasWrapperStructure{X}
467
+ @traitimpl HasWrapperStructure{X} < - haswrapperstructure (X)
468
+
469
+ # Forward various structure query functions to the parent for wrappers
470
+
471
+ @traitfn opbandwidths (A:: X ) where {X; ! HasWrapperStructure{X}} =
472
+ (size (A,1 )- 1 ,size (A,2 )- 1 )
473
+ @traitfn opbandwidths (A:: X ) where {X; HasWrapperStructure{X}} =
474
+ bandwidths (A. op)
475
+
476
+ @traitfn opstride (A:: X ) where {X; HasWrapperStructure{X}} =
477
+ stride (A. op)
478
+ @traitfn opstride (A:: X ) where {X; ! HasWrapperStructure{X}} =
479
+ isdiag (A) ? factorial (10 ) : 1
480
+
481
+ @traitfn opisblockbanded (A:: X ) where {X; HasWrapperStructure{X}} =
482
+ isblockbanded (A. op)
483
+ @traitfn opisblockbanded (A:: X ) where {X; ! HasWrapperStructure{X}} =
484
+ all (isfinite, blockbandwidths (A)):: Bool
485
+
486
+ @traitfn opisbandedblockbanded (A:: X ) where {X; HasWrapperStructure{X}} =
487
+ isbandedblockbanded (A. op)
488
+ @traitfn opisbandedblockbanded (A:: X ) where {X; ! HasWrapperStructure{X}} =
489
+ isbandedblockbandedabove (A) && isbandedblockbandedbelow (A)
490
+
491
+ @traitfn opisbanded (A:: X ) where {X; HasWrapperStructure{X}} =
492
+ isbanded (A. op)
493
+ @traitfn opisbanded (A:: X ) where {X; ! HasWrapperStructure{X}} =
494
+ all (isfinite, bandwidths (A)):: Bool
495
+
496
+ @traitfn opisraggedbelow (A:: X ) where {X; HasWrapperStructure{X}} =
497
+ israggedbelow (A. op)
498
+ @traitfn function opisraggedbelow (A:: X ) where {X; ! HasWrapperStructure{X}}
499
+ isbandedbelow (A):: Bool ||
500
+ isbandedblockbanded (A):: Bool ||
501
+ isblockbandedbelow (A):: Bool
502
+ end
503
+
504
+ # this should be determinable at compile time
505
+ # TODO : I think it can be generalized to the case when the domainspace
506
+ # blocklengths == rangespace blocklengths, in which case replace the definition
507
+ # of p with maximum(blocklength(domainspace(A)))
508
+ @traitfn opblockbandwidths (A:: X ) where {X; HasWrapperStructure{X}} =
509
+ opblockbandwidths (A. op)
510
+ @traitfn function opblockbandwidths (A:: X ) where {X; ! HasWrapperStructure{X}}
511
+ hastrivialblocks (A) && return bandwidths (A)
512
+
513
+ if hasconstblocks (A)
514
+ a,b = bandwidths (A)
515
+ p = getindex_value (blocklengths (domainspace (A)))
516
+ return (- fld (- a,p),- fld (- b,p))
517
+ end
518
+
519
+ # TODO : Generalize to finite dimensional
520
+ if size (A,2 ) == 1
521
+ rs = rangespace (A)
522
+
523
+ if hasconstblocks (rs)
524
+ a = bandwidth (A,1 )
525
+ p = getindex_value (blocklengths (rs))
526
+ return (- fld (- a,p),0 )
527
+ end
528
+ end
529
+
530
+ return (length (blocklengths (rangespace (A)))- 1 ,length (blocklengths (domainspace (A)))- 1 )
531
+ end
532
+
533
+ @traitfn opsubblockbandwidths (A:: X ) where {X; HasWrapperStructure{X}} =
534
+ subblockbandwidths (A. op)
535
+ @traitfn opsubblockbandwidths (A:: X ) where {X; ! HasWrapperStructure{X}} =
536
+ maximum (blocklengths (rangespace (A)))- 1 , maximum (blocklengths (domainspace (A)))- 1
537
+
538
+ @traitfn opsize (A:: X , k:: Integer ) where {X; HasWrapperStructure{X}} =
539
+ opsize (A. op, k)
540
+ @traitfn opsize (:: X , k:: PosInfinity ) where {X; HasWrapperStructure{X}} = ℵ₀
541
+
542
+ defaultsize (A, k) = k== 1 ? dimension (rangespace (A)) : dimension (domainspace (A))
543
+ @traitfn opsize (A:: X , k:: Integer ) where {X; ! HasWrapperStructure{X}} =
544
+ defaultsize (A, k)
490
545
491
546
# use this for wrapper operators that have the same structure but
492
547
# not necessarily the same entries
493
548
#
494
549
# Ex: c*op or real(op)
495
- macro wrapperstructure (Wrap, forwardsize = true )
496
- fns = [:(ApproxFunBase. bandwidths),:(LinearAlgebra. stride),
497
- :(ApproxFunBase. isbandedblockbanded),:(ApproxFunBase. isblockbanded),
498
- :(ApproxFunBase. israggedbelow),:(ApproxFunBase. isbanded),
499
- :(ApproxFunBase. blockbandwidths),:(ApproxFunBase. subblockbandwidths),
500
- :(LinearAlgebra. issymmetric)]
501
-
502
- if forwardsize
503
- fns = [fns; :(Base. size)]
504
- end
550
+ macro wrapperstructure (Wrap)
551
+ fns = [:(LinearAlgebra. issymmetric)]
505
552
506
553
v1 = map (fns) do func
507
-
508
554
:($ func (D:: $Wrap ) = $ func (D. op))
509
555
end
510
556
511
557
fns2 = [:(ApproxFunBase. bandwidth),:(ApproxFunBase. colstart),:(ApproxFunBase. colstop),
512
558
:(ApproxFunBase. rowstart),:(ApproxFunBase. rowstop),:(ApproxFunBase. blockbandwidth),
513
559
:(ApproxFunBase. subblockbandwidth)]
514
560
515
- if forwardsize
516
- fns2 = [fns2; :(Base. size)]
517
- end
518
-
519
561
v2 = map (fns2) do func
520
562
quote
521
563
$ func (D:: $Wrap ,k:: Integer ) = $ func (D. op,k)
@@ -524,7 +566,7 @@ macro wrapperstructure(Wrap, forwardsize = true)
524
566
end
525
567
526
568
ret = quote
527
- ApproxFunBase. haswrapperstructure (:: $Wrap ) = true
569
+ ApproxFunBase. haswrapperstructure (:: Type{<: $Wrap} ) = true
528
570
$ (v1... )
529
571
$ (v2... )
530
572
end
537
579
# use this for wrapper operators that have the same entries but
538
580
# not necessarily the same spaces
539
581
#
540
- macro wrappergetindex (Wrap, forwardsize = true )
582
+ macro wrappergetindex (Wrap)
541
583
v = map ((:(ApproxFunBase. BandedMatrix),:(ApproxFunBase. RaggedMatrix),
542
584
:(Base. Matrix),:(Base. Vector),:(Base. AbstractVector))) do TYP
543
585
quote
@@ -602,7 +644,7 @@ macro wrappergetindex(Wrap, forwardsize = true)
602
644
ApproxFunBase. default_BandedBlockBandedMatrix)
603
645
end
604
646
605
- ApproxFunBase. @wrapperstructure ($ Wrap, $ forwardsize ) # structure is automatically inherited
647
+ ApproxFunBase. @wrapperstructure ($ Wrap) # structure is automatically inherited
606
648
end
607
649
608
650
esc (ret)
0 commit comments