// File: xbai0624[P]dnn/src/Network.cpp
// Function: Network::ConstructLayers(TrainingType)
void Network::ConstructLayers(TrainingType _training_type) // test purelly fully connected, deep network, 100 layers
{
    // Network structure: {Image->Input->FC->FC->FC->Output}
    TrainingType training_type = _training_type;
    training_type = TrainingType::NewTraining;
    double learning_rate = 0.1;

    // 1) Data interface, this is a tool class, for data prepare
    DataInterface *data_interface = new DataInterface("simulation_data/data_signal_train.dat", "simulation_data/data_cosmic_train.dat", LayerDimension::_1D, std::pair<int, int>(900, 1), 200);

    // 3) input layer   ID=0
    LayerParameterList p_list0(LayerType::input, LayerDimension::_1D, data_interface, 0, 0, 
            std::pair<size_t, size_t>(0, 0), learning_rate, false, 0, 0, Regularization::Undefined, 0, ActuationFuncType::Undefined, training_type, false);
    Layer* layer_input = new ConstructLayer(p_list0);
    // NOTE: a data_interface class pointer must be passed to input layer before calling input_layer->Init() function
    //       because Initialization rely on data_interface
    layer_input->Init();

    // 4) 49 middle layers: fc layer 
    const int NLayer = 20;
    Layer *l_mid[NLayer];
    // layer 0
    LayerParameterList p_list1(LayerType::fullyConnected, LayerDimension::_1D, data_interface, 890, 0, 
            std::pair<size_t, size_t>(0, 0), learning_rate, false, 2, 0.5, Regularization::L2, 0.1, ActuationFuncType::Relu, training_type, true);
    l_mid[0] = new ConstructLayer(p_list1);
    l_mid[0]->SetPrevLayer(layer_input);
    l_mid[0]->Init();
    // layer 1 - layer 46
    for(int i=1;i<NLayer;i++)
    {
        int n_neurons = 890 - ((890-4)/(NLayer-1))*i;
        LayerParameterList p_list_mid(LayerType::fullyConnected, LayerDimension::_1D, data_interface, n_neurons, 0, 
                std::pair<size_t, size_t>(0, 0), learning_rate, false, 2, 0.5, Regularization::L2, 0.1, ActuationFuncType::Relu, training_type, true);
        l_mid[i] = new ConstructLayer(p_list_mid);
        l_mid[i]->SetPrevLayer(l_mid[i-1]);
        l_mid[i]->Init();
    }


    // 5) output layer ID = 7
    LayerParameterList p_list_output(LayerType::output, LayerDimension::_1D, data_interface, 2, 0, 
            std::pair<size_t, size_t>(0, 0), learning_rate, false, 0, 0., Regularization::L2, 0.1, ActuationFuncType::SoftMax, training_type, false);
    Layer* layer_output = new ConstructLayer(p_list_output);
    layer_output -> SetPrevLayer(l_mid[NLayer-1]);
    layer_output -> Init();

    // 6) connect all layers; SetNextLayer must be after all layers have finished initialization
    //                        input layer not needed to set, input layer has no update on w & b
    //                        input layer is just for data transfer (prepare)
    //l1->SetNextLayer(l2);
    //l2->SetNextLayer(l3);
    //l3->SetNextLayer(layer_output); // This line is ugly, to be improved
    for(int i=0;i<NLayer-1;i++)
        l_mid[i]->SetNextLayer(l_mid[i+1]);
    l_mid[NLayer-1]->SetNextLayer(layer_output);

    // 7) save all constructed layers
    __inputLayer = layer_input;
    __outputLayer = layer_output;
    //__middleAndOutputLayers.push_back(l1); // must be pushed in order
    //__middleAndOutputLayers.push_back(l2); // must be pushed in order
    //__middleAndOutputLayers.push_back(l3);
    //__middleAndOutputLayers.push_back(layer_output);
    for(int i=0;i<NLayer;i++)
        __middleAndOutputLayers.push_back(l_mid[i]);
    __middleAndOutputLayers.push_back(layer_output);
    //cout<<"total number of layers: "<<__middleAndOutputLayers.size()<<endl;
    __dataInterface = data_interface;
}

// Assembly:
subq $0x588, %rsp            # imm = 0x588
movq %rdi, 0x580(%rsp)
movl %esi, 0x57c(%rsp)
movq 0x580(%rsp), %rax
movq %rax, 0xb8(%rsp)
movl 0x57c(%rsp), %eax
movl %eax, 0x578(%rsp)
movl $0x0, 0x578(%rsp)
movabsq $0x3fb999999999999a, %rax # imm = 0x3FB999999999999A
movq %rax, 0x570(%rsp)
movl $0xc8, %edi
callq 0x4240
movq %rax, 0xc0(%rsp)
movl $0x384, 0x55c(%rsp) # imm = 0x384
movl $0x1, 0x558(%rsp)
leaq 0x560(%rsp), %rdi
leaq 0x55c(%rsp), %rsi
leaq 0x558(%rsp), %rdx
callq 0x27b90
jmp 0x45368
movq 0xc0(%rsp), %rdi
movq 0x560(%rsp), %r8
leaq 0x10519(%rip), %rsi     # 0x55898
leaq 0x10538(%rip), %rdx     # 0x558be
xorl %ecx, %ecx
movl $0xc8, %r9d
callq 0x39860
jmp 0x45395
movq 0xc0(%rsp), %rax
movq %rax, 0x568(%rsp)
movq 0x568(%rsp), %rax
movq %rax, 0xa8(%rsp)
movl $0x0, 0x4cc(%rsp)
movl $0x0, 0x4c8(%rsp)
leaq 0x4d0(%rsp), %rdi
leaq 0x4cc(%rsp), %rsi
leaq 0x4c8(%rsp), %rdx
callq 0x279d0
movq 0xa8(%rsp), %rcx
movsd 0x570(%rsp), %xmm0
movl 0x578(%rsp), %edx
movups 0x4d0(%rsp), %xmm1
movq %rsp, %rax
movups %xmm1, (%rax)
movl %edx, 0x30(%rax)
movl $0x0, 0x38(%rax)
movl $0x4, 0x28(%rax)
movl $0x2, 0x20(%rax)
movl $0x0, 0x18(%rax)
movl $0x0, 0x10(%rax)
xorl %edx, %edx
movl %edx, %r9d
leaq 0x4e0(%rsp), %rdi
movl $0x3, %esi
xorps %xmm2, %xmm2
movq %r9, %r8
movaps %xmm2, %xmm1
callq 0x46830
movl $0x490, %edi            # imm = 0x490
callq 0x4240
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0xb0(%rsp)
movq 0x540(%rsp), %rax
movq %rax, 0x4b0(%rsp)
movups 0x530(%rsp), %xmm0
movaps %xmm0, 0x4a0(%rsp)
movups 0x520(%rsp), %xmm0
movaps %xmm0, 0x490(%rsp)
movups 0x4e0(%rsp), %xmm0
movups 0x4f0(%rsp), %xmm1
movups 0x500(%rsp), %xmm2
movups 0x510(%rsp), %xmm3
movaps %xmm3, 0x480(%rsp)
movaps %xmm2, 0x470(%rsp)
movaps %xmm1, 0x460(%rsp)
movaps %xmm0, 0x450(%rsp)
movq 0x4b0(%rsp), %rcx
movq %rsp, %rax
movq %rcx, 0x60(%rax)
movaps 0x4a0(%rsp), %xmm0
movups %xmm0, 0x50(%rax)
movaps 0x490(%rsp), %xmm0
movups %xmm0, 0x40(%rax)
movaps 0x450(%rsp), %xmm0
movaps 0x460(%rsp), %xmm1
movaps 0x470(%rsp), %xmm2
movaps 0x480(%rsp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0x4ea0
jmp 0x45539
movq 0xb0(%rsp), %rax
movq %rax, 0x4c0(%rsp)
movq 0x4c0(%rsp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movl $0x14, 0x44c(%rsp)
movq 0x568(%rsp), %rax
movq %rax, 0x98(%rsp)
movl $0x0, 0x324(%rsp)
movl $0x0, 0x320(%rsp)
leaq 0x328(%rsp), %rdi
leaq 0x324(%rsp), %rsi
leaq 0x320(%rsp), %rdx
callq 0x279d0
movq 0x98(%rsp), %rcx
movsd 0x570(%rsp), %xmm0
movl 0x578(%rsp), %edx
movups 0x328(%rsp), %xmm1
movq %rsp, %rax
movups %xmm1, (%rax)
movl %edx, 0x30(%rax)
movl $0x1, 0x38(%rax)
movl $0x3, 0x28(%rax)
movl $0x0, 0x20(%rax)
movl $0x2, 0x18(%rax)
movl $0x0, 0x10(%rax)
xorl %edx, %edx
movl %edx, %r9d
leaq 0x338(%rsp), %rdi
movl $0x37a, %r8d            # imm = 0x37A
movsd 0xca01(%rip), %xmm1     # 0x52010
movsd 0x10279(%rip), %xmm2    # 0x55890
movl %edx, %esi
callq 0x46830
movl $0x490, %edi            # imm = 0x490
callq 0x4240
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0xa0(%rsp)
movq 0x398(%rsp), %rax
movq %rax, 0x310(%rsp)
movups 0x388(%rsp), %xmm0
movaps %xmm0, 0x300(%rsp)
movups 0x378(%rsp), %xmm0
movaps %xmm0, 0x2f0(%rsp)
movups 0x338(%rsp), %xmm0
movups 0x348(%rsp), %xmm1
movups 0x358(%rsp), %xmm2
movups 0x368(%rsp), %xmm3
movaps %xmm3, 0x2e0(%rsp)
movaps %xmm2, 0x2d0(%rsp)
movaps %xmm1, 0x2c0(%rsp)
movaps %xmm0, 0x2b0(%rsp)
movq 0x310(%rsp), %rcx
movq %rsp, %rax
movq %rcx, 0x60(%rax)
movaps 0x300(%rsp), %xmm0
movups %xmm0, 0x50(%rax)
movaps 0x2f0(%rsp), %xmm0
movups %xmm0, 0x40(%rax)
movaps 0x2b0(%rsp), %xmm0
movaps 0x2c0(%rsp), %xmm1
movaps 0x2d0(%rsp), %xmm2
movaps 0x2e0(%rsp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0x4ea0
jmp 0x45703
movq 0xa0(%rsp), %rax
movq %rax, 0x3a0(%rsp)
movq 0x3a0(%rsp), %rdi
movq 0x4c0(%rsp), %rsi
movq (%rdi), %rax
callq *0x1e8(%rax)
movq 0x3a0(%rsp), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
movl $0x1, 0x2ac(%rsp)
cmpl $0x14, 0x2ac(%rsp)
jge 0x45a24
movl 0x2ac(%rsp), %eax
imull $0x2e, %eax, %ecx
movl $0x37a, %eax            # imm = 0x37A
subl %ecx, %eax
movl %eax, 0x2a8(%rsp)
movq 0x568(%rsp), %rax
movq %rax, 0x80(%rsp)
movslq 0x2a8(%rsp), %rax
movq %rax, 0x88(%rsp)
movl $0x0, 0x22c(%rsp)
movl $0x0, 0x228(%rsp)
leaq 0x230(%rsp), %rdi
leaq 0x22c(%rsp), %rsi
leaq 0x228(%rsp), %rdx
callq 0x279d0
movq 0x80(%rsp), %rcx
movq 0x88(%rsp), %r8
movsd 0x570(%rsp), %xmm0
movl 0x578(%rsp), %edx
movups 0x230(%rsp), %xmm1
movq %rsp, %rax
movups %xmm1, (%rax)
movl %edx, 0x30(%rax)
movl $0x1, 0x38(%rax)
movl $0x3, 0x28(%rax)
movl $0x0, 0x20(%rax)
movl $0x2, 0x18(%rax)
movl $0x0, 0x10(%rax)
xorl %edx, %edx
movl %edx, %r9d
leaq 0x240(%rsp), %rdi
movsd 0xc7e9(%rip), %xmm1     # 0x52010
movsd 0x10061(%rip), %xmm2    # 0x55890
movl %edx, %esi
callq 0x46830
movl $0x490, %edi            # imm = 0x490
callq 0x4240
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x90(%rsp)
movq 0x2a0(%rsp), %rax
movq %rax, 0x220(%rsp)
movups 0x290(%rsp), %xmm0
movaps %xmm0, 0x210(%rsp)
movups 0x280(%rsp), %xmm0
movaps %xmm0, 0x200(%rsp)
movups 0x240(%rsp), %xmm0
movups 0x250(%rsp), %xmm1
movups 0x260(%rsp), %xmm2
movups 0x270(%rsp), %xmm3
movaps %xmm3, 0x1f0(%rsp)
movaps %xmm2, 0x1e0(%rsp)
movaps %xmm1, 0x1d0(%rsp)
movaps %xmm0, 0x1c0(%rsp)
movq 0x220(%rsp), %rcx
movq %rsp, %rax
movq %rcx, 0x60(%rax)
movaps 0x210(%rsp), %xmm0
movups %xmm0, 0x50(%rax)
movaps 0x200(%rsp), %xmm0
movups %xmm0, 0x40(%rax)
movaps 0x1c0(%rsp), %xmm0
movaps 0x1d0(%rsp), %xmm1
movaps 0x1e0(%rsp), %xmm2
movaps 0x1f0(%rsp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0x4ea0
jmp 0x4591b
movq 0x90(%rsp), %rcx
movslq 0x2ac(%rsp), %rax
movq %rcx, 0x3a0(%rsp,%rax,8)
movslq 0x2ac(%rsp), %rax
movq 0x3a0(%rsp,%rax,8), %rdi
movl 0x2ac(%rsp), %eax
subl $0x1, %eax
cltq
movq 0x3a0(%rsp,%rax,8), %rsi
movq (%rdi), %rax
callq *0x1e8(%rax)
movslq 0x2ac(%rsp), %rax
movq 0x3a0(%rsp,%rax,8), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
movl 0x2ac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2ac(%rsp)
jmp 0x45745
movq 0xc0(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x550(%rsp)
movl %eax, 0x54c(%rsp)
callq 0x4220
jmp 0x45d19
movq 0xb0(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x550(%rsp)
movl %eax, 0x54c(%rsp)
callq 0x4220
jmp 0x45d19
movq 0xa0(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x550(%rsp)
movl %eax, 0x54c(%rsp)
callq 0x4220
jmp 0x45d19
movq 0x90(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x550(%rsp)
movl %eax, 0x54c(%rsp)
callq 0x4220
jmp 0x45d19
movq 0x568(%rsp), %rax
movq %rax, 0x70(%rsp)
movl $0x0, 0x144(%rsp)
movl $0x0, 0x140(%rsp)
leaq 0x148(%rsp), %rdi
leaq 0x144(%rsp), %rsi
leaq 0x140(%rsp), %rdx
callq 0x279d0
movq 0x70(%rsp), %rcx
movsd 0x570(%rsp), %xmm0
movl 0x578(%rsp), %edx
movups 0x148(%rsp), %xmm1
movq %rsp, %rax
movups %xmm1, (%rax)
movl %edx, 0x30(%rax)
movl $0x0, 0x38(%rax)
movl $0x1, 0x28(%rax)
movl $0x0, 0x20(%rax)
movl $0x0, 0x18(%rax)
movl $0x0, 0x10(%rax)
xorl %edx, %edx
movl %edx, %r9d
leaq 0x158(%rsp), %rdi
movl $0x4, %esi
movl $0x2, %r8d
xorps %xmm1, %xmm1
movsd 0xfdc0(%rip), %xmm2     # 0x55890
callq 0x46830
movl $0x490, %edi            # imm = 0x490
callq 0x4240
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x78(%rsp)
movq 0x1b8(%rsp), %rax
movq %rax, 0x130(%rsp)
movups 0x1a8(%rsp), %xmm0
movaps %xmm0, 0x120(%rsp)
movups 0x198(%rsp), %xmm0
movaps %xmm0, 0x110(%rsp)
movups 0x158(%rsp), %xmm0
movups 0x168(%rsp), %xmm1
movups 0x178(%rsp), %xmm2
movups 0x188(%rsp), %xmm3
movaps %xmm3, 0x100(%rsp)
movaps %xmm2, 0xf0(%rsp)
movaps %xmm1, 0xe0(%rsp)
movaps %xmm0, 0xd0(%rsp)
movq 0x130(%rsp), %rcx
movq %rsp, %rax
movq %rcx, 0x60(%rax)
movaps 0x120(%rsp), %xmm0
movups %xmm0, 0x50(%rax)
movaps 0x110(%rsp), %xmm0
movups %xmm0, 0x40(%rax)
movaps 0xd0(%rsp), %xmm0
movaps 0xe0(%rsp), %xmm1
movaps 0xf0(%rsp), %xmm2
movaps 0x100(%rsp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0x4ea0
jmp 0x45bb7
movq 0x78(%rsp), %rax
movq %rax, 0x138(%rsp)
movq 0x138(%rsp), %rdi
movq 0x438(%rsp), %rsi
movq (%rdi), %rax
callq *0x1e8(%rax)
movq 0x138(%rsp), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
movl $0x0, 0xcc(%rsp)
cmpl $0x13, 0xcc(%rsp)
jge 0x45c63
movslq 0xcc(%rsp), %rax
movq 0x3a0(%rsp,%rax,8), %rdi
movl 0xcc(%rsp), %eax
addl $0x1, %eax
cltq
movq 0x3a0(%rsp,%rax,8), %rsi
movq (%rdi), %rax
callq *0x1f0(%rax)
movl 0xcc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xcc(%rsp)
jmp 0x45bf6
movq 0x78(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x550(%rsp)
movl %eax, 0x54c(%rsp)
callq 0x4220
jmp 0x45d19
movq 0x438(%rsp), %rdi
movq 0x138(%rsp), %rsi
movq (%rdi), %rax
callq *0x1f0(%rax)
movq 0xb8(%rsp), %rax
movq 0x4c0(%rsp), %rcx
movq %rcx, 0x18(%rax)
movq 0x138(%rsp), %rcx
movq %rcx, 0x20(%rax)
movl $0x0, 0xc8(%rsp)
cmpl $0x14, 0xc8(%rsp)
jge 0x45ce8
movq 0xb8(%rsp), %rdi
movslq 0xc8(%rsp), %rax
leaq 0x3a0(%rsp), %rsi
shlq $0x3, %rax
addq %rax, %rsi
callq 0x46930
movl 0xc8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc8(%rsp)
jmp 0x45ca7
movq 0xb8(%rsp), %rdi
leaq 0x138(%rsp), %rsi
callq 0x46930
movq 0xb8(%rsp), %rax
movq 0x568(%rsp), %rcx
movq %rcx, 0x28(%rax)
addq $0x588, %rsp            # imm = 0x588
retq
movq 0x550(%rsp), %rdi
callq 0x43f0
nopw %cs:(%rax,%rax)