@@ -29,7 +29,7 @@ function plan_chebyshevtransform!(x::AbstractArray{T,N}, ::Val{1}, dims...; kws.
29
29
end
30
30
end
31
31
function plan_chebyshevtransform! (x:: AbstractArray{T,N} , :: Val{2} , dims... ; kws... ) where {T<: fftwNumber ,N}
32
- length (x) ≤ 1 && throw (ArgumentError (" Array must contain at least 2 entries" ))
32
+ any ( ≤ ( 1 ), size (x)) && throw (ArgumentError (" Array must contain at least 2 entries" ))
33
33
ChebyshevTransformPlan {T,2,kindtuple(SECONDKIND,N,dims...)} (FFTW. plan_r2r! (x, FFTW. REDFT00, dims... ; kws... ))
34
34
end
35
35
@@ -42,7 +42,7 @@ function plan_chebyshevtransform(x::AbstractArray{T,N}, ::Val{1}, dims...; kws..
42
42
end
43
43
end
44
44
function plan_chebyshevtransform (x:: AbstractArray{T,N} , :: Val{2} , dims... ; kws... ) where {T<: fftwNumber ,N}
45
- length (x) ≤ 1 && throw (ArgumentError (" Vector must contain at least 2 entries" ))
45
+ any ( ≤ ( 1 ), size (x)) && throw (ArgumentError (" Array must contain at least 2 entries" ))
46
46
ChebyshevTransformPlan {T,2,kindtuple(SECONDKIND,N,dims...)} (FFTW. plan_r2r (x, FFTW. REDFT00, dims... ; kws... ))
47
47
end
48
48
@@ -202,22 +202,22 @@ end
202
202
plan_ichebyshevtransform! (x:: AbstractArray , dims... ; kws... ) = plan_ichebyshevtransform! (x, Val (1 ), dims... ; kws... )
203
203
plan_ichebyshevtransform (x:: AbstractArray , dims... ; kws... ) = plan_ichebyshevtransform (x, Val (1 ), dims... ; kws... )
204
204
205
- @inline _icheb1_prerescale ! (_, x:: AbstractVector ) = (x[1 ] *= 2 )
206
- @inline function _icheb1_prerescale ! (d:: Number , x:: AbstractMatrix )
205
+ @inline _icheb1_prescale ! (_, x:: AbstractVector ) = (x[1 ] *= 2 )
206
+ @inline function _icheb1_prescale ! (d:: Number , x:: AbstractMatrix )
207
207
if isone (d)
208
208
lmul! (2 , view (x,1 ,:))
209
209
else
210
210
lmul! (2 , view (x,:,1 ))
211
211
end
212
212
x
213
213
end
214
- @inline function _icheb1_prerescale ! (d:: UnitRange , x:: AbstractMatrix )
214
+ @inline function _icheb1_prescale ! (d:: UnitRange , x:: AbstractMatrix )
215
215
lmul! (2 , view (x,:,1 ))
216
216
lmul! (2 , view (x,1 ,:))
217
217
x
218
218
end
219
- @inline _icheb1_postrescale ! (_, x:: AbstractVector ) = (x[1 ] /= 2 )
220
- @inline function _icheb1_postrescale ! (d:: Number , x:: AbstractMatrix )
219
+ @inline _icheb1_postscale ! (_, x:: AbstractVector ) = (x[1 ] /= 2 )
220
+ @inline function _icheb1_postscale ! (d:: Number , x:: AbstractMatrix )
221
221
if isone (d)
222
222
ldiv! (2 , view (x,1 ,:))
223
223
else
226
226
x
227
227
end
228
228
229
- @inline function _icheb1_postrescale ! (d:: UnitRange , x:: AbstractMatrix )
229
+ @inline function _icheb1_postscale ! (d:: UnitRange , x:: AbstractMatrix )
230
230
ldiv! (2 , view (x,1 ,:))
231
231
ldiv! (2 , view (x,:,1 ))
232
232
x
@@ -236,7 +236,7 @@ function *(P::IChebyshevTransformPlan{T,1,K,true,N}, x::AbstractArray{T,N}) wher
236
236
n = length (x)
237
237
n == 0 && return x
238
238
239
- _icheb1_prerescale ! (P. plan. region, x)
239
+ _icheb1_prescale ! (P. plan. region, x)
240
240
x = ldiv! (2 ^ length (P. plan. region), P. plan* x)
241
241
x
242
242
end
@@ -246,14 +246,14 @@ function mul!(y::AbstractArray{T,N}, P::IChebyshevTransformPlan{T,1,K,false,N},
246
246
length (y) == n || throw (DimensionMismatch (" output must match dimension" ))
247
247
n == 0 && return y
248
248
249
- _icheb1_prerescale ! (P. plan. region, x) # Todo: don't mutate x
249
+ _icheb1_prescale ! (P. plan. region, x) # Todo: don't mutate x
250
250
_plan_mul! (y, P. plan, x)
251
- _icheb1_postrescale ! (P. plan. region, x)
251
+ _icheb1_postscale ! (P. plan. region, x)
252
252
ldiv! (2 ^ length (P. plan. region), y)
253
253
end
254
254
255
- @inline _icheb2_prerescale ! (_, x:: AbstractVector ) = (x[1 ] *= 2 ; x[end ] *= 2 )
256
- @inline function _icheb2_prerescale ! (d:: Number , x:: AbstractMatrix )
255
+ @inline _icheb2_prescale ! (_, x:: AbstractVector ) = (x[1 ] *= 2 ; x[end ] *= 2 )
256
+ @inline function _icheb2_prescale ! (d:: Number , x:: AbstractMatrix )
257
257
if isone (d)
258
258
lmul! (2 , @view (x[1 ,:]))
259
259
lmul! (2 , @view (x[end ,:]))
263
263
end
264
264
x
265
265
end
266
- @inline function _icheb2_prerescale ! (d:: UnitRange , x:: AbstractMatrix )
266
+ @inline function _icheb2_prescale ! (d:: UnitRange , x:: AbstractMatrix )
267
267
lmul! (2 , @view (x[1 ,:]))
268
268
lmul! (2 , @view (x[end ,:]))
269
269
lmul! (2 , @view (x[:,1 ]))
@@ -289,20 +289,20 @@ end
289
289
x
290
290
end
291
291
@inline function _icheb2_rescale! (d:: Number , y:: AbstractArray{T} ) where T
292
- _icheb2_prerescale ! (d, y)
292
+ _icheb2_prescale ! (d, y)
293
293
lmul! (convert (T, size (y,d) - 1 )/ 2 , y)
294
294
y
295
295
end
296
296
@inline function _icheb2_rescale! (d:: UnitRange , y:: AbstractArray{T} ) where T
297
- _icheb2_prerescale ! (d, y)
297
+ _icheb2_prescale ! (d, y)
298
298
lmul! (prod (convert .(T, size (y) .- 1 )./ 2 ), y)
299
299
y
300
300
end
301
301
302
302
function * (P:: IChebyshevTransformPlan{T,2,K,true,N} , x:: AbstractArray{T,N} ) where {T<: fftwNumber ,K,N}
303
303
n = length (x)
304
304
305
- _icheb2_prerescale ! (P. plan. region, x)
305
+ _icheb2_prescale ! (P. plan. region, x)
306
306
x = inv (P)* x
307
307
_icheb2_rescale! (P. plan. region, x)
308
308
end
@@ -311,7 +311,7 @@ function mul!(y::AbstractArray{T,N}, P::IChebyshevTransformPlan{T,2,K,false,N},
311
311
n = length (x)
312
312
length (y) == n || throw (DimensionMismatch (" output must match dimension" ))
313
313
314
- _icheb2_prerescale ! (P. plan. region, x)
314
+ _icheb2_prescale ! (P. plan. region, x)
315
315
_plan_mul! (y, inv (P), x)
316
316
_icheb2_postrescale! (P. plan. region, x)
317
317
_icheb2_rescale! (P. plan. region, y)
@@ -324,71 +324,117 @@ ichebyshevtransform(x, dims...; kwds...) = plan_ichebyshevtransform(x, dims...;
324
324
325
325
# # Chebyshev U
326
326
327
- struct ChebyshevUTransformPlan{T,kind,inplace,P} <: ChebyshevPlan{T}
328
- plan:: FFTW.r2rFFTWPlan{T,P,true,1,UnitRange{Int}}
329
- ChebyshevUTransformPlan {T,kind,inplace,P} (plan) where {T,kind,inplace,P} = new {T,kind,inplace,P} (plan)
330
- ChebyshevUTransformPlan {T,kind,inplace,P} () where {T,kind,inplace,P} = new {T,kind,inplace,P} ()
331
- end
332
-
333
- ChebyshevUTransformPlan {T,kind,inplace} (plan:: FFTW.r2rFFTWPlan{T,P} ) where {T,kind,inplace,P} =
334
- ChebyshevUTransformPlan {T,kind,inplace,P} (plan)
327
+ const UFIRSTKIND = 9
328
+ const USECONDKIND = 7
335
329
336
- ChebyshevUTransformPlan {T,kind,inplace} (plan:: ChebyshevUTransformPlan{T,kind,inp,P} ) where {T,kind,inplace,inp,P} =
337
- ChebyshevUTransformPlan {T,kind,inplace,P} (plan. plan)
330
+ struct ChebyshevUTransformPlan{T,kind,K,inplace,N,R} <: ChebyshevPlan{T}
331
+ plan:: FFTW.r2rFFTWPlan{T,K,inplace,N,R}
332
+ ChebyshevUTransformPlan {T,kind,K,inplace,N,R} (plan) where {T,kind,K,inplace,N,R} = new {T,kind,K,inplace,N,R} (plan)
333
+ ChebyshevUTransformPlan {T,kind,K,inplace,N,R} () where {T,kind,K,inplace,N,R} = new {T,kind,K,inplace,N,R} ()
334
+ end
338
335
336
+ ChebyshevUTransformPlan {T,kind,K} (plan:: FFTW.r2rFFTWPlan{T,K,inplace,N,R} ) where {T,kind,K,inplace,N,R} =
337
+ ChebyshevUTransformPlan {T,kind,K,inplace,N,R} (plan)
339
338
340
339
341
- function plan_chebyshevutransform! (x:: AbstractVector{T } , :: Val{1} ) where T<: fftwNumber
340
+ function plan_chebyshevutransform! (x:: AbstractArray{T,N } , :: Val{1} , dims ... ; kws ... ) where { T<: fftwNumber ,N}
342
341
if isempty (x)
343
- ChebyshevUTransformPlan {T,1,true,(9, )} ()
342
+ ChebyshevUTransformPlan {T,1,kindtuple(UFIRSTKIND,N,dims...), true,N,isempty(dims) ? UnitRange{Int} : typeof(dims )} ()
344
343
else
345
- ChebyshevUTransformPlan {T,1,true,(9, )} (FFTW. plan_r2r! (x, FFTW. RODFT10))
344
+ ChebyshevUTransformPlan {T,1,kindtuple(UFIRSTKIND,N,dims... )} (FFTW. plan_r2r! (x, FFTW. RODFT10, dims ... ; kws ... ))
346
345
end
347
346
end
348
- function plan_chebyshevutransform! (x:: AbstractVector{T } , :: Val{2} ) where T<: fftwNumber
349
- length (x) ≤ 1 && throw (ArgumentError (" Vector must contain at least 2 entries" ))
350
- ChebyshevUTransformPlan {T,2,true,(7, )} (FFTW. plan_r2r! (x, FFTW. RODFT00))
347
+ function plan_chebyshevutransform! (x:: AbstractArray{T,N } , :: Val{2} , dims ... ; kws ... ) where { T<: fftwNumber ,N}
348
+ any ( ≤ ( 1 ), size (x)) && throw (ArgumentError (" Array must contain at least 2 entries" ))
349
+ ChebyshevUTransformPlan {T,2,kindtuple(USECONDKIND,N,dims... )} (FFTW. plan_r2r! (x, FFTW. RODFT00, dims ... ; kws ... ))
351
350
end
352
351
353
- function plan_chebyshevutransform (x:: AbstractVector{T } , :: Val{1} ) where T<: fftwNumber
352
+ function plan_chebyshevutransform (x:: AbstractArray{T,N } , :: Val{1} , dims ... ; kws ... ) where { T<: fftwNumber ,N}
354
353
if isempty (x)
355
- ChebyshevUTransformPlan {T,1,false,(9, )} ()
354
+ ChebyshevUTransformPlan {T,1,kindtuple(UFIRSTKIND,N,dims...), false,N,isempty(dims) ? UnitRange{Int} : typeof(dims )} ()
356
355
else
357
- ChebyshevUTransformPlan {T,1,false,(9, )} (FFTW. plan_r2r! (x, FFTW. RODFT10))
356
+ ChebyshevUTransformPlan {T,1,kindtuple(UFIRSTKIND,N,dims... )} (FFTW. plan_r2r (x, FFTW. RODFT10, dims ... ; kws ... ))
358
357
end
359
358
end
360
- function plan_chebyshevutransform (x:: AbstractVector{T } , :: Val{2} ) where T<: fftwNumber
361
- length (x) ≤ 1 && throw (ArgumentError (" Vector must contain at least 2 entries" ))
362
- ChebyshevUTransformPlan {T,2,false,(7, )} (FFTW. plan_r2r! (x, FFTW. RODFT00))
359
+ function plan_chebyshevutransform (x:: AbstractArray{T,N } , :: Val{2} , dims ... ; kws ... ) where { T<: fftwNumber ,N}
360
+ any ( ≤ ( 1 ), size (x)) && throw (ArgumentError (" Array must contain at least 2 entries" ))
361
+ ChebyshevUTransformPlan {T,2,kindtuple(USECONDKIND,N,dims... )} (FFTW. plan_r2r (x, FFTW. RODFT00, dims ... ; kws ... ))
363
362
end
364
363
365
- plan_chebyshevutransform! (x:: AbstractVector ) = plan_chebyshevutransform! (x, Val (1 ))
366
- plan_chebyshevutransform (x:: AbstractVector ) = plan_chebyshevutransform (x, Val (1 ))
364
+ plan_chebyshevutransform! (x:: AbstractArray , dims ... ; kws ... ) = plan_chebyshevutransform! (x, Val (1 ), dims ... ; kws ... )
365
+ plan_chebyshevutransform (x:: AbstractArray , dims ... ; kws ... ) = plan_chebyshevutransform (x, Val (1 ), dims ... ; kws ... )
367
366
368
367
369
- function * (P :: ChebyshevUTransformPlan{T,1,true} , x:: AbstractVector{T} ) where T
368
+ @inline function _chebu1_prescale! (_, x:: AbstractVector{T} ) where T
370
369
n = length (x)
371
- n ≤ 1 && return x
372
-
373
370
for k= 1 : n # sqrt(1-x_j^2) weight
374
371
x[k] *= sinpi (one (T)/ (2 n) + (k- one (T))/ n)/ n
375
372
end
373
+ x
374
+ end
375
+
376
+ @inline function _chebu1_postscale! (_, x:: AbstractVector{T} ) where T
377
+ n = length (x)
378
+ for k= 1 : n # sqrt(1-x_j^2) weight
379
+ x[k] /= sinpi (one (T)/ (2 n) + (k- one (T))/ n)/ n
380
+ end
381
+ x
382
+ end
383
+
384
+ function * (P:: ChebyshevUTransformPlan{T,1,K,true} , x:: AbstractVector{T} ) where {T,K}
385
+ length (x) ≤ 1 && return x
386
+ _chebu1_prescale! (P. plan. region, x)
376
387
P. plan * x
377
388
end
378
389
379
- function * ( P:: ChebyshevUTransformPlan{T,2,true } , x:: AbstractVector{T} ) where T
390
+ function mul! (y :: AbstractVector{T} , P:: ChebyshevUTransformPlan{T,1,K,false } , x:: AbstractVector{T} ) where {T,K}
380
391
n = length (x)
381
- n ≤ 1 && return x
392
+ length (x) ≤ 1 && return copyto! (y, x)
393
+ _chebu1_prescale! (P. plan. region, x)
394
+ _plan_mul! (y, P. plan, x)
395
+ _chebu1_postscale! (P. plan. region, x)
396
+ y
397
+ end
382
398
399
+ @inline function _chebu2_prescale! (_, x:: AbstractVector{T} ) where T
400
+ n = length (x)
383
401
c = one (T)/ (n+ 1 )
384
402
for k= 1 : n # sqrt(1-x_j^2) weight
385
403
x[k] *= sinpi (k* c)
386
404
end
387
- lmul! (c, P. plan * x)
405
+ x
406
+ end
407
+
408
+ @inline function _chebu2_postscale! (_, x:: AbstractVector{T} ) where T
409
+ n = length (x)
410
+ c = one (T)/ (n+ 1 )
411
+ for k= 1 : n # sqrt(1-x_j^2) weight
412
+ x[k] /= sinpi (k* c)
413
+ end
414
+ x
388
415
end
389
416
390
- chebyshevutransform! (x:: AbstractVector{T} , kind= Val (1 )) where {T<: fftwNumber } =
391
- plan_chebyshevutransform! (x, kind)* x
417
+ function * (P:: ChebyshevUTransformPlan{T,2,K,true} , x:: AbstractVector{T} ) where {T,K}
418
+ n = length (x)
419
+ n ≤ 1 && return x
420
+ _chebu2_prescale! (P. plan. region, x)
421
+ lmul! (one (T)/ (n+ 1 ), P. plan * x)
422
+ end
423
+
424
+ function mul! (y:: AbstractVector{T} , P:: ChebyshevUTransformPlan{T,2,K,false} , x:: AbstractVector{T} ) where {T,K}
425
+ n = length (x)
426
+ n ≤ 1 && return copyto! (y, x)
427
+ _chebu2_prescale! (P. plan. region, x)
428
+ _plan_mul! (y, P. plan, x)
429
+ _chebu2_postscale! (P. plan. region, x)
430
+ lmul! (one (T)/ (n+ 1 ), y)
431
+ end
432
+
433
+ * (P:: ChebyshevUTransformPlan{T,kind,K,false,N} , x:: AbstractArray{T,N} ) where {T,kind,K,N} =
434
+ mul! (similar (x), P, x)
435
+
436
+ chebyshevutransform! (x:: AbstractVector{T} , dims... ; kws... ) where {T<: fftwNumber } =
437
+ plan_chebyshevutransform! (x, dims... ; kws... )* x
392
438
393
439
394
440
"""
@@ -397,9 +443,8 @@ chebyshevutransform!(x::AbstractVector{T}, kind=Val(1)) where {T<:fftwNumber} =
397
443
transforms from values on a Chebyshev grid of the first or second kind to Chebyshev
398
444
coefficients of the 2nd kind (Chebyshev U expansion).
399
445
"""
400
- chebyshevutransform (x, kind = Val ( 1 )) = chebyshevutransform! ( Array (x), kind)
446
+ chebyshevutransform (x, dims ... ; kws ... ) = plan_chebyshevutransform (x, dims ... ; kws ... ) * x
401
447
402
- * (P:: ChebyshevUTransformPlan{T,k,false} , x:: AbstractVector{T} ) where {T,k} = ChebyshevUTransformPlan {T,k,true} (P)* Array (x)
403
448
404
449
# # Inverse transforms take ChebyshevU coefficients and produce values at ChebyshevU points of the first and second kinds
405
450
0 commit comments