// File: 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
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rax
cmpq -0x18(%rbp), %rax
jb 0x2a8aa
movb $0x0, -0x1(%rbp)
jmp 0x2acc9
xorps %xmm0, %xmm0
movsd %xmm0, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movb $0x2b, -0x2d(%rbp)
movb $0x2b, -0x2e(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x38(%rbp)
movl $0x0, -0x3c(%rbp)
movb $0x0, -0x3d(%rbp)
movb $0x0, -0x3e(%rbp)
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2b, %eax
je 0x2a8f0
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2d, %eax
jne 0x2a921
movq -0x38(%rbp), %rax
movb (%rax), %al
movb %al, -0x2d(%rbp)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x18(%rbp), %rax
je 0x2a91f
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2e, %eax
jne 0x2a91f
movb $0x1, -0x3e(%rbp)
jmp 0x2a94d
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
subl $0x30, %eax
cmpl $0xa, %eax
jae 0x2a932
jmp 0x2a94b
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2e, %eax
jne 0x2a944
movb $0x1, -0x3e(%rbp)
jmp 0x2a949
jmp 0x2acc5
jmp 0x2a94b
jmp 0x2a94d
movq -0x38(%rbp), %rax
cmpq -0x18(%rbp), %rax
setne %al
andb $0x1, %al
movb %al, -0x3d(%rbp)
testb $0x1, -0x3e(%rbp)
jne 0x2a9df
jmp 0x2a965
xorl %eax, %eax
testb $0x1, -0x3d(%rbp)
movb %al, -0x45(%rbp)
je 0x2a983
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
subl $0x30, %eax
cmpl $0xa, %eax
setb %al
movb %al, -0x45(%rbp)
movb -0x45(%rbp), %al
testb $0x1, %al
jne 0x2a98c
jmp 0x2a9dd
movsd 0x53b24(%rip), %xmm0    # 0x7e4b8
mulsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x28(%rbp)
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
subl $0x30, %eax
cvtsi2sd %eax, %xmm0
addsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x28(%rbp)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x18(%rbp), %rax
setne %al
andb $0x1, %al
movb %al, -0x3d(%rbp)
jmp 0x2a965
jmp 0x2a9df
testb $0x1, -0x3e(%rbp)
jne 0x2a9f2
cmpl $0x0, -0x3c(%rbp)
jne 0x2a9f0
jmp 0x2acc5
jmp 0x2a9f2
testb $0x1, -0x3d(%rbp)
jne 0x2a9fd
jmp 0x2ac47
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2e, %eax
jne 0x2aaf0
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
movl $0x1, -0x3c(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x18(%rbp), %rax
setne %al
andb $0x1, %al
movb %al, -0x3d(%rbp)
xorl %eax, %eax
testb $0x1, -0x3d(%rbp)
movb %al, -0x46(%rbp)
je 0x2aa4e
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
subl $0x30, %eax
cmpl $0xa, %eax
setb %al
movb %al, -0x46(%rbp)
movb -0x46(%rbp), %al
testb $0x1, %al
jne 0x2aa5a
jmp 0x2aaee
movl $0x8, -0x44(%rbp)
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
subl $0x30, %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x50(%rbp)
cmpl $0x8, -0x3c(%rbp)
jge 0x2aa91
movslq -0x3c(%rbp), %rcx
leaq 0x541fb(%rip), %rax     # 0x7ec80
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, -0x58(%rbp)
jmp 0x2aaa8
xorl %edi, %edi
subl -0x3c(%rbp), %edi
movsd 0x53a1a(%rip), %xmm0    # 0x7e4b8
callq 0x2e700
movsd %xmm0, -0x58(%rbp)
movsd -0x50(%rbp), %xmm0
movsd -0x58(%rbp), %xmm2
movsd -0x28(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x28(%rbp)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x18(%rbp), %rax
setne %al
andb $0x1, %al
movb %al, -0x3d(%rbp)
jmp 0x2aa30
jmp 0x2ab11
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x65, %eax
je 0x2ab08
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x45, %eax
jne 0x2ab0a
jmp 0x2ab0f
jmp 0x2ac47
jmp 0x2ab11
testb $0x1, -0x3d(%rbp)
jne 0x2ab1c
jmp 0x2ac47
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x65, %eax
je 0x2ab38
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x45, %eax
jne 0x2ac45
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x18(%rbp), %rax
setne %al
andb $0x1, %al
movb %al, -0x3d(%rbp)
testb $0x1, -0x3d(%rbp)
je 0x2ab89
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2b, %eax
je 0x2ab72
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2d, %eax
jne 0x2ab89
movq -0x38(%rbp), %rax
movb (%rax), %al
movb %al, -0x2e(%rbp)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x2aba1
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
subl $0x30, %eax
cmpl $0xa, %eax
jae 0x2ab9a
jmp 0x2ab9f
jmp 0x2acc5
jmp 0x2aba1
movl $0x0, -0x3c(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x18(%rbp), %rax
setne %al
andb $0x1, %al
movb %al, -0x3d(%rbp)
xorl %eax, %eax
testb $0x1, -0x3d(%rbp)
movb %al, -0x59(%rbp)
je 0x2abd6
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
subl $0x30, %eax
cmpl $0xa, %eax
setb %al
movb %al, -0x59(%rbp)
movb -0x59(%rbp), %al
testb $0x1, %al
jne 0x2abdf
jmp 0x2ac1d
imull $0xa, -0x2c(%rbp), %eax
movl %eax, -0x2c(%rbp)
movq -0x38(%rbp), %rax
movsbl (%rax), %eax
subl $0x30, %eax
addl -0x2c(%rbp), %eax
movl %eax, -0x2c(%rbp)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x18(%rbp), %rax
setne %al
andb $0x1, %al
movb %al, -0x3d(%rbp)
jmp 0x2abb8
movsbl -0x2e(%rbp), %edx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl $0x1, %ecx
cmpl $0x2b, %edx
cmovel %ecx, %eax
imull -0x2c(%rbp), %eax
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x3c(%rbp)
jne 0x2ac43
jmp 0x2acc5
jmp 0x2ac45
jmp 0x2ac47
movsbl -0x2d(%rbp), %edx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl $0x1, %ecx
cmpl $0x2b, %edx
cmovel %ecx, %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x68(%rbp)
cmpl $0x0, -0x2c(%rbp)
je 0x2ac9f
movsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x78(%rbp)
movl -0x2c(%rbp), %edi
movsd 0x53841(%rip), %xmm0    # 0x7e4c0
callq 0x2e700
movaps %xmm0, %xmm1
movsd -0x78(%rbp), %xmm0
mulsd %xmm1, %xmm0
movl -0x2c(%rbp), %edi
callq 0x7740
movsd %xmm0, -0x70(%rbp)
jmp 0x2aca9
movsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x70(%rbp)
movsd -0x68(%rbp), %xmm0
movsd -0x70(%rbp), %xmm1
mulsd %xmm1, %xmm0
movq -0x20(%rbp), %rax
movsd %xmm0, (%rax)
movb $0x1, -0x1(%rbp)
jmp 0x2acc9
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x80, %rsp
popq %rbp
retq
nopw (%rax,%rax)