@approx(x:numeric, y:numeric)    ; listable
The function call can also be written with the special syntax
       (x ~ y)
note that the parenthesis are mandatory.

This predicate returns true if

       abs(x - y) <  $APPROX_ABS
or     
       abs((x - y)/max(x, y)) <  $APPROX_RATIO

The predefined variable $APPROX_ABS is initalized to 1e-5 so (x ~ y) means x and y differ by less than 0.00001. The predefined variable $APPROX_RATIO is initalized to 0.1 so (x ~ y) means x and y differ by less than 10% .

By changing the value of these variables, one changes the level of approximation for the following calls to @approx. The value of $APPROX_ABS controls the absolute difference of the two arguments, while $APPROX_RATIO controls the relative difference. The function returns false if the constraints on the absolute difference and the relative difference, are not meet.

Notice: Using this function to check if a number is near zero is adequate and amounts to looking at the absolute difference: (x ~ 0) results in the comparaison of fabs(x) which is compared to $APPROX_ABS while the relative difference evaluates to 1 (as a result of abs(x/x)).

Extension: The predicate is extended in three ways to handle arbitrary data structures:

  • If one argument is a tab and the other is a numeric u, the numeric argument is extended into a tab (all elements of the extension are equal to u) and the predicate returns true if it hold pointwise for all elements of the tabs. For example

             (tab[1, 2] ~ 1.000001)
    
    returns false because we have (1 ~ 1.000001) but we don’t have (2 ~ 1.000001).

  • The function accepts nested tabs as arguments and in this case distributes itself over the elements of the arrays as needed.

  • If the the arguments are neither a numeric nor a tab, they must be equal.