// File: ghulette[P]neural-net-openmp/neuralnet.cpp
// Function: NeuralNet::NeuralNet(int, int, int)
NeuralNet::NeuralNet(int n_inputs, int n_hidden, int n_outputs) {
  num_inputs = n_inputs;
  num_hidden = n_hidden;
  num_outputs = n_outputs;
  
  hidden_values = new double[num_hidden];
  hidden_weight_deltas = new double[num_hidden];
  hidden_weights_buffer = new double[num_hidden * num_inputs];
  hidden_weights = new double*[num_hidden];
  
  #pragma omp parallel for
  for(int i=0; i < num_hidden; i++) {
    hidden_weights[i] = hidden_weights_buffer + (i * num_inputs);
    for(int j=0; j < num_inputs; j++) {
      hidden_weights[i][j] = rand_weight();
    }
  }
  
  output_values = new double[num_outputs];
  output_weight_deltas = new double[num_outputs];
  output_weights_buffer = new double[num_outputs * num_hidden];
  output_weights = new double*[num_outputs];
  
  #pragma omp parallel for
  for(int i=0; i < num_outputs; i++) {
    output_weights[i] = output_weights_buffer + (i * num_hidden);
    for(int j=0; j < num_hidden; j++) {
      output_weights[i][j] = rand_weight();
    }
  }
  
#ifdef _OPENMP
#pragma omp parallel 
    {
#pragma omp single
    std::cout << "Using OpenMP with " << omp_get_num_threads() 
              << " threads" << std::endl;
    }
#endif
}

// Assembly:
subq $0x38, %rsp
movq %rdi, 0x30(%rsp)
movl %esi, 0x2c(%rsp)
movl %edx, 0x28(%rsp)
movl %ecx, 0x24(%rsp)
movq 0x30(%rsp), %rax
movq %rax, 0x8(%rsp)
movl 0x2c(%rsp), %ecx
movl %ecx, (%rax)
movl 0x28(%rsp), %ecx
movl %ecx, 0x4(%rax)
movl 0x24(%rsp), %ecx
movl %ecx, 0x8(%rax)
movslq 0x4(%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x28(%rax)
movslq 0x4(%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq 0x8(%rsp), %rcx
movq %rax, 0x20(%rcx)
movl 0x4(%rcx), %eax
imull (%rcx), %eax
cltq
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x18(%rax)
movslq 0x4(%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x10(%rax)
movl $0x0, 0x20(%rsp)
movq 0x8(%rsp), %rcx
movl 0x20(%rsp), %eax
cmpl 0x4(%rcx), %eax
jge 0x484a
movq 0x8(%rsp), %rax
movq 0x18(%rax), %rdx
movl 0x20(%rsp), %ecx
imull (%rax), %ecx
movslq %ecx, %rcx
shlq $0x3, %rcx
addq %rcx, %rdx
movq 0x10(%rax), %rax
movslq 0x20(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movl $0x0, 0x1c(%rsp)
movq 0x8(%rsp), %rcx
movl 0x1c(%rsp), %eax
cmpl (%rcx), %eax
jge 0x4838
callq 0x4fe0
movq 0x8(%rsp), %rax
movq 0x10(%rax), %rax
movslq 0x20(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movslq 0x1c(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x47fd
jmp 0x483a
movl 0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
jmp 0x47c0
movq 0x8(%rsp), %rax
movslq 0x8(%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x48(%rax)
movslq 0x8(%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq 0x8(%rsp), %rcx
movq %rax, 0x40(%rcx)
movl 0x8(%rcx), %eax
imull 0x4(%rcx), %eax
cltq
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x38(%rax)
movslq 0x8(%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x30(%rax)
movl $0x0, 0x18(%rsp)
movq 0x8(%rsp), %rcx
movl 0x18(%rsp), %eax
cmpl 0x8(%rcx), %eax
jge 0x49a9
movq 0x8(%rsp), %rax
movq 0x38(%rax), %rdx
movl 0x18(%rsp), %ecx
imull 0x4(%rax), %ecx
movslq %ecx, %rcx
shlq $0x3, %rcx
addq %rcx, %rdx
movq 0x30(%rax), %rax
movslq 0x18(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movl $0x0, 0x14(%rsp)
movq 0x8(%rsp), %rcx
movl 0x14(%rsp), %eax
cmpl 0x4(%rcx), %eax
jge 0x4997
callq 0x4fe0
movq 0x8(%rsp), %rax
movq 0x30(%rax), %rax
movslq 0x18(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movslq 0x14(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14(%rsp)
jmp 0x495b
jmp 0x4999
movl 0x18(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0x491d
addq $0x38, %rsp
retq
nop