// File: /workspace/github_cpp_makefile_star2_O1/alan0201tw[P]RayTracer/include/tiny_obj_loader.h
// Function: tinyobj::tryParseDouble(char const*, char const*, double*)
static bool tryParseDouble(const char *s, const char *s_end, double *result) {
  if (s >= s_end) {
    return false;
  }

  double mantissa = 0.0;
  // This exponent is base 2 rather than 10.
  // However the exponent we parse is supposed to be one of ten,
  // thus we must take care to convert the exponent/and or the
  // mantissa to a * 2^E, where a is the mantissa and E is the
  // exponent.
  // To get the final double we will use ldexp, it requires the
  // exponent to be in base 2.
  int exponent = 0;

  // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED
  // TO JUMP OVER DEFINITIONS.
  char sign = '+';
  char exp_sign = '+';
  char const *curr = s;

  // How many characters were read in a loop.
  int read = 0;
  // Tells whether a loop terminated due to reaching s_end.
  bool end_not_reached = false;
  bool leading_decimal_dots = false;

  /*
          BEGIN PARSING.
  */

  // Find out what sign we've got.
  if (*curr == '+' || *curr == '-') {
    sign = *curr;
    curr++;
    if ((curr != s_end) && (*curr == '.')) {
      // accept. Somethig like `.7e+2`, `-.5234`
      leading_decimal_dots = true;
    }
  } else if (IS_DIGIT(*curr)) { /* Pass through. */
  } else if (*curr == '.') {
    // accept. Somethig like `.7e+2`, `-.5234`
    leading_decimal_dots = true;
  } else {
    goto fail;
  }

  // Read the integer part.
  end_not_reached = (curr != s_end);
  if (!leading_decimal_dots) {
    while (end_not_reached && IS_DIGIT(*curr)) {
      mantissa *= 10;
      mantissa += static_cast<int>(*curr - 0x30);
      curr++;
      read++;
      end_not_reached = (curr != s_end);
    }
  }

  // We must make sure we actually got something.
  if (!leading_decimal_dots) {
    if (read == 0) goto fail;
  }

  // We allow numbers of form "#", "###" etc.
  if (!end_not_reached) goto assemble;

  // Read the decimal part.
  if (*curr == '.') {
    curr++;
    read = 1;
    end_not_reached = (curr != s_end);
    while (end_not_reached && IS_DIGIT(*curr)) {
      static const double pow_lut[] = {
          1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001,
      };
      const int lut_entries = sizeof pow_lut / sizeof pow_lut[0];

      // NOTE: Don't use powf here, it will absolutely murder precision.
      mantissa += static_cast<int>(*curr - 0x30) *
                  (read < lut_entries ? pow_lut[read] : std::pow(10.0, -read));
      read++;
      curr++;
      end_not_reached = (curr != s_end);
    }
  } else if (*curr == 'e' || *curr == 'E') {
  } else {
    goto assemble;
  }

  if (!end_not_reached) goto assemble;

  // Read the exponent part.
  if (*curr == 'e' || *curr == 'E') {
    curr++;
    // Figure out if a sign is present and if it is.
    end_not_reached = (curr != s_end);
    if (end_not_reached && (*curr == '+' || *curr == '-')) {
      exp_sign = *curr;
      curr++;
    } else if (IS_DIGIT(*curr)) { /* Pass through. */
    } else {
      // Empty E is not allowed.
      goto fail;
    }

    read = 0;
    end_not_reached = (curr != s_end);
    while (end_not_reached && IS_DIGIT(*curr)) {
      exponent *= 10;
      exponent += static_cast<int>(*curr - 0x30);
      curr++;
      read++;
      end_not_reached = (curr != s_end);
    }
    exponent *= (exp_sign == '+' ? 1 : -1);
    if (read == 0) goto fail;
  }

assemble:
  *result = (sign == '+' ? 1 : -1) *
            (exponent ? std::ldexp(mantissa * std::pow(5.0, exponent), exponent)
                      : mantissa);
  return true;
fail:
  return false;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
cmpq %rsi, %rdi
jae 0x1aee4
movq %rdx, %r13
movq %rsi, %r14
movq %rdi, %r15
movzbl (%rdi), %eax
cmpl $0x2d, %eax
je 0x1ae55
cmpl $0x2b, %eax
jne 0x1ae66
incq %r15
cmpq %r14, %r15
je 0x1ae78
cmpb $0x2e, (%r15)
sete %dl
jmp 0x1ae7a
movsbl %al, %ecx
addl $-0x30, %ecx
movb $0x2b, %bpl
cmpl $0xa, %ecx
jae 0x1aede
xorl %edx, %edx
jmp 0x1ae7c
xorl %edx, %edx
movl %eax, %ebp
cmpq %r14, %r15
setne %al
xorpd %xmm2, %xmm2
movb $0x1, %cl
testb %dl, %dl
jne 0x1aeef
cmpq %r14, %r15
je 0x1aeda
movsbl (%r15), %edx
addl $-0x30, %edx
cmpl $0xa, %edx
setb %cl
jae 0x1aeef
incq %r15
movsd 0x21795(%rip), %xmm0    # 0x3c640
movapd %xmm2, %xmm1
xorps %xmm2, %xmm2
cvtsi2sd %edx, %xmm2
mulsd %xmm0, %xmm1
addsd %xmm1, %xmm2
cmpq %r14, %r15
setne %al
je 0x1aeec
movsbl (%r15), %edx
addl $-0x30, %edx
incq %r15
cmpl $0x9, %edx
jbe 0x1aeab
decq %r15
jmp 0x1aeef
xorl %ecx, %ecx
jmp 0x1aeef
movb $0x1, %dl
cmpb $0x2e, %al
je 0x1ae7c
xorl %r12d, %r12d
jmp 0x1b0ba
movq %r14, %r15
xorl %r12d, %r12d
testb %cl, %cl
je 0x1b0ba
testb %al, %al
je 0x1b071
movzbl (%r15), %ecx
cmpl $0x65, %ecx
je 0x1afce
cmpl $0x45, %ecx
je 0x1afce
cmpl $0x2e, %ecx
jne 0x1b071
leaq 0x1(%r15), %rcx
cmpq %r14, %rcx
setne %al
je 0x1afbc
movsbl 0x1(%r15), %ebx
addl $-0x30, %ebx
cmpl $0x9, %ebx
ja 0x1afbc
movb %bpl, 0x7(%rsp)
movq %r13, 0x8(%rsp)
addq $0x2, %r15
movl $0x1, %r13d
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
cmpq $0x7, %r13
ja 0x1af6c
leaq 0x21dbc(%rip), %rax     # 0x3cd20
movsd (%rax,%r13,8), %xmm0
jmp 0x1af8c
xorps %xmm1, %xmm1
cvtsi2sd %ebp, %xmm1
movsd 0x216c5(%rip), %xmm0    # 0x3c640
movapd %xmm2, 0x10(%rsp)
callq 0x66d0
movapd 0x10(%rsp), %xmm2
xorps %xmm1, %xmm1
cvtsi2sd %ebx, %xmm1
mulsd %xmm0, %xmm1
addsd %xmm1, %xmm2
cmpq %r14, %r15
setne %al
je 0x1afc1
incq %r13
movsbl (%r15), %ebx
addl $-0x30, %ebx
incq %r15
decl %ebp
cmpl $0x9, %ebx
jbe 0x1af57
decq %r15
jmp 0x1afc4
movq %rcx, %r15
jmp 0x1afce
movq %r14, %r15
movq 0x8(%rsp), %r13
movb 0x7(%rsp), %bpl
testb %al, %al
je 0x1b071
movzbl (%r15), %eax
orl $0x20, %eax
cmpl $0x65, %eax
jne 0x1b071
leaq 0x1(%r15), %rcx
cmpq %r14, %rcx
je 0x1b013
movzbl (%rcx), %eax
cmpl $0x2d, %eax
je 0x1affc
cmpl $0x2b, %eax
jne 0x1b013
addq $0x2, %r15
xorl %ecx, %ecx
cmpb $0x2b, %al
sete %cl
leal -0x1(,%rcx,2), %eax
movq %r15, %rcx
jmp 0x1b027
movsbl (%rcx), %edx
addl $-0x30, %edx
movl $0x1, %eax
cmpl $0x9, %edx
ja 0x1aee4
cmpq %r14, %rcx
je 0x1b060
xorl %edx, %edx
xorl %r12d, %r12d
movsbl (%rcx,%rdx), %esi
addl $-0x30, %esi
cmpl $0x9, %esi
ja 0x1b059
leal (%r12,%r12,4), %edi
leal (%rsi,%rdi,2), %r12d
leaq (%rcx,%rdx), %rsi
incq %rsi
incq %rdx
cmpq %r14, %rsi
jne 0x1b031
movl $0x1, %edx
testl %edx, %edx
sete %cl
jmp 0x1b065
movb $0x1, %cl
xorl %r12d, %r12d
testb %cl, %cl
jne 0x1aee4
imull %eax, %r12d
testl %r12d, %r12d
je 0x1b0a3
xorps %xmm1, %xmm1
cvtsi2sd %r12d, %xmm1
movsd 0x2156a(%rip), %xmm0    # 0x3c5f0
movapd %xmm2, 0x10(%rsp)
callq 0x66d0
mulsd 0x10(%rsp), %xmm0
movl %r12d, %edi
callq 0x65a0
movapd %xmm0, %xmm2
cmpb $0x2b, %bpl
je 0x1b0b1
xorpd 0x2152f(%rip), %xmm2    # 0x3c5e0
movsd %xmm2, (%r13)
movb $0x1, %r12b
movl %r12d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq