// File: /workspace/github_c_makefile_star2_O2/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 %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
xorl %r12d, %r12d
leaq 0x6cdd(%rip), %r13      # 0xcaa0
cmpq $0x330, %r12            # imm = 0x330
je 0x5de2
movq (%r12,%r13), %rsi
movq %rbx, %rdi
callq 0x21d0
testl %eax, %eax
je 0x5df8
addq $0x30, %r12
jmp 0x5dc3
leaq 0x378d(%rip), %rdi      # 0x9576
xorl %r15d, %r15d
movq %rbx, %rsi
xorl %eax, %eax
callq 0x6e9a
jmp 0x5dff
testq %r12, %r12
sete %r15b
movl 0x28(%r12,%r13), %ecx
movq %rsp, %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x6b09
testb %al, %al
je 0x5e57
movsd 0x20(%r12,%r13), %xmm2
mulsd (%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, (%rsp)
testb %r15b, %r15b
je 0x5e63
ucomisd %xmm1, %xmm0
jb 0x5e72
sqrtsd %xmm0, %xmm0
jmp 0x5e77
cvttsd2si 0x18(%r12,%r13), %r14
jmp 0x5f13
addsd 0x3215(%rip), %xmm0     # 0x9080
cvttsd2si %xmm0, %r15
jmp 0x5ec4
callq 0x2350
mulsd 0x3209(%rip), %xmm0     # 0x9088
addsd 0x31f9(%rip), %xmm0     # 0x9080
cvttsd2si %xmm0, %rax
cvtsi2sd %rax, %xmm0
maxsd 0x8(%r12,%r13), %xmm0
cvttsd2si %xmm0, %rax
cvtsi2sd %rax, %xmm0
minsd 0x10(%r12,%r13), %xmm0
cvttsd2si %xmm0, %r15
movsd (%rsp), %xmm0
leaq 0x36f5(%rip), %rdi      # 0x95af
movq %r15, %rsi
movb $0x1, %al
callq 0x6d78
movslq %ebp, %r14
imulq %r15, %r14
cvtsi2sd %r14, %xmm1
movsd 0x18(%r12,%r13), %xmm0
ucomisd %xmm1, %xmm0
jne 0x5edf
jnp 0x5efa
movsd 0x8(%r12,%r13), %xmm2
ucomisd %xmm1, %xmm2
ja 0x5ef5
ucomisd 0x10(%r12,%r13), %xmm1
jbe 0x5efa
cvttsd2si %xmm0, %r14
movsd (%rsp), %xmm0
leaq 0x36bf(%rip), %rdi      # 0x95c5
movq %rbx, %rsi
movq %r14, %rdx
movb $0x1, %al
callq 0x6d78
movq %r14, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq