#!/bin/sh

# Compare two (newline-separated) lists of floating point numbers. To
# accomplish this in POSIX shell, we...
#
# 1. Number both lists using the "nl" utility.
# 2. Write both numbered lists to separate temporary files.
# 3. Use "join" to combine the two numbered lists into a single column
#    by pairing like-numbered lines.
# 4. Use "awk" to print "FAIL" for any rows whose two (non-line-number)
#    columns differ by more than $CFPL_EPSILON.
# 5. Check to see if anything is output by the procedure above; it
#    should not be.

# The absolute tolerance for the difference of two floating point
# numbers.
CFPL_EPSILON=0.000001

# Files used to hold the expected and actual outputs. Default them
# empty.
CFPL_EXPECTED=""
CFPL_ACTUAL=""

# The overall result of this test; assume success.
CFPL_RESULT=0

posix_mktemp(){
  # Securely create a temporary file under ${TMPDIR} using the
  # template "tmpXXXXXX", and echo the result to stdout. This works
  # around the absence of "mktemp" in the POSIX standard.
  printf 'mkstemp(template)' | m4 -D template="${TMPDIR:-/tmp}/tmpXXXXXX"
}

cfpl_cleanup(){
    if [ $CFPL_RESULT -eq 0 ]; then
	printf "PASS\n"
    else
	printf "FAIL\n"
    fi
    rm "${CFPL_ACTUAL}" "${CFPL_EXPECTED}"
    exit $CFPL_RESULT
}

compare_fp_lists(){
  CFPL_EXPECTED="$(posix_mktemp)"
  CFPL_ACTUAL="$(posix_mktemp)"
  printf "${1}" | nl > "${CFPL_EXPECTED}"
  printf "${2}" | nl > "${CFPL_ACTUAL}"

  CFPL_ACTUAL_LINES=$(wc -l < "${CFPL_ACTUAL}")

  # Both files should have the same (positive) number of lines;
  # otherwise we might wind up joining an empty input file into what
  # is then guaranteed to be an empty output file which vacuously
  # passes.
  if [ "${CFPL_ACTUAL_LINES}" = "0" ]; then
    CFPL_RESULT=1
    cfpl_cleanup
  fi

  if [ "${CFPL_ACTUAL_LINES}" != "$(wc -l < "${CFPL_EXPECTED}")" ]; then
    CFPL_RESULT=1
    cfpl_cleanup
  fi

  CFPL_OUTPUT=$(join "${CFPL_EXPECTED}" "${CFPL_ACTUAL}" | \
    awk "{if (sqrt(((\$2 - \$3)^2)) > ${CFPL_EPSILON}) { print \"FAIL\" };}")

  if [ $? -ne 0 ]; then
    # awk could have failed
    CFPL_RESULT=1
    cfpl_cleanup
  fi

  if [ -z "${CFPL_OUTPUT}" ]; then
    CFPL_RESULT=0
  else
    CFPL_RESULT=1
  fi

  cfpl_cleanup
}
