
# const TRAVIS_SKIP = VERSION.minor != 4 && !isnothing(get(ENV, "TRAVIS_BRANCH", nothing))

function test_fixed_size(A, At, B, Bt, Aa, Aat, Ba, Bat)::NTuple{4,Float64}
    t0 = @elapsed(@test Aa * Ba ≈ A * B)
    t1 = @elapsed(@test Aa * Bat ≈ A * Bt)
    t2 = @elapsed(@test Aat * Ba ≈ At * B)
    t3 = @elapsed(@test Aat * Bat ≈ At * Bt)
    t0, t1, t2, t3
end
    

function test_fixed_size(M, K, N)
    A = @StrideArray rand(M,K);
    B = @StrideArray rand(K,N);
    At = (@StrideArray rand(K,M))';
    Bt = (@StrideArray rand(N,K))';
    Aa = Array(A); Ba = Array(B);
    Aat = Array(At); Bat = Array(Bt);
    t0 = test_fixed_size(A, At, B, Bt, Aa, Aat, Ba, Bat)
    t1 = test_fixed_size(StrideArrays.make_dynamic(A), StrideArrays.make_dynamic(At), B, Bt, Aa, Aat, Ba, Bat)
    t2 = test_fixed_size(A, At, StrideArrays.make_dynamic(B), StrideArrays.make_dynamic(Bt), Aa, Aat, Ba, Bat)
    t3 = test_fixed_size(StrideArrays.make_dynamic(A), StrideArrays.make_dynamic(At), StrideArrays.make_dynamic(B), StrideArrays.make_dynamic(Bt), Aa, Aat, Ba, Bat)
    gflops = let gflop = 2e-9M*K*N
        map((t0, t1, t2, t3)) do t
            gflop ./ t
        end
    end
    @show (M,K,N), gflops
    nothing
end

test_fixed_size(M) = test_fixed_size(M, M, M)

# gmul(A, B) = LinearAlgebra.generic_matmatmul('N','N', A, B)

@testset "MatrixMultiply" begin
    r = 2:12
    for M ∈ r, K ∈ r, N ∈ r
        test_fixed_size(M, K, N)
    end
    r = 13:33
    for M ∈ r
        test_fixed_size(M)
    end
    M = K = N = 80
    A = @StrideArray rand(M,K);
    B = @StrideArray rand(K,N);
    C = StrideArray{Float64}(undef, (StaticInt(M),StaticInt(N)));
    M, K, N = 23, 37, 19
    @views begin
        Av = A[1:M, 1:K]; 
        Bv = B[1:K, 1:N]; 
        Cv = C[1:M, 1:N]; 
        Avsl = A[StaticInt(1):M, StaticInt(1):K]; 
        Bvsl = B[StaticInt(1):K, StaticInt(1):N]; 
        Cvsl = C[StaticInt(1):M, StaticInt(1):N]; 
        Avsr = A[StaticInt(1):StaticInt(M), StaticInt(1):StaticInt(K)]; 
        Bvsr = B[StaticInt(1):StaticInt(K), StaticInt(1):StaticInt(N)]; 
        Cvsr = C[StaticInt(1):StaticInt(M), StaticInt(1):StaticInt(N)]; 
    end
    Creference = Array(Av) * Array(Bvsl);
    time = @elapsed mul!(Cv, Av, Bv)
    @test Creference ≈ Cv
    @show M, K, N, time
    time = @elapsed mul!(Cvsl, Avsl, Bvsl)
    @test Creference ≈ Cv
    @show M, K, N, time
    time = @elapsed mul!(Cvsr, Avsr, Bvsr)
    @test Creference ≈ Cv
    @show M, K, N, time

    Av = A[1:M, 1:K]; 
    Bv = B[1:K, 1:N]; 
    Cv = C[1:M, 1:N]; 
    Avsl = A[StaticInt(1):M, StaticInt(1):K]; 
    Bvsl = B[StaticInt(1):K, StaticInt(1):N]; 
    Cvsl = C[StaticInt(1):M, StaticInt(1):N]; 
    Avsr = A[StaticInt(1):StaticInt(M), StaticInt(1):StaticInt(K)]; 
    Bvsr = B[StaticInt(1):StaticInt(K), StaticInt(1):StaticInt(N)]; 
    Cvsr = C[StaticInt(1):StaticInt(M), StaticInt(1):StaticInt(N)]; 
    Creference = Array(Av) * Array(Bvsl);
    time = @elapsed mul!(Cv, Av, Bv)
    @test Creference ≈ Cv
    @show M, K, N, time
    time = @elapsed mul!(Cvsl, Avsl, Bvsl)
    @test Creference ≈ Cv
    @show M, K, N, time
    time = @elapsed mul!(Cvsr, Avsr, Bvsr)
    @test Creference ≈ Cv
    @show M, K, N, time
end


