#######################################################################
# Fix FPU precision
#######################################################################
# SYMPOW really needs doubles to have *exactly* 53 bits precision,
# they need to be true IEEE-754 double precision numbers.
# In particular, we need to avoid 80 bits extended precision on i386
# and we need to avoid fused multiply-add instructions (e.g. on ia64).
# We might need to add various flags to CFLAGS to ensure this.
# See Trac tickets #9703, #9734, #9166, #11226, #11920.

# Usage: try_add_CFLAG $FLAG
# Try adding $FLAG to $CFLAGS, compile and run the fpubits program.
# If it compiles and running it doesn't crash it (with an Illegal
# Instruction for example), then we add $FLAG to $CFLAGS.
# Return 0 if we added $FLAG and the FPU correctly used 53 bits,
# return 1 if we added $FLAG but the FPU doesn't use 53 bits,
# return 2 if we did not add $FLAG.
try_add_CFLAG()
{
    # We use -O3 here to really force generation of fused
    # multiply-add instructions and to keep floats as much as
    # possible in registers.
    # We compile in the (already patched!) src/fpu.c which only does
    # something if the macro x86 is defined.
    if $CC -O3 $CFLAGS $FLAG config/fpubits1.c config/fpubits2.c src/fpu.c -o config/fpubits 2>/dev/null; then
        # Compiled successfully, now run it
        config/fpubits >/dev/null 2>/dev/null
        status=$?
        if [ $status -le 1 ]; then
            # The program ran successfully.  For now, we don't need
            # the exit status to be zero (indicating exactly 53 bits),
            # we simply need the program not to crash (which would
            # give an exit status > 128).
            CFLAGS="$CFLAGS $FLAG"
            return $status
        fi
    fi
    return 2
}

# These flags never hurt, so add them if possible
for FLAG in '-fno-fast-math' '-mfpmath=sse' '-Dx86'; do
    try_add_CFLAG $FLAG
done

# Add at most one flag of the following to avoid gcc warnings:
# gcc versions which support -ffp-contract deprecate -mno-fused-madd
for FLAG in '-ffp-contract=on' '-mno-fused-madd'; do
    try_add_CFLAG $FLAG && break
done

# Some flags to try as last resort.  These hurt performance, so only add
# them if needed.
for FLAG in '' '-ffloat-store' '-O0'; do
    # Stop the loop if the FPU precision already is 53 bits
    try_add_CFLAG $FLAG && break
done


# Check the actual FPU precision with our new flags.
$CC -O3 $CFLAGS config/fpubits1.c config/fpubits2.c src/fpu.c -o config/fpubits
if [ $? -ne 0 ]; then
    echo >&2 "Error: the command below failed:"
    echo >&2 "$CC -O3 $CFLAGS config/fpubits1.c config/fpubits2.c src/fpu.c -o config/fpubits"
    exit 1
fi
export CFLAGS

echo "CFLAGS for SYMPOW:$CFLAGS"

config/fpubits
status=$?
[ $status -eq 1 ] && sdh_die <<_EOF_
Error: the Quad Double library used by SYMPOW assumes IEEE-754 double
precision numbers with exactly 53 bits in the mantissa (64 bits in
total).  Unfortunately, this is not the case on your system and we
currently have no workaround for your system.  Running SYMPOW will
almost certainly fail on some inputs.

Please report this problem to sage-devel
(http://groups.google.com/group/sage-devel), mentioning in particular
your operating system, processor type and compiler version
(run $CC --version).
_EOF_

[ $status -ne 0 ] && sdh_die <<_EOF_
Error: something very bad happened while checking the precision of your
FPU.  Please report this problem (mentioning any error messages above)
to sage-devel (http://groups.google.com/group/sage-devel).
Mention in particular your operating system and compiler version
(run $CC --version).
_EOF_


#######################################################################
# Configure
#######################################################################
cd src/
# Force bash as shell
bash ./Configure || sdh_die "Error configuring SYMPOW"

#######################################################################
# Build
#######################################################################
sdh_make

#######################################################################
# Install
#######################################################################
TARGET="$SAGE_LOCAL/lib/sympow"

# Remove old install if any
rm -rf "$TARGET"

sdh_install sympow *.gp new_data datafiles "$TARGET"

# Create binary versions of datafiles
# Note: This should probably be a post-install step since it requires calling
# the compiled sympow binary; however in this case it happens to work fine
# since it does not have any external dependencies and can run from the temp
# install dir
cd "${SAGE_DESTDIR}${TARGET}/datafiles"
for file in *.txt; do
    NUM=`grep -c AT $file`
    ../sympow -txt2bin "$NUM" <$file ${file/%txt/bin} || \
        sdh_die "Error running SYMPOW"
done

# Create sympow script in $SAGE_LOCAL/bin
BIN="$SAGE_DESTDIR_LOCAL/bin"
mkdir -p "$BIN"
SCRIPT="$BIN/sympow"

cat >"$SCRIPT" <<'EOF'
cd "$SAGE_LOCAL/lib/sympow"
exec ./sympow "$@"
EOF

chmod +x "$SCRIPT"
