text:
# RUN: julia -e "import Brutus; Brutus.lit(:emit_lowered)" --startup-file=no %s 2>&1 | FileCheck %s

# Intentionally bad code
function matmul!(C, A, B)
    for i in 1:size(A, 1)
        for k in 1:size(A, 2)
            for j in 1:size(B, 2)
                @inbounds C[i, j] += A[i, k] * B[k, j]
            end
        end
    end
    return nothing
end

emit(matmul!, Matrix{Float64}, Matrix{Float64}, Matrix{Float64})

# CHECK: Core.MethodMatch(Tuple{typeof(Main.Main.matmul!), Matrix{Float64}, Matrix{Float64}, Matrix{Float64}}, svec(), matmul!(C, A, B) in Main.Main at /{{.*}}/test/Codegen/lower/matmul.jl:4, true)after translating to MLIR in JLIR dialect:module  {
# CHECK-NEXT:   func nested @"Tuple{typeof(Main.matmul!), Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}}"(%arg0: !jlir<"typeof(Main.matmul!)">, %arg1: !jlir<"Array{Float64, 2}">, %arg2: !jlir<"Array{Float64, 2}">, %arg3: !jlir<"Array{Float64, 2}">) -> !jlir.Nothing attributes {llvm.emit_c_interface} {
# CHECK-NEXT:     "jlir.goto"()[^bb1] : () -> ()
# CHECK-NEXT:   ^bb1:  // pred: ^bb0
# CHECK-NEXT:     %0 = "jlir.constant"() {value = #jlir.Core.arraysize} : () -> !jlir<"typeof(Core.arraysize)">
# CHECK-NEXT:     %1 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %2 = "jlir.call"(%0, %arg2, %1) : (!jlir<"typeof(Core.arraysize)">, !jlir<"Array{Float64, 2}">, !jlir.Int64) -> !jlir.Int64
# CHECK-NEXT:     %3 = "jlir.constant"() {value = #jlir<"#<intrinsic #29 sle_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %4 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %5 = "jlir.call"(%3, %4, %2) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     %6 = "jlir.constant"() {value = #jlir.ifelse} : () -> !jlir<"typeof(ifelse)">
# CHECK-NEXT:     %7 = "jlir.constant"() {value = #jlir<"0">} : () -> !jlir.Int64
# CHECK-NEXT:     %8 = "jlir.call"(%6, %5, %2, %7) : (!jlir<"typeof(ifelse)">, !jlir.Bool, !jlir.Int64, !jlir.Int64) -> !jlir.Int64
# CHECK-NEXT:     %9 = "jlir.constant"() {value = #jlir<"#<intrinsic #27 slt_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %10 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %11 = "jlir.call"(%9, %8, %10) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%11)[^bb3, ^bb2] {operand_segment_sizes = dense<[1, 0, 0]> : vector<3xi32>} : (!jlir.Bool) -> ()
# CHECK-NEXT:   ^bb2:  // pred: ^bb1
# CHECK-NEXT:     %12 = "jlir.constant"() {value = #jlir.true} : () -> !jlir.Bool
# CHECK-NEXT:     %13 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %14 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     "jlir.goto"(%12, %13, %14)[^bb4] : (!jlir.Bool, !jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb3:  // pred: ^bb1
# CHECK-NEXT:     %15 = "jlir.constant"() {value = #jlir.false} : () -> !jlir.Bool
# CHECK-NEXT:     %16 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %17 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     "jlir.goto"(%15, %16, %17)[^bb4] : (!jlir.Bool, !jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb4(%18: !jlir.Bool, %19: !jlir.Int64, %20: !jlir.Int64):  // 2 preds: ^bb2, ^bb3
# CHECK-NEXT:     %21 = "jlir.constant"() {value = #jlir<"#<intrinsic #44 not_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %22 = "jlir.call"(%21, %18) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Bool) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%22, %19, %20)[^bb28, ^bb5] {operand_segment_sizes = dense<[1, 0, 2]> : vector<3xi32>} : (!jlir.Bool, !jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb5(%23: !jlir.Int64, %24: !jlir.Int64):  // 2 preds: ^bb4, ^bb27
# CHECK-NEXT:     %25 = "jlir.constant"() {value = #jlir.Core.arraysize} : () -> !jlir<"typeof(Core.arraysize)">
# CHECK-NEXT:     %26 = "jlir.constant"() {value = #jlir<"2">} : () -> !jlir.Int64
# CHECK-NEXT:     %27 = "jlir.call"(%25, %arg2, %26) : (!jlir<"typeof(Core.arraysize)">, !jlir<"Array{Float64, 2}">, !jlir.Int64) -> !jlir.Int64
# CHECK-NEXT:     %28 = "jlir.constant"() {value = #jlir<"#<intrinsic #29 sle_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %29 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %30 = "jlir.call"(%28, %29, %27) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     %31 = "jlir.constant"() {value = #jlir.ifelse} : () -> !jlir<"typeof(ifelse)">
# CHECK-NEXT:     %32 = "jlir.constant"() {value = #jlir<"0">} : () -> !jlir.Int64
# CHECK-NEXT:     %33 = "jlir.call"(%31, %30, %27, %32) : (!jlir<"typeof(ifelse)">, !jlir.Bool, !jlir.Int64, !jlir.Int64) -> !jlir.Int64
# CHECK-NEXT:     %34 = "jlir.constant"() {value = #jlir<"#<intrinsic #27 slt_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %35 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %36 = "jlir.call"(%34, %33, %35) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%36)[^bb7, ^bb6] {operand_segment_sizes = dense<[1, 0, 0]> : vector<3xi32>} : (!jlir.Bool) -> ()
# CHECK-NEXT:   ^bb6:  // pred: ^bb5
# CHECK-NEXT:     %37 = "jlir.constant"() {value = #jlir.true} : () -> !jlir.Bool
# CHECK-NEXT:     %38 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %39 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     "jlir.goto"(%37, %38, %39)[^bb8] : (!jlir.Bool, !jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb7:  // pred: ^bb5
# CHECK-NEXT:     %40 = "jlir.constant"() {value = #jlir.false} : () -> !jlir.Bool
# CHECK-NEXT:     %41 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %42 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     "jlir.goto"(%40, %41, %42)[^bb8] : (!jlir.Bool, !jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb8(%43: !jlir.Bool, %44: !jlir.Int64, %45: !jlir.Int64):  // 2 preds: ^bb6, ^bb7
# CHECK-NEXT:     %46 = "jlir.constant"() {value = #jlir<"#<intrinsic #44 not_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %47 = "jlir.call"(%46, %43) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Bool) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%47, %44, %45)[^bb23, ^bb9] {operand_segment_sizes = dense<[1, 0, 2]> : vector<3xi32>} : (!jlir.Bool, !jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb9(%48: !jlir.Int64, %49: !jlir.Int64):  // 2 preds: ^bb8, ^bb22
# CHECK-NEXT:     %50 = "jlir.constant"() {value = #jlir.Core.arraysize} : () -> !jlir<"typeof(Core.arraysize)">
# CHECK-NEXT:     %51 = "jlir.constant"() {value = #jlir<"2">} : () -> !jlir.Int64
# CHECK-NEXT:     %52 = "jlir.call"(%50, %arg3, %51) : (!jlir<"typeof(Core.arraysize)">, !jlir<"Array{Float64, 2}">, !jlir.Int64) -> !jlir.Int64
# CHECK-NEXT:     %53 = "jlir.constant"() {value = #jlir<"#<intrinsic #29 sle_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %54 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %55 = "jlir.call"(%53, %54, %52) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     %56 = "jlir.constant"() {value = #jlir.ifelse} : () -> !jlir<"typeof(ifelse)">
# CHECK-NEXT:     %57 = "jlir.constant"() {value = #jlir<"0">} : () -> !jlir.Int64
# CHECK-NEXT:     %58 = "jlir.call"(%56, %55, %52, %57) : (!jlir<"typeof(ifelse)">, !jlir.Bool, !jlir.Int64, !jlir.Int64) -> !jlir.Int64
# CHECK-NEXT:     %59 = "jlir.constant"() {value = #jlir<"#<intrinsic #27 slt_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %60 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %61 = "jlir.call"(%59, %58, %60) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%61)[^bb11, ^bb10] {operand_segment_sizes = dense<[1, 0, 0]> : vector<3xi32>} : (!jlir.Bool) -> ()
# CHECK-NEXT:   ^bb10:  // pred: ^bb9
# CHECK-NEXT:     %62 = "jlir.constant"() {value = #jlir.true} : () -> !jlir.Bool
# CHECK-NEXT:     %63 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %64 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     "jlir.goto"(%62, %63, %64)[^bb12] : (!jlir.Bool, !jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb11:  // pred: ^bb9
# CHECK-NEXT:     %65 = "jlir.constant"() {value = #jlir.false} : () -> !jlir.Bool
# CHECK-NEXT:     %66 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %67 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     "jlir.goto"(%65, %66, %67)[^bb12] : (!jlir.Bool, !jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb12(%68: !jlir.Bool, %69: !jlir.Int64, %70: !jlir.Int64):  // 2 preds: ^bb10, ^bb11
# CHECK-NEXT:     %71 = "jlir.constant"() {value = #jlir<"#<intrinsic #44 not_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %72 = "jlir.call"(%71, %68) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Bool) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%72, %69, %70)[^bb18, ^bb13] {operand_segment_sizes = dense<[1, 0, 2]> : vector<3xi32>} : (!jlir.Bool, !jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb13(%73: !jlir.Int64, %74: !jlir.Int64):  // 2 preds: ^bb12, ^bb17
# CHECK-NEXT:     %75 = "jlir.constant"() {value = #jlir.Core.arrayref} : () -> !jlir<"typeof(Core.arrayref)">
# CHECK-NEXT:     %76 = "jlir.constant"() {value = #jlir.false} : () -> !jlir.Bool
# CHECK-NEXT:     %77 = "jlir.call"(%75, %76, %arg1, %23, %73) : (!jlir<"typeof(Core.arrayref)">, !jlir.Bool, !jlir<"Array{Float64, 2}">, !jlir.Int64, !jlir.Int64) -> !jlir.Float64
# CHECK-NEXT:     %78 = "jlir.constant"() {value = #jlir.Core.arrayref} : () -> !jlir<"typeof(Core.arrayref)">
# CHECK-NEXT:     %79 = "jlir.constant"() {value = #jlir.false} : () -> !jlir.Bool
# CHECK-NEXT:     %80 = "jlir.call"(%78, %79, %arg2, %23, %48) : (!jlir<"typeof(Core.arrayref)">, !jlir.Bool, !jlir<"Array{Float64, 2}">, !jlir.Int64, !jlir.Int64) -> !jlir.Float64
# CHECK-NEXT:     %81 = "jlir.constant"() {value = #jlir.Core.arrayref} : () -> !jlir<"typeof(Core.arrayref)">
# CHECK-NEXT:     %82 = "jlir.constant"() {value = #jlir.false} : () -> !jlir.Bool
# CHECK-NEXT:     %83 = "jlir.call"(%81, %82, %arg3, %48, %73) : (!jlir<"typeof(Core.arrayref)">, !jlir.Bool, !jlir<"Array{Float64, 2}">, !jlir.Int64, !jlir.Int64) -> !jlir.Float64
# CHECK-NEXT:     %84 = "jlir.constant"() {value = #jlir<"#<intrinsic #14 mul_float>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %85 = "jlir.call"(%84, %80, %83) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Float64, !jlir.Float64) -> !jlir.Float64
# CHECK-NEXT:     %86 = "jlir.constant"() {value = #jlir<"#<intrinsic #12 add_float>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %87 = "jlir.call"(%86, %77, %85) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Float64, !jlir.Float64) -> !jlir.Float64
# CHECK-NEXT:     %88 = "jlir.constant"() {value = #jlir.Core.arrayset} : () -> !jlir<"typeof(Core.arrayset)">
# CHECK-NEXT:     %89 = "jlir.constant"() {value = #jlir.false} : () -> !jlir.Bool
# CHECK-NEXT:     %90 = "jlir.call"(%88, %89, %arg1, %87, %23, %73) : (!jlir<"typeof(Core.arrayset)">, !jlir.Bool, !jlir<"Array{Float64, 2}">, !jlir.Float64, !jlir.Int64, !jlir.Int64) -> !jlir<"Array{Float64, 2}">
# CHECK-NEXT:     %91 = "jlir.constant"() {value = #jlir<"===">} : () -> !jlir<"typeof(===)">
# CHECK-NEXT:     %92 = "jlir.call"(%91, %74, %58) : (!jlir<"typeof(===)">, !jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%92)[^bb15, ^bb14] {operand_segment_sizes = dense<[1, 0, 0]> : vector<3xi32>} : (!jlir.Bool) -> ()
# CHECK-NEXT:   ^bb14:  // pred: ^bb13
# CHECK-NEXT:     %93 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %94 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %95 = "jlir.constant"() {value = #jlir.true} : () -> !jlir.Bool
# CHECK-NEXT:     "jlir.goto"(%93, %94, %95)[^bb16] : (!jlir.Int64, !jlir.Int64, !jlir.Bool) -> ()
# CHECK-NEXT:   ^bb15:  // pred: ^bb13
# CHECK-NEXT:     %96 = "jlir.constant"() {value = #jlir<"#<intrinsic #2 add_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %97 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %98 = "jlir.call"(%96, %74, %97) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Int64, !jlir.Int64) -> !jlir.Int64
# CHECK-NEXT:     %99 = "jlir.constant"() {value = #jlir.false} : () -> !jlir.Bool
# CHECK-NEXT:     "jlir.goto"(%98, %98, %99)[^bb16] : (!jlir.Int64, !jlir.Int64, !jlir.Bool) -> ()
# CHECK-NEXT:   ^bb16(%100: !jlir.Int64, %101: !jlir.Int64, %102: !jlir.Bool):  // 2 preds: ^bb14, ^bb15
# CHECK-NEXT:     %103 = "jlir.constant"() {value = #jlir<"#<intrinsic #44 not_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %104 = "jlir.call"(%103, %102) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Bool) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%104)[^bb18, ^bb17] {operand_segment_sizes = dense<[1, 0, 0]> : vector<3xi32>} : (!jlir.Bool) -> ()
# CHECK-NEXT:   ^bb17:  // pred: ^bb16
# CHECK-NEXT:     "jlir.goto"(%100, %101)[^bb13] : (!jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb18:  // 2 preds: ^bb12, ^bb16
# CHECK-NEXT:     %105 = "jlir.constant"() {value = #jlir<"===">} : () -> !jlir<"typeof(===)">
# CHECK-NEXT:     %106 = "jlir.call"(%105, %49, %33) : (!jlir<"typeof(===)">, !jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%106)[^bb20, ^bb19] {operand_segment_sizes = dense<[1, 0, 0]> : vector<3xi32>} : (!jlir.Bool) -> ()
# CHECK-NEXT:   ^bb19:  // pred: ^bb18
# CHECK-NEXT:     %107 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %108 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %109 = "jlir.constant"() {value = #jlir.true} : () -> !jlir.Bool
# CHECK-NEXT:     "jlir.goto"(%107, %108, %109)[^bb21] : (!jlir.Int64, !jlir.Int64, !jlir.Bool) -> ()
# CHECK-NEXT:   ^bb20:  // pred: ^bb18
# CHECK-NEXT:     %110 = "jlir.constant"() {value = #jlir<"#<intrinsic #2 add_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %111 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %112 = "jlir.call"(%110, %49, %111) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Int64, !jlir.Int64) -> !jlir.Int64
# CHECK-NEXT:     %113 = "jlir.constant"() {value = #jlir.false} : () -> !jlir.Bool
# CHECK-NEXT:     "jlir.goto"(%112, %112, %113)[^bb21] : (!jlir.Int64, !jlir.Int64, !jlir.Bool) -> ()
# CHECK-NEXT:   ^bb21(%114: !jlir.Int64, %115: !jlir.Int64, %116: !jlir.Bool):  // 2 preds: ^bb19, ^bb20
# CHECK-NEXT:     %117 = "jlir.constant"() {value = #jlir<"#<intrinsic #44 not_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %118 = "jlir.call"(%117, %116) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Bool) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%118)[^bb23, ^bb22] {operand_segment_sizes = dense<[1, 0, 0]> : vector<3xi32>} : (!jlir.Bool) -> ()
# CHECK-NEXT:   ^bb22:  // pred: ^bb21
# CHECK-NEXT:     "jlir.goto"(%114, %115)[^bb9] : (!jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb23:  // 2 preds: ^bb8, ^bb21
# CHECK-NEXT:     %119 = "jlir.constant"() {value = #jlir<"===">} : () -> !jlir<"typeof(===)">
# CHECK-NEXT:     %120 = "jlir.call"(%119, %24, %8) : (!jlir<"typeof(===)">, !jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%120)[^bb25, ^bb24] {operand_segment_sizes = dense<[1, 0, 0]> : vector<3xi32>} : (!jlir.Bool) -> ()
# CHECK-NEXT:   ^bb24:  // pred: ^bb23
# CHECK-NEXT:     %121 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %122 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %123 = "jlir.constant"() {value = #jlir.true} : () -> !jlir.Bool
# CHECK-NEXT:     "jlir.goto"(%121, %122, %123)[^bb26] : (!jlir.Int64, !jlir.Int64, !jlir.Bool) -> ()
# CHECK-NEXT:   ^bb25:  // pred: ^bb23
# CHECK-NEXT:     %124 = "jlir.constant"() {value = #jlir<"#<intrinsic #2 add_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %125 = "jlir.constant"() {value = #jlir<"1">} : () -> !jlir.Int64
# CHECK-NEXT:     %126 = "jlir.call"(%124, %24, %125) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Int64, !jlir.Int64) -> !jlir.Int64
# CHECK-NEXT:     %127 = "jlir.constant"() {value = #jlir.false} : () -> !jlir.Bool
# CHECK-NEXT:     "jlir.goto"(%126, %126, %127)[^bb26] : (!jlir.Int64, !jlir.Int64, !jlir.Bool) -> ()
# CHECK-NEXT:   ^bb26(%128: !jlir.Int64, %129: !jlir.Int64, %130: !jlir.Bool):  // 2 preds: ^bb24, ^bb25
# CHECK-NEXT:     %131 = "jlir.constant"() {value = #jlir<"#<intrinsic #44 not_int>">} : () -> !jlir<"typeof(Core.IntrinsicFunction)">
# CHECK-NEXT:     %132 = "jlir.call"(%131, %130) : (!jlir<"typeof(Core.IntrinsicFunction)">, !jlir.Bool) -> !jlir.Bool
# CHECK-NEXT:     "jlir.gotoifnot"(%132)[^bb28, ^bb27] {operand_segment_sizes = dense<[1, 0, 0]> : vector<3xi32>} : (!jlir.Bool) -> ()
# CHECK-NEXT:   ^bb27:  // pred: ^bb26
# CHECK-NEXT:     "jlir.goto"(%128, %129)[^bb5] : (!jlir.Int64, !jlir.Int64) -> ()
# CHECK-NEXT:   ^bb28:  // 2 preds: ^bb4, ^bb26
# CHECK-NEXT:     %133 = "jlir.constant"() {value = #jlir.nothing} : () -> !jlir.Nothing
# CHECK-NEXT:     "jlir.return"(%133) : (!jlir.Nothing) -> ()
# CHECK-NEXT:   }
# CHECK-NEXT: }

# CHECK: module  {
# CHECK-NEXT:   func nested @"Tuple{typeof(Main.matmul!), Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}}"(%arg0: !jlir<"typeof(Main.matmul!)">, %arg1: memref<?x?xf64>, %arg2: memref<?x?xf64>, %arg3: memref<?x?xf64>) -> !jlir.Nothing attributes {llvm.emit_c_interface} {
# CHECK-NEXT:     %c1_i64 = constant 1 : i64
# CHECK-NEXT:     %c0_i64 = constant 0 : i64
# CHECK-NEXT:     %c2_i64 = constant 2 : i64
# CHECK-NEXT:     %c2 = constant 2 : index
# CHECK-NEXT:     %c1 = constant 1 : index
# CHECK-NEXT:     %false = constant false
# CHECK-NEXT:     %true = constant true
# CHECK-NEXT:     %0 = "jlir.convertstd"(%c1_i64) : (i64) -> index
# CHECK-NEXT:     %1 = subi %c2, %0 : index
# CHECK-NEXT:     %2 = dim %arg2, %1 : memref<?x?xf64>
# CHECK-NEXT:     %3 = "jlir.convertstd"(%2) : (index) -> i64
# CHECK-NEXT:     %4 = cmpi sle, %c1_i64, %3 : i64
# CHECK-NEXT:     %5 = select %4, %3, %c0_i64 : i64
# CHECK-NEXT:     %6 = "jlir.convertstd"(%5) : (i64) -> !jlir.Int64
# CHECK-NEXT:     %7 = cmpi slt, %5, %c1_i64 : i64
# CHECK-NEXT:     cond_br %7, ^bb1, ^bb2(%false, %c1_i64, %c1_i64 : i1, i64, i64)
# CHECK-NEXT:   ^bb1:  // pred: ^bb0
# CHECK-NEXT:     %8 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %9 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %10 = "jlir.convertstd"(%8) : (!jlir.Int64) -> i64
# CHECK-NEXT:     %11 = "jlir.convertstd"(%9) : (!jlir.Int64) -> i64
# CHECK-NEXT:     br ^bb2(%true, %10, %11 : i1, i64, i64)
# CHECK-NEXT:   ^bb2(%12: i1, %13: i64, %14: i64):  // 2 preds: ^bb0, ^bb1
# CHECK-NEXT:     %15 = xor %12, %true : i1
# CHECK-NEXT:     cond_br %15, ^bb3(%13, %14 : i64, i64), ^bb21
# CHECK-NEXT:   ^bb3(%16: i64, %17: i64):  // 2 preds: ^bb2, ^bb20
# CHECK-NEXT:     %18 = "jlir.convertstd"(%17) : (i64) -> !jlir.Int64
# CHECK-NEXT:     %19 = "jlir.convertstd"(%c2_i64) : (i64) -> index
# CHECK-NEXT:     %20 = subi %c2, %19 : index
# CHECK-NEXT:     %21 = dim %arg2, %20 : memref<?x?xf64>
# CHECK-NEXT:     %22 = "jlir.convertstd"(%21) : (index) -> i64
# CHECK-NEXT:     %23 = cmpi sle, %c1_i64, %22 : i64
# CHECK-NEXT:     %24 = select %23, %22, %c0_i64 : i64
# CHECK-NEXT:     %25 = "jlir.convertstd"(%24) : (i64) -> !jlir.Int64
# CHECK-NEXT:     %26 = cmpi slt, %24, %c1_i64 : i64
# CHECK-NEXT:     cond_br %26, ^bb4, ^bb5(%false, %c1_i64, %c1_i64 : i1, i64, i64)
# CHECK-NEXT:   ^bb4:  // pred: ^bb3
# CHECK-NEXT:     %27 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %28 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %29 = "jlir.convertstd"(%27) : (!jlir.Int64) -> i64
# CHECK-NEXT:     %30 = "jlir.convertstd"(%28) : (!jlir.Int64) -> i64
# CHECK-NEXT:     br ^bb5(%true, %29, %30 : i1, i64, i64)
# CHECK-NEXT:   ^bb5(%31: i1, %32: i64, %33: i64):  // 2 preds: ^bb3, ^bb4
# CHECK-NEXT:     %34 = xor %31, %true : i1
# CHECK-NEXT:     cond_br %34, ^bb6(%32, %33 : i64, i64), ^bb17
# CHECK-NEXT:   ^bb6(%35: i64, %36: i64):  // 2 preds: ^bb5, ^bb16
# CHECK-NEXT:     %37 = "jlir.convertstd"(%36) : (i64) -> !jlir.Int64
# CHECK-NEXT:     %38 = dim %arg3, %20 : memref<?x?xf64>
# CHECK-NEXT:     %39 = "jlir.convertstd"(%38) : (index) -> i64
# CHECK-NEXT:     %40 = cmpi sle, %c1_i64, %39 : i64
# CHECK-NEXT:     %41 = select %40, %39, %c0_i64 : i64
# CHECK-NEXT:     %42 = "jlir.convertstd"(%41) : (i64) -> !jlir.Int64
# CHECK-NEXT:     %43 = cmpi slt, %41, %c1_i64 : i64
# CHECK-NEXT:     cond_br %43, ^bb7, ^bb8(%false, %c1_i64, %c1_i64 : i1, i64, i64)
# CHECK-NEXT:   ^bb7:  // pred: ^bb6
# CHECK-NEXT:     %44 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %45 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %46 = "jlir.convertstd"(%44) : (!jlir.Int64) -> i64
# CHECK-NEXT:     %47 = "jlir.convertstd"(%45) : (!jlir.Int64) -> i64
# CHECK-NEXT:     br ^bb8(%true, %46, %47 : i1, i64, i64)
# CHECK-NEXT:   ^bb8(%48: i1, %49: i64, %50: i64):  // 2 preds: ^bb6, ^bb7
# CHECK-NEXT:     %51 = xor %48, %true : i1
# CHECK-NEXT:     cond_br %51, ^bb9(%49, %50 : i64, i64), ^bb13
# CHECK-NEXT:   ^bb9(%52: i64, %53: i64):  // 2 preds: ^bb8, ^bb12
# CHECK-NEXT:     %54 = "jlir.convertstd"(%53) : (i64) -> !jlir.Int64
# CHECK-NEXT:     %55 = "jlir.convertstd"(%16) : (i64) -> index
# CHECK-NEXT:     %56 = subi %55, %c1 : index
# CHECK-NEXT:     %57 = "jlir.convertstd"(%52) : (i64) -> index
# CHECK-NEXT:     %58 = subi %57, %c1 : index
# CHECK-NEXT:     %59 = load %arg1[%58, %56] : memref<?x?xf64>
# CHECK-NEXT:     %60 = "jlir.convertstd"(%35) : (i64) -> index
# CHECK-NEXT:     %61 = subi %60, %c1 : index
# CHECK-NEXT:     %62 = load %arg2[%61, %56] : memref<?x?xf64>
# CHECK-NEXT:     %63 = load %arg3[%58, %61] : memref<?x?xf64>
# CHECK-NEXT:     %64 = mulf %62, %63 : f64
# CHECK-NEXT:     %65 = addf %59, %64 : f64
# CHECK-NEXT:     store %65, %arg1[%58, %56] : memref<?x?xf64>
# CHECK-NEXT:     %66 = "jlir.==="(%54, %42) : (!jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     %67 = "jlir.convertstd"(%66) : (!jlir.Bool) -> i1
# CHECK-NEXT:     cond_br %67, ^bb10, ^bb11
# CHECK-NEXT:   ^bb10:  // pred: ^bb9
# CHECK-NEXT:     %68 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %69 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %70 = "jlir.convertstd"(%68) : (!jlir.Int64) -> i64
# CHECK-NEXT:     %71 = "jlir.convertstd"(%69) : (!jlir.Int64) -> i64
# CHECK-NEXT:     br ^bb12(%70, %71, %true : i64, i64, i1)
# CHECK-NEXT:   ^bb11:  // pred: ^bb9
# CHECK-NEXT:     %72 = addi %53, %c1_i64 : i64
# CHECK-NEXT:     br ^bb12(%72, %72, %false : i64, i64, i1)
# CHECK-NEXT:   ^bb12(%73: i64, %74: i64, %75: i1):  // 2 preds: ^bb10, ^bb11
# CHECK-NEXT:     %76 = xor %75, %true : i1
# CHECK-NEXT:     cond_br %76, ^bb9(%73, %74 : i64, i64), ^bb13
# CHECK-NEXT:   ^bb13:  // 2 preds: ^bb8, ^bb12
# CHECK-NEXT:     %77 = "jlir.==="(%37, %25) : (!jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     %78 = "jlir.convertstd"(%77) : (!jlir.Bool) -> i1
# CHECK-NEXT:     cond_br %78, ^bb14, ^bb15
# CHECK-NEXT:   ^bb14:  // pred: ^bb13
# CHECK-NEXT:     %79 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %80 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %81 = "jlir.convertstd"(%79) : (!jlir.Int64) -> i64
# CHECK-NEXT:     %82 = "jlir.convertstd"(%80) : (!jlir.Int64) -> i64
# CHECK-NEXT:     br ^bb16(%81, %82, %true : i64, i64, i1)
# CHECK-NEXT:   ^bb15:  // pred: ^bb13
# CHECK-NEXT:     %83 = addi %36, %c1_i64 : i64
# CHECK-NEXT:     br ^bb16(%83, %83, %false : i64, i64, i1)
# CHECK-NEXT:   ^bb16(%84: i64, %85: i64, %86: i1):  // 2 preds: ^bb14, ^bb15
# CHECK-NEXT:     %87 = xor %86, %true : i1
# CHECK-NEXT:     cond_br %87, ^bb6(%84, %85 : i64, i64), ^bb17
# CHECK-NEXT:   ^bb17:  // 2 preds: ^bb5, ^bb16
# CHECK-NEXT:     %88 = "jlir.==="(%18, %6) : (!jlir.Int64, !jlir.Int64) -> !jlir.Bool
# CHECK-NEXT:     %89 = "jlir.convertstd"(%88) : (!jlir.Bool) -> i1
# CHECK-NEXT:     cond_br %89, ^bb18, ^bb19
# CHECK-NEXT:   ^bb18:  // pred: ^bb17
# CHECK-NEXT:     %90 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %91 = "jlir.undef"() : () -> !jlir.Int64
# CHECK-NEXT:     %92 = "jlir.convertstd"(%90) : (!jlir.Int64) -> i64
# CHECK-NEXT:     %93 = "jlir.convertstd"(%91) : (!jlir.Int64) -> i64
# CHECK-NEXT:     br ^bb20(%92, %93, %true : i64, i64, i1)
# CHECK-NEXT:   ^bb19:  // pred: ^bb17
# CHECK-NEXT:     %94 = addi %17, %c1_i64 : i64
# CHECK-NEXT:     br ^bb20(%94, %94, %false : i64, i64, i1)
# CHECK-NEXT:   ^bb20(%95: i64, %96: i64, %97: i1):  // 2 preds: ^bb18, ^bb19
# CHECK-NEXT:     %98 = xor %97, %true : i1
# CHECK-NEXT:     cond_br %98, ^bb3(%95, %96 : i64, i64), ^bb21
# CHECK-NEXT:   ^bb21:  // 2 preds: ^bb2, ^bb20
# CHECK-NEXT:     %99 = "jlir.constant"() {value = #jlir.nothing} : () -> !jlir.Nothing
# CHECK-NEXT:     return %99 : !jlir.Nothing
# CHECK-NEXT:   }
# CHECK-NEXT: }

# CHECK:   llvm.func @"Tuple{typeof(Main.matmul!), Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}}"(%arg0: !llvm.ptr<struct<"struct_jl_value_type", opaque>>, %arg1: !llvm.ptr<f64>, %arg2: !llvm.ptr<f64>, %arg3: i64, %arg4: i64, %arg5: i64, %arg6: i64, %arg7: i64, %arg8: !llvm.ptr<f64>, %arg9: !llvm.ptr<f64>, %arg10: i64, %arg11: i64, %arg12: i64, %arg13: i64, %arg14: i64, %arg15: !llvm.ptr<f64>, %arg16: !llvm.ptr<f64>, %arg17: i64, %arg18: i64, %arg19: i64, %arg20: i64, %arg21: i64) -> !llvm.ptr<struct<"struct_jl_value_type", opaque>> attributes {llvm.emit_c_interface, sym_visibility = "nested"} {
# CHECK-NEXT:     %0 = llvm.mlir.undef : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %1 = llvm.insertvalue %arg1, %0[0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %2 = llvm.insertvalue %arg2, %1[1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %3 = llvm.insertvalue %arg3, %2[2] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %4 = llvm.insertvalue %arg4, %3[3, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %5 = llvm.insertvalue %arg6, %4[4, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %6 = llvm.insertvalue %arg5, %5[3, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %7 = llvm.insertvalue %arg7, %6[4, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %8 = llvm.insertvalue %arg8, %0[0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %9 = llvm.insertvalue %arg9, %8[1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %10 = llvm.insertvalue %arg10, %9[2] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %11 = llvm.insertvalue %arg11, %10[3, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %12 = llvm.insertvalue %arg13, %11[4, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %13 = llvm.insertvalue %arg12, %12[3, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %14 = llvm.insertvalue %arg14, %13[4, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %15 = llvm.insertvalue %arg15, %0[0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %16 = llvm.insertvalue %arg16, %15[1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %17 = llvm.insertvalue %arg17, %16[2] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %18 = llvm.insertvalue %arg18, %17[3, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %19 = llvm.insertvalue %arg20, %18[4, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %20 = llvm.insertvalue %arg19, %19[3, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %21 = llvm.insertvalue %arg21, %20[4, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %22 = llvm.mlir.constant({{[0-9]+}} : i64) : i64
# CHECK-NEXT:     %23 = llvm.mlir.constant({{[0-9]+}} : i64) : i64
# CHECK-NEXT:     %24 = llvm.mlir.constant({{[0-9]+}} : i64) : i64
# CHECK-NEXT:     %25 = llvm.mlir.constant(2 : index) : i64
# CHECK-NEXT:     %26 = llvm.mlir.constant(1 : index) : i64
# CHECK-NEXT:     %27 = llvm.mlir.constant(false) : i1
# CHECK-NEXT:     %28 = llvm.mlir.constant(true) : i1
# CHECK-NEXT:     %29 = llvm.sub %25, %22  : i64
# CHECK-NEXT:     %30 = llvm.mlir.constant(0 : index) : i64
# CHECK-NEXT:     %31 = llvm.extractvalue %14[3] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %32 = llvm.alloca %26 x !llvm.array<2 x i64> : (i64) -> !llvm.ptr<array<2 x i64>>
# CHECK-NEXT:     llvm.store %31, %32 : !llvm.ptr<array<2 x i64>>
# CHECK-NEXT:     %33 = llvm.getelementptr %32[%30, %29] : (!llvm.ptr<array<2 x i64>>, i64, i64) -> !llvm.ptr<i64>
# CHECK-NEXT:     %34 = llvm.load %33 : !llvm.ptr<i64>
# CHECK-NEXT:     %35 = llvm.icmp "sle" %22, %34 : i64
# CHECK-NEXT:     %36 = llvm.select %35, %34, %23 : i1, i64
# CHECK-NEXT:     %37 = llvm.icmp "slt" %36, %22 : i64
# CHECK-NEXT:     llvm.cond_br %37, ^bb1, ^bb2(%27, %22, %22 : i1, i64, i64)
# CHECK-NEXT:   ^bb1:  // pred: ^bb0
# CHECK-NEXT:     %38 = llvm.mlir.undef : i64
# CHECK-NEXT:     llvm.br ^bb2(%28, %38, %38 : i1, i64, i64)
# CHECK-NEXT:   ^bb2(%39: i1, %40: i64, %41: i64):  // 2 preds: ^bb0, ^bb1
# CHECK-NEXT:     %42 = llvm.xor %39, %28  : i1
# CHECK-NEXT:     llvm.cond_br %42, ^bb3(%40, %41 : i64, i64), ^bb21
# CHECK-NEXT:   ^bb3(%43: i64, %44: i64):  // 2 preds: ^bb2, ^bb20
# CHECK-NEXT:     %45 = llvm.sub %25, %24  : i64
# CHECK-NEXT:     %46 = llvm.alloca %26 x !llvm.array<2 x i64> : (i64) -> !llvm.ptr<array<2 x i64>>
# CHECK-NEXT:     llvm.store %31, %46 : !llvm.ptr<array<2 x i64>>
# CHECK-NEXT:     %47 = llvm.getelementptr %46[%30, %45] : (!llvm.ptr<array<2 x i64>>, i64, i64) -> !llvm.ptr<i64>
# CHECK-NEXT:     %48 = llvm.load %47 : !llvm.ptr<i64>
# CHECK-NEXT:     %49 = llvm.icmp "sle" %22, %48 : i64
# CHECK-NEXT:     %50 = llvm.select %49, %48, %23 : i1, i64
# CHECK-NEXT:     %51 = llvm.icmp "slt" %50, %22 : i64
# CHECK-NEXT:     llvm.cond_br %51, ^bb4, ^bb5(%27, %22, %22 : i1, i64, i64)
# CHECK-NEXT:   ^bb4:  // pred: ^bb3
# CHECK-NEXT:     %52 = llvm.mlir.undef : i64
# CHECK-NEXT:     llvm.br ^bb5(%28, %52, %52 : i1, i64, i64)
# CHECK-NEXT:   ^bb5(%53: i1, %54: i64, %55: i64):  // 2 preds: ^bb3, ^bb4
# CHECK-NEXT:     %56 = llvm.xor %53, %28  : i1
# CHECK-NEXT:     llvm.cond_br %56, ^bb6(%54, %55 : i64, i64), ^bb17
# CHECK-NEXT:   ^bb6(%57: i64, %58: i64):  // 2 preds: ^bb5, ^bb16
# CHECK-NEXT:     %59 = llvm.extractvalue %21[3] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %60 = llvm.alloca %26 x !llvm.array<2 x i64> : (i64) -> !llvm.ptr<array<2 x i64>>
# CHECK-NEXT:     llvm.store %59, %60 : !llvm.ptr<array<2 x i64>>
# CHECK-NEXT:     %61 = llvm.getelementptr %60[%30, %45] : (!llvm.ptr<array<2 x i64>>, i64, i64) -> !llvm.ptr<i64>
# CHECK-NEXT:     %62 = llvm.load %61 : !llvm.ptr<i64>
# CHECK-NEXT:     %63 = llvm.icmp "sle" %22, %62 : i64
# CHECK-NEXT:     %64 = llvm.select %63, %62, %23 : i1, i64
# CHECK-NEXT:     %65 = llvm.icmp "slt" %64, %22 : i64
# CHECK-NEXT:     llvm.cond_br %65, ^bb7, ^bb8(%27, %22, %22 : i1, i64, i64)
# CHECK-NEXT:   ^bb7:  // pred: ^bb6
# CHECK-NEXT:     %66 = llvm.mlir.undef : i64
# CHECK-NEXT:     llvm.br ^bb8(%28, %66, %66 : i1, i64, i64)
# CHECK-NEXT:   ^bb8(%67: i1, %68: i64, %69: i64):  // 2 preds: ^bb6, ^bb7
# CHECK-NEXT:     %70 = llvm.xor %67, %28  : i1
# CHECK-NEXT:     llvm.cond_br %70, ^bb9(%68, %69 : i64, i64), ^bb13
# CHECK-NEXT:   ^bb9(%71: i64, %72: i64):  // 2 preds: ^bb8, ^bb12
# CHECK-NEXT:     %73 = llvm.sub %43, %26  : i64
# CHECK-NEXT:     %74 = llvm.sub %71, %26  : i64
# CHECK-NEXT:     %75 = llvm.extractvalue %7[1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %76 = llvm.extractvalue %7[4, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %77 = llvm.mul %74, %76  : i64
# CHECK-NEXT:     %78 = llvm.add %77, %73  : i64
# CHECK-NEXT:     %79 = llvm.getelementptr %75[%78] : (!llvm.ptr<f64>, i64) -> !llvm.ptr<f64>
# CHECK-NEXT:     %80 = llvm.load %79 : !llvm.ptr<f64>
# CHECK-NEXT:     %81 = llvm.sub %57, %26  : i64
# CHECK-NEXT:     %82 = llvm.extractvalue %14[1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %83 = llvm.extractvalue %14[4, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %84 = llvm.mul %81, %83  : i64
# CHECK-NEXT:     %85 = llvm.add %84, %73  : i64
# CHECK-NEXT:     %86 = llvm.getelementptr %82[%85] : (!llvm.ptr<f64>, i64) -> !llvm.ptr<f64>
# CHECK-NEXT:     %87 = llvm.load %86 : !llvm.ptr<f64>
# CHECK-NEXT:     %88 = llvm.extractvalue %21[1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %89 = llvm.extractvalue %21[4, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %90 = llvm.mul %74, %89  : i64
# CHECK-NEXT:     %91 = llvm.add %90, %81  : i64
# CHECK-NEXT:     %92 = llvm.getelementptr %88[%91] : (!llvm.ptr<f64>, i64) -> !llvm.ptr<f64>
# CHECK-NEXT:     %93 = llvm.load %92 : !llvm.ptr<f64>
# CHECK-NEXT:     %94 = llvm.fmul %87, %93  : f64
# CHECK-NEXT:     %95 = llvm.fadd %80, %94  : f64
# CHECK-NEXT:     llvm.store %95, %79 : !llvm.ptr<f64>
# CHECK-NEXT:     %96 = llvm.icmp "eq" %72, %64 : i64
# CHECK-NEXT:     llvm.cond_br %96, ^bb10, ^bb11
# CHECK-NEXT:   ^bb10:  // pred: ^bb9
# CHECK-NEXT:     %97 = llvm.mlir.undef : i64
# CHECK-NEXT:     llvm.br ^bb12(%97, %97, %28 : i64, i64, i1)
# CHECK-NEXT:   ^bb11:  // pred: ^bb9
# CHECK-NEXT:     %98 = llvm.add %72, %22  : i64
# CHECK-NEXT:     llvm.br ^bb12(%98, %98, %27 : i64, i64, i1)
# CHECK-NEXT:   ^bb12(%99: i64, %100: i64, %101: i1):  // 2 preds: ^bb10, ^bb11
# CHECK-NEXT:     %102 = llvm.xor %101, %28  : i1
# CHECK-NEXT:     llvm.cond_br %102, ^bb9(%99, %100 : i64, i64), ^bb13
# CHECK-NEXT:   ^bb13:  // 2 preds: ^bb8, ^bb12
# CHECK-NEXT:     %103 = llvm.icmp "eq" %58, %50 : i64
# CHECK-NEXT:     llvm.cond_br %103, ^bb14, ^bb15
# CHECK-NEXT:   ^bb14:  // pred: ^bb13
# CHECK-NEXT:     %104 = llvm.mlir.undef : i64
# CHECK-NEXT:     llvm.br ^bb16(%104, %104, %28 : i64, i64, i1)
# CHECK-NEXT:   ^bb15:  // pred: ^bb13
# CHECK-NEXT:     %105 = llvm.add %58, %22  : i64
# CHECK-NEXT:     llvm.br ^bb16(%105, %105, %27 : i64, i64, i1)
# CHECK-NEXT:   ^bb16(%106: i64, %107: i64, %108: i1):  // 2 preds: ^bb14, ^bb15
# CHECK-NEXT:     %109 = llvm.xor %108, %28  : i1
# CHECK-NEXT:     llvm.cond_br %109, ^bb6(%106, %107 : i64, i64), ^bb17
# CHECK-NEXT:   ^bb17:  // 2 preds: ^bb5, ^bb16
# CHECK-NEXT:     %110 = llvm.icmp "eq" %44, %36 : i64
# CHECK-NEXT:     llvm.cond_br %110, ^bb18, ^bb19
# CHECK-NEXT:   ^bb18:  // pred: ^bb17
# CHECK-NEXT:     %111 = llvm.mlir.undef : i64
# CHECK-NEXT:     llvm.br ^bb20(%111, %111, %28 : i64, i64, i1)
# CHECK-NEXT:   ^bb19:  // pred: ^bb17
# CHECK-NEXT:     %112 = llvm.add %44, %22  : i64
# CHECK-NEXT:     llvm.br ^bb20(%112, %112, %27 : i64, i64, i1)
# CHECK-NEXT:   ^bb20(%113: i64, %114: i64, %115: i1):  // 2 preds: ^bb18, ^bb19
# CHECK-NEXT:     %116 = llvm.xor %115, %28  : i1
# CHECK-NEXT:     llvm.cond_br %116, ^bb3(%113, %114 : i64, i64), ^bb21
# CHECK-NEXT:   ^bb21:  // 2 preds: ^bb2, ^bb20
# CHECK-NEXT:     %117 = llvm.mlir.constant({{[0-9]+}} : i64) : i64
# CHECK-NEXT:     %118 = llvm.inttoptr %117 : i64 to !llvm.ptr<struct<"struct_jl_value_type", opaque>>
# CHECK-NEXT:     llvm.return %118 : !llvm.ptr<struct<"struct_jl_value_type", opaque>>
# CHECK-NEXT:   }
# CHECK-NEXT:   llvm.func @"_mlir_ciface_Tuple{typeof(Main.matmul!), Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}}"(%arg0: !llvm.ptr<struct<"struct_jl_value_type", opaque>>, %arg1: !llvm.ptr<struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>>, %arg2: !llvm.ptr<struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>>, %arg3: !llvm.ptr<struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>>) -> !llvm.ptr<struct<"struct_jl_value_type", opaque>> attributes {llvm.emit_c_interface, sym_visibility = "nested"} {
# CHECK-NEXT:     %0 = llvm.load %arg1 : !llvm.ptr<struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>>
# CHECK-NEXT:     %1 = llvm.extractvalue %0[0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %2 = llvm.extractvalue %0[1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %3 = llvm.extractvalue %0[2] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %4 = llvm.extractvalue %0[3, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %5 = llvm.extractvalue %0[3, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %6 = llvm.extractvalue %0[4, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %7 = llvm.extractvalue %0[4, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %8 = llvm.load %arg2 : !llvm.ptr<struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>>
# CHECK-NEXT:     %9 = llvm.extractvalue %8[0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %10 = llvm.extractvalue %8[1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %11 = llvm.extractvalue %8[2] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %12 = llvm.extractvalue %8[3, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %13 = llvm.extractvalue %8[3, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %14 = llvm.extractvalue %8[4, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %15 = llvm.extractvalue %8[4, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %16 = llvm.load %arg3 : !llvm.ptr<struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>>
# CHECK-NEXT:     %17 = llvm.extractvalue %16[0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %18 = llvm.extractvalue %16[1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %19 = llvm.extractvalue %16[2] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %20 = llvm.extractvalue %16[3, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %21 = llvm.extractvalue %16[3, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %22 = llvm.extractvalue %16[4, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %23 = llvm.extractvalue %16[4, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
# CHECK-NEXT:     %24 = llvm.call @"Tuple{typeof(Main.matmul!), Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}}"(%arg0, %1, %2, %3, %4, %5, %6, %7, %9, %10, %11, %12, %13, %14, %15, %17, %18, %19, %20, %21, %22, %23) : (!llvm.ptr<struct<"struct_jl_value_type", opaque>>, !llvm.ptr<f64>, !llvm.ptr<f64>, i64, i64, i64, i64, i64, !llvm.ptr<f64>, !llvm.ptr<f64>, i64, i64, i64, i64, i64, !llvm.ptr<f64>, !llvm.ptr<f64>, i64, i64, i64, i64, i64) -> !llvm.ptr<struct<"struct_jl_value_type", opaque>>
# CHECK-NEXT:     llvm.return %24 : !llvm.ptr<struct<"struct_jl_value_type", opaque>>
# CHECK-NEXT:   }
# CHECK-NEXT: }

ext: jl

max_stars_repo_name: stephenneuendorffer/brutus

max_issues_repo_name: stephenneuendorffer/brutus

max_forks_repo_name: stephenneuendorffer/brutus


text:
abstract type AbstractBackend end
function backend_display end

@enum ImageStorageFormat JuliaNative GLNative

"""
Current backend
"""
const current_backend = Ref{Union{Missing,AbstractBackend}}(missing)
const use_display = Ref{Bool}(true)

function inline!(inline = true)
    use_display[] = !inline
    return
end

function register_backend!(backend::AbstractBackend)
    current_backend[] = backend
    return
end

function push_screen!(scene::Scene, display)
    # Ok lets leave a warning here until we fix CairoMakie!
    @debug("Backend doesn't return screen from show methods. This needs fixing!")
end

function push_screen!(scene::Scene, display::AbstractDisplay)
    push!(scene.current_screens, display)
    deregister = nothing
    deregister = on(events(scene).window_open) do is_open
        # when screen closes, it should set the scene isopen event to false
        # so that's when we can remove the display
        if !is_open
            filter!(x-> x !== display, scene.current_screens)
            deregister !== nothing && off(deregister)
        end
    end
    return
end

function backend_display(::Missing, ::Scene)
    error("""
    No backend available (GLMakie, CairoMakie, WGLMakie)!
    Maybe you imported GLMakie but it didn't build correctly.
    In that case, try `]build GLMakie` and watch out for any warnings.
    If that's not the case, make sure to explicitely import any of the mentioned backends.
    """)
end

Base.display(fap::FigureAxisPlot) = display(fap.figure)
Base.display(fig::Figure) = display(fig.scene)

function Base.display(scene::Scene)

    if !use_display[]
        return Core.invoke(display, Tuple{Any}, scene)
    else
        # set update to true, without triggering an event
        # this just indicates, that now we may update on e.g. resize
        update!(scene)
        screen = backend_display(current_backend[], scene)
        push_screen!(scene, screen)
        return screen
    end
end

function Base.showable(mime::MIME{M}, scene::Scene) where M
    backend_showable(current_backend[], mime, scene)
end
# ambig
function Base.showable(mime::MIME"application/json", scene::Scene)
    backend_showable(current_backend[], mime, scene)
end
function Base.showable(mime::MIME{M}, fig::FigureLike) where M
    backend_showable(current_backend[], mime, get_scene(fig))
end
# ambig
function Base.showable(mime::MIME"application/json", fig::FigureLike)
    backend_showable(current_backend[], mime, get_scene(fig))
end

function backend_showable(::Backend, ::Mime, ::Scene) where {Backend, Mime <: MIME}
    hasmethod(backend_show, Tuple{Backend, IO, Mime, Scene})
end

# fallback show when no backend is selected
function backend_show(backend, io::IO, ::MIME"text/plain", scene::Scene)
    if backend isa Missing
        @warn """
        Printing Scene as text because no backend is available (GLMakie, CairoMakie, WGLMakie).
        Maybe you imported GLMakie but it didn't build correctly.
        In that case, try `]build GLMakie` and watch out for any warnings.
        """
    end
    print(io, scene)
    return
end

function Base.show(io::IO, ::MIME"text/plain", scene::Scene)
    show(io, scene)
end

Base.show(io::IO, m::MIME, fap::FigureAxisPlot) = show(io, m, fap.figure)
Base.show(io::IO, m::MIME, fig::Figure) = show(io, m, fig.scene)

function Base.show(io::IO, m::MIME, scene::Scene)
    # set update to true, without triggering an event
    # this just indicates, that now we may update on e.g. resize
    update!(scene)

    # Here, we deal with the Juno plotsize.
    # Since SVGs are in units of pt, which is 1/72 in,
    # and pixels (which Juno reports its plotsize as)
    # are 1/96 in, we need to rescale the scene,
    # whose units are in pt, into the expected size in px.
    # This means we have to scale by a factor of 72/96.
    res = get(io, :juno_plotsize, nothing)
    if !isnothing(res)
        if m isa MIME"image/svg+xml"
            res = round.(Int, res .* 0.75)
        end
        resize!(scene, res...)
    end
    ioc = IOContext(io,
        :full_fidelity => true,
        :pt_per_unit => get(io, :pt_per_unit, 1.0),
        :px_per_unit => get(io, :px_per_unit, 1.0)
    )
    screen = backend_show(current_backend[], ioc, m, scene)
    push_screen!(scene, screen)
    return screen
end

"""
    Stepper(scene, path; format = :jpg)

Creates a Stepper for generating progressive plot examples.

Each "step" is saved as a separate file in the folder
pointed to by `path`, and the format is customizable by
`format`, which can be any output type your backend supports.
"""
mutable struct FolderStepper
    scene::Scene
    folder::String
    format::Symbol
    step::Int
end

mutable struct RamStepper
    scene::Scene
    images::Vector{Matrix{RGBf0}}
    format::Symbol
end

Stepper(scene::FigureLike, path::String, step::Int; format=:png) = FolderStepper(get_scene(scene), path, format, step)
Stepper(scene::FigureLike; format=:png) = RamStepper(get_scene(scene), Matrix{RGBf0}[], format)

function Stepper(scene::FigureLike, path::String; format = :png)
    ispath(path) || mkpath(path)
    FolderStepper(get_scene(scene), path, format, 1)
end

"""
    step!(s::Stepper)

steps through a `Makie.Stepper` and outputs a file with filename `filename-step.jpg`.
This is useful for generating progressive plot examples.
"""
function step!(s::FolderStepper)
    FileIO.save(joinpath(s.folder, basename(s.folder) * "-$(s.step).$(s.format)"), s.scene)
    s.step += 1
    return s
end

function step!(s::RamStepper)
    img = convert(Matrix{RGBf0}, colorbuffer(s.scene))
    push!(s.images, img)
    return s
end

function FileIO.save(dir::String, s::RamStepper)
    if !isdir(dir)
        mkpath(dir)
    end
    for (i, img) in enumerate(s.images)
        FileIO.save(joinpath(dir, "step-$i.$(s.format)"), img)
    end
end

format2mime(::Type{FileIO.format"PNG"})  = MIME("image/png")
format2mime(::Type{FileIO.format"SVG"})  = MIME("image/svg+xml")
format2mime(::Type{FileIO.format"JPEG"}) = MIME("image/jpeg")
format2mime(::Type{FileIO.format"TIFF"}) = MIME("image/tiff")
format2mime(::Type{FileIO.format"BMP"}) = MIME("image/bmp")
format2mime(::Type{FileIO.format"PDF"})  = MIME("application/pdf")
format2mime(::Type{FileIO.format"TEX"})  = MIME("application/x-tex")
format2mime(::Type{FileIO.format"EPS"})  = MIME("application/postscript")
format2mime(::Type{FileIO.format"HTML"}) = MIME("text/html")

filetype(::FileIO.File{F}) where F = F
# Allow format to be overridden with first argument

"""
    FileIO.save(filename, scene; resolution = size(scene), pt_per_unit = 1.0, px_per_unit = 1.0)

Save a `Scene` with the specified filename and format.

# Supported Formats

- `GLMakie`: `.png`, `.jpeg`, and `.bmp`
- `CairoMakie`: `.svg`, `.pdf`, `.png`, and `.jpeg`
- `WGLMakie`: `.png`

# Supported Keyword Arguments

## All Backends

- `resolution`: `(width::Int, height::Int)` of the scene in dimensionless units (equivalent to `px` for GLMakie and WGLMakie).

## CairoMakie

- `pt_per_unit`: The size of one scene unit in `pt` when exporting to a vector format.
- `px_per_unit`: The size of one scene unit in `px` when exporting to a bitmap format. This provides a mechanism to export the same scene with higher or lower resolution.
"""
function FileIO.save(
        filename::String, fig::FigureLike; args...
    )
    FileIO.save(FileIO.query(filename), fig; args...)
end

function FileIO.save(
        file::FileIO.Formatted, fig::FigureLike;
        resolution = size(get_scene(fig)),
        pt_per_unit = 1.0,
        px_per_unit = 1.0,
    )
    scene = get_scene(fig)
    resolution != size(scene) && resize!(scene, resolution)
    filename = FileIO.filename(file)
    # Delete previous file if it exists and query only the file string for type.
    # We overwrite existing files anyway, so this doesn't change the behavior.
    # But otherwise we could get a filetype :UNKNOWN from a corrupt existing file
    # (from an error during save, e.g.), therefore we don't want to rely on the
    # type readout from an existing file.
    isfile(filename) && rm(filename)
    # query the filetype only from the file extension
    F = filetype(file)

    open(filename, "w") do s
        iocontext = IOContext(s,
            :full_fidelity => true,
            :pt_per_unit => pt_per_unit,
            :px_per_unit => px_per_unit
        )
        show(iocontext, format2mime(F), scene)
    end
end

"""
    record_events(f, scene::Scene, path::String)

Records all window events that happen while executing function `f`
for `scene` and serializes them to `path`.
"""
function record_events(f, scene::Scene, path::String)
    display(scene)
    result = Vector{Pair{Float64, Pair{Symbol, Any}}}()
    for field in fieldnames(Events)
        on(getfield(scene.events, field)) do value
            value = isa(value, Set) ? copy(value) : value
            push!(result, time() => (field => value))
        end
    end
    f()
    open(path, "w") do io
        serialize(io, result)
    end
end

"""
    replay_events(f, scene::Scene, path::String)
    replay_events(scene::Scene, path::String)

Replays the serialized events recorded with `record_events` in `path` in `scene`.
"""
replay_events(scene::Scene, path::String) = replay_events(()-> nothing, scene, path)
function replay_events(f, scene::Scene, path::String)
    events = open(io-> deserialize(io), path)
    sort!(events, by = first)
    for i in 1:length(events)
        t1, (field, value) = events[i]
        field == :mousedrag && continue
        if field == :mousebuttons
            Base.invokelatest() do
                getfield(scene.events, field)[] = value
            end
        else
            Base.invokelatest() do
                getfield(scene.events, field)[] = value
            end
        end
        f()
        if i < length(events)
            t2, (field, value) = events[i + 1]
            # min sleep time 0.001
            if (t2 - t1 > 0.001)
                sleep(t2 - t1)
            else
                yield()
            end
        end
    end
end

struct RecordEvents
    scene::Scene
    path::String
end

Base.display(re::RecordEvents) = display(re.scene)

struct VideoStream
    io
    process
    screen
    path::String
end

"""
    VideoStream(scene::Scene, framerate = 24)

Returns a stream and a buffer that you can use, which don't allocate for new frames.
Use [`recordframe!(stream)`](@ref) to add new video frames to the stream, and
[`save(path, stream)`](@ref) to save the video.
"""
function VideoStream(
        scene::Scene; framerate::Integer = 24
    )
    #codec = `-codec:v libvpx -quality good -cpu-used 0 -b:v 500k -qmin 10 -qmax 42 -maxrate 500k -bufsize 1000k -threads 8`
    dir = mktempdir()
    path = joinpath(dir, "$(gensym(:video)).mkv")
    update!(scene)
    screen = backend_display(current_backend[], scene)
    push_screen!(scene, screen)
    _xdim, _ydim = size(scene)
    xdim = iseven(_xdim) ? _xdim : _xdim + 1
    ydim = iseven(_ydim) ? _ydim : _ydim + 1
    process = @ffmpeg_env open(`$(FFMPEG.ffmpeg) -framerate $(framerate) -loglevel quiet -f rawvideo -pixel_format rgb24 -r $framerate -s:v $(xdim)x$(ydim) -i pipe:0 -vf vflip -y $path`, "w")
    return VideoStream(process.in, process, screen, abspath(path))
end

function VideoStream(fig::FigureAxisPlot; kw...)
    VideoStream(fig.figure; kw...)
end
function VideoStream(fig::Figure; kw...)
    VideoStream(fig.scene; kw...)
end

# This has to be overloaded by the backend for its screen type.
function colorbuffer(x::AbstractScreen)
    error("colorbuffer not implemented for screen $(typeof(x))")
end

function jl_to_gl_format(image)
    @static if VERSION < v"1.6"
        d1, d2 = size(image)
        bufc = Array{eltype(image)}(undef, d2, d1) #permuted
        ind1, ind2 = axes(image)
        n = first(ind1) + last(ind1)
        for i in ind1
            @simd for j in ind2
                @inbounds bufc[j, n-i] = image[i, j]
            end
        end
        return bufc
    else
        reverse!(image; dims=1)
        return collect(PermutedDimsArray(image, (2, 1)))
    end
end

# less specific for overloading by backends
function colorbuffer(screen::Any, format::ImageStorageFormat = JuliaNative)
    image = colorbuffer(screen)
    if format == GLNative
        if string(typeof(screen)) == "GLMakie.Screen"
            @warn "Inefficient re-conversion back to GLNative buffer format. Update GLMakie to support direct buffer access" maxlog=1
        end
        return jl_to_gl_format(image)
    elseif format == JuliaNative
        return image
    end
end

"""
    colorbuffer(scene, format::ImageStorageFormat = JuliaNative)
    colorbuffer(screen, format::ImageStorageFormat = JuliaNative)

Returns the content of the given scene or screen rasterised to a Matrix of
Colors. The return type is backend-dependent, but will be some form of RGB
or RGBA.

- `format = JuliaNative` : Returns a buffer in the format of standard julia images (dims permuted and one reversed)
- `format = GLNative` : Returns a more efficient format buffer for GLMakie which can be directly
                        used in FFMPEG without conversion
"""
function colorbuffer(scene::Scene, format::ImageStorageFormat = JuliaNative)
    screen = getscreen(scene)
    if isnothing(screen)
        if ismissing(current_backend[])
            error("""
                You have not loaded a backend.  Please load one (`using GLMakie` or `using CairoMakie`)
                before trying to render a Scene.
                """)
        else
            return colorbuffer(backend_display(current_backend[], scene), format)
        end
    end
    return colorbuffer(screen, format)
end

"""
    recordframe!(io::VideoStream)

Adds a video frame to the VideoStream `io`.
"""
function recordframe!(io::VideoStream)
    frame = convert(Matrix{RGB{N0f8}}, colorbuffer(io.screen, GLNative))
    _xdim, _ydim = size(frame)
    if isodd(_xdim) || isodd(_ydim)
        xdim = iseven(_xdim) ? _xdim : _xdim + 1
        ydim = iseven(_ydim) ? _ydim : _ydim + 1
        padded = fill(zero(eltype(frame)), (xdim, ydim))
        padded[1:_xdim, 1:_ydim] = frame
        frame = padded
    end
    write(io.io, frame)
    return
end

"""
    save(path::String, io::VideoStream; framerate = 24, compression = 20)

Flushes the video stream and converts the file to the extension found in `path`,
which can be one of the following:
- `.mkv`  (the default, doesn't need to convert)
- `.mp4`  (good for Web, most supported format)
- `.webm` (smallest file size)
- `.gif`  (largest file size for the same quality)

`.mp4` and `.mk4` are marginally bigger and `.gif`s are up to
6 times bigger with the same quality!

The `compression` argument controls the compression ratio; `51` is the
highest compression, and `0` is the lowest (lossless).

See the docs of [`VideoStream`](@ref) for how to create a VideoStream.
If you want a simpler interface, consider using [`record`](@ref).

"""
function save(path::String, io::VideoStream;
              framerate::Int = 24, compression = 20)
    close(io.process)
    wait(io.process)
    p, typ = splitext(path)
    if typ == ".mkv"
        cp(io.path, path, force=true)
    else
        mktempdir() do dir
            out = joinpath(dir, "out$(typ)")
            if typ == ".mp4"
                ffmpeg_exe(`-loglevel quiet -i $(io.path) -crf $compression -c:v libx264 -preset slow -r $framerate -pix_fmt yuv420p -c:a libvo_aacenc -b:a 128k -y $out`)
            elseif typ == ".webm"
                ffmpeg_exe(`-loglevel quiet -i $(io.path) -crf $compression -c:v libvpx-vp9 -threads 16 -b:v 2000k -c:a libvorbis -threads 16 -r $framerate -vf scale=iw:ih -y $out`)
            elseif typ == ".gif"
                filters = "fps=$framerate,scale=iw:ih:flags=lanczos"
                palette_path = dirname(io.path)
                pname = joinpath(palette_path, "palette.bmp")
                isfile(pname) && rm(pname, force = true)
                ffmpeg_exe(`-loglevel quiet -i $(io.path) -vf "$filters,palettegen" -y $pname`)
                ffmpeg_exe(`-loglevel quiet -i $(io.path) -i $pname -lavfi "$filters [x]; [x][1:v] paletteuse" -y $out`)
                rm(pname, force = true)
            else
                rm(io.path)
                error("Video type $typ not known")
            end
            cp(out, path, force=true)
        end
    end
    rm(io.path)
    return path
end

"""
    record(func, figure, path; framerate = 24, compression = 20)
    record(func, figure, path, iter;
            framerate = 24, compression = 20, sleep = true)

The first signature provides `func` with a VideoStream, which it should call
`recordframe!(io)` on when recording a frame.

The second signature iterates `iter`, calling `recordframe!(io)` internally
after calling `func` with the current iteration element.

Both notations require a Figure, FigureAxisPlot or Scene `figure` to work.

The animation is then saved to `path`, with the format determined by `path`'s
extension.  Allowable extensions are:
- `.mkv`  (the default, doesn't need to convert)
- `.mp4`  (good for Web, most supported format)
- `.webm` (smallest file size)
- `.gif`  (largest file size for the same quality)

`.mp4` and `.mk4` are marginally bigger than `webm` and `.gif`s are up to
6 times bigger with the same quality!

The `compression` argument controls the compression ratio; `51` is the
highest compression, and `0` is the lowest (lossless).

When `sleep` is set to `true` (the default), AbstractPlotting will
display the animation in real-time by sleeping in between frames.
Thus, a 24-frame, 24-fps recording would take one second to record.

When it is set to `false`, frames are rendered as fast as the backend
can render them.  Thus, a 24-frame, 24-fps recording would usually
take much less than one second in GLMakie.

Typical usage patterns would look like:

```julia
record(figure, "video.mp4", itr) do i
    func(i) # or some other manipulation of the figure
end
```

or, for more tweakability,

```julia
record(figure, "test.gif") do io
    for i = 1:100
        func!(figure)     # animate figure
        recordframe!(io)  # record a new frame
    end
end
```

If you want a more tweakable interface, consider using [`VideoStream`](@ref) and
[`save`](@ref).

## Extended help
### Examples

```julia
fig, ax, p = lines(rand(10))
record(fig, "test.gif") do io
    for i in 1:255
        p[:color] = RGBf0(i/255, (255 - i)/255, 0) # animate figure
        recordframe!(io)
    end
end
```
or
```julia
fig, ax, p = lines(rand(10))
record(fig, "test.gif", 1:255) do i
    p[:color] = RGBf0(i/255, (255 - i)/255, 0) # animate figure
end
```
"""
function record(func, scene, path; framerate::Int = 24, compression = 20)
    io = Record(func, scene; framerate = framerate)
    save(path, io; framerate = framerate, compression = compression)
end

function Record(func, scene; framerate=24)
    io = VideoStream(scene; framerate = framerate)
    func(io)
    return io
end

function record(func, scene, path, iter; framerate::Int = 24, compression = 20)
    io = Record(func, scene, iter; framerate=framerate)
    save(path, io, framerate = framerate, compression = compression)
end

function Record(func, scene, iter; framerate::Int = 24)
    io = VideoStream(scene; framerate=framerate)
    for i in iter
        t1 = time()
        func(i)
        recordframe!(io)
        @debug "Recording" progress=i/length(iter)
        yield()
    end
    return io
end

function Base.show(io::IO, ::MIME"text/html", vs::VideoStream)
    mktempdir() do dir
        path = save(vs, joinpath(dir, "video.mp4"))
        print(
            io,
            """<video autoplay controls><source src="data:video/x-m4v;base64,""",
            base64encode(open(read, path)),
            """" type="video/mp4"></video>"""
        )
    end
end


text:
module Exam

using
    Gumbo,
    AbstractTrees,
    UUIDs,
    ZipFile,
    LightXML,
    DataStructures

include("response.jl")
include("question.jl")
include("parse.jl")

include("read.jl")

include("qti.jl")
include("media.jl")

end # module


text:
# # Example Catalog

using Plots, AnalogDataAssimilation

σ = 10.0
ρ = 28.0
β = 8.0 / 3

dt_integration = 0.01
dt_states = 1
dt_obs = 8
parameters = [σ, ρ, β]
var_obs = [1]
nb_loop_train = 100
nb_loop_test = 10
sigma2_catalog = 0.0
sigma2_obs = 2.0

ssm = StateSpaceModel(
    lorenz63,
    dt_integration,
    dt_states,
    dt_obs,
    parameters,
    var_obs,
    nb_loop_train,
    nb_loop_test,
    sigma2_catalog,
    sigma2_obs,
)

xt, yo, catalog = generate_data(ssm, [10.0; 0.0; 0.0]);

# ## Time series

plot(catalog.analogs[1, :])
plot!(catalog.analogs[2, :])
plot!(catalog.analogs[3, :])

# ## Phase space plot

p = plot3d(
    1,
    xlim = (-25, 25),
    ylim = (-25, 25),
    zlim = (0, 50),
    title = "Lorenz 63",
    marker = 1,
)
for x in eachcol(catalog.analogs)
    push!(p, x...)
end
p


text:
#name: Scatter Plot
#language: julia
#tags: demo, viewers, hide-suggestions
#input: dataframe t
#input: column xColumnName
#input: column yColumnName
#input: column colorColumnName
#output: graphics

using Plots;
colors = [RGB(x, x, x) for (x) in t[colorColumnName]]
scat = scatter(t[xColumnName], t[yColumnName], markercolor=colors, xlabel=xColumnName, ylabel=yColumnName, legend=false)
display(scat)

max_stars_repo_name: AndSviat/public

max_issues_repo_name: AndSviat/public

max_forks_repo_name: AndSviat/public


text:
using HDF5, GeoData, Test, Statistics, Dates
using GeoData: Time, window, name
testpath = joinpath(dirname(pathof(GeoData)), "../test/")
include(joinpath(testpath, "test_utils.jl"))

# TODO example files without a login requirement
path1 = joinpath(testpath, "data/SMAP_L4_SM_gph_20160101T223000_Vv4011_001.h5")
path2 = joinpath(testpath, "data/SMAP_L4_SM_gph_20160102T223000_Vv4011_001.h5")

@testset "stack" begin
    stack = SMAPstack(path1)

    @testset "conversion to GeoArray" begin
        smaparray = stack["soil_temp_layer1"][Lat(), Lon()]
        @test smaparray isa GeoArray{Float32,2}
        @test dims(smaparray) isa Tuple{<:Lon{<:Array{Float32,1}}, <:Lat{<:Array{Float32,1}}}
        @test span(smaparray) isa Tuple{Irregular{Tuple{Float32,Float32}},Irregular{Tuple{Float32,Float32}}}
        @test span(smaparray) == (Irregular((-180.0f0, 180.0f0)), Irregular((-85.04456f0, 85.04456f0)))
        @test bounds(smaparray) == ((-180.0f0, 180.0f0), (-85.04456f0, 85.04456f0))
        @test index(smaparray) isa Tuple{Vector{Float32},Vector{Float32}}
        @test refdims(smaparray) isa Tuple{<:Ti}
        @test missingval(smaparray) == -9999.0
        @test smaparray[1] == -9999.0
        @test name(smaparray) == :soil_temp_layer1
        dt = DateTime(2016, 1, 1, 22, 30)
        step_ = Hour(3)
        @test refdims(stack) ==
            (Ti(dt:step_:dt; mode=Sampled(Ordered(), Regular(step_), Intervals(Start()))),)
        # Currently empty
        @test metadata(smaparray) isa SMAPstackMetadata
    end

    @testset "conversion to GeoStack" begin
        # Stack Constructors
        # This uses too much ram! There is a lingering memory leak in HDF5.
        # geostack = GeoStack(stack)
        # @test Symbol.(Tuple(keys(stack))) == keys(geostack)
        geostack = GeoStack(stack; keys=(:baseflow_flux, :snow_mass, :soil_temp_layer1))
        @test keys(geostack) == (:baseflow_flux, :snow_mass, :soil_temp_layer1)
    end

    if VERSION > v"1.1-"
        @testset "copy" begin
            geoarray = zero(stack[:soil_temp_layer1])
            @test geoarray isa GeoArray
            @test geoarray != stack[:soil_temp_layer1]
            copy!(geoarray, stack, :soil_temp_layer1)
            @test geoarray == stack[:soil_temp_layer1]
        end
    end

    @testset "window" begin
        windowedstack = SMAPstack(path1; window=(Lat(1:5), Lon(1:5), Ti(1)))
        @test window(windowedstack) == (Lat(1:5), Lon(1:5), Ti(1))
        windowedarray = windowedstack[:soil_temp_layer1]
        @test size(windowedarray) == (5, 5)
        @test windowedarray[1:3, 2:2] == reshape([-9999.0, -9999.0, -9999.0], 3, 1)
        @test windowedarray[1:3, 2] == [-9999.0, -9999.0, -9999.0]
        @test windowedarray[1, 2] == -9999.0
        windowedstack = SMAPstack(path1; window=(Lat(1:5), Lon(1:5), Ti(1:1)))
        windowedarray = windowedstack[:soil_temp_layer1]
        @test windowedarray[1:3, 2:2, 1] == reshape([-9999.0, -9999.0, -9999.0], 3, 1)
        @test windowedarray[1:3, 2, 1] == [-9999.0, -9999.0, -9999.0]
        @test windowedarray[1, 2, 1] == -9999.0
        windowedstack = SMAPstack(path1; window=(Ti(1),))
        windowedarray = windowedstack[:soil_temp_layer1]
        @test windowedarray[1:3, 2:2] == reshape([-9999.0, -9999.0, -9999.0], 3, 1)
        @test windowedarray[1:3, 2] == [-9999.0, -9999.0, -9999.0]
        @test windowedarray[1, 2] == -9999.0
    end

    @testset "show" begin
        sh1 = sprint(show, stack[:soil_temp_layer1])
        # Test but don't lock this down too much
        @test occursin("GeoArray", sh1)
        @test occursin("Latitude", sh1)
        @test occursin("Longitude", sh1)
        @test occursin("Time", sh1)
        sh2 = sprint(show, stack[:soil_temp_layer1][Lat(Between(0, 100)), Lon(Between(1, 100))])
        # Test but don't lock this down too much
        @test occursin("GeoArray", sh2)
        @test occursin("Latitude", sh2)
        @test occursin("Longitude", sh2)
        @test occursin("Time", sh2)
    end

end

@testset "series" begin
    series = SMAPseries([path1, path2]);
    val.(dims(series))
    @test series[1] isa SMAPstack
    @test first(bounds(series, Ti)) == DateTime(2016, 1, 1, 22, 30)
    @test last(bounds(series, Ti)) == DateTime(2016, 1, 3, 1, 30)
    modified_series = modify(Array, series)
    stackkeys = keys(modified_series[1])
    @test typeof(modified_series) <: GeoSeries{<:GeoStack{<:NamedTuple{stackkeys,<:Tuple{<:GeoArray{Float32,2,<:Tuple,<:Tuple,<:Array{Float32,2}},Vararg}}}}
end


text:
using Test

@testset "All tests" begin
    # Defines helper functions and includes tests for these
    include("test_util.jl")

    # The rest are straightforward tests of StationXML
    include("accessors.jl")
    include("types.jl")
    include("conversion.jl")
    include("util.jl")
    include("parsing.jl")
    include("io.jl")
    include("merge.jl")
end


text:
@safetestset "POST form payload" begin

  using Genie, HTTP

  route("/") do
    "GET"
  end

  route("/", method = POST) do
    params(:greeting)
  end

  port = nothing
  port = rand(8500:8900)

  up(port; open_browser = false)

  response = HTTP.request("POST", "http://localhost:$port/", ["Content-Type" => "application/x-www-form-urlencoded"], "greeting=Hello")
  @test response.status == 200
  @test String(response.body) == "Hello"

  response = HTTP.request("GET", "http://localhost:$port/", ["Content-Type" => "application/x-www-form-urlencoded"], "greeting=Hello")
  @test response.status == 200
  @test String(response.body) == "GET"

  down()
  sleep(1)
  server = nothing
  port = nothing
end


text:
using Test

using MarketData
using TimeSeries

using MarketTechnicals

@testset "Utilities" begin

@testset "typical price" begin
    ts = collect(Date(2017, 5, 1):Day(1):Date(2017, 5, 5))
    ta = typical(TimeArray(ts, reshape(1:15, (5, 3)), [:High, :Low, :Close]))

    @test timestamp(ta)[1]   == Date(2017, 5, 1)
    @test timestamp(ta)[end] == Date(2017, 5, 5)
    @test values(ta)         == [6, 7, 8, 9, 10]
end

@testset "relu" begin
    @test MarketTechnicals.relu(10) == 10
    @test MarketTechnicals.relu(-5) == 0
    @test MarketTechnicals.relu(0)  == 0

    date = collect(Date(2017, 5, 1):Day(1):Date(2017, 5, 3))
    ta = TimeArray(date, [10, -5, 0], [:magic], "meta")
    ta = MarketTechnicals.relu(ta)
    @test timestamp(ta)[1] == Date(2017, 5, 1)
    @test values(ta)       == [10, 0, 0]
    @test colnames(ta)     == [:magic]
    @test meta(ta)         == "meta"
end

@testset "wilder_smooth" begin
    date = collect(Date(2017, 5, 1):Day(1):Date(2017, 5, 5))
    ta = TimeArray(date, [0, 10, 5, 6, 7], [:magic], "meta")
    ta = MarketTechnicals.wilder_smooth(ta, 3)
    @test timestamp(ta)[1] == Date(2017, 5, 3)
    @test values(ta)[1]    == 15.
    @test values(ta)[2]    == 16.
    @test colnames(ta)     == [:magic]
    @test meta(ta)         == "meta"

    ta = TimeArray(date, [0, 10, 5, 6, 7], [:magic], "meta")
    ta = MarketTechnicals.wilder_smooth(ta, 3, padding=true)
    @test timestamp(ta)[1]     == Date(2017, 5, 1)
    @test isnan(values(ta)[1])
    @test isnan(values(ta)[2])
    @test values(ta)[3]        == 15.
    @test values(ta)[4]        == 16.
    @test colnames(ta)         == [:magic]
    @test meta(ta)             == "meta"

    ta = TimeArray(date, [0, 4, 5, 6, 7], [:magic], "meta")
    ta = MarketTechnicals.wilder_smooth(ta, 3, dx=true)
    @test timestamp(ta)[1] == Date(2017, 5, 3)
    @test values(ta)[1]    == 3.
    @test values(ta)[2]    == 4.
    @test colnames(ta)     == [:magic]
    @test meta(ta)         == "meta"
end

end  # @testset "Utilities"


text:
@testset "types" begin
    Class          = DiagnosisClassification.Class
    DiagnosisClass = DiagnosisClassification.DiagnosisClass
    @testset begin
        domain = "diagnosis"
        system = "hello"
        value  = "world"
        @test DiagnosisClass(; system, value) == Class(; domain, system, value)
    end
end


text:
version = v"1.3.6"
api_version = v"1.1.2"

# Collection of sources required to build this package
#
# The level zero repository contains both the API headers and a loader,
# which are versioned independently.
sources = [
    GitSource("https://github.com/oneapi-src/level-zero.git",
              "bb89202bfd8c5e05b54d16fc8d9ad9e6c7142a09"),
]


text:
module GeometryTests

using Gridap
using GridapDistributed
using PartitionedArrays
using LinearAlgebra
using Test

function main(parts)

  output = mkpath(joinpath(@__DIR__,"output"))

  if length(size(parts)) == 2
    domain = (0,4,0,4)
    cells = (4,4)
  elseif length(size(parts)) == 3
    domain = (0,4,0,4,0,4)
    cells = (4,4,4)
  end

  model = CartesianDiscreteModel(parts,domain,cells)
  writevtk(model,joinpath(output,"model"))

  gmodel = CartesianDiscreteModel(domain,cells)

  if length(cells) == 2 && prod(cells) == 16
    smodel = simplexify(gmodel)
    if length(parts) == 4
      cell_to_part = [
        1,1,1,1,1,1,1,1,
        1,2,2,2,2,2,2,3,
        3,3,3,3,3,3,3,3,
        3,3,4,4,4,4,4,4]
    else
      cell_to_part = fill(1,num_cells(smodel))
    end
    cell_graph = GridapDistributed.compute_cell_graph(smodel)
    @test LinearAlgebra.issymmetric(cell_graph)
    @test LinearAlgebra.ishermitian(cell_graph)
    dmodel = DiscreteModel(parts,smodel,cell_to_part)
    writevtk(dmodel,joinpath(output,"dmodel"))
  end

  map_parts(model.models,model.gids.partition) do lmodel,gids
    @test test_local_part_face_labelings_consistency(lmodel,gids,gmodel)
  end

  grid = get_grid(model)
  labels = get_grid(model)

  Ω = Triangulation(with_ghost,model)
  writevtk(Ω,joinpath(output,"Ω"))

  Ω = Triangulation(no_ghost,model)
  writevtk(Ω,joinpath(output,"Ω"))

  Γ = Boundary(with_ghost,model,tags="boundary")
  writevtk(Γ,joinpath(output,"Γ"))

  Γ = Boundary(no_ghost,model,tags="boundary")
  writevtk(Γ,joinpath(output,"Γ"))

end

function test_local_part_face_labelings_consistency(lmodel::CartesianDiscreteModel{D},gids,gmodel) where {D}
   local_topology         = lmodel.grid_topology
   global_topology        = gmodel.grid_topology
   local_labelings        = lmodel.face_labeling
   global_labelings       = gmodel.face_labeling
   l_d_to_dface_to_entity = local_labelings.d_to_dface_to_entity
   g_d_to_dface_to_entity = global_labelings.d_to_dface_to_entity
   #traverse local cells
   for cell_lid=1:num_cells(lmodel)
        cell_gid=gids.lid_to_gid[cell_lid]
        for d=0:D-1
             local_cell_to_faces = local_topology.n_m_to_nface_to_mfaces[D+1,d+1]
             global_cell_to_faces = global_topology.n_m_to_nface_to_mfaces[D+1,d+1]
             la = local_cell_to_faces.ptrs[cell_lid]
             lb = local_cell_to_faces.ptrs[cell_lid+1]
             ga = global_cell_to_faces.ptrs[cell_gid]
             gb = global_cell_to_faces.ptrs[cell_gid+1]
             @assert (lb-la)==(gb-ga)
             for i=0:lb-la-1
                 face_lid = local_cell_to_faces.data[la+i]
                 face_gid = global_cell_to_faces.data[ga+i]
                 local_entity = l_d_to_dface_to_entity[d+1][face_lid]
                 global_entity = g_d_to_dface_to_entity[d+1][face_gid]
                 if (local_entity != global_entity)
                     return false
                 end
             end
        end
   end
   return true
end

end # module


text:
import UUIDs: UUID, uuid1
import .Configuration

###
# CLIENT
###

mutable struct ClientSession
    id::Symbol
    stream::Any
    connected_notebook::Union{Notebook,Nothing}
    pendingupdates::Channel
end

ClientSession(id::Symbol, stream) = let
    ClientSession(id, stream, nothing, Channel(1024))
end

"A combination of _client ID_ and a _request ID_. The front-end generates a unqique ID for every request that it sends. The back-end (the stuff you are currently reading) can respond to a specific request. In that case, the response does not go through the normal message handlers in the front-end, but it flies directly to the place where the message was sent. (It resolves the promise returned by `send(...)`.)"
struct Initiator
    client::ClientSession
    request_id::Symbol
end
function Base.getproperty(initiator::Initiator, property::Symbol)
    if property == :client_id
        getfield(initiator, :client).id
    else
        getfield(initiator, property)
    end
end

###
# SERVER
###

"""
The `ServerSession` keeps track of:

- `connected_clients`: connected (web) clients
- `notebooks`: running notebooks
- `secret`: the web access token
- `options`: global pluto configuration `Options` for this session.
"""
Base.@kwdef mutable struct ServerSession
    connected_clients::Dict{Symbol,ClientSession} = Dict{Symbol,ClientSession}()
    notebooks::Dict{UUID,Notebook} = Dict{UUID,Notebook}()
    secret::String = String(rand(('a':'z') ∪ ('A':'Z') ∪ ('0':'9'), 8))
    binder_token::Union{String,Nothing} = nothing
    options::Configuration.Options = Configuration.Options()
end

###
# UPDATE MESSAGE
###

struct UpdateMessage
    type::Symbol
    message::Any
    notebook::Union{Notebook,Nothing}
    cell::Union{Cell,Nothing}
    initiator::Union{Initiator,Nothing}
end

UpdateMessage(type::Symbol, message::Any) = UpdateMessage(type, message, nothing, nothing, nothing)
UpdateMessage(type::Symbol, message::Any, notebook::Notebook) = UpdateMessage(type, message, notebook, nothing, nothing)

function clientupdate_notebook_list(notebooks; initiator::Union{Initiator,Nothing}=nothing)
    UpdateMessage(:notebook_list,
        Dict(
            :notebooks => [
                Dict(
                    :notebook_id => notebook.notebook_id,
                    :path => notebook.path,
                    :in_temp_dir => startswith(notebook.path, new_notebooks_directory()),
                    :shortpath => basename(notebook.path)
                ) for notebook in values(notebooks)
            ]
        ), nothing, nothing, initiator)
end


text:
#@reexport module BlazeMap

#export fit_blaze_1d, make_flat_blaze, make_blaze, calc_blaze, eval_blaze
#export calc_normalizations, renormalize

#import ..AbstractBlazeType, ..AbstractBlaze1DType, ..AbstractBlaze2DType
import ..AbstractEchelleObservation, ..AbstractEchelleObservationSet
import ..default_pixel_buffer_lo, ..default_pixel_buffer_hi
import ..max_num_pixels_per_order
import ..num_pixels_per_order, ..num_orders, ..num_obs
#import ..calc_blaze
#using ..BlazeCommon

struct BlazeMap1D{T1,T2,T3} <: AbstractBlaze1DType where {T1<:Integer, T2<:Real, T3<:Real}
   order::T1
   log_lambda_lo::T2
   log_lambda_hi::T2
   pixel_range::UnitRange{T1}
   model::AbstractArray{T3,1}
end
export BlazeMap1D

function make_flat_blaze(;num_pixels_per_order::Integer = max_num_pixels_per_order,
      pixel_range::AbstractRange = 1:num_pixels_per_order,
      order::Integer = 0, log_lambda_lo::Real = 0.0, log_lambda_hi::Real = 0.0)
      return BlazeMap1D(order, log_lambda_lo, log_lambda_hi, pixel_range, ones(length(pixel_range)) )
end
make_flat_blaze_map_1d = make_flat_blaze
export make_flat_blaze_map_1d

# TODO: Change calc_blaze to eval_blaze
function calc_blaze(b::BlazeMap1D{T1,T2,T3}, pixel::T4) where {T1<:Integer, T2<:Real, T3<:Real, T4<:Real}
      #println("# pix_rng.lo=", b.pixel_range[1], " pix=", pixel, " pix_rng.hi=", b.pixel_range[end], "len(pix_rng)=", length(b.pixel_range))
      #@assert (b.pixel_range[1]-1) <= pixel <= (b.pixel_range[end] +1)
      @assert 1 <= pixel <= length(b.model)
      pixel_lo = max(1, floor(Int64,pixel))
      pixel_hi = min(pixel_lo+1, b.pixel_range[end])
      w_hi = (pixel-pixel_lo)
      w_lo = 1-w_hi
      w_lo*b.model[pixel_lo] + w_hi*b.model[pixel_hi]
end

function calc_blaze(b::BlazeMap1D{T1,T2,T3}, pixel::T4) where {T1<:Integer, T2<:Real, T3<:Real, T4<:Integer}
      @assert b.pixel_range[1] <= pixel <= b.pixel_range[end]
      b.model[pixel]
end
export calc_blaze

function calc_blaze_at_log_lambda(b::BT, log_lambda::Real) where {BT<:AbstractBlaze1DType }
      pixel = (log_lambda-b.log_lambda_lo)/(b.log_lambda_hi-b.log_lambda_lo)*(length(b.pixel_range)-1) + b.pixel_range[1]
      calc_blaze(b,pixel)
end
function calc_blaze_at_log_lambda(b::BT, log_lambda::Union{AbstractRange{T},AbstractArray{T,1}}) where {BT<:AbstractBlaze1DType, T<:Real }
      map(ll->calc_blaze_at_log_lambda(b,ll),log_lambda)
end
export calc_blaze_at_log_lambda

#=
function calc_blaze(b::BT, pixel_range::AbstractRange{T2}) where {BT<:AbstractBlaze1DType, T2<:Integer}
      @assert b.pixel_range[1]-0.5 <= pixel_range[1] <= b.pixel_range[end]+0.5
      @assert b.pixel_range[1]-0.5 <= pixel_range[end] <= b.pixel_range[end]+0.5
      b.model[pixel_range]
end

=#

struct BlazeMap2D{T1,T2,T3} <: AbstractBlaze2DType where {T1<:Integer, T2<:Real, T3<:Real}
   blaze_list::Vector{BlazeMap1D{T1,T2,T3}}
end
export BlazeMap2D

function make_flat_blaze_map_2d(;num_pixels_per_order::Integer = max_num_pixels_per_order,
      num_orders::T1 = max_num_orders,
      pixel_range::AbstractArray{AbstractRange} = fill(1:num_pixels_per_order, num_orders),
      orders::AbstractArray{T1,1} = collect(1:num_orders),
      log_lambda_lo::AbstractArray{T2,1} = zeros(num_orders), log_lambda_hi::AbstractArray{T2,1} = zeros(num_orders)
      ) where { T1<:Integer, T2<:Real }
      @assert length(pixel_range) == length(orders) == length(log_lambda_lo) == length(log_lambda_hi) >= 1
      blaze_map = ones(length(pixel_range[1]))
      return BlazeMap2D( [
            BlazeMap1D(orders[i], log_lambda_lo[i], log_lambda_hi[i], pixel_range[i], blaze_map )
                  for i in 1:length(orders) ] )
end
export make_flat_blaze_map_2d

function covert_blaze_map_into_blaze_polynomial(b::BMT; degree = default_blaze_degree
   ) where { BMT <: BlazeMap1D }
   poly_model = fit_blaze_1d(b.pixel_range, b.model[b.pixel_range], degree=degree)
   BlazePolynomial(b.order,b.lambda_lo,b.lambda_hi,b.pixel_range,poly_model)
end

function covert_blaze_map_into_blaze_polynomial(blaze_list::BMT; degree = default_blaze_degree
      ) where { BMT <: BlazeMap2D }
   BlazeMap2D( [ covert_blaze_map_into_blaze_polynomial(blaze_list[i],degree=degree) for i in 1:length(blaze_list) ] )
end
export covert_blaze_map_into_blaze_polynomial

#include("common.jl")

#end # module BlazeMap


text:
module aoc15

export spoken, playUpToTurn

function spoken(inputs, turn)
    if turn <= length(inputs)
        return inputs[turn]
    end
    # play the first rounds with the given input
    turnMemory = Dict() # the key is a spoken number and the value is the last round this key is spoken
    latestTurn = length(inputs)
    latestNumber = inputs[latestTurn]
    for i in eachindex(inputs)
        turnMemory[inputs[i]] = i
    end
    # play the remaining rounds
    return playUpToTurn(turnMemory, latestNumber, latestTurn, turn)
end

function playUpToTurn(relevantTurns, currentNumber, from, upTo)
    result = 0
    while from < upTo
        roundResult = 0
        if haskey(relevantTurns, currentNumber)
            roundResult = from - relevantTurns[currentNumber]
        end
        relevantTurns[currentNumber] = from
        from = from + 1
        currentNumber = roundResult
        result = roundResult
    end
    return result
end

end


text:
module ExpmV

# defaults
const DEFAULT_SHIFT = true

# package code goes here
include("utils.jl")
include("expmv_fun.jl")
include("degree_selector.jl")
include("normAm.jl")
include("expmv_tspan.jl")
include("select_taylor_degree.jl")
include("norm1est.jl")
include("normest1.jl")

end # module


text:
#
using Plots, Distributions, DataFrames, DelimitedFiles, ColorSchemes, LaTeXStrings, Roots, NLsolve, Random
#
include("toolbox.jl")
#
Random.seed!(12345)
global ee = 1e-8
## generate random sample from the qExponential distribution
xs = [0.1:0.001:1;]
plot(xs,dqexp(xs,0.9,10.))
#
data = rqexp(50,0.9,10.)
#
histogram(data,normalize=true,color="beige",bins=500,label="data")
xs = [minimum(data):0.001:maximum(data);]
plot!(xs,dqexp(xs,0.9,10.),linewidth=2,xlim=[0,1],label=L"\rho_1^{\dagger}(x)",color="red")
#
savefig("qexpdata.pdf") # Figure 1
#
########################################################################
## Calculate \beta-estimators via the Shannon and Renyi MaxEnt procedures
Random.seed!(4545)
global ee = 1e-09

qs = [0.55, 0.65, 0.75];#LinRange(0.55, 0.9, nsims)
betatrue = 10.;
qestimse = zeros(length(qs));
ss, nreps = 10000, 10000; # sample size and Monte Carlo repetitions
bestimse_sh = zeros(nreps,length(qs));
bestimse_r1 = zeros(nreps,length(qs));
bestimse_r2 = zeros(nreps,length(qs));

@time for i in 1:length(qs)
   display("$i/3")
   tt = monteCarlo_betas(ss, nreps, qs[i], betatrue);
   bestimse_sh[:,i] = tt[:,1];
   bestimse_r1[:,i] = tt[:,2];
   bestimse_r2[:,i] = tt[:,3];
end
##############
# writedlm("bestimseNe04_nsims10000_sh.txt",bestimse_sh)
# writedlm("bestimseNe04_nsims10000_r1.txt",bestimse_r1)
# writedlm("bestimseNe04_nsims10000_r2.txt",bestimse_r2)
####
# bestimse_sh = readdlm("bestimseNe03_nsims10000_sh.txt");
# bestimse_r1 = readdlm("bestimseNe03_nsims10000_r1.txt");
# bestimse_r2 = readdlm("bestimseNe03_nsims10000_r2.txt");
#
# bestimse_sh2 = readdlm("bestimseNe04_nsims10000_sh.txt");
# bestimse_r12 = readdlm("bestimseNe04_nsims10000_r1.txt");
# bestimse_r22 = readdlm("bestimseNe04_nsims10000_r2.txt");
####
pyplot()

a = kde_lscv(bestimse_sh[:,1]);
xvals, densityvals = a.x, a.density
p11 = plot(xvals, densityvals,label="Shannon",linewidth=2,title=L"(a)\,\, Q=0.55, \, n=10^3",titlefontsize=10,legendfontsize=7,legend=:topright,ylab="Density",xlim=[0,25],ylim=[0,1.5])
a = kde_lscv(bestimse_r1[:,1]);
xvals, densityvals = a.x, a.density
p11 = plot!(xvals, densityvals,label="Renyi (lin.)",linewidth=2)
a = kde_lscv(bestimse_r2[:,1]);
xvals, densityvals = a.x, a.density
p11 = plot!(xvals, densityvals,label="Renyi (esc.)",linewidth=2)
vline!([betatrue],label="",c="black",line=:dash)
#
a = kde_lscv(bestimse_sh[:,2]);
xvals, densityvals = a.x, a.density
p12 = plot(xvals, densityvals,linewidth=2,title=L"(b)\,\, Q=0.65, \, n=10^3",titlefontsize=10,legendfontsize=7,label="",xlim=[0,13],ylim=[0,2.5])
a = kde_lscv(bestimse_r1[:,2]);
xvals, densityvals = a.x, a.density
p12 = plot!(xvals, densityvals,linewidth=2,label="")
a = kde_lscv(bestimse_r2[:,2]);
xvals, densityvals = a.x, a.density
p12 = plot!(xvals, densityvals,linewidth=2,label="")
vline!([betatrue],label="",c="black",line=:dash)
#
a = kde_lscv(bestimse_sh[:,3]);
xvals, densityvals = a.x, a.density
p13 = plot(xvals, densityvals,linewidth=2,title=L"(c)\,\, Q=0.75,\, n=10^3",titlefontsize=10,legendfontsize=7,label="",xlim=[0,13],ylim=[0,3.5])
a = kde_lscv(bestimse_r1[:,3]);
xvals, densityvals = a.x, a.density
p13 = plot!(xvals, densityvals,linewidth=2,label="")
a = kde_lscv(bestimse_r2[:,3]);
xvals, densityvals = a.x, a.density
p13 = plot!(xvals, densityvals,linewidth=2,label="")
vline!([betatrue],label="",c="black",line=:dash)
#
a = kde_lscv(bestimse_sh2[:,1]);
xvals, densityvals = a.x, a.density
p21 = plot(xvals, densityvals,label="Shannon",linewidth=2,title=L"(d)\,\, Q=0.55, \, n=10^4",titlefontsize=10,legendfontsize=7,legend=:topright,ylab="Density",xlim=[0,25],ylim=[0,1.5])
a = kde_lscv(bestimse_r12[:,1]);
xvals, densityvals = a.x, a.density
p21 = plot!(xvals, densityvals,label="Renyi (lin.)",linewidth=2)
a = kde_lscv(bestimse_r22[:,1]);
xvals, densityvals = a.x, a.density
p21 = plot!(xvals, densityvals,label="Renyi (esc.)",linewidth=2)
vline!([betatrue],label="",c="black",line=:dash)
#
a = kde_lscv(bestimse_sh2[:,2]);
xvals, densityvals = a.x, a.density
p22 = plot(xvals, densityvals,linewidth=2,title=L"(e)\,\, Q=0.65, \, n=10^4",titlefontsize=10,legendfontsize=7,label="",xlab=L"\hat{\Lambda}",xlim=[0,13],ylim=[0,2.5])
a = kde_lscv(bestimse_r12[:,2]);
xvals, densityvals = a.x, a.density
p22 = plot!(xvals, densityvals,linewidth=2,label="")
a = kde_lscv(bestimse_r22[:,2]);
xvals, densityvals = a.x, a.density
p22 = plot!(xvals, densityvals,linewidth=2,label="")
vline!([betatrue],label="",c="black",line=:dash)
#
a = kde_lscv(bestimse_sh2[:,3]);
xvals, densityvals = a.x, a.density
p23 = plot(xvals, densityvals,linewidth=2,title=L"(f)\,\, Q=0.75,\, n=10^4",titlefontsize=10,legendfontsize=7,label="",xlim=[0,13],ylim=[0,3.5])
a = kde_lscv(bestimse_r12[:,3]);
xvals, densityvals = a.x, a.density
p23 = plot!(xvals, densityvals,linewidth=2,label="")
a = kde_lscv(bestimse_r22[:,3]);
xvals, densityvals = a.x, a.density
p23 = plot!(xvals, densityvals,linewidth=2,label="")
vline!([betatrue],label="",c="black",line=:dash)
#
plot(p11,p12,p13,p21,p22,p23,layout=(2,3)) # Figure 3
plot!(size=(1000,500))
# savefig("kdes_qs_ns2.pdf")

########################################################################
## Calculate \beta-estimators via the Shannon and Renyi MaxEnt procedures

nsims = 200 # number of simulations
qs = LinRange(0.51, 0.9, nsims) # grid of q values
betas = LinRange(1., 100., nsims) # grid of \beta values
# initialization
bestimse_sh = zeros(nsims, nsims)
bestimse_r1 = zeros(nsims, nsims)
bestimse_r2 = zeros(nsims, nsims)
qestimse = zeros(nsims, nsims)
strue = zeros(nsims, nsims)
ss, nreps = 1000, 1000 # sample size and Monte Carlo repetitions

#
@time for i in 1:nsims
   display("$i/$nsims")
   for j in 1:nsims
      tt = sqrt.(monteCarloMSE(ss, nreps, qs[i], betas[j])) # root of the MSE
      qestimse[i,j] = tt[1]
      bestimse_sh[i,j] = tt[2]
      bestimse_r1[i,j] = tt[3]
      bestimse_r2[i,j] = tt[4]
   end
end
###
# save results
# writedlm("q_estimations.txt",qestimse)
# writedlm("b_estimations_sh.txt",bestimse_sh)
# writedlm("b_estimations_linear.txt",bestimse_r1)
# writedlm("b_estimations_escort.txt",bestimse_r2)
###

# Calculate relative RMS errors
for i in 1:length(bestimse_sh[:,1])
   bestimse_sh[:,i] = bestimse_sh[:,i] / betas[i]
   bestimse_r1[:,i] = bestimse_r1[:,i] / betas[i]
   bestimse_r2[:,i] = bestimse_r2[:,i] / betas[i]
end

## Plot results
p1 = heatmap(qs[1:end],betas[1:end],transpose(log10.(bestimse_r1[1:end,1:end])),c=cgrad(ColorSchemes.jet1.colors),
   xlabel=L"q",ylabel=L"\beta",title=(L"\log{\hat{MSE}}"))
#
p2 = heatmap(qs[1:end],betas[1:end],transpose(log10.(bestimse_r2[1:end,1:end])),c=cgrad(ColorSchemes.jet1.colors),
   xlabel=L"q",ylabel=L"\beta",line_z=[-1.5,0.5])
#
p3 = heatmap(qs[1:end],betas[1:end],transpose(log10.(bestimse_sh[1:end,1:end])),c=cgrad(ColorSchemes.jet1.colors),
   xlabel=L"q",ylabel=L"\beta",line_z=[-1.5,0.5])
#
plot(p1,p2,p3,layout=(3,1))
##
savefig("colormaps.png") # Figure 5

#########################################################################################################################
#########################################################################################################################

max_stars_repo_name: kkaloudis/qExponential-MaxEnt

max_issues_repo_name: kkaloudis/qExponential-MaxEnt

max_forks_repo_name: kkaloudis/qExponential-MaxEnt


text:
# Stable Set
# ==========

mutable struct StableSet{T} <: Base.AbstractSet{T}
    dict::StableDict{T, Nothing}

    function StableSet{T}() where T
        return new{T}(StableDict{T, Nothing}())
    end
end

function StableSet(vals)
    set = StableSet{eltype(vals)}()
    for v in vals
        push!(set, v)
    end
    return set
end

function Base.copy(set::StableSet)
    newset = StableSet{eltype(set)}()
    newset.dict = copy(set.dict)
    return newset
end

function Base.length(set::StableSet)
    return length(set.dict)
end

function Base.eltype(::Type{StableSet{T}}) where T
    return T
end

function Base.:(==)(set1::StableSet, set2::StableSet)
    if length(set1) == length(set2)
        for x in set1
            if x ∉ set2
                return false
            end
        end
        return true
    end
    return false
end

function Base.hash(set::StableSet, h::UInt)
    h = hash(Base.hashs_seed, h)
    for x in set
        h = xor(h, hash(x))
    end
    return h
end

function Base.in(val, set::StableSet)
    return haskey(set.dict, val)
end

function Base.push!(set::StableSet, val)
    v = convert(eltype(set), val)
    if v ∉ set
        set.dict[v] = nothing
    end
    return set
end

function Base.pop!(set::StableSet)
    return pop!(set.dict)[1]
end

function Base.delete!(set::StableSet, val)
    delete!(set.dict, val)
    return set
end

function Base.union!(set::StableSet, xs)
    for x in xs
        push!(set, x)
    end
    return set
end

function Base.union(set::StableSet, xs)
    return union!(copy(set), xs)
end

function Base.filter(f::Function, set::StableSet)
    newset = Set{eltype(set)}()
    for x in set
        if f(x)
            push!(newset, x)
        end
    end
    return newset
end

function Base.iterate(set::StableSet, s=iterate(set.dict))
    if s == nothing
        return nothing
    end
    return s[1][1], iterate(set.dict, s[2])
end


text:
# Note that this script can accept some limited command-line arguments, run
# `julia build_tarballs.jl --help` to see a usage message.
using BinaryBuilder
name = "Cairo"
version = v"1.12.12"
#
# function url2hash(url)
#     path = download(url)
#     open(io-> bytes2hex(BinaryProvider.sha256(io)), path)
# end
# url2hash("https://www.cairographics.org/releases/cairo-1.14.12.tar.xz") |> println

sources = [
    "https://www.cairographics.org/releases/cairo-1.14.12.tar.xz" =>
    "8c90f00c500b2299c0a323dd9beead2a00353752b2092ead558139bd67f7bf16",
]

# Bash recipe for building across all platforms
script = raw"""
cd $WORKSPACE/srcdir
cd cairo-1.14.12/
LDFLAGS="-L$prefix/lib" CPPFLAGS="-I$prefix/include" ./configure --prefix=$prefix --host=$target --disable-static --disable-xlib --disable-ft --disable-dependency-tracking
make -j${ncore}
make install
exit
"""

# These are the platforms we will build for by default, unless further
# platforms are passed in on the command line
platforms = supported_platforms()

# The products that we will ensure are always built
products(prefix) = [
    LibraryProduct(prefix, "libcairo", :libcairo),
]

# Dependencies that must be installed before this package can be built
dependencies = [
    "https://github.com/bicycle1885/ZlibBuilder/releases/download/v1.0.1/build_Zlib.v1.2.11.jl",
    "https://github.com/SimonDanisch/LibpngBuilder/releases/download/v1.6.31/build_libpng.v1.0.0.jl",
    "https://github.com/staticfloat/PixmanBuilder/releases/download/v0.34.0-1/build_Pixman.v0.34.0.jl",
    "https://github.com/JuliaGraphics/FreeTypeBuilder/releases/download/v2.9.1-2/build_FreeType2.v2.9.1.jl"
]

# Build the tarballs, and possibly a `build.jl` as well.
build_tarballs(ARGS, name, version, sources, script, platforms, products, dependencies)

max_stars_repo_name: giordano/CairoBuilder

max_issues_repo_name: giordano/CairoBuilder

max_forks_repo_name: giordano/CairoBuilder


text:
# Note that this script can accept some limited command-line arguments, run
# `julia build_tarballs.jl --help` to see a usage message.
using Base.BinaryPlatforms
using BinaryBuilder, Pkg

name = "VideoCaptureWrap"
version = v"0.9.0"

# copy LICENSE file
cp("LICENSE", joinpath("src", "LICENSE"), force=true)

# Collection of sources required to complete build
sources = [
    DirectorySource("src", target="projectname"),
]
# Bash recipe for building across all platforms
script = raw"""
# Override compiler ID to silence the horrible "No features found" cmake error
if [[ $target == *"apple-darwin"* ]]; then
  macos_extra_flags="-DCMAKE_CXX_COMPILER_ID=AppleClang -DCMAKE_CXX_COMPILER_VERSION=10.0.0 -DCMAKE_CXX_STANDARD_COMPUTED_DEFAULT=11"
fi

Julia_PREFIX=$prefix

mkdir build
cd build
cmake -DJulia_PREFIX=$Julia_PREFIX -DCMAKE_FIND_ROOT_PATH=$prefix -DJlCxx_DIR=$prefix/lib/cmake/JlCxx \
      -DCMAKE_INSTALL_PREFIX=$prefix -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TARGET_TOOLCHAIN} \
      $macos_extra_flags -DCMAKE_BUILD_TYPE=Release \
      ../projectname/
VERBOSE=ON cmake --build . --config Release --target install -- -j${nproc}
cd ..
install_license projectname/LICENSE
"""

# These are the platforms we will build for by default, unless further
# platforms are passed in on the command line
platforms = [
    Platform("i686", "linux", libc="glibc"),
    Platform("x86_64", "linux", libc="glibc"),
    Platform("aarch64", "linux"; libc="glibc"),
    Platform("armv7l", "linux"; libc="glibc"),
   #Linux(:powerpc64le, libc=:glibc), <- OpenCVQt_jll does not provide for this platform
   #Linux(:i686, libc=:musl), <- OpenCV_jll does not provide for this platform
   #Linux(:x86_64, libc=:musl), <- fails
    Platform("aarch64", "linux"; libc="musl"),
    Platform("armv7l", "linux"; libc="musl"),
    Platform("x86_64", "macos"),
    #FreeBSD(:x86_64), <- fails,
    Platform("x86_64", "windows"),
    Platform("i686", "windows"),
] |> expand_cxxstring_abis

# The products that we will ensure are always built

products = [
    LibraryProduct("libvideocapture", :libvideocapture), # our application
]

# Dependencies that must be installed before this package can be built
dependencies = [
    Dependency(PackageSpec(name="libcxxwrap_julia_jll", rev="libcxxwrap_julia-v0.8.7+0")),
    Dependency(PackageSpec(; name="OpenCVQt_jll", uuid="2e4a2372-4a7c-5bb9-ae2d-b1938f154ce2", url="https://github.com/terasakisatoshi/OpenCVQt_jll.jl", rev="OpenCVQt-v0.7.1+0")),
    BuildDependency(PackageSpec(name="libjulia_jll", version=v"1.6.0")),
]

# Build the tarballs, and possibly a `build.jl` as well.
build_tarballs(ARGS, name, version, sources, script, platforms, products, dependencies; preferred_gcc_version = v"7")


text:
module Utilities

using FFTW

##############################
## INDEX MAPPTING FUNCTIONS ##
##############################

"""
maps (τ,site) ==> index in vector
"""
@inline function get_index(τ::Int, site::Int, Lτ::Int)::Int

    return (site-1)*Lτ + τ
end

"""
maps index in vector ==> site in lattice
"""
@inline function get_site(index::Int, Lτ::Int)::Int

    return div(index-1,Lτ) + 1
end

"""
maps index in vector ==> τ imaginary time slice
"""
@inline function get_τ(index::Int, Lτ::Int)::Int

    return (index-1)%Lτ + 1
end

"""
Reshapes with zero allocations, returns an instance of Base.ReshapedArray.
Discussion found at: https://github.com/JuliaLang/julia/issues/36313
"""
function reshaped(a::AbstractArray{T,M}, dims::NTuple{N,Int}) where {T,N,M}
    return invoke(Base._reshape, Tuple{AbstractArray,typeof(dims)}, a, dims)
end

function reshaped(a::AbstractArray{T,M}, dims...) where {T,M}
    return reshaped(a, dims)
end

"""
Averages over translational symmetry between arrays `f` and `g` by doing an FFT accelerated convolution.
The result is output into the array `fg`. The arrays `f` and `g` are left modified by this function.
"""
function translational_average!(fg::AbstractArray{T},f::AbstractArray{T},g::AbstractArray{T}) where {T<:Complex}

    fft!(f)
    fft!(g)
    N  = length(f)
    g′ = fg
    circshift!(g′, g, size(fg,d)-1 for d in 1:ndims(fg))
    reverse!(g′)
    @. fg = f * g′ / N
    ifft!(fg)
    return nothing
end

"""
Simpson integration over vector.
"""
function simpson(f::AbstractVector{T1},dx::T2)::T1 where {T1<:Number,T2<:Number}

    L = length(f)
    F = T1(0.0)
    for i in 2:2:L-1
        F += dx * ( 1/3*f[i-1] + 4/3*f[i] + 1/3*f[i+1] )
    end
    if iseven(L)
        F += dx * ( 5/12*f[L] + 2/3*f[L-1] - 1/12*f[L-2] )
    end
    return F
end

"""
Swap values between arrays.
"""
function swap!(v::AbstractArray{T},u::AbstractArray{T}) where {T<:Number}

    @fastmath @inbounds for i in eachindex(u)
        tmp  = u[i]
        u[i] = v[i]
        v[i] = tmp
    end

    return nothing
end

####################
## MATH FUNCTIONS ##
####################

"""
Delta function.
"""
@inline function δ(i::T,j::T)::T where {T<:Number}

    return i==j
end

@inline function δ(i::T)::T where {T<:Number}

    return iszero(i)
end

"""
Heaviside step function.
"""
@inline function θ(i::T)::T where {T<:Number}

    return i>0
end

end

max_stars_repo_name: cohensbw/Langevin

max_issues_repo_name: cohensbw/ElPhDynamics

max_forks_repo_name: cohensbw/ElPhDynamics