// File: /workspace/github_cpp_makefile_star2_O3/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 0x1a747
movq %rdx, %rbx
movq %rsi, %r14
movq %rdi, %r15
movzbl (%rdi), %ebp
cmpl $0x2d, %ebp
je 0x1a532
cmpl $0x2b, %ebp
jne 0x1a549
incq %r15
cmpq %r14, %r15
je 0x1a558
xorpd %xmm2, %xmm2
cmpb $0x2e, (%r15)
jne 0x1a561
jmp 0x1a5e0
movsbl %bpl, %eax
addl $-0x30, %eax
cmpl $0xa, %eax
jae 0x1a5b0
movb $0x2b, %bpl
cmpq %r14, %r15
je 0x1a747
xorpd %xmm2, %xmm2
xorl %eax, %eax
movsd 0x22271(%rip), %xmm0    # 0x3c7e0
movsbl (%r15,%rax), %ecx
addl $-0x30, %ecx
cmpl $0x9, %ecx
ja 0x1a5a3
movapd %xmm2, %xmm1
mulsd %xmm0, %xmm1
xorps %xmm2, %xmm2
cvtsi2sd %ecx, %xmm2
addsd %xmm1, %xmm2
leaq (%r15,%rax), %rcx
incq %rcx
incq %rax
cmpq %r14, %rcx
jne 0x1a56f
jmp 0x1a730
testl %eax, %eax
je 0x1a747
addq %rax, %r15
jmp 0x1a5c1
cmpb $0x2e, %bpl
jne 0x1a747
movb $0x2b, %bpl
xorpd %xmm2, %xmm2
movzbl (%r15), %eax
cmpl $0x65, %eax
je 0x1a674
cmpl $0x45, %eax
je 0x1a674
cmpl $0x2e, %eax
jne 0x1a730
leaq 0x1(%r15), %rax
cmpq %r14, %rax
je 0x1a730
movq %rbx, 0x8(%rsp)
movl $0x1, %r12d
movl $0xffffffff, %r13d      # imm = 0xFFFFFFFF
movsbl (%r15,%r12), %eax
leal -0x30(%rax), %ebx
cmpl $0x9, %ebx
ja 0x1a66c
cmpq $0x7, %r12
ja 0x1a620
leaq 0x22898(%rip), %rax     # 0x3ceb0
movsd (%rax,%r12,8), %xmm0
jmp 0x1a641
xorps %xmm1, %xmm1
cvtsi2sd %r13d, %xmm1
movsd 0x221b0(%rip), %xmm0    # 0x3c7e0
movapd %xmm2, 0x10(%rsp)
callq 0x66d0
movapd 0x10(%rsp), %xmm2
xorps %xmm1, %xmm1
cvtsi2sd %ebx, %xmm1
mulsd %xmm0, %xmm1
addsd %xmm1, %xmm2
decl %r13d
leaq (%r15,%r12), %rax
incq %rax
incq %r12
cmpq %r14, %rax
jne 0x1a5fe
movq 0x8(%rsp), %rbx
jmp 0x1a730
addq %r12, %r15
movq 0x8(%rsp), %rbx
movzbl %al, %eax
orl $0x20, %eax
cmpl $0x65, %eax
jne 0x1a730
leaq 0x1(%r15), %rax
movsbl 0x1(%r15), %edx
cmpq %r14, %rax
je 0x1a6b6
cmpb $0x2d, %dl
je 0x1a69e
movzbl %dl, %ecx
cmpl $0x2b, %ecx
jne 0x1a6b6
addq $0x2, %r15
xorl %eax, %eax
cmpb $0x2b, %dl
sete %al
leal -0x1(,%rax,2), %ecx
movq %r15, %rax
jmp 0x1a6c7
addl $-0x30, %edx
movl $0x1, %ecx
cmpl $0x9, %edx
ja 0x1a747
xorl %r15d, %r15d
cmpq %r14, %rax
je 0x1a74a
xorl %edx, %edx
movsbl (%rax,%rdx), %esi
addl $-0x30, %esi
cmpl $0x9, %esi
ja 0x1a6f6
leal (%r15,%r15,4), %edi
leal (%rsi,%rdi,2), %r15d
leaq (%rax,%rdx), %rsi
incq %rsi
incq %rdx
cmpq %r14, %rsi
jne 0x1a6d1
jmp 0x1a6fa
testl %edx, %edx
je 0x1a747
testl %r15d, %r15d
je 0x1a730
imull %ecx, %r15d
xorps %xmm1, %xmm1
cvtsi2sd %r15d, %xmm1
movsd 0x2207d(%rip), %xmm0    # 0x3c790
movapd %xmm2, 0x10(%rsp)
callq 0x66d0
mulsd 0x10(%rsp), %xmm0
movl %r15d, %edi
callq 0x65a0
movapd %xmm0, %xmm2
cmpb $0x2b, %bpl
je 0x1a73e
xorpd 0x22042(%rip), %xmm2    # 0x3c780
movsd %xmm2, (%rbx)
movb $0x1, %r15b
jmp 0x1a74a
xorl %r15d, %r15d
movl %r15d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq