// File: /workspace/github_c_makefile_star2_O3/canboat[P]canboat/n2kd/gps_ais.c
// Function: aisFloat
static long int aisFloat(const char *msg, const char *fieldName)
{
#define DEGREES_PER_RADIAN (57.295779513)
#define SECONDS_PER_MINUTE (60.0)
#define KNOTS_IN_MS (1.943844492)
#define ROT_MULTIPLICATOR (4.733)
#define SOG_MULTIPLICATOR (10.0)
#define COG_MULTIPLICATOR (10.0)
#define NO_MULTIPLICATOR (1.0)
#define LON_MULTIPLICATOR (600000.0)
#define LAT_MULTIPLICATOR (600000.0)
#define SIZE_MULTIPLICATOR (10.0)
#define DRAUGHT_MULTIPLICATOR (10.0)
#define ALTITUDE_MULTIPLICATOR (1.0)

  typedef struct
  {
    const char *value;
    double      min;
    double      max;
    double      defValue;
    double      multiplier;
    Unit        unit;
  } floatParam;

  int      i;
  double   value;
  int      sign;
  long int result;

  floatParam paramRange[] = {{/* Clamp Rate of Turn to -127 .. 127 (which boils down to 720 degs/min)
                               */
                              "Rate of Turn",
                              -127,
                              127,
                              -128,
                              SECONDS_PER_MINUTE},
                             {"SOG", 0, 1022, 1023, KNOTS_IN_MS * SOG_MULTIPLICATOR, U_VELOCITY},
                             {"COG", 0, 3599, 3600, COG_MULTIPLICATOR, U_ANGLE},
                             {"Heading", 0, 359, 511, NO_MULTIPLICATOR, U_ANGLE},
                             {"Longitude", -108000000, 108000000, 0x6791AC0, LON_MULTIPLICATOR, U_GEO},
                             {"Latitude", -54000000, 54000000, 0x3412140, LAT_MULTIPLICATOR, U_GEO},
                             {"Length", 0, 10220, 0, SIZE_MULTIPLICATOR, U_DISTANCE},
                             {"Beam", 0, 1260, 0, SIZE_MULTIPLICATOR, U_DISTANCE},
                             {"Position reference from Starboard", 0, 630, 0, SIZE_MULTIPLICATOR, U_DISTANCE},
                             {"Position reference from Bow", 0, 5110, 0, SIZE_MULTIPLICATOR, U_DISTANCE},
                             {"Draft", 0, 255, 0, DRAUGHT_MULTIPLICATOR, U_DISTANCE},
                             {"True Heading", 0, 359, 511, NO_MULTIPLICATOR},
                             {"Length/Diameter", 0, 10220, 0, SIZE_MULTIPLICATOR, U_DISTANCE},
                             {"Beam/Diameter", 0, 1260, 0, SIZE_MULTIPLICATOR, U_DISTANCE},
                             {"Position Reference from Starboard Edge", 0, 630, 0, SIZE_MULTIPLICATOR, U_DISTANCE},
                             {"Position Reference from True North Facing Edge", 0, 5110, 0, SIZE_MULTIPLICATOR, U_DISTANCE},
                             {"Altitude", 0, 4094, 4095, ALTITUDE_MULTIPLICATOR, U_DISTANCE}};

  for (i = 0; i < ARRAY_SIZE(paramRange); i++)
  {
    if (!strcmp(fieldName, paramRange[i].value))
    {
      break;
    }
  }
  if (i == ARRAY_SIZE(paramRange))
  {
    logAbort("Unhandled AIS number field '%s'; please report this bug\n", fieldName);
  }

  if (!getJSONNumber(msg, fieldName, &value, paramRange[i].unit))
  {
    return paramRange[i].defValue;
  }
  value *= paramRange[i].multiplier;
  sign = (value >= 0) - (value < 0);
  value *= sign;
  if (i == 0)
  {
    // ROT is calculated with a non-linear value in ITU-R M.1371...
    result = (long int) (ROT_MULTIPLICATOR * sqrt(value) + 0.5);
    result = CB_MAX(result, paramRange[i].min);
    result = CB_MIN(result, paramRange[i].max);
    logDebug("ROT %f deg/min -> %d\n", value, result);
  }
  else
  {
    result = (long int) (value + 0.5);
  }
  result *= sign;
  // Make sure values are valid
  if (result != paramRange[i].defValue && (result < paramRange[i].min || result > paramRange[i].max))
  {
    result = paramRange[i].defValue;
  }

  logDebug("aisFloat %s = %f = %d\n", fieldName, value, result);
  return result;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x10, %rsp
movq %rsi, %rbx
movq %rdi, %r14
leaq 0x77c8(%rip), %r15      # 0xdaa0
xorl %r12d, %r12d
movq (%r15), %rsi
movq %rbx, %rdi
callq 0x21d0
testl %eax, %eax
je 0x6313
decq %r12
addq $0x30, %r15
cmpq $-0x11, %r12
jne 0x62db
leaq 0x4278(%rip), %rdi      # 0xa576
xorl %r15d, %r15d
movq %rbx, %rsi
xorl %eax, %eax
callq 0x762f
movl $0x11, %r12d
jmp 0x631d
testq %r12, %r12
sete %r15b
negq %r12
leaq (%r12,%r12,2), %rax
shlq $0x4, %rax
leaq 0x7774(%rip), %rcx      # 0xdaa0
leaq (%rcx,%rax), %r12
movl 0x28(%rax,%rcx), %ecx
leaq 0x8(%rsp), %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x726b
testb %al, %al
je 0x638b
movsd 0x20(%r12), %xmm2
mulsd 0x8(%rsp), %xmm2
xorpd %xmm1, %xmm1
xorl %ebp, %ebp
ucomisd %xmm2, %xmm1
seta %bpl
ucomisd %xmm1, %xmm2
adcl $-0x1, %ebp
negl %ebp
cvtsi2sd %ebp, %xmm0
mulsd %xmm2, %xmm0
movsd %xmm0, 0x8(%rsp)
testb %r15b, %r15b
je 0x6397
ucomisd %xmm1, %xmm0
jb 0x63a6
sqrtsd %xmm0, %xmm0
jmp 0x63ab
cvttsd2si 0x18(%r12), %r14
jmp 0x6452
addsd 0x3ce1(%rip), %xmm0     # 0xa080
cvttsd2si %xmm0, %r15
jmp 0x63ff
callq 0x2340
mulsd 0x3cd5(%rip), %xmm0     # 0xa088
addsd 0x3cc5(%rip), %xmm0     # 0xa080
cvttsd2si %xmm0, %rax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
maxsd 0x8(%r12), %xmm0
cvttsd2si %xmm0, %rax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
minsd 0x10(%r12), %xmm0
cvttsd2si %xmm0, %r15
movsd 0x8(%rsp), %xmm0
leaq 0x41ba(%rip), %rdi      # 0xa5af
movq %r15, %rsi
movb $0x1, %al
callq 0x7509
movslq %ebp, %r14
imulq %r15, %r14
xorps %xmm1, %xmm1
cvtsi2sd %r14, %xmm1
movsd 0x18(%r12), %xmm0
ucomisd %xmm1, %xmm0
jne 0x641d
jnp 0x6438
movsd 0x8(%r12), %xmm2
ucomisd %xmm1, %xmm2
ja 0x6433
ucomisd 0x10(%r12), %xmm1
jbe 0x6438
cvttsd2si %xmm0, %r14
movsd 0x8(%rsp), %xmm0
leaq 0x4180(%rip), %rdi      # 0xa5c5
movq %rbx, %rsi
movq %r14, %rdx
movb $0x1, %al
callq 0x7509
movq %r14, %rax
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq