1#!/bin/bash 2 3# ULP error check script. 4# 5# Copyright (c) 2019-2024, Arm Limited. 6# SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception 7 8#set -x 9set -eu 10 11# cd to bin directory. 12cd "${0%/*}" 13 14rmodes='n u d z' 15#rmodes=n 16flags="${ULPFLAGS:--q}" 17emu="$@" 18 19FAIL=0 20PASS=0 21 22t() { 23 # First argument: routine name 24 routine=$1; shift 25 # Second and third argument: lo and hi bounds 26 # Extra processing needed for bivariate routines 27 IFS=',' read -ra LO <<< "$1"; shift 28 IFS=',' read -ra HI <<< "$1"; shift 29 ITV="${LO[0]} ${HI[0]}" 30 for i in "${!LO[@]}"; do 31 [[ "$i" -eq "0" ]] || ITV="$ITV x ${LO[$i]} ${HI[$i]}" 32 done 33 # Fourth argument: number of test points 34 n=$1; shift 35 # Any remaining arguments forwards directly to ulp tool 36 extra_flags="$@" 37 38 # Read ULP limits, fenv expectation and control values from autogenerated files 39 limits_file=$LIMITS 40 [ $r == "n" ] || limits_file=${limits_file}_nn 41 L=$(grep "^$routine " $limits_file | awk '{print $2}') 42 [ -n "$L" ] || { echo ERROR: Could not determine ULP limit for $routine in $limits_file && false; } 43 cvals=($(grep "^$routine " $CVALS | awk '{print $2}')) 44 45 if grep -q "^$routine$" $DISABLE_FENV; then extra_flags="$extra_flags -f"; fi 46 # Emulate a do-while loop to loop over cvals, but still execute once if it is empty 47 while : ; do 48 # Empty string if we are at the end of cvals array 49 c_arg="" 50 [ -z "${cvals[0]:-}" ] || c_arg="-c ${cvals[0]}" 51 $emu ./ulp -e $L $flags $extra_flags -r $r $c_arg $routine $ITV $n && PASS=$((PASS+1)) || FAIL=$((FAIL+1)) 52 # Shift cvals by 1, and break if it is now empty 53 cvals=("${cvals[@]:1}") 54 [ -n "${cvals[0]:-}" ] || break 55 done 56 57 # Run ULP tool 58 59} 60 61check() { 62 $emu ./ulp -f -q "$@" 63} 64 65if [[ $WANT_EXPERIMENTAL_MATH -eq 1 ]] && [[ $WANT_SVE_TESTS -eq 1 ]] && [[ $USE_MPFR -eq 0 ]]; then 66 # No guarantees about powi accuracy, so regression-test for exactness 67 # w.r.t. the custom reference impl in ulp_wrappers.h 68 if [ -z "$FUNC" ] || [ "$FUNC" == "_ZGVsMxvv_powi" ]; then 69 check -q -f -e 0 _ZGVsMxvv_powi 0 inf x 0 1000 100000 70 check -q -f -e 0 _ZGVsMxvv_powi -0 -inf x 0 1000 100000 71 check -q -f -e 0 _ZGVsMxvv_powi 0 inf x -0 -1000 100000 72 check -q -f -e 0 _ZGVsMxvv_powi -0 -inf x -0 -1000 100000 73 fi 74 if [ -z "$FUNC" ] || [ "$FUNC" == "_ZGVsMxvv_powk" ]; then 75 check -q -f -e 0 _ZGVsMxvv_powk 0 inf x 0 1000 100000 76 check -q -f -e 0 _ZGVsMxvv_powk -0 -inf x 0 1000 100000 77 check -q -f -e 0 _ZGVsMxvv_powk 0 inf x -0 -1000 100000 78 check -q -f -e 0 _ZGVsMxvv_powk -0 -inf x -0 -1000 100000 79 fi 80fi 81 82# Test generic routines in all rounding modes 83for r in $rmodes 84do 85 while read F LO HI N 86 do 87 [[ -z $F ]] || t $F $LO $HI $N 88 done << EOF 89$(grep "\b$FUNC\b" $GEN_ITVS) 90EOF 91done 92 93# Only test arch-specific routines in round-to-nearest, with sign of zero ignored (-z flag) 94r=n 95while read F LO HI N 96do 97 [[ -z $F ]] || t $F $LO $HI $N -z 98done << EOF 99$(grep "\b$FUNC\b" $ARCH_ITVS) 100EOF 101 102[ 0 -eq $FAIL ] || { 103 echo "FAILED $FAIL PASSED $PASS" 104 exit 1 105} 106