user: Translate the below assembly code into C programming language:

```asm
<ln_grid_search>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  push   %rbx
  sub    $0x88,%rsp
  mov    %rdi,-0x48(%rbp)
  mov    %rsi,-0x50(%rbp)
  mov    %edx,-0x54(%rbp)
  movsd  %xmm0,-0x60(%rbp)
  movsd  %xmm1,-0x68(%rbp)
  movsd  %xmm2,-0x70(%rbp)
  mov    %rcx,-0x78(%rbp)
  mov    %r8d,-0x58(%rbp)
  mov    %r9,-0x80(%rbp)
  movsd  %xmm3,-0x88(%rbp)
  pxor   %xmm0,%xmm0
  comisd -0x70(%rbp),%xmm0
  jbe    L10
  mov    -0x54(%rbp),%edx
  mov    -0x50(%rbp),%rcx
  mov    -0x48(%rbp),%rax
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <ln_argmin_asymptotic@plt>
  movq   %xmm0,%rax
  mov    %rax,-0x70(%rbp)
  mov    -0x78(%rbp),%rax
  lea    D2(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L10
  mov    -0x70(%rbp),%rax
  movq   %rax,%xmm0
  call   <log10@plt>
  movq   %xmm0,%rax
  mov    %rax,-0x70(%rbp)
L10:
  mov    -0x58(%rbp),%eax
  cltq
  shl    $0x3,%eax
  mov    %eax,%edi
  call   <malloc@plt>
  mov    %rax,-0x28(%rbp)
  movsd  -0x68(%rbp),%xmm0
  subsd  -0x60(%rbp),%xmm0
  mov    -0x58(%rbp),%eax
  sub    $0x1,%eax
  pxor   %xmm1,%xmm1
  cvtsi2sd %eax,%xmm1
  divsd  %xmm1,%xmm0
  movsd  %xmm0,-0x20(%rbp)
  movl   $0x0,-0x34(%rbp)
  jmp    L50
L66:
  pxor   %xmm0,%xmm0
  cvtsi2sdl -0x34(%rbp),%xmm0
  mulsd  -0x20(%rbp),%xmm0
  addsd  -0x60(%rbp),%xmm0
  mov    -0x34(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  addsd  -0x70(%rbp),%xmm0
  movsd  %xmm0,(%rax)
  addl   $0x1,-0x34(%rbp)
L50:
  mov    -0x34(%rbp),%eax
  cmp    -0x58(%rbp),%eax
  jl     L66
  mov    -0x78(%rbp),%rax
  lea    D2(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L47
  movl   $0x0,-0x30(%rbp)
  jmp    L11
L15:
  mov    -0x30(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  mov    (%rax),%rax
  mov    -0x30(%rbp),%edx
  movslq %edx,%rdx
  lea    0x0(,%rdx,8),%rcx
  mov    -0x28(%rbp),%rdx
  lea    (%rcx,%rdx,1),%rbx
  movq   %rax,%xmm0
  mov    $0xa,%edi
  call   <pow@plt>
  movq   %xmm0,%rax
  mov    %rax,(%rbx)
  addl   $0x1,-0x30(%rbp)
L11:
  mov    -0x30(%rbp),%eax
  cmp    -0x58(%rbp),%eax
  jl     L15
L47:
  mov    -0x88(%rbp),%rdi
  mov    -0x80(%rbp),%r9
  mov    -0x58(%rbp),%r8d
  mov    -0x28(%rbp),%rcx
  mov    -0x54(%rbp),%edx
  mov    -0x50(%rbp),%rsi
  mov    -0x48(%rbp),%rax
  movq   %rdi,%xmm0
  mov    %rax,%rdi
  call   <ln_grid_optimal@plt>
  mov    %eax,-0x2c(%rbp)
  mov    -0x2c(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  movsd  (%rax),%xmm0
  movsd  %xmm0,-0x18(%rbp)
  mov    -0x28(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  movsd  -0x18(%rbp),%xmm0
  movq   %xmm0,%rax
  movq   %rax,%xmm0
  mov    -0x8(%rbp),%rbx
  leave
  ret
```

tool_calls: name: disassemble_data
arguments: label: D2
datatype: string

tool: D2: log

assistant: ```c
double ln_grid_search(const double *data, const double *weight, const int n, const double xmin, const double xmax, double offset, const char *scale, const int k, const char *risk_function, const double threshold) {
  if (offset < 0) {
    offset = ln_argmin_asymptotic(data, weight, n);
    if (strcmp(scale, "log") == 0) {
      offset = log10(offset);
    }
  }
  double *bandwidths = malloc(k * sizeof(double));
  double delta = (xmax - xmin) / (k - 1);
  for (int i = 0; i < k; i++) {
    bandwidths[i] = i * delta + xmin + offset;
  }
  if (strcmp(scale, "log") == 0) {
    for (int i = 0; i < k; i++) {
      bandwidths[i] = pow(10, bandwidths[i]);
    }
  }
  int idx = ln_grid_optimal(data, weight, n, bandwidths, k, risk_function, threshold);
  double result = bandwidths[idx];
  free(bandwidths);
  return result;
}
```