; SPIR-V
; Version: 1.0
; Generator: rspirv
; Bound: 95
OpCapability Shader
OpExtension "SPV_KHR_storage_buffer_storage_class"
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %84 "main" %81
OpExecutionMode %84 LocalSize 1 1 1
%3 = OpString "collatz.wgsl"
OpSource Unknown 0 %3 "struct PrimeIndices {
    data: array<u32>
} // this is used as both input and output for convenience

@group(0) @binding(0)
var<storage,read_write> v_indices: PrimeIndices;

// The Collatz Conjecture states that for any integer n:
// If n is even, n = n/2
// If n is odd, n = 3n+1
// And repeat this process for each new n, you will always eventually reach 1.
// Though the conjecture has not been proven, no counterexample has ever been found.
// This function returns how many times this recurrence needs to be applied to reach 1.
fn collatz_iterations(n_base: u32) -> u32 {
    var n = n_base;
    var i: u32 = 0u;
    while n > 1u {
        if n % 2u == 0u {
            n = n / 2u;
        }
        else {
            n = 3u * n + 1u;
        }
        i = i + 1u;
    }
    return i;
}

@compute @workgroup_size(1)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
    v_indices.data[global_id.x] = collatz_iterations(v_indices.data[global_id.x]);
}
"
OpMemberName %6 0 "data"
OpName %6 "PrimeIndices"
OpName %8 "v_indices"
OpName %10 "naga_mod"
OpName %12 "lhs"
OpName %13 "rhs"
OpName %21 "naga_div"
OpName %22 "lhs"
OpName %23 "rhs"
OpName %29 "n_base"
OpName %30 "collatz_iterations"
OpName %34 "n"
OpName %37 "i"
OpName %49 "loop_bound"
OpName %81 "global_id"
OpName %84 "main"
OpDecorate %5 ArrayStride 4
OpMemberDecorate %6 0 Offset 0
OpDecorate %6 Block
OpDecorate %8 DescriptorSet 0
OpDecorate %8 Binding 0
OpDecorate %81 BuiltIn GlobalInvocationId
%2 = OpTypeVoid
%4 = OpTypeInt 32 0
%5 = OpTypeRuntimeArray %4
%6 = OpTypeStruct %5
%7 = OpTypeVector %4 3
%9 = OpTypePointer StorageBuffer %6
%8 = OpVariable  %9  StorageBuffer
%11 = OpTypeFunction %4 %4 %4
%15 = OpTypeBool
%16 = OpConstant  %4  0
%18 = OpConstant  %4  1
%31 = OpTypeFunction %4 %4
%32 = OpConstant  %4  2
%33 = OpConstant  %4  3
%35 = OpTypePointer Function %4
%36 = OpConstantNull  %4
%43 = OpTypeVector %4 2
%44 = OpTypePointer Function %43
%45 = OpTypeVector %15 2
%46 = OpConstantComposite  %43  %16 %16
%47 = OpConstant  %4  4294967295
%48 = OpConstantComposite  %43  %47 %47
%82 = OpTypePointer Input %7
%81 = OpVariable  %82  Input
%85 = OpTypeFunction %2
%87 = OpTypePointer StorageBuffer %5
%89 = OpTypePointer StorageBuffer %4
%10 = OpFunction  %4  None %11
%12 = OpFunctionParameter  %4
%13 = OpFunctionParameter  %4
%14 = OpLabel
%17 = OpIEqual  %15  %13 %16
%19 = OpSelect  %4  %17 %18 %13
%20 = OpUMod  %4  %12 %19
OpReturnValue %20
OpFunctionEnd
%21 = OpFunction  %4  None %11
%22 = OpFunctionParameter  %4
%23 = OpFunctionParameter  %4
%24 = OpLabel
%25 = OpIEqual  %15  %23 %16
%26 = OpSelect  %4  %25 %18 %23
%27 = OpUDiv  %4  %22 %26
OpReturnValue %27
OpFunctionEnd
%30 = OpFunction  %4  None %31
%29 = OpFunctionParameter  %4
%28 = OpLabel
%34 = OpVariable  %35  Function %36
%37 = OpVariable  %35  Function %16
%49 = OpVariable  %44  Function %46
OpBranch %38
%38 = OpLabel
OpLine %3 15 5
OpStore %34 %29
OpBranch %39
%39 = OpLabel
OpLine %3 17 5
OpLoopMerge %40 %42 None
OpBranch %50
%50 = OpLabel
%51 = OpLoad  %43  %49
%52 = OpIEqual  %45  %48 %51
%53 = OpAll  %15  %52
OpSelectionMerge %54 None
OpBranchConditional %53 %40 %54
%54 = OpLabel
%55 = OpCompositeExtract  %4  %51 1
%56 = OpIEqual  %15  %55 %47
%57 = OpSelect  %4  %56 %18 %16
%58 = OpCompositeConstruct  %43  %57 %18
%59 = OpIAdd  %43  %51 %58
OpStore %49 %59
OpBranch %41
%41 = OpLabel
OpLine %3 1 1
%60 = OpLoad  %4  %34
OpLine %3 17 11
%61 = OpUGreaterThan  %15  %60 %18
OpLine %3 17 10
OpSelectionMerge %62 None
OpBranchConditional %61 %62 %63
%63 = OpLabel
OpBranch %40
%62 = OpLabel
OpBranch %64
%64 = OpLabel
OpLine %3 1 1
%66 = OpLoad  %4  %34
OpLine %3 18 12
%67 = OpFunctionCall  %4  %10 %66 %32
OpLine %3 18 12
%68 = OpIEqual  %15  %67 %16
OpLine %3 18 9
OpSelectionMerge %69 None
OpBranchConditional %68 %70 %71
%70 = OpLabel
OpLine %3 1 1
%72 = OpLoad  %4  %34
OpLine %3 19 17
%73 = OpFunctionCall  %4  %21 %72 %32
OpLine %3 19 13
OpStore %34 %73
OpBranch %69
%71 = OpLabel
OpLine %3 22 17
%74 = OpLoad  %4  %34
%75 = OpIMul  %4  %33 %74
OpLine %3 22 17
%76 = OpIAdd  %4  %75 %18
OpLine %3 22 13
OpStore %34 %76
OpBranch %69
%69 = OpLabel
OpLine %3 1 1
%77 = OpLoad  %4  %37
OpLine %3 24 13
%78 = OpIAdd  %4  %77 %18
OpLine %3 24 9
OpStore %37 %78
OpBranch %65
%65 = OpLabel
OpBranch %42
%42 = OpLabel
OpBranch %39
%40 = OpLabel
OpLine %3 1 1
%79 = OpLoad  %4  %37
OpReturnValue %79
OpFunctionEnd
%84 = OpFunction  %2  None %85
%80 = OpLabel
%83 = OpLoad  %7  %81
OpBranch %86
%86 = OpLabel
OpLine %3 31 5
%88 = OpCompositeExtract  %4  %83 0
OpLine %3 31 54
%90 = OpCompositeExtract  %4  %83 0
%91 = OpAccessChain  %89  %8 %16 %90
%92 = OpLoad  %4  %91
OpLine %3 31 35
%93 = OpFunctionCall  %4  %30 %92
OpLine %3 31 5
%94 = OpAccessChain  %89  %8 %16 %88
OpStore %94 %93
OpReturn
OpFunctionEnd