diff --git a/src/Hadamard.jl b/src/Hadamard.jl index f3ac173..048c490 100644 --- a/src/Hadamard.jl +++ b/src/Hadamard.jl @@ -17,8 +17,8 @@ module Hadamard export fwht, ifwht, fwht_natural, ifwht_natural, fwht_natural!, ifwht_natural!, fwht_dyadic, ifwht_dyadic, hadamard, walsh using FFTW, LinearAlgebra -import FFTW: set_timelimit, dims_howmany, unsafe_execute!, cFFTWPlan, r2rFFTWPlan, PlanPtr, fftwNumber, ESTIMATE, NO_TIMELIMIT, R2HC -import AbstractFFTs: normalization, complexfloat +using FFTW: unsafe_set_timelimit, @exclusive, dims_howmany, unsafe_execute!, cFFTWPlan, r2rFFTWPlan, PlanPtr, fftwNumber, ESTIMATE, NO_TIMELIMIT, R2HC +using AbstractFFTs: normalization, complexfloat # A power-of-two dimension to be transformed is interpreted as a # 2x2x2x....x2x2 multidimensional DFT. This function transforms @@ -62,11 +62,12 @@ const libfftwf = isdefined(FFTW, :libfftwf) ? FFTW.libfftwf : FFTW.libfftw3f for (Tr,Tc,fftw,lib) in ((:Float64,:ComplexF64,"fftw",libfftw), (:Float32,:ComplexF32,"fftwf",libfftwf)) - @eval function Plan_Hadamard(X::StridedArray{$Tc,N}, Y::StridedArray{$Tc,N}, + @eval @exclusive function Plan_Hadamard(X::StridedArray{$Tc,N}, Y::StridedArray{$Tc,N}, region, flags::Unsigned, timelimit::Real, bitreverse::Bool) where {N} - set_timelimit($Tr, timelimit) - dims, howmany = dims_howmany(X, Y, [size(X)...], region) + unsafe_set_timelimit($Tr, timelimit) + R = isa(region, Tuple) ? region : copy(region) + dims, howmany = dims_howmany(X, Y, size(X), R) dims = hadamardize(dims, bitreverse) plan = ccall(($(string(fftw,"_plan_guru64_dft")),$lib[]), PlanPtr, @@ -74,7 +75,7 @@ for (Tr,Tc,fftw,lib) in ((:Float64,:ComplexF64,"fftw",libfftw), Ptr{$Tc}, Ptr{$Tc}, Int32, UInt32), size(dims,2), dims, size(howmany,2), howmany, X, Y, FFTW.FORWARD, flags) - set_timelimit($Tr, NO_TIMELIMIT) + unsafe_set_timelimit($Tr, NO_TIMELIMIT) if plan == C_NULL if $(FFTW.fftw_provider == "mkl") error("MKL is not supported — reconfigure FFTW.jl to use FFTW") @@ -82,14 +83,15 @@ for (Tr,Tc,fftw,lib) in ((:Float64,:ComplexF64,"fftw",libfftw), error("FFTW could not create plan") # shouldn't normally happen end end - return cFFTWPlan{$Tc,FFTW.FORWARD,X===Y,N}(plan, flags, region, X, Y) + return cFFTWPlan{$Tc,FFTW.FORWARD,X===Y,N}(plan, flags, R, X, Y) end - @eval function Plan_Hadamard(X::StridedArray{$Tr,N}, Y::StridedArray{$Tr,N}, + @eval @exclusive function Plan_Hadamard(X::StridedArray{$Tr,N}, Y::StridedArray{$Tr,N}, region, flags::Unsigned, timelimit::Real, bitreverse::Bool) where {N} - set_timelimit($Tr, timelimit) - dims, howmany = dims_howmany(X, Y, [size(X)...], region) + unsafe_set_timelimit($Tr, timelimit) + R = isa(region, Tuple) ? region : copy(region) + dims, howmany = dims_howmany(X, Y, size(X), R) dims = hadamardize(dims, bitreverse) kind = Array{Int32}(undef, size(dims,2)) kind .= R2HC @@ -99,7 +101,7 @@ for (Tr,Tc,fftw,lib) in ((:Float64,:ComplexF64,"fftw",libfftw), Ptr{$Tr}, Ptr{$Tr}, Ptr{Int32}, UInt32), size(dims,2), dims, size(howmany,2), howmany, X, Y, kind, flags) - set_timelimit($Tr, NO_TIMELIMIT) + unsafe_set_timelimit($Tr, NO_TIMELIMIT) if plan == C_NULL if $(FFTW.fftw_provider == "mkl") error("MKL is not supported — reconfigure FFTW.jl to use FFTW") @@ -107,7 +109,7 @@ for (Tr,Tc,fftw,lib) in ((:Float64,:ComplexF64,"fftw",libfftw), error("FFTW could not create plan") # shouldn't normally happen end end - return r2rFFTWPlan{$Tr,Vector{Int32},X===Y,N}(plan, flags, region, X, Y, kind) + return r2rFFTWPlan{$Tr,Vector{Int32},X===Y,N}(plan, flags, R, X, Y, kind) end end @@ -371,7 +373,7 @@ end """ walsh(n) -Return a Walsh matrix of order `n`, which must be a power of two, in sequency ordering. +Return a Walsh matrix of order `n`, which must be a power of two, in sequency ordering. This is related to the Hadamard matrix [`hadamard(n)`](@ref) by a bit-reversal permutation followed by a Gray-code permutation of the rows. @@ -390,7 +392,7 @@ function walsh(n::Int) j = b ⊻ (b >> 1) # binary sequency index j + 1 # 1-based index end - for i in 0:n-1 ] + for i in 0:n-1 ] return hadamard(n)[j, :] end diff --git a/test/runtests.jl b/test/runtests.jl index 129d7ed..d4a33d2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,133 +1,138 @@ using Hadamard, Test, LinearAlgebra -H8 = [ 1 1 1 1 1 1 1 1 - 1 1 1 1 -1 -1 -1 -1 - 1 1 -1 -1 -1 -1 1 1 - 1 1 -1 -1 1 1 -1 -1 - 1 -1 -1 1 1 -1 -1 1 - 1 -1 -1 1 -1 1 1 -1 - 1 -1 1 -1 -1 1 -1 1 - 1 -1 1 -1 1 -1 1 -1 ] - -H8n = [ 1 1 1 1 1 1 1 1 - 1 -1 1 -1 1 -1 1 -1 - 1 1 -1 -1 1 1 -1 -1 - 1 -1 -1 1 1 -1 -1 1 - 1 1 1 1 -1 -1 -1 -1 - 1 -1 1 -1 -1 1 -1 1 - 1 1 -1 -1 -1 -1 1 1 - 1 -1 -1 1 -1 1 1 -1 ] - -H8d = [ 1 1 1 1 1 1 1 1 - 1 1 1 1 -1 -1 -1 -1 - 1 1 -1 -1 1 1 -1 -1 - 1 1 -1 -1 -1 -1 1 1 - 1 -1 1 -1 1 -1 1 -1 - 1 -1 1 -1 -1 1 -1 1 - 1 -1 -1 1 1 -1 -1 1 - 1 -1 -1 1 -1 1 1 -1 ] - - -I8 = Matrix{Float64}(I,8,8) -iI8 = Matrix{Int8}(I,8,8) - -@test ifwht(I8,1) == H8 -@test ifwht(I8,2)' == H8 -@test ifwht_natural(I8,1) == H8n -@test ifwht_natural(I8,2)' == H8n -@test ifwht_dyadic(I8,1) == H8d -@test ifwht_dyadic(I8,2)' == H8d - -@test ifwht(iI8,1) == H8 -@test ifwht(iI8,2)' == H8 -@test ifwht_natural(iI8,1) == H8n -@test ifwht_natural(iI8,2)' == H8n -@test ifwht_dyadic(iI8,1) == H8d -@test ifwht_dyadic(iI8,2)' == H8d - -H32 = [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 - 1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 - 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 - 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 1 1 1 1 -1 -1 -1 -1 - 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 - 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 - 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 - 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 - 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 - 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 - 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 - 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 1 1 -1 -1 - 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 - 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 - 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 - 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 - 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 - 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 - 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 - 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 - 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 - 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 - 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 - 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 - 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 - 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 - 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 - 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 1 -1 1 -1 - 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 - 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 ] - - I32 = Matrix{Float64}(I,32,32) - iI32 = Matrix{Int8}(I,32,32) - -@test ifwht(I32,1) == H32 -@test ifwht(I32,2)' == H32 - -@test ifwht(iI32,1) == H32 -@test ifwht(iI32,2)' == H32 - -X = reshape(sin.([1:1024*32;]), 1024,32); norminf(A) = maximum(abs, A) # non-lazy transpose for 0.7: transp(x::AbstractMatrix) = permutedims(x, (2,1)) -for f in (:fwht, :fwht_natural, :fwht_dyadic) - fi = Symbol(string("i", f)) - @eval begin - @test norminf(X - $fi($f(X))) < 1e-14 - @test norminf(X - $fi($f(X,1),1)) < 1e-14 - @test norminf(X - $fi($f(X,2),2)) < 1e-14 - @test norminf($f($f(X,1),2) - $f(X)) < 1e-14 - @test norminf(transp($f(transp(X),1)) - $f(X,2)) < 1e-14 +# test input data +X = reshape(sin.([1:1024*32;]), 1024,32) + +@testset "fast Walsh–Hadamard transforms" begin + H8 = [ 1 1 1 1 1 1 1 1 + 1 1 1 1 -1 -1 -1 -1 + 1 1 -1 -1 -1 -1 1 1 + 1 1 -1 -1 1 1 -1 -1 + 1 -1 -1 1 1 -1 -1 1 + 1 -1 -1 1 -1 1 1 -1 + 1 -1 1 -1 -1 1 -1 1 + 1 -1 1 -1 1 -1 1 -1 ] + + H8n = [ 1 1 1 1 1 1 1 1 + 1 -1 1 -1 1 -1 1 -1 + 1 1 -1 -1 1 1 -1 -1 + 1 -1 -1 1 1 -1 -1 1 + 1 1 1 1 -1 -1 -1 -1 + 1 -1 1 -1 -1 1 -1 1 + 1 1 -1 -1 -1 -1 1 1 + 1 -1 -1 1 -1 1 1 -1 ] + + H8d = [ 1 1 1 1 1 1 1 1 + 1 1 1 1 -1 -1 -1 -1 + 1 1 -1 -1 1 1 -1 -1 + 1 1 -1 -1 -1 -1 1 1 + 1 -1 1 -1 1 -1 1 -1 + 1 -1 1 -1 -1 1 -1 1 + 1 -1 -1 1 1 -1 -1 1 + 1 -1 -1 1 -1 1 1 -1 ] + + + I8 = Matrix{Float64}(I,8,8) + iI8 = Matrix{Int8}(I,8,8) + + @test ifwht(I8,1) == H8 + @test ifwht(I8,2)' == H8 + @test ifwht_natural(I8,1) == H8n + @test ifwht_natural(I8,2)' == H8n + @test ifwht_dyadic(I8,1) == H8d + @test ifwht_dyadic(I8,2)' == H8d + + @test ifwht(iI8,1) == H8 + @test ifwht(iI8,2)' == H8 + @test ifwht_natural(iI8,1) == H8n + @test ifwht_natural(iI8,2)' == H8n + @test ifwht_dyadic(iI8,1) == H8d + @test ifwht_dyadic(iI8,2)' == H8d + + H32 = [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 + 1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 + 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 + 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 1 1 1 1 -1 -1 -1 -1 + 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 + 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 + 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 + 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 + 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 + 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 + 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 + 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 1 1 -1 -1 + 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 + 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 + 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 + 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 + 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 + 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 + 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 + 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 + 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 + 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 + 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 + 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 + 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 + 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 + 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 + 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1 1 -1 1 -1 + 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 + 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 ] + + I32 = Matrix{Float64}(I,32,32) + iI32 = Matrix{Int8}(I,32,32) + + @test ifwht(I32,1) == H32 + @test ifwht(I32,2)' == H32 + + @test ifwht(iI32,1) == H32 + @test ifwht(iI32,2)' == H32 + + for f in (:fwht, :fwht_natural, :fwht_dyadic) + fi = Symbol(string("i", f)) + @eval begin + @test norminf(X - $fi($f(X))) < 1e-14 + @test norminf(X - $fi($f(X,1),1)) < 1e-14 + @test norminf(X - $fi($f(X,2),2)) < 1e-14 + @test norminf($f($f(X,1),2) - $f(X)) < 1e-14 + @test norminf(transp($f(transp(X),1)) - $f(X,2)) < 1e-14 + end end -end -@test hadamard(8) == H8n -@test ifwht_natural(I32, 1) == hadamard(32) -@test ifwht_natural(Matrix{Float64}(I,2,2), 1) == hadamard(2) + @test hadamard(8) == H8n + @test ifwht_natural(I32, 1) == hadamard(32) + @test ifwht_natural(Matrix{Float64}(I,2,2), 1) == hadamard(2) -let X = copy(I32) - @test ifwht_natural!(X, 1) == X == hadamard(32) - @test fwht_natural!(X, 1) == X == I32 + let X = copy(I32) + @test ifwht_natural!(X, 1) == X == hadamard(32) + @test fwht_natural!(X, 1) == X == I32 + end end -print("Checking unitarity of hadamard(n): ") -sizes = Int[] -for i = 4:4:1200 - H = try - Matrix{Int}(hadamard(i)) - catch - Int[] - end - if !isempty(H) - print(i, ", ") - @test norminf(H'*H - size(H,1)*I) == 0 - push!(sizes, i) +@testset "hadamard(n)" begin + sizes = Int[] + for i = 4:4:1200 + H = try + Matrix{Int}(hadamard(i)) + catch + Matrix{Int}(undef,0,0) + end + if !isempty(H) + # print(i, ", ") + @test norminf(H'*H - size(H,1)*I) == 0 + push!(sizes, i) + end end + @test sizes == [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, 344, 352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 428, 432, 440, 448, 456, 464, 472, 480, 488, 496, 504, 512, 528, 544, 560, 576, 592, 608, 624, 640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, 848, 856, 864, 880, 896, 912, 928, 944, 960, 976, 992, 1008, 1024, 1040, 1056, 1088, 1104, 1120, 1152, 1184, 1200] end -@test sizes == [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, 344, 352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 428, 432, 440, 448, 456, 464, 472, 480, 488, 496, 504, 512, 528, 544, 560, 576, 592, 608, 624, 640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, 848, 856, 864, 880, 896, 912, 928, 944, 960, 976, 992, 1008, 1024, 1040, 1056, 1088, 1104, 1120, 1152, 1184, 1200] @testset "walsh(n)" begin @test walsh(8) == [1 1 1 1 1 1 1 1; 1 1 1 1 -1 -1 -1 -1; 1 1 -1 -1 -1 -1 1 1; 1 1 -1 -1 1 1 -1 -1; 1 -1 -1 1 1 -1 -1 1; 1 -1 -1 1 -1 1 1 -1; 1 -1 1 -1 -1 1 -1 1; 1 -1 1 -1 1 -1 1 -1] @@ -137,4 +142,3 @@ end end end -println(".\nSuccess!")