|
PPL
0.12.1
|
The base class of all concrete expressions. More...
#include <Concrete_Expression.types.hh>
Related Functions | |
(Note that these are not member functions.) | |
| template<typename Target , typename FP_Interval_Type > | |
| static bool | add_linearize (const Binary_Operator< Target > &bop_expr, const FP_Oracle< Target, FP_Interval_Type > &oracle, const std::map< dimension_type, Linear_Form< FP_Interval_Type > > &lf_store, Linear_Form< FP_Interval_Type > &result) |
| template<typename Target , typename FP_Interval_Type > | |
| static bool | sub_linearize (const Binary_Operator< Target > &bop_expr, const FP_Oracle< Target, FP_Interval_Type > &oracle, const std::map< dimension_type, Linear_Form< FP_Interval_Type > > &lf_store, Linear_Form< FP_Interval_Type > &result) |
| template<typename Target , typename FP_Interval_Type > | |
| static bool | mul_linearize (const Binary_Operator< Target > &bop_expr, const FP_Oracle< Target, FP_Interval_Type > &oracle, const std::map< dimension_type, Linear_Form< FP_Interval_Type > > &lf_store, Linear_Form< FP_Interval_Type > &result) |
| template<typename Target , typename FP_Interval_Type > | |
| static bool | div_linearize (const Binary_Operator< Target > &bop_expr, const FP_Oracle< Target, FP_Interval_Type > &oracle, const std::map< dimension_type, Linear_Form< FP_Interval_Type > > &lf_store, Linear_Form< FP_Interval_Type > &result) |
| template<typename Target , typename FP_Interval_Type > | |
| static bool | cast_linearize (const Cast_Operator< Target > &cast_expr, const FP_Oracle< Target, FP_Interval_Type > &oracle, const std::map< dimension_type, Linear_Form< FP_Interval_Type > > &lf_store, Linear_Form< FP_Interval_Type > &result) |
| template<typename Target , typename FP_Interval_Type > | |
| bool | linearize (const Concrete_Expression< Target > &expr, const FP_Oracle< Target, FP_Interval_Type > &oracle, const std::map< dimension_type, Linear_Form< FP_Interval_Type > > &lf_store, Linear_Form< FP_Interval_Type > &result) |
| Linearizes a floating point expression. | |
The base class of all concrete expressions.
|
related |
Helper function used by linearize to linearize a sum of floating point expressions.
Makes result become the linearization of *this in the given composite abstract store.
| Target | A type template parameter specifying the instantiation of Concrete_Expression to be used. |
| FP_Interval_Type | A type template parameter for the intervals used in the abstract domain. The interval bounds should have a floating point type. |
true if the linearization succeeded, false otherwise.| bop_expr | The binary operator concrete expression to linearize. Its binary operator type must be ADD. |
| oracle | The FP_Oracle to be queried. |
| lf_store | The linear form abstract store. |
| result | The modified linear form. |
Let
and
be two linear forms and
a sound abstract operator on linear forms such that:
Given an expression
and a composite abstract store
, we construct the interval linear form
as follows:
where
is the relative error associated to
(see method relative_error of class Linear_Form) and
is a rounding error computed by function compute_absolute_error.
Definition at line 110 of file linearize.hh.
References Parma_Polyhedra_Library::Linear_Form< C >::overflows(), PPL_ASSERT, and Parma_Polyhedra_Library::Linear_Form< C >::relative_error().
{
PPL_ASSERT(bop_expr.binary_operator() == Binary_Operator<Target>::ADD);
typedef typename FP_Interval_Type::boundary_type analyzer_format;
typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
typedef Box<FP_Interval_Type> FP_Interval_Abstract_Store;
typedef std::map<dimension_type, FP_Linear_Form> FP_Linear_Form_Abstract_Store;
if (!linearize(*(bop_expr.left_hand_side()), oracle, lf_store, result))
return false;
Floating_Point_Format analyzed_format =
bop_expr.type().floating_point_format();
FP_Linear_Form rel_error;
result.relative_error(analyzed_format, rel_error);
result += rel_error;
FP_Linear_Form linearized_second_operand;
if (!linearize(*(bop_expr.right_hand_side()), oracle, lf_store,
linearized_second_operand))
return false;
result += linearized_second_operand;
linearized_second_operand.relative_error(analyzed_format, rel_error);
result += rel_error;
FP_Interval_Type absolute_error =
compute_absolute_error<FP_Interval_Type>(analyzed_format);
result += absolute_error;
return !result.overflows();
}
|
related |
Helper function used by linearize to linearize a cast floating point expression.
Makes result become the linearization of *this in the given composite abstract store.
| Target | A type template parameter specifying the instantiation of Concrete_Expression to be used. |
| FP_Interval_Type | A type template parameter for the intervals used in the abstract domain. The interval bounds should have a floating point type. |
true if the linearization succeeded, false otherwise.| cast_expr | The cast operator concrete expression to linearize. |
| oracle | The FP_Oracle to be queried. |
| lf_store | The linear form abstract store. |
| result | The modified linear form. |
Definition at line 629 of file linearize.hh.
References Parma_Polyhedra_Library::FP_Oracle< Target, FP_Interval_Type >::get_integer_expr_value(), Parma_Polyhedra_Library::is_less_precise_than(), Parma_Polyhedra_Library::Linear_Form< C >::overflows(), and Parma_Polyhedra_Library::Linear_Form< C >::relative_error().
{
typedef typename FP_Interval_Type::boundary_type analyzer_format;
typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
typedef Box<FP_Interval_Type> FP_Interval_Abstract_Store;
typedef std::map<dimension_type, FP_Linear_Form> FP_Linear_Form_Abstract_Store;
Floating_Point_Format analyzed_format =
cast_expr.type().floating_point_format();
const Concrete_Expression<Target>* cast_arg = cast_expr.argument();
if (cast_arg->type().is_floating_point()) {
if (!linearize(*cast_arg, oracle, lf_store, result))
return false;
if (!is_less_precise_than(analyzed_format,
cast_arg->type().floating_point_format()) ||
result == FP_Linear_Form(FP_Interval_Type(0)) ||
result == FP_Linear_Form(FP_Interval_Type(1)))
/*
FIXME: find a general way to check if the casted constant
is exactly representable in the less precise format.
*/
/*
We are casting to a more precise format or casting
a definitely safe value: do not add errors.
*/
return true;
}
else {
FP_Interval_Type expr_value;
if (!oracle.get_integer_expr_value(*cast_arg, expr_value))
return false;
result = FP_Linear_Form(expr_value);
if (is_less_precise_than(Float<analyzer_format>::Binary::floating_point_format, analyzed_format) ||
result == FP_Linear_Form(FP_Interval_Type(0)) ||
result == FP_Linear_Form(FP_Interval_Type(1)))
/*
FIXME: find a general way to check if the casted constant
is exactly representable in the less precise format.
*/
/*
We are casting to a more precise format or casting
a definitely safe value: do not add errors.
*/
return true;
}
FP_Linear_Form rel_error;
result.relative_error(analyzed_format, rel_error);
result += rel_error;
FP_Interval_Type absolute_error =
compute_absolute_error<FP_Interval_Type>(analyzed_format);
result += absolute_error;
return !result.overflows();
}
|
related |
Helper function used by linearize to linearize a division of floating point expressions.
Makes result become the linearization of *this in the given composite abstract store.
| Target | A type template parameter specifying the instantiation of Concrete_Expression to be used. |
| FP_Interval_Type | A type template parameter for the intervals used in the abstract domain. The interval bounds should have a floating point type. |
true if the linearization succeeded, false otherwise.| bop_expr | The binary operator concrete expression to linearize. Its binary operator type must be DIV. |
| oracle | The FP_Oracle to be queried. |
| lf_store | The linear form abstract store. |
| result | The modified linear form. |
Let
and
be two linear forms,
and
two sound abstract operator on linear forms such that:
Given an expression
and a composite abstract store
, we construct the interval linear form
as follows:
given an expression
and a composite abstract store
, we construct the interval linear form
as follows:
where
is the relative error associated to
(see method relative_error of class Linear_Form),
is the intervalization of
(see method intervalize of class Linear_Form), and
is a rounding error computed by function compute_absolute_error.
Definition at line 553 of file linearize.hh.
References Parma_Polyhedra_Library::Linear_Form< C >::overflows(), PPL_ASSERT, and Parma_Polyhedra_Library::Linear_Form< C >::relative_error().
{
PPL_ASSERT(bop_expr.binary_operator() == Binary_Operator<Target>::DIV);
typedef typename FP_Interval_Type::boundary_type analyzer_format;
typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
typedef Box<FP_Interval_Type> FP_Interval_Abstract_Store;
typedef std::map<dimension_type, FP_Linear_Form> FP_Linear_Form_Abstract_Store;
FP_Linear_Form linearized_second_operand;
if (!linearize(*(bop_expr.right_hand_side()), oracle, lf_store,
linearized_second_operand))
return false;
FP_Interval_Type intervalized_second_operand;
if (!linearized_second_operand.intervalize(oracle,
intervalized_second_operand))
return false;
// Check if we may divide by zero.
if ((intervalized_second_operand.lower_is_boundary_infinity() ||
intervalized_second_operand.lower() <= 0) &&
(intervalized_second_operand.upper_is_boundary_infinity() ||
intervalized_second_operand.upper() >= 0))
return false;
if (!linearize(*(bop_expr.left_hand_side()), oracle, lf_store, result))
return false;
Floating_Point_Format analyzed_format =
bop_expr.type().floating_point_format();
FP_Linear_Form rel_error;
result.relative_error(analyzed_format, rel_error);
result /= intervalized_second_operand;
rel_error /= intervalized_second_operand;
result += rel_error;
FP_Interval_Type absolute_error =
compute_absolute_error<FP_Interval_Type>(analyzed_format);
result += absolute_error;
return !result.overflows();
}
|
related |
Linearizes a floating point expression.
Makes result become a linear form that correctly approximates the value of expr in the given composite abstract store.
| Target | A type template parameter specifying the instantiation of Concrete_Expression to be used. |
| FP_Interval_Type | A type template parameter for the intervals used in the abstract domain. The interval bounds should have a floating point type. |
true if the linearization succeeded, false otherwise.| expr | The concrete expression to linearize. |
| oracle | The FP_Oracle to be queried. |
| lf_store | The linear form abstract store. |
| result | Becomes the linearized expression. |
Formally, if expr represents the expression
and lf_store represents the linear form abstract store
, then result will become
if the linearization succeeds.
Definition at line 722 of file linearize.hh.
References Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::FP_Oracle< Target, FP_Interval_Type >::get_associated_dimensions(), Parma_Polyhedra_Library::FP_Oracle< Target, FP_Interval_Type >::get_fp_constant_value(), Parma_Polyhedra_Library::FP_Oracle< Target, FP_Interval_Type >::get_interval(), Parma_Polyhedra_Library::Linear_Form< C >::negate(), Parma_Polyhedra_Library::not_a_dimension(), Parma_Polyhedra_Library::Linear_Form< C >::overflows(), PPL_ASSERT, PPL_COMPILE_TIME_CHECK, and PPL_UNREACHABLE.
{
typedef typename FP_Interval_Type::boundary_type analyzer_format;
typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
typedef Box<FP_Interval_Type> FP_Interval_Abstract_Store;
typedef std::map<dimension_type, FP_Linear_Form> FP_Linear_Form_Abstract_Store;
PPL_ASSERT(expr.type().is_floating_point());
// Check that analyzer_format is a floating point type.
PPL_COMPILE_TIME_CHECK(!std::numeric_limits<analyzer_format>::is_exact,
"linearize<Target, FP_Interval_Type>:"
" FP_Interval_Type is not the type of an interval with floating point boundaries.");
switch(expr.kind()) {
case Integer_Constant<Target>::KIND:
PPL_UNREACHABLE;
break;
case Floating_Point_Constant<Target>::KIND:
{
const Floating_Point_Constant<Target>* fpc_expr =
expr.template as<Floating_Point_Constant>();
FP_Interval_Type constant_value;
if (!oracle.get_fp_constant_value(*fpc_expr, constant_value))
return false;
result = FP_Linear_Form(constant_value);
return true;
}
case Unary_Operator<Target>::KIND:
{
const Unary_Operator<Target>* uop_expr =
expr.template as<Unary_Operator>();
switch (uop_expr->unary_operator()) {
case Unary_Operator<Target>::UPLUS:
return linearize(*(uop_expr->argument()), oracle, lf_store, result);
case Unary_Operator<Target>::UMINUS:
if (!linearize(*(uop_expr->argument()), oracle, lf_store, result))
return false;
result.negate();
return true;
case Unary_Operator<Target>::BNOT:
throw std::runtime_error("PPL internal error: unimplemented");
break;
default:
PPL_UNREACHABLE;
break;
}
break;
}
case Binary_Operator<Target>::KIND:
{
const Binary_Operator<Target>* bop_expr =
expr.template as<Binary_Operator>();
switch (bop_expr->binary_operator()) {
case Binary_Operator<Target>::ADD:
return add_linearize(*bop_expr, oracle, lf_store, result);
case Binary_Operator<Target>::SUB:
return sub_linearize(*bop_expr, oracle, lf_store, result);
case Binary_Operator<Target>::MUL:
return mul_linearize(*bop_expr, oracle, lf_store, result);
case Binary_Operator<Target>::DIV:
return div_linearize(*bop_expr, oracle, lf_store, result);
case Binary_Operator<Target>::REM:
case Binary_Operator<Target>::BAND:
case Binary_Operator<Target>::BOR:
case Binary_Operator<Target>::BXOR:
case Binary_Operator<Target>::LSHIFT:
case Binary_Operator<Target>::RSHIFT:
// FIXME: can we do better?
return false;
default:
PPL_UNREACHABLE;
return false;
}
break;
}
case Approximable_Reference<Target>::KIND:
{
const Approximable_Reference<Target>* ref_expr =
expr.template as<Approximable_Reference>();
std::set<dimension_type> associated_dimensions;
if (!oracle.get_associated_dimensions(*ref_expr, associated_dimensions)
|| associated_dimensions.empty())
/*
We were unable to find any associated space dimension:
linearization fails.
*/
return false;
if (associated_dimensions.size() == 1) {
/* If a linear form associated to the only referenced
space dimension exists in lf_store, return that form.
Otherwise, return the simplest linear form. */
dimension_type variable_index = *associated_dimensions.begin();
PPL_ASSERT(variable_index != not_a_dimension());
typename FP_Linear_Form_Abstract_Store::const_iterator
variable_value = lf_store.find(variable_index);
if (variable_value == lf_store.end()) {
result = FP_Linear_Form(Variable(variable_index));
return true;
}
result = FP_Linear_Form(variable_value->second);
/* FIXME: do we really need to contemplate the possibility
that an unbounded linear form was saved into lf_store? */
return !result.overflows();
}
/*
Here associated_dimensions.size() > 1. Try to return the LUB
of all intervals associated to each space dimension.
*/
PPL_ASSERT(associated_dimensions.size() > 1);
std::set<dimension_type>::const_iterator i = associated_dimensions.begin();
std::set<dimension_type>::const_iterator i_end =
associated_dimensions.end();
FP_Interval_Type lub(EMPTY);
for (; i != i_end; ++i) {
FP_Interval_Type curr_int;
PPL_ASSERT(*i != not_a_dimension());
if (!oracle.get_interval(*i, curr_int))
return false;
lub.join_assign(curr_int);
}
result = FP_Linear_Form(lub);
return !result.overflows();
}
case Cast_Operator<Target>::KIND:
{
const Cast_Operator<Target>* cast_expr =
expr.template as<Cast_Operator>();
return cast_linearize(*cast_expr, oracle, lf_store, result);
}
default:
PPL_UNREACHABLE;
break;
}
PPL_UNREACHABLE;
return false;
}
|
related |
Helper function used by linearize to linearize a product of floating point expressions.
Makes result become the linearization of *this in the given composite abstract store.
| Target | A type template parameter specifying the instantiation of Concrete_Expression to be used. |
| FP_Interval_Type | A type template parameter for the intervals used in the abstract domain. The interval bounds should have a floating point type. |
true if the linearization succeeded, false otherwise.| bop_expr | The binary operator concrete expression to linearize. Its binary operator type must be MUL. |
| oracle | The FP_Oracle to be queried. |
| lf_store | The linear form abstract store. |
| result | The modified linear form. |
Let
and
be two linear forms,
and
two sound abstract operators on linear forms such that:
Given an expression
and a composite abstract store
, we construct the interval linear form
as follows:
.
Given an expression
and a composite abstract store
, we construct the interval linear form
as follows:
Given an expression
and a composite abstract store
, we construct the interval linear form
as follows:
where
is the relative error associated to
(see method relative_error of class Linear_Form),
is the intervalization of
(see method intervalize of class Linear_Form), and
is a rounding error computed by function compute_absolute_error.
Even though we intervalize the first operand in the above example, the actual implementation utilizes an heuristics for choosing which of the two operands must be intervalized in order to obtain the most precise result.
Definition at line 367 of file linearize.hh.
References Parma_Polyhedra_Library::Linear_Form< C >::overflows(), PPL_ASSERT, and Parma_Polyhedra_Library::Linear_Form< C >::relative_error().
{
PPL_ASSERT(bop_expr.binary_operator() == Binary_Operator<Target>::MUL);
typedef typename FP_Interval_Type::boundary_type analyzer_format;
typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
typedef Box<FP_Interval_Type> FP_Interval_Abstract_Store;
typedef std::map<dimension_type, FP_Linear_Form> FP_Linear_Form_Abstract_Store;
/*
FIXME: We currently adopt the "Interval-Size Local" strategy in order to
decide which of the two linear forms must be intervalized, as described
in Section 6.2.4 ("Multiplication Strategies") of Antoine Mine's Ph.D.
thesis "Weakly Relational Numerical Abstract Domains".
In this Section are also described other multiplication strategies, such
as All-Cases, Relative-Size Local, Simplification-Driven Global and
Homogeneity Global.
*/
// Here we choose which of the two linear forms must be intervalized.
// true if we intervalize the first form, false if we intervalize the second.
bool intervalize_first;
FP_Linear_Form linearized_first_operand;
if (!linearize(*(bop_expr.left_hand_side()), oracle, lf_store,
linearized_first_operand))
return false;
FP_Interval_Type intervalized_first_operand;
if (!linearized_first_operand.intervalize(oracle, intervalized_first_operand))
return false;
FP_Linear_Form linearized_second_operand;
if (!linearize(*(bop_expr.right_hand_side()), oracle, lf_store,
linearized_second_operand))
return false;
FP_Interval_Type intervalized_second_operand;
if (!linearized_second_operand.intervalize(oracle,
intervalized_second_operand))
return false;
// FIXME: we are not sure that what we do here is policy-proof.
if (intervalized_first_operand.is_bounded()) {
if (intervalized_second_operand.is_bounded()) {
analyzer_format first_interval_size
= intervalized_first_operand.upper()
- intervalized_first_operand.lower();
analyzer_format second_interval_size
= intervalized_second_operand.upper()
- intervalized_second_operand.lower();
if (first_interval_size <= second_interval_size)
intervalize_first = true;
else
intervalize_first = false;
}
else
intervalize_first = true;
}
else {
if (intervalized_second_operand.is_bounded())
intervalize_first = false;
else
return false;
}
// Here we do the actual computation.
// For optimizing, we store the relative error directly into result.
Floating_Point_Format analyzed_format =
bop_expr.type().floating_point_format();
if (intervalize_first) {
linearized_second_operand.relative_error(analyzed_format, result);
linearized_second_operand *= intervalized_first_operand;
result *= intervalized_first_operand;
result += linearized_second_operand;
}
else {
linearized_first_operand.relative_error(analyzed_format, result);
linearized_first_operand *= intervalized_second_operand;
result *= intervalized_second_operand;
result += linearized_first_operand;
}
FP_Interval_Type absolute_error =
compute_absolute_error<FP_Interval_Type>(analyzed_format);
result += absolute_error;
return !result.overflows();
}
|
related |
Helper function used by linearize to linearize a difference of floating point expressions.
Makes result become the linearization of *this in the given composite abstract store.
| Target | A type template parameter specifying the instantiation of Concrete_Expression to be used. |
| FP_Interval_Type | A type template parameter for the intervals used in the abstract domain. The interval bounds should have a floating point type. |
true if the linearization succeeded, false otherwise.| bop_expr | The binary operator concrete expression to linearize. Its binary operator type must be SUB. |
| oracle | The FP_Oracle to be queried. |
| lf_store | The linear form abstract store. |
| result | The modified linear form. |
Let
and
be two linear forms,
and
two sound abstract operators on linear form such that:
Given an expression
and a composite abstract store
, we construct the interval linear form
on
as follows:
where
is the relative error associated to
(see method relative_error of class Linear_Form) and
is a rounding error computed by function compute_absolute_error.
Definition at line 224 of file linearize.hh.
References Parma_Polyhedra_Library::Linear_Form< C >::overflows(), PPL_ASSERT, and Parma_Polyhedra_Library::Linear_Form< C >::relative_error().
{
PPL_ASSERT(bop_expr.binary_operator() == Binary_Operator<Target>::SUB);
typedef typename FP_Interval_Type::boundary_type analyzer_format;
typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
typedef Box<FP_Interval_Type> FP_Interval_Abstract_Store;
typedef std::map<dimension_type, FP_Linear_Form> FP_Linear_Form_Abstract_Store;
if (!linearize(*(bop_expr.left_hand_side()), oracle, lf_store, result))
return false;
Floating_Point_Format analyzed_format =
bop_expr.type().floating_point_format();
FP_Linear_Form rel_error;
result.relative_error(analyzed_format, rel_error);
result += rel_error;
FP_Linear_Form linearized_second_operand;
if (!linearize(*(bop_expr.right_hand_side()), oracle, lf_store,
linearized_second_operand))
return false;
result -= linearized_second_operand;
linearized_second_operand.relative_error(analyzed_format, rel_error);
result += rel_error;
FP_Interval_Type absolute_error =
compute_absolute_error<FP_Interval_Type>(analyzed_format);
result += absolute_error;
return !result.overflows();
}