1/*  Constraint logic programming over continuous domains
    2
    3    Author:        Edison Mera
    4    E-mail:        efmera@gmail.com
    5    WWW:           https://github.com/edisonm/assertions
    6    Copyright (C): 2020, Process Design Center, Breda, The Netherlands.
    7    All rights reserved.
    8
    9    Redistribution and use in source and binary forms, with or without
   10    modification, are permitted provided that the following conditions
   11    are met:
   12
   13    1. Redistributions of source code must retain the above copyright
   14       notice, this list of conditions and the following disclaimer.
   15
   16    2. Redistributions in binary form must reproduce the above copyright
   17       notice, this list of conditions and the following disclaimer in
   18       the documentation and/or other materials provided with the
   19       distribution.
   20
   21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32    POSSIBILITY OF SUCH DAMAGE.
   33*/
   34
   35:- export(eepsilon/2).   36:- export(eepsilon/3).   37:- export(eval/3).   38:- export(cast/3).   39:- export(castable/2).   40:- export(compare/4).   41:- export(near_compare/4).   42
   43:- use_module(library(solution_sequences)).   44
   45:- public eval_1/4.   46
   47eval_1(Type, Arg, eval(Type, Arg, EA), EA).
   48
   49eval(_, Expr, _) :-
   50    var(Expr),
   51    !,
   52    fail.
   53eval(Type, Expr, C) :-
   54    do_eval(Expr, Type, C),
   55    !.
   56eval(Type, Value, C) :-
   57    cast(Type, Value, C),
   58    !.
   59eval(Type, Value, _) :-
   60    throw(error(type_error(evaluable, Type:Value), _)).
   61
   62cast(Type, Value, C) :-
   63    ( inner_cast(Type, Value, C)
   64    ->true
   65    ; integer(Value)
   66    ->term_string(Value, String),
   67      cast(Type, String, C)
   68    ; rational(Value)
   69    ->X is numerator(Value),
   70      Y is denominator(Value),
   71      do_eval(X/Y, Type, C)
   72    ).
   73
   74castable(Type, Value) :-
   75    cd_prefix(Type, Pref, _),
   76    atom_concat(is_, Pref, Func),
   77    Body =.. [Func, Value],
   78    necki,
   79    Body.
   80
   81inner_cast(Type, Value, C) :-
   82    cd_prefix(Type, Pref, EAL),
   83    append([Value|EAL], [C], AL),
   84    Body =.. [Pref|AL],
   85    necki,
   86    Body.
   87
   88do_eval_cputime(T, V) :-
   89    X is cputime,
   90    inner_cast(T, X, V).
   91
   92do_eval_z(Type, C) :- cast(Type, 0, C).
   93
   94eepsilon(T, E) :-
   95    reserve_eps(N),
   96    eval(T, N*epsilon, E).
   97
   98eepsilon(T, N, E) :-
   99    eepsilon(T, R),
  100    eval(T, R*N, E).
  101
  102compare(Type, Op, A, B) :-
  103    eval(Type, A, X),
  104    eval(Type, B, Y),
  105    compare_b(Op, Type, X, Y).
  106
  107near_compare(Type, Op, A, B) :-
  108    eval(Type, A, X),
  109    eval(Type, B, Y),
  110    near_compare_b(Type, Op, X, Y).
  111
  112near_compare_b(Type, Op, X, Y) :-
  113    ( compare_b(=, Type, X, Y)
  114    ->compare_eq(Op)
  115    ; eepsilon(Type, max(abs(X), abs(Y)), E),
  116      compare(Op, Type, X, Y, E)
  117    ).
  118
  119compare(=,  T, A, B, E) :- compare(T, =<, abs(A - B), E).
  120compare(=<, T, A, B, E) :- compare(T, =<, A - B, E).
  121compare(>=, T, A, B, E) :- compare(T, =<, B - A, E).
  122compare(<,  T, A, B, E) :- compare(T, >, B - A, E).
  123compare(>,  T, A, B, E) :- compare(T, >, A - B, E).
  124compare(\=, T, A, B, E) :- compare(T, >, abs(A - B), E).
  125
  126compare_b(Op, Type, X, Y) :-
  127    op_pred(Op, Pred),
  128    Body =.. [Pred, Type, X, Y],
  129    necki,
  130    Body.
  131
  132Head :-
  133    op_pred(_, Pred),
  134    Head =.. [Pred, Type, X, Y],
  135    cd_prefix(Type, Pref, _),
  136    atomic_list_concat([Pref, '_', Pred], F),
  137    Body =.. [F, X, Y],
  138    necki,
  139    Body.
  140
  141Head :-
  142    distinct(Pred, expr_pred(_, Pred)),
  143    Pred =.. [Name|AL],
  144    Head =.. [Name, Type, C|AL],
  145    cd_prefix(Type, Pref, EAL),
  146    atomic_list_concat([Pref, '_', Name], BN),
  147    append(EAL, [C|AL], BL),
  148    Body =.. [BN|BL],
  149    necki,
  150    Body