@approx(x:numeric, y:numeric)    ; listable
@approx(x, y)                    ; 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
       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).

  • if the two arguments are map, the predicate returns true if the two maps have the same set of keys, and for each key, the predicate is true for the associated values.

  • The function accepts nested tabs and maps as arguments. In this case, it distributes itself over the elements of the arrays as needed or over the map's items.

  • If the the arguments are neither numeric nor tab or maps, they must be strictly equal.