user: Converte this assembly snippet into its equivalent C code:

```asm
<wcsunits>:
  endbr64
  push   %r13
  mov    %r8,%r13
  push   %r12
  mov    %rcx,%r12
  push   %rbp
  mov    %rsi,%rbp
  push   %rbx
  mov    %rdx,%rbx
  sub    $0x158,%rsp
  mov    %fs:0x28,%rax
  mov    %rax,0x148(%rsp)
  xor    %eax,%eax
  lea    0x30(%rsp),%rcx
  lea    0x20(%rsp),%rdx
  lea    0x18(%rsp),%rsi
  call   <wcsulex@plt>
  test   %eax,%eax
  je     L48
L256:
  mov    0x148(%rsp),%rdx
  sub    %fs:0x28,%rdx
  jne    L227
  add    $0x158,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  ret
  nopl   (%rax)
L48:
  lea    0xc0(%rsp),%rcx
  lea    0x28(%rsp),%rdx
  mov    %rbp,%rdi
  lea    0x1c(%rsp),%rsi
  call   <wcsulex@plt>
  test   %eax,%eax
  jne    L256
  movsd  0xc0(%rsp),%xmm0
  ucomisd 0x30(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x38(%rsp),%xmm0
  ucomisd 0xc8(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x40(%rsp),%xmm0
  ucomisd 0xd0(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x48(%rsp),%xmm0
  ucomisd 0xd8(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x50(%rsp),%xmm0
  ucomisd 0xe0(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x58(%rsp),%xmm0
  ucomisd 0xe8(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x60(%rsp),%xmm0
  ucomisd 0xf0(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x68(%rsp),%xmm0
  ucomisd 0xf8(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x70(%rsp),%xmm0
  ucomisd 0x100(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x78(%rsp),%xmm0
  ucomisd 0x108(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x80(%rsp),%xmm0
  ucomisd 0x110(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x88(%rsp),%xmm0
  ucomisd 0x118(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x90(%rsp),%xmm0
  ucomisd 0x120(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0x98(%rsp),%xmm0
  ucomisd 0x128(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0xa0(%rsp),%xmm0
  ucomisd 0x130(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0xa8(%rsp),%xmm0
  ucomisd 0x138(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  0xb0(%rsp),%xmm0
  ucomisd 0x140(%rsp),%xmm0
  jp     L524
  jne    L524
  movsd  D9(%rip),%xmm0
  mov    0x18(%rsp),%edx
  movq   $0x0,(%rbx)
  movq   $0x0,(%r12)
  movsd  %xmm0,0x0(%r13)
  cmp    $0x2,%edx
  je     L368
  jg     L364
  test   %edx,%edx
  je     L424
  cmp    $0x1,%edx
  jne    L509
  mov    0x1c(%rsp),%edx
  mov    %eax,0xc(%rsp)
  cmp    $0x1,%edx
  je     L194
  mov    D13(%rip),%rax
  cmp    $0x2,%edx
  jne    L279
L247:
  mov    %rax,(%rbx)
L278:
  movsd  0x20(%rsp),%xmm0
  divsd  0x28(%rsp),%xmm0
  call   <log@plt>
  mov    0xc(%rsp),%eax
  movsd  %xmm0,(%r12)
  jmp    L256
  nopl   0x0(%rax,%rax,1)
L524:
  mov    $0xa,%eax
  jmp    L256
  nopw   0x0(%rax,%rax,1)
L364:
  cmp    $0x3,%edx
  jne    L509
  cmpl   $0x3,0x1c(%rsp)
  jne    L279
  movsd  %xmm0,(%rbx)
  movsd  0x20(%rsp),%xmm0
  divsd  0x28(%rsp),%xmm0
  movsd  %xmm0,0x0(%r13)
  jmp    L256
  nopw   0x0(%rax,%rax,1)
L509:
  mov    $0x9,%eax
  jmp    L256
  nopw   0x0(%rax,%rax,1)
L279:
  mov    $0xb,%eax
  jmp    L256
L194:
  movsd  %xmm0,(%rbx)
  movsd  0x20(%rsp),%xmm0
  divsd  0x28(%rsp),%xmm0
  call   <log10@plt>
  mov    0xc(%rsp),%eax
  movsd  %xmm0,(%r12)
  jmp    L256
  xchg   %ax,%ax
L368:
  mov    0x1c(%rsp),%edx
  mov    %eax,0xc(%rsp)
  cmp    $0x1,%edx
  je     L53
  cmp    $0x2,%edx
  jne    L279
  movsd  %xmm0,(%rbx)
  jmp    L278
  nopl   0x0(%rax,%rax,1)
L424:
  mov    0x1c(%rsp),%eax
  test   %eax,%eax
  jne    L279
  movsd  0x20(%rsp),%xmm0
  divsd  0x28(%rsp),%xmm0
  movsd  %xmm0,(%rbx)
  jmp    L256
L53:
  mov    D11(%rip),%rax
  jmp    L247
L227:
  call   <__stack_chk_fail@plt>
```

tool_calls: name: read_data
arguments: tag: D9
type: f64
name: read_data
arguments: tag: D13
type: byte[8]
name: read_data
arguments: tag: D11
type: byte[8]

tool: D9: 1

tool: {"D13": [0x16,0x55,0xb5,0xbb,0xb1,0x6b,0x02,0x40]}

tool: {"D11": [0x0d,0xe5,0x26,0x15,0x7b,0xcb,0xdb,0x3f]}

assistant: ```c
int wcsunits(const char have[], const char want[], double *scale, double *offset, double *power) {
  int func1, func2, i, status;
  double scale1, scale2, units1[17], units2[17];
  if ((status = wcsulex(have, &func1, &scale1, units1))) {
    return status;
  }
  if ((status = wcsulex(want, &func2, &scale2, units2))) {
    return status;
  }
  for (i = 0; i < 17; i++) {
    if (units1[i] != units2[i]) {
      return 10;
    }
  }
  *scale = 0.0;
  *offset = 0.0;
  *power = 1.0;
  switch (func1) {
  case 0:
    if (func2) {
      return 11;
    }
    *scale = scale1 / scale2;
    break;
  case 1:
    if (func2 == 1) {
      *scale = 1.0;
      *offset = log10(scale1 / scale2);
    } else if (func2 == 2) {
      *scale = log(10.0);
      *offset = log(scale1 / scale2);
    } else {
      return 11;
    }
    break;
  case 2:
    if (func2 == 1) {
      *scale = 1.0 / log(10.0);
      *offset = log(scale1 / scale2);
    } else if (func2 == 2) {
      *scale = 1.0;
      *offset = log(scale1 / scale2);
    } else {
      return 11;
    }
    break;
  case 3:
    if (func2 != 3) {
      return 11;
    }
    *scale = 1.0;
    *power = scale1 / scale2;
    break;
  default:
    return 9;
  }
  return 0;
}
```