// File: yuang-chen[P]paraGCN/src/gcn.cpp
// Function: GCN::GCN(GCNParams, GCNData*)
GCN::GCN(GCNParams params, GCNData *input_data) {
    this->params = params;
    this->data = input_data;
    modules.reserve(8);
    variables.reserve(8);
    //1.1 register and initialize the input data
    variables.emplace_back(data->feature_index.indices.size(), false);
    input = &variables.back();
//1.2 dropout the input data
    modules.push_back(new Dropout(input, params.dropout));
    //2.1 register and get the * at layer 1
    variables.emplace_back(params.num_nodes * params.hidden_dim);
    Variable *layer1_var1 = &variables.back();
    //2.2 register weights at layer 1 and randomize them
    variables.emplace_back(params.input_dim * params.hidden_dim, true, true);
    Variable *layer1_weight = &variables.back();
    layer1_weight->glorot(params.input_dim, params.hidden_dim);
  
//2.3 X.spmm(W0): compute the feature with filters 
    modules.push_back(new SparseMatmul(input, layer1_weight, layer1_var1, 
        params.num_nodes, params.input_dim, params.hidden_dim, &data->feature_index));
    //3.1 register and normalized var at layer 1
    variables.emplace_back(params.num_nodes * params.hidden_dim);
    Variable *layer1_var2 = &variables.back();
//3.2  A^XW0: normalize the output from last layer
    modules.push_back(new GraphSum(layer1_var1, layer1_var2,
         &data->graph, params.hidden_dim));
//4. ReLU(A^XW0)
    modules.push_back(new ReLU(layer1_var2));
//5. dropout and get ready for the 2nd layer 
    modules.push_back(new Dropout(layer1_var2, params.dropout));
    //6.1 do it for the 2nd layer
    variables.emplace_back(params.num_nodes * params.output_dim);
    Variable *layer2_var1 = &variables.back();
    //6.2 weights of the 2nd layer 
    variables.emplace_back(params.hidden_dim * params.output_dim, true, true);
    Variable *layer2_weight = &variables.back();
    layer2_weight->glorot(params.hidden_dim, params.output_dim);
//6.3 ReLU(A^XW0)W1: dense matrix multiply
    modules.push_back(new Matmul(layer1_var2, layer2_weight, layer2_var1, 
        params.num_nodes, params.hidden_dim, params.output_dim));
    //7.1 for the output
    variables.emplace_back(params.num_nodes * params.output_dim);
    output = &variables.back();
//7.2 A^(ReLU(A^XW0)W1): normalize layer2_var1,
    modules.push_back(new GraphSum(layer2_var1, output, &data->graph, params.output_dim));
    truth = vector<int>(params.num_nodes);
//8. cross entropy loss, the softmaxt function are inside of it
    modules.push_back(new CrossEntropyLoss(output, truth.data(), &loss, params.output_dim));
    
    AdamParams adam_params = AdamParams::get_default();
    adam_params.lr = params.learning_rate;
    adam_params.weight_decay = params.weight_decay;
    optimizer = Adam({{layer1_weight, true}, {layer2_weight, false}}, adam_params);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2a0, %rsp            # imm = 0x2A0
leaq 0x10(%rbp), %rax
movq %rax, -0x1c0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x1a0(%rbp)
addq $0x8, %rdi
movq %rdi, -0x1b8(%rbp)
callq 0x4ba0
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
movq %rdi, -0x1b0(%rbp)
callq 0x4bc0
movq -0x1a0(%rbp), %rdi
addq $0x48, %rdi
movq %rdi, -0x1a8(%rbp)
callq 0x4be0
movq -0x1a0(%rbp), %rdi
addq $0x68, %rdi
movq %rdi, -0x198(%rbp)
callq 0x4c00
jmp 0x3850
movq -0x1a0(%rbp), %rdi
movq -0x1c0(%rbp), %rax
movl 0x20(%rax), %ecx
movl %ecx, 0xb8(%rdi)
movups (%rax), %xmm0
movups 0x10(%rax), %xmm1
movups %xmm1, 0xa8(%rdi)
movups %xmm0, 0x98(%rdi)
movq -0x10(%rbp), %rax
movq %rax, (%rdi)
addq $0x8, %rdi
movl $0x8, %esi
callq 0x4c20
jmp 0x3893
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
movl $0x8, %esi
callq 0x4d20
jmp 0x38aa
movq -0x1a0(%rbp), %rax
movq %rax, %rcx
addq $0x20, %rcx
movq %rcx, -0x1c8(%rbp)
movq (%rax), %rdi
callq 0x4ea0
movq -0x1c8(%rbp), %rdi
movq %rax, -0x28(%rbp)
movb $0x0, -0x29(%rbp)
leaq -0x28(%rbp), %rsi
leaq -0x29(%rbp), %rdx
callq 0x4e20
jmp 0x38e5
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
callq 0x4ec0
movq %rax, %rcx
movq -0x1a0(%rbp), %rax
movq %rcx, 0x38(%rax)
addq $0x8, %rax
movq %rax, -0x1d8(%rbp)
movl $0x20, %edi
callq 0x3260
movq %rax, -0x1d0(%rbp)
jmp 0x3921
movq -0x1d0(%rbp), %rdi
movq -0x1c0(%rbp), %rax
movq -0x1a0(%rbp), %rcx
movq 0x38(%rcx), %rsi
movss 0x10(%rax), %xmm0
callq 0xc7a0
jmp 0x3946
movq -0x1d8(%rbp), %rdi
movq -0x1d0(%rbp), %rax
movq %rax, -0x38(%rbp)
leaq -0x38(%rbp), %rsi
callq 0x4f00
jmp 0x3963
movq -0x1c0(%rbp), %rcx
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
movl (%rcx), %eax
movl 0x8(%rcx), %ecx
imull %ecx, %eax
movl %eax, -0x3c(%rbp)
leaq -0x3c(%rbp), %rsi
callq 0x4f30
jmp 0x398b
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
movq %rdi, -0x1e0(%rbp)
callq 0x4ec0
movq -0x1c0(%rbp), %rcx
movq -0x1e0(%rbp), %rdi
movq %rax, -0x48(%rbp)
movl 0x4(%rcx), %eax
movl 0x8(%rcx), %ecx
imull %ecx, %eax
movl %eax, -0x4c(%rbp)
movb $0x1, -0x4d(%rbp)
movb $0x1, -0x4e(%rbp)
leaq -0x4c(%rbp), %rsi
leaq -0x4d(%rbp), %rdx
leaq -0x4e(%rbp), %rcx
callq 0x4fb0
jmp 0x39db
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
callq 0x4ec0
movq %rax, %rcx
movq -0x1c0(%rbp), %rax
movq %rcx, -0x58(%rbp)
movq -0x58(%rbp), %rdi
movl 0x4(%rax), %esi
movl 0x8(%rax), %edx
callq 0xceb0
jmp 0x3a0a
movq -0x1a0(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x1f0(%rbp)
movl $0x38, %edi
callq 0x3260
movq %rax, -0x1e8(%rbp)
jmp 0x3a2f
movq -0x1e8(%rbp), %rdi
movq -0x1c0(%rbp), %rax
movq -0x1a0(%rbp), %rcx
movq (%rcx), %r11
movq 0x38(%rcx), %rsi
movq -0x58(%rbp), %rdx
movq -0x48(%rbp), %rcx
movl (%rax), %r8d
movl 0x4(%rax), %r9d
movl 0x8(%rax), %r10d
movq %rsp, %rax
movq %r11, 0x8(%rax)
movl %r10d, (%rax)
callq 0xba20
jmp 0x3a6f
movq -0x1f0(%rbp), %rdi
movq -0x1e8(%rbp), %rax
movq %rax, -0x60(%rbp)
leaq -0x60(%rbp), %rsi
callq 0x4f00
jmp 0x3a8c
movq -0x1c0(%rbp), %rcx
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
movl (%rcx), %eax
movl 0x8(%rcx), %ecx
imull %ecx, %eax
movl %eax, -0x64(%rbp)
leaq -0x64(%rbp), %rsi
callq 0x4f30
jmp 0x3ab4
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
callq 0x4ec0
movq %rax, %rcx
movq -0x1a0(%rbp), %rax
movq %rcx, -0x70(%rbp)
addq $0x8, %rax
movq %rax, -0x200(%rbp)
movl $0x28, %edi
callq 0x3260
movq %rax, -0x1f8(%rbp)
jmp 0x3af0
movq -0x1f8(%rbp), %rdi
movq -0x1c0(%rbp), %rax
movq -0x1a0(%rbp), %rcx
movq -0x48(%rbp), %rsi
movq -0x70(%rbp), %rdx
movq (%rcx), %rcx
addq $0x30, %rcx
movl 0x8(%rax), %r8d
callq 0xbd90
jmp 0x3b1f
movq -0x200(%rbp), %rdi
movq -0x1f8(%rbp), %rax
movq %rax, -0x78(%rbp)
leaq -0x78(%rbp), %rsi
callq 0x4f00
jmp 0x3b3c
movq -0x1a0(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x210(%rbp)
movl $0x18, %edi
callq 0x3260
movq %rax, -0x208(%rbp)
jmp 0x3b61
movq -0x208(%rbp), %rdi
movq -0x70(%rbp), %rsi
callq 0xc560
jmp 0x3b73
movq -0x210(%rbp), %rdi
movq -0x208(%rbp), %rax
movq %rax, -0x80(%rbp)
leaq -0x80(%rbp), %rsi
callq 0x4f00
jmp 0x3b90
movq -0x1a0(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x220(%rbp)
movl $0x20, %edi
callq 0x3260
movq %rax, -0x218(%rbp)
jmp 0x3bb5
movq -0x218(%rbp), %rdi
movq -0x1c0(%rbp), %rax
movq -0x70(%rbp), %rsi
movss 0x10(%rax), %xmm0
callq 0xc7a0
jmp 0x3bd3
movq -0x220(%rbp), %rdi
movq -0x218(%rbp), %rax
movq %rax, -0x88(%rbp)
leaq -0x88(%rbp), %rsi
callq 0x4f00
jmp 0x3bf6
movq -0x1c0(%rbp), %rcx
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
movl (%rcx), %eax
movl 0xc(%rcx), %ecx
imull %ecx, %eax
movl %eax, -0x8c(%rbp)
leaq -0x8c(%rbp), %rsi
callq 0x4f30
jmp 0x3c24
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
movq %rdi, -0x228(%rbp)
callq 0x4ec0
movq -0x1c0(%rbp), %rcx
movq -0x228(%rbp), %rdi
movq %rax, -0x98(%rbp)
movl 0x8(%rcx), %eax
movl 0xc(%rcx), %ecx
imull %ecx, %eax
movl %eax, -0x9c(%rbp)
movb $0x1, -0x9d(%rbp)
movb $0x1, -0x9e(%rbp)
leaq -0x9c(%rbp), %rsi
leaq -0x9d(%rbp), %rdx
leaq -0x9e(%rbp), %rcx
callq 0x4fb0
jmp 0x3c89
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
callq 0x4ec0
movq %rax, %rcx
movq -0x1c0(%rbp), %rax
movq %rcx, -0xa8(%rbp)
movq -0xa8(%rbp), %rdi
movl 0x8(%rax), %esi
movl 0xc(%rax), %edx
callq 0xceb0
jmp 0x3cbe
movq -0x1a0(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x238(%rbp)
movl $0x30, %edi
callq 0x3260
movq %rax, -0x230(%rbp)
jmp 0x3ce3
movq -0x230(%rbp), %rdi
movq -0x1c0(%rbp), %rax
movq -0x70(%rbp), %rsi
movq -0xa8(%rbp), %rdx
movq -0x98(%rbp), %rcx
movl (%rax), %r8d
movl 0x8(%rax), %r9d
movl 0xc(%rax), %r10d
movq %rsp, %rax
movl %r10d, (%rax)
callq 0xb6c0
jmp 0x3d1b
movq -0x238(%rbp), %rdi
movq -0x230(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq -0xb0(%rbp), %rsi
callq 0x4f00
jmp 0x3d3e
movq -0x1c0(%rbp), %rcx
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
movl (%rcx), %eax
movl 0xc(%rcx), %ecx
imull %ecx, %eax
movl %eax, -0xb4(%rbp)
leaq -0xb4(%rbp), %rsi
callq 0x4f30
jmp 0x3d6c
movq -0x1a0(%rbp), %rdi
addq $0x20, %rdi
callq 0x4ec0
movq %rax, %rcx
movq -0x1a0(%rbp), %rax
movq %rcx, 0x40(%rax)
addq $0x8, %rax
movq %rax, -0x248(%rbp)
movl $0x28, %edi
callq 0x3260
movq %rax, -0x240(%rbp)
jmp 0x3da8
movq -0x240(%rbp), %rdi
movq -0x1c0(%rbp), %rax
movq -0x1a0(%rbp), %rdx
movq -0x98(%rbp), %rsi
movq (%rdx), %rcx
movq 0x40(%rdx), %rdx
addq $0x30, %rcx
movl 0xc(%rax), %r8d
callq 0xbd90
jmp 0x3dda
movq -0x248(%rbp), %rdi
movq -0x240(%rbp), %rax
movq %rax, -0xc0(%rbp)
leaq -0xc0(%rbp), %rsi
callq 0x4f00
jmp 0x3dfd
movq -0x1c0(%rbp), %rax
movslq (%rax), %rax
movq %rax, -0x258(%rbp)
leaq -0xd9(%rbp), %rdi
movq %rdi, -0x250(%rbp)
callq 0x5040
movq -0x258(%rbp), %rsi
movq -0x250(%rbp), %rdx
leaq -0xd8(%rbp), %rdi
callq 0x5060
jmp 0x3e3d
movq -0x1a0(%rbp), %rdi
addq $0x48, %rdi
leaq -0xd8(%rbp), %rsi
movq %rsi, -0x270(%rbp)
callq 0x50d0
movq -0x270(%rbp), %rdi
callq 0x5100
leaq -0xd9(%rbp), %rdi
callq 0x5160
movq -0x1a0(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x268(%rbp)
movl $0x28, %edi
callq 0x3260
movq %rax, -0x260(%rbp)
jmp 0x3e98
movq -0x1a0(%rbp), %rdi
movq 0x40(%rdi), %rax
movq %rax, -0x278(%rbp)
addq $0x48, %rdi
callq 0x5180
movq -0x1a0(%rbp), %rcx
movq -0x260(%rbp), %rdi
movq -0x278(%rbp), %rsi
movq %rax, %rdx
movq -0x1c0(%rbp), %rax
addq $0x60, %rcx
movl 0xc(%rax), %r8d
callq 0xc210
jmp 0x3ee1
movq -0x268(%rbp), %rdi
movq -0x260(%rbp), %rax
movq %rax, -0xe8(%rbp)
leaq -0xe8(%rbp), %rsi
callq 0x4f00
jmp 0x3f04
leaq -0xfc(%rbp), %rdi
callq 0xd7f0
jmp 0x3f12
movq -0x1c0(%rbp), %rax
movss 0x14(%rax), %xmm0
movss %xmm0, -0xfc(%rbp)
movss 0x18(%rax), %xmm0
movss %xmm0, -0xec(%rbp)
movb $0x1, -0x179(%rbp)
leaq -0x178(%rbp), %rdi
leaq -0x58(%rbp), %rsi
leaq -0x179(%rbp), %rdx
callq 0x51a0
jmp 0x3f53
leaq -0x168(%rbp), %rdi
movb $0x0, -0x17a(%rbp)
leaq -0xa8(%rbp), %rsi
leaq -0x17a(%rbp), %rdx
callq 0x51a0
jmp 0x3f76
leaq -0x178(%rbp), %rax
movq %rax, -0x158(%rbp)
movq $0x2, -0x150(%rbp)
leaq -0x17b(%rbp), %rdi
movq %rdi, -0x280(%rbp)
callq 0x51d0
movq -0x280(%rbp), %rcx
movq -0x158(%rbp), %rsi
movq -0x150(%rbp), %rdx
leaq -0x148(%rbp), %rdi
callq 0x51f0
jmp 0x3fc5
movl -0xec(%rbp), %eax
movl %eax, -0x180(%rbp)
movups -0xfc(%rbp), %xmm0
movaps %xmm0, -0x190(%rbp)
movl -0x180(%rbp), %ecx
movq %rsp, %rax
movl %ecx, 0x10(%rax)
movaps -0x190(%rbp), %xmm0
movups %xmm0, (%rax)
leaq -0x130(%rbp), %rdi
leaq -0x148(%rbp), %rsi
callq 0xd980
jmp 0x400a
movq -0x1a0(%rbp), %rdi
addq $0x68, %rdi
leaq -0x130(%rbp), %rsi
callq 0x5270
leaq -0x130(%rbp), %rdi
callq 0x52c0
leaq -0x148(%rbp), %rdi
callq 0x52e0
leaq -0x17b(%rbp), %rdi
callq 0x5340
addq $0x2a0, %rsp            # imm = 0x2A0
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
jmp 0x41d2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
jmp 0x41c6
movq -0x1d0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
movl $0x20, %esi
callq 0x3270
jmp 0x41c6
movq -0x1e8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
movl $0x38, %esi
callq 0x3270
jmp 0x41c6
movq -0x1f8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
movl $0x28, %esi
callq 0x3270
jmp 0x41c6
movq -0x208(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
movl $0x18, %esi
callq 0x3270
jmp 0x41c6
movq -0x218(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
movl $0x20, %esi
callq 0x3270
jmp 0x41c6
movq -0x230(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
movl $0x30, %esi
callq 0x3270
jmp 0x41c6
movq -0x240(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
movl $0x28, %esi
callq 0x3270
jmp 0x41c6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
leaq -0xd9(%rbp), %rdi
callq 0x5160
jmp 0x41c6
movq -0x260(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
movl $0x28, %esi
callq 0x3270
jmp 0x41c6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
jmp 0x41ba
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
leaq -0x148(%rbp), %rdi
callq 0x52e0
leaq -0x17b(%rbp), %rdi
callq 0x5340
movq -0x198(%rbp), %rdi
callq 0x52c0
movq -0x1a8(%rbp), %rdi
callq 0x5100
movq -0x1b0(%rbp), %rdi
callq 0x5360
movq -0x1b8(%rbp), %rdi
callq 0x53c0
movq -0x18(%rbp), %rdi
callq 0x3420
nop