#!/bin/bash

. faustpath

FILES=""
IOS="0"
DOUBLE="0"
OPTIONS=""
LIBS=""
TESTS="all"
RUN=1
NOTRACE=false
GENERIC=false

# Set default value for CXX
if [ "$CXX" = "" ]; then
    CXX=g++
fi

while [ $1 ]
do
    p=$1

    if [ $p = "-help" ] || [ $p = "-h" ]; then
        echo "faustbench [-notrace] [-generic] [-ios] [-single] [-fast] [-run <num>] [-double] [additional Faust options (-vec -vs 8...)] foo.dsp"
        echo "Use '-notrace' to only generate the best compilation parameters"
        echo "Use '-generic' to compile for a generic processor, otherwise -march=native will be used"
        echo "Use '-ios' to generate an iOS project"
        echo "Use '-single' to only execute the scalar test"
        echo "Use '-fast' to only execute some tests"
        echo "Use '-run <num>' to execute each test <num> times"
        echo "Use '-double' to compile DSP in double and set FAUSTFLOAT to double"
        echo "Use 'export CXX=/path/to/compiler' before running faustbench to change the C++ compiler"
        echo "Use 'export CXXFLAGS=options' before running faustbench to change the C++ compiler options"
        exit
    fi

    if [ "$p" = "-ios" ]; then
        IOS="1"
    elif [ "$p" = "-notrace" ]; then
        NOTRACE=true
    elif [ "$p" = "-generic" ]; then
        GENERIC=true
    elif [ "$p" = "-fast" ]; then
        TESTS="fast"
    elif [ "$p" = "-single" ]; then
        TESTS="single"
    elif [ "$p" = "-run" ]; then
        shift
        RUN=$1
    elif [ "$p" = "-double" ]; then
        DOUBLE="1"
        OPTIONS="$OPTIONS $p"
    elif [[ -f "$p" ]]; then
        FILES="$FILES $p"
    elif [ ${p:0:1} = "-" ]; then
        OPTIONS="$OPTIONS $p"
    else
        OPTIONS="$OPTIONS $p"
    fi

shift

done

# Set default value for CXXFLAGS
if [ "$CXXFLAGS" = "" ]; then
    if $GENERIC; then
        CXXFLAGS="-Ofast"
    else
        CXXFLAGS="-Ofast -march=native"
    fi
fi

if [[ $(uname) == Darwin ]]; then
    LIBS=-lc++
    CXXFLAGS+=" -fbracket-depth=512"
fi

if ! $NOTRACE ; then
	echo "Selected compiler is $CXX with CXXFLAGS = $CXXFLAGS"
fi

for p in $FILES; do

    CUR=$(pwd)
    f=$(basename "$p")
    SRCDIR=$(dirname "$p")
    dspName="${f%.dsp}"

    # creates a temporary dir
    TDR=$(mktemp -d faust.XXX)
    TMP="$TDR/${f%.dsp}"
    mkdir "$TMP"

    # creates and compile multiple DSP bench tool
    if [ "$OPTIONS" != "" ] ; then
    	if ! $NOTRACE ; then
        	echo "Compiled with additional options :$OPTIONS"
        fi
    fi

    if [ $TESTS == "all" ] ; then

        faust -cn dsp_scal $OPTIONS "$SRCDIR/$f" -o "$TMP/dsp_scal.h"
        faust -cn dsp_scal_exp10 $OPTIONS -exp10 "$SRCDIR/$f" -o "$TMP/dsp_scal_exp10.h"

        faust -cn dsp_vec0_4 $OPTIONS -vec -lv 0 -vs 4 "$SRCDIR/$f" -o "$TMP/dsp_vec0_4.h"
        faust -cn dsp_vec0_8 $OPTIONS -vec -lv 0 -vs 8 "$SRCDIR/$f" -o "$TMP/dsp_vec0_8.h"
        faust -cn dsp_vec0_16 $OPTIONS -vec -lv 0 -vs 16 "$SRCDIR/$f" -o "$TMP/dsp_vec0_16.h"
        faust -cn dsp_vec0_32 $OPTIONS -vec -lv 0 -vs 32 "$SRCDIR/$f" -o "$TMP/dsp_vec0_32.h"
        faust -cn dsp_vec0_64 $OPTIONS -vec -lv 0 -vs 64 "$SRCDIR/$f" -o "$TMP/dsp_vec0_64.h"
        faust -cn dsp_vec0_128 $OPTIONS -vec -lv 0 -vs 128 "$SRCDIR/$f" -o "$TMP/dsp_vec0_128.h"
        faust -cn dsp_vec0_256 $OPTIONS -vec -lv 0 -vs 256 "$SRCDIR/$f" -o "$TMP/dsp_vec0_256.h"
        faust -cn dsp_vec0_512 $OPTIONS -vec -lv 0 -vs 512 "$SRCDIR/$f" -o "$TMP/dsp_vec0_512.h"

        faust -cn dsp_vec0g_4 $OPTIONS -vec -lv 0 -vs 4 -g "$SRCDIR/$f" -o "$TMP/dsp_vec0g_4.h"
        faust -cn dsp_vec0g_8 $OPTIONS -vec -lv 0 -vs 8 -g "$SRCDIR/$f" -o "$TMP/dsp_vec0g_8.h"
        faust -cn dsp_vec0g_16 $OPTIONS -vec -lv 0 -vs 16 -g "$SRCDIR/$f" -o "$TMP/dsp_vec0g_16.h"
        faust -cn dsp_vec0g_32 $OPTIONS -vec -lv 0 -vs 32 -g "$SRCDIR/$f" -o "$TMP/dsp_vec0g_32.h"
        faust -cn dsp_vec0g_64 $OPTIONS -vec -lv 0 -vs 64 -g "$SRCDIR/$f" -o "$TMP/dsp_vec0g_64.h"
        faust -cn dsp_vec0g_128 $OPTIONS -vec -lv 0 -vs 128 -g "$SRCDIR/$f" -o "$TMP/dsp_vec0g_128.h"
        faust -cn dsp_vec0g_256 $OPTIONS -vec -lv 0 -vs 256 -g "$SRCDIR/$f" -o "$TMP/dsp_vec0g_256.h"
        faust -cn dsp_vec0g_512 $OPTIONS -vec -lv 0 -vs 512 -g "$SRCDIR/$f" -o "$TMP/dsp_vec0g_512.h"

        faust -cn dsp_vec1_4 $OPTIONS -vec -lv 1 -vs 4 "$SRCDIR/$f" -o "$TMP/dsp_vec1_4.h"
        faust -cn dsp_vec1_8 $OPTIONS -vec -lv 1 -vs 8 "$SRCDIR/$f" -o "$TMP/dsp_vec1_8.h"
        faust -cn dsp_vec1_16 $OPTIONS -vec -lv 1 -vs 16 "$SRCDIR/$f" -o "$TMP/dsp_vec1_16.h"
        faust -cn dsp_vec1_32 $OPTIONS -vec -lv 1 -vs 32 "$SRCDIR/$f" -o "$TMP/dsp_vec1_32.h"
        faust -cn dsp_vec1_64 $OPTIONS -vec -lv 1 -vs 64 "$SRCDIR/$f" -o "$TMP/dsp_vec1_64.h"
        faust -cn dsp_vec1_128 $OPTIONS -vec -lv 1 -vs 128 "$SRCDIR/$f" -o "$TMP/dsp_vec1_128.h"
        faust -cn dsp_vec1_256 $OPTIONS -vec -lv 1 -vs 256 "$SRCDIR/$f" -o "$TMP/dsp_vec1_256.h"
        faust -cn dsp_vec1_512 $OPTIONS -vec -lv 1 -vs 512 "$SRCDIR/$f" -o "$TMP/dsp_vec1_512.h"

        faust -cn dsp_vec1g_4 $OPTIONS -vec -lv 1 -vs 4 -g "$SRCDIR/$f" -o "$TMP/dsp_vec1g_4.h"
        faust -cn dsp_vec1g_8 $OPTIONS -vec -lv 1 -vs 8 -g "$SRCDIR/$f" -o "$TMP/dsp_vec1g_8.h"
        faust -cn dsp_vec1g_16 $OPTIONS -vec -lv 1 -vs 16 -g "$SRCDIR/$f" -o "$TMP/dsp_vec1g_16.h"
        faust -cn dsp_vec1g_32 $OPTIONS -vec -lv 1 -vs 32 -g "$SRCDIR/$f" -o "$TMP/dsp_vec1g_32.h"
        faust -cn dsp_vec1g_64 $OPTIONS -vec -lv 1 -vs 64 -g "$SRCDIR/$f" -o "$TMP/dsp_vec1g_64.h"
        faust -cn dsp_vec1g_128 $OPTIONS -vec -lv 1 -vs 128 -g "$SRCDIR/$f" -o "$TMP/dsp_vec1g_128.h"
        faust -cn dsp_vec1g_256 $OPTIONS -vec -lv 1 -vs 256 -g "$SRCDIR/$f" -o "$TMP/dsp_vec1g_256.h"
        faust -cn dsp_vec1g_512 $OPTIONS -vec -lv 1 -vs 512 -g "$SRCDIR/$f" -o "$TMP/dsp_vec1g_512.h"

    elif [ $TESTS == "fast" ] ; then

        faust -cn dsp_scal $OPTIONS "$SRCDIR/$f" -o "$TMP/dsp_scal.h"
        faust -cn dsp_vec0_32 $OPTIONS -vec -lv 0 -vs 32 "$SRCDIR/$f" -o "$TMP/dsp_vec0_32.h"
        faust -cn dsp_vec0g_32 $OPTIONS -vec -lv 0 -vs 32 -g "$SRCDIR/$f" -o "$TMP/dsp_vec0g_32.h"
        faust -cn dsp_vec1_32 $OPTIONS -vec -lv 1 -vs 32 "$SRCDIR/$f" -o "$TMP/dsp_vec1_32.h"
        faust -cn dsp_vec1g_32 $OPTIONS -vec -lv 1 -vs 32 -g "$SRCDIR/$f" -o "$TMP/dsp_vec1g_32.h"

    elif [ $TESTS == "single" ] ; then

        faust -cn dsp_scal $OPTIONS "$SRCDIR/$f" -o "$TMP/dsp_scal.h"
    fi

    if [ $IOS == "1" ] ; then
        echo "Files generated for iOS project in $TMP"
        if [ $DOUBLE == "1" ] ; then
            echo " #define FAUSTFLOAT double" | cat - "$FAUSTLIB/faustbench.cpp" > temp && mv temp "$TMP/faustbench.cpp"
        else
            echo " #define FAUSTFLOAT float" | cat - "$FAUSTLIB/faustbench.cpp" > temp && mv temp "$TMP/faustbench.cpp"
        fi
        cp -r $FAUSTLIB/iOS-bench/* $TMP
        exit
    fi

    cd "$TMP"

    if [ $DOUBLE == "1" ] ; then
        echo " #define FAUSTFLOAT double" | cat - "$FAUSTLIB/faustbench.cpp" > temp && mv temp "faustbench.cpp"
    else
        echo " #define FAUSTFLOAT float" | cat - "$FAUSTLIB/faustbench.cpp" > temp && mv temp "faustbench.cpp"
    fi

    if [ $TESTS == "all" ] ; then
        $CXX $CXXFLAGS -std=c++11 -I . -I ../../ -DALL_TESTS faustbench.cpp $LIBS -o $dspName
    elif [ $TESTS == "fast" ] ; then
        $CXX $CXXFLAGS -std=c++11 -I . -I ../../ -DFAST_TESTS faustbench.cpp $LIBS -o $dspName
    elif [ $TESTS == "single" ] ; then
        $CXX $CXXFLAGS -std=c++11 -I . -I ../../ -DSINGLE_TESTS faustbench.cpp $LIBS -o $dspName
    fi

    # run bench
    cd ../../
    if $NOTRACE; then
    	./$TDR/$dspName/$dspName -run $RUN -notrace
    else
    	./$TDR/$dspName/$dspName -run $RUN
    fi

    # cleanup
    rm -rf "$TDR"

done

