// File: /workspace/github_c_makefile_star2_O0/aligusnet[P]morpheus/tests/numeric_gradient_test.c
// Function: test_numeric_gradient
void test_numeric_gradient() {
  morpheus_reg_t reg_none;
  reg_none.type = morpheus_reg_none;

  morpheus_reg_t reg_l2;
  reg_l2.type = morpheus_reg_l2;
  reg_l2.lambda = 1;

  double X[] = {
    1, 3,
    1, 5,
    1, 10,
    1, 0,
    1, 4
  };
  double y[] = {9, 13, 23, 3, 11};

  double tmp_buffer[2*5];

  morpheus_params_t data;
  data.data.x = X;
  data.data.y = y;
  data.data.num_features = 2;
  data.data.num_examples = 5;
  data.data.layout = morpheus_row_major;
  data.memory_buffer = tmp_buffer;

  double tmp_buffer2[2*5];
  morpheus_numeric_gradient_params_t params;
  params.f = (morpheus_f)morpheus_ls_cost;
  params.num_variables = data.data.num_features;
  params.eps = 1e-5;
  params.memory_buffer = tmp_buffer2;

  double theta[] = {3, 3};

  double grad[2];
  double num_grad[2];

  // No regularization
  data.reg = reg_none;
  morpheus_ls_gradient(theta, &data, grad);

  morpheus_numeric_gradient(&params, theta, &data, num_grad);
  TEST_ASSERT_EQUAL_DOUBLE_ARRAY(num_grad, grad, 2);

  // L2 regularization
  data.reg = reg_l2;
  morpheus_ls_gradient(theta, &data, grad);

  morpheus_numeric_gradient(&params, theta, &data, num_grad);
  TEST_ASSERT_EQUAL_DOUBLE_ARRAY(num_grad, grad, 2);
}

// Assembly:
subq $0x1d8, %rsp            # imm = 0x1D8
movl $0x0, 0x1c8(%rsp)
movl $0x1, 0x1b8(%rsp)
movsd 0x8b3b(%rip), %xmm0     # 0xb5c0
movsd %xmm0, 0x1c0(%rsp)
leaq 0x160(%rsp), %rdi
leaq 0x9193(%rip), %rsi      # 0xbc30
movl $0x50, %edx
callq 0x1150
leaq 0x130(%rsp), %rdi
xorl %esi, %esi
movl $0x28, %edx
callq 0x1040
movsd 0x86f5(%rip), %xmm0     # 0xb1b8
movsd %xmm0, 0x130(%rsp)
movsd 0x86dc(%rip), %xmm0     # 0xb1b0
movsd %xmm0, 0x138(%rsp)
movsd 0x86c3(%rip), %xmm0     # 0xb1a8
movsd %xmm0, 0x140(%rsp)
movsd 0x86aa(%rip), %xmm0     # 0xb1a0
movsd %xmm0, 0x148(%rsp)
movsd 0x8691(%rip), %xmm0     # 0xb198
movsd %xmm0, 0x150(%rsp)
leaq 0x160(%rsp), %rax
movq %rax, 0xa8(%rsp)
leaq 0x130(%rsp), %rax
movq %rax, 0xb0(%rsp)
movl $0x2, 0xb8(%rsp)
movl $0x5, 0xbc(%rsp)
movl $0x15, 0xc0(%rsp)
leaq 0xe0(%rsp), %rax
movq %rax, 0xd8(%rsp)
leaq 0x2af8(%rip), %rax      # 0x5660
movq %rax, 0x30(%rsp)
movl 0xb8(%rsp), %eax
movl %eax, 0x38(%rsp)
movsd 0x90a0(%rip), %xmm0     # 0xbc20
movsd %xmm0, 0x40(%rsp)
leaq 0x50(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x90e9(%rip), %rax      # 0xbc80
movq %rax, 0x20(%rsp)
movq 0x90e5(%rip), %rax      # 0xbc88
movq %rax, 0x28(%rsp)
movq 0x1c8(%rsp), %rax
movq %rax, 0xc8(%rsp)
movq 0x1d0(%rsp), %rax
movq %rax, 0xd0(%rsp)
leaq 0x20(%rsp), %rdi
leaq 0x10(%rsp), %rdx
leaq 0xa8(%rsp), %rsi
callq 0x56a0
leaq 0x20(%rsp), %rsi
movq %rsp, %rcx
leaq 0x30(%rsp), %rdi
leaq 0xa8(%rsp), %rdx
callq 0x5110
movq %rsp, %rdi
leaq 0x10(%rsp), %rsi
movl $0x2, %edx
xorl %eax, %eax
movl %eax, %ecx
movl $0x32, %r8d
movl $0x1, %r9d
callq 0x8ec0
movq 0x1b8(%rsp), %rax
movq %rax, 0xc8(%rsp)
movq 0x1c0(%rsp), %rax
movq %rax, 0xd0(%rsp)
leaq 0x20(%rsp), %rdi
leaq 0x10(%rsp), %rdx
leaq 0xa8(%rsp), %rsi
callq 0x56a0
leaq 0x20(%rsp), %rsi
movq %rsp, %rcx
leaq 0x30(%rsp), %rdi
leaq 0xa8(%rsp), %rdx
callq 0x5110
movq %rsp, %rdi
leaq 0x10(%rsp), %rsi
movl $0x2, %edx
xorl %eax, %eax
movl %eax, %ecx
movl $0x39, %r8d
movl $0x1, %r9d
callq 0x8ec0
addq $0x1d8, %rsp            # imm = 0x1D8
retq
nopw %cs:(%rax,%rax)