SCHEMA mathematical_functions_schema; -- This file constitutes document WG12 N921 -- Master document: ISO 10303-50:2001 -- EXPRESS last modified: 2001-09-07 REFERENCE FROM ISO13584_generic_expressions_schema -- ISO 13584-20 (binary_generic_expression, environment, generic_expression, generic_literal, generic_variable, multiple_arity_generic_expression, simple_generic_expression, unary_generic_expression, variable_semantics); REFERENCE FROM ISO13584_expressions_schema -- ISO 13584-20 (abs_function AS abs_expression, acos_function AS acos_expression, and_expression, asin_function AS asin_expression, atan_function AS atan_expression, binary_boolean_expression, binary_function_call AS binary_numeric_call_expression, binary_numeric_expression, boolean_defined_function AS boolean_defined_expression, boolean_expression, boolean_literal, boolean_variable, comparison_equal, comparison_expression, comparison_greater, comparison_greater_equal, comparison_less, comparison_less_equal, comparison_not_equal, concat_expression, cos_function AS cos_expression, defined_function AS defined_expression, div_expression, equals_expression, exp_function AS exp_expression, expression, format_function AS format_expression, index_expression, int_literal, int_numeric_variable, int_value_function AS int_value_expression, integer_defined_function AS integer_defined_expression, interval_expression, length_function AS length_expression, like_expression, literal_number, log_function AS log_expression, log10_function AS log10_expression, log2_function AS log2_expression, maximum_function AS maximum_expression, minimum_function AS minimum_expression, minus_expression, minus_function AS unary_minus_expression, mod_expression, mult_expression, multiple_arity_boolean_expression, multiple_arity_function_call AS multiple_arity_numeric_call_expression, multiple_arity_numeric_expression, not_expression, numeric_defined_function AS numeric_defined_expression, numeric_expression, numeric_variable, odd_function AS odd_expression, or_expression, plus_expression, power_expression, real_defined_function AS real_defined_expression, real_literal, real_numeric_variable, simple_boolean_expression, simple_numeric_expression, simple_string_expression, sin_function AS sin_expression, slash_expression, sql_mappable_defined_function AS sql_mappable_defined_expression, square_root_function AS square_root_expression, string_defined_function AS string_defined_expression, string_expression, string_literal, string_variable, substring_expression, tan_function AS tan_expression, unary_boolean_expression, unary_function_call AS unary_numeric_call_expression, unary_numeric_expression, value_function AS value_expression, variable, xor_expression); REFERENCE FROM support_resource_schema -- ISO 10303-41 (label, text); REFERENCE FROM external_reference_schema -- ISO 10303-41 (externally_defined_item); REFERENCE FROM geometry_schema -- ISO 10303-42 (curve, dimension_of, point, surface, volume); CONSTANT schema_prefix : STRING := 'MATHEMATICAL_FUNCTIONS_SCHEMA.'; the_integers : elementary_space := make_elementary_space(es_integers); the_reals : elementary_space := make_elementary_space(es_reals); the_complex_numbers : elementary_space := make_elementary_space(es_complex_numbers); the_numbers : elementary_space := make_elementary_space(es_numbers); the_logicals : elementary_space := make_elementary_space(es_logicals); the_booleans : elementary_space := make_elementary_space(es_booleans); the_strings : elementary_space := make_elementary_space(es_strings); the_binarys : elementary_space := make_elementary_space(es_binarys); the_maths_spaces : elementary_space := make_elementary_space(es_maths_spaces); the_generics : elementary_space := make_elementary_space(es_generics); the_empty_space : finite_space := make_finite_space([]); the_nonnegative_reals : real_interval_from_min := make_real_interval_from_min(0.0, closed); the_zero_one_interval : finite_real_interval := make_finite_real_interval( 0.0, closed, 1.0, closed); the_zero_pi_interval : finite_real_interval := make_finite_real_interval( 0.0, closed, pi, closed); the_neg1_one_interval : finite_real_interval := make_finite_real_interval( -1.0, closed, 1.0, closed); the_neghalfpi_halfpi_interval : finite_real_interval := make_finite_real_interval( -0.5*pi, closed, 0.5*pi, closed); the_negpi_pi_interval : finite_real_interval := make_finite_real_interval( -pi, open, pi, closed); the_zero_tuple_space : listed_product_space := make_listed_product_space([]); the_tuples : extended_tuple_space := make_extended_tuple_space( the_zero_tuple_space, the_generics); the_integer_tuples : extended_tuple_space := make_extended_tuple_space( the_zero_tuple_space, the_integers); the_real_tuples : extended_tuple_space := make_extended_tuple_space( the_zero_tuple_space, the_reals); the_complex_tuples : extended_tuple_space := make_extended_tuple_space( the_zero_tuple_space, the_complex_numbers); the_empty_maths_tuple : maths_tuple := []; the_empty_maths_value : maths_value := the_empty_maths_tuple; the_empty_atom_based_tuple : atom_based_tuple := []; the_empty_atom_based_value : atom_based_value := the_empty_atom_based_tuple; END_CONSTANT; TYPE nonnegative_integer = INTEGER; WHERE nonnegativity: SELF >= 0; END_TYPE; TYPE positive_integer = nonnegative_integer; WHERE positivity: SELF > 0; END_TYPE; TYPE zero_or_one = nonnegative_integer; WHERE in_range: (SELF = 0) OR (SELF = 1); END_TYPE; TYPE one_or_two = positive_integer; WHERE in_range: (SELF = 1) OR (SELF = 2); END_TYPE; TYPE maths_number = NUMBER; END_TYPE; TYPE maths_real = REAL; END_TYPE; TYPE maths_integer = INTEGER; END_TYPE; TYPE maths_logical = LOGICAL; END_TYPE; TYPE maths_boolean = BOOLEAN; END_TYPE; TYPE maths_string = STRING; END_TYPE; TYPE maths_binary = BINARY; END_TYPE; TYPE maths_simple_atom = SELECT (maths_number, maths_real, maths_number, maths_logical, maths_boolean, maths_string, maths_binary); END_TYPE; TYPE maths_atom = SELECT (maths_simple_atom, maths_enum_atom); END_TYPE; TYPE atom_based_tuple = LIST OF atom_based_value; END_TYPE; TYPE atom_based_value = SELECT (maths_atom, atom_based_tuple); END_TYPE; TYPE maths_tuple = LIST [0:?] OF maths_value; END_TYPE; TYPE maths_value = SELECT (atom_based_value, maths_tuple, generic_expression); WHERE constancy: NOT ('GENERIC_EXPRESSION' IN stripped_typeof(SELF)) OR expression_is_constant(SELF); END_TYPE; TYPE maths_expression = SELECT (atom_based_value, maths_tuple, generic_expression); END_TYPE; TYPE maths_function_select = SELECT (maths_function, elementary_function_enumerators); END_TYPE; TYPE input_selector = positive_integer; END_TYPE; TYPE elementary_space_enumerators = ENUMERATION OF (es_numbers, es_complex_numbers, es_reals, es_integers, es_logicals, es_booleans, es_strings, es_binarys, es_maths_spaces, es_maths_functions, es_generics); END_TYPE; TYPE ordering_type = ENUMERATION OF (by_rows, by_columns); END_TYPE; TYPE lower_upper = ENUMERATION OF (lower, upper); END_TYPE; TYPE symmetry_type = ENUMERATION OF (identity, skew, hermitian, skew_hermitian); END_TYPE; TYPE elementary_function_enumerators = ENUMERATION OF (ef_and, ef_or, ef_not, ef_xor, ef_negate_i, ef_add_i, ef_subtract_i, ef_multiply_i, ef_divide_i, ef_mod_i, ef_exponentiate_i, ef_eq_i, ef_ne_i, ef_gt_i, ef_lt_i, ef_ge_i, ef_le_i, ef_abs_i, ef_max_i, ef_min_i, ef_if_i, ef_negate_r, ef_reciprocal_r, ef_add_r, ef_subtract_r, ef_multiply_r, ef_divide_r, ef_mod_r, ef_exponentiate_r, ef_exponentiate_ri, ef_eq_r, ef_ne_r, ef_gt_r, ef_lt_r, ef_ge_r, ef_le_r, ef_abs_r, ef_max_r, ef_min_r, ef_acos_r, ef_asin_r, ef_atan2_r, ef_cos_r, ef_exp_r, ef_ln_r, ef_log2_r, ef_log10_r, ef_sin_r, ef_sqrt_r, ef_tan_r, ef_if_r, ef_form_c, ef_rpart_c, ef_ipart_c, ef_negate_c, ef_reciprocal_c, ef_add_c, ef_subtract_c, ef_multiply_c, ef_divide_c, ef_exponentiate_c, ef_exponentiate_ci, ef_eq_c, ef_ne_c, ef_conjugate_c, ef_abs_c, ef_arg_c, ef_cos_c, ef_exp_c, ef_ln_c, ef_sin_c, ef_sqrt_c, ef_tan_c, ef_if_c, ef_subscript_s, ef_eq_s, ef_ne_s, ef_gt_s, ef_lt_s, ef_ge_s, ef_le_s, ef_subsequence_s, ef_concat_s, ef_size_s, ef_format, ef_value, ef_like, ef_if_s, ef_subscript_b, ef_eq_b, ef_ne_b, ef_gt_b, ef_lt_b, ef_ge_b, ef_le_b, ef_subsequence_b, ef_concat_b, ef_size_b, ef_if_b, ef_subscript_t, ef_eq_t, ef_ne_t, ef_concat_t, ef_size_t, ef_entuple, ef_detuple, ef_insert, ef_remove, ef_if_t, ef_sum_it, ef_product_it, ef_add_it, ef_subtract_it, ef_scalar_mult_it, ef_dot_prod_it, ef_sum_rt, ef_product_rt, ef_add_rt, ef_subtract_rt, ef_scalar_mult_rt, ef_dot_prod_rt, ef_norm_rt, ef_sum_ct, ef_product_ct, ef_add_ct, ef_subtract_ct, ef_scalar_mult_ct, ef_dot_prod_ct, ef_norm_ct, ef_if, ef_ensemble, ef_member_of); END_TYPE; TYPE open_closed = ENUMERATION OF (open, closed); END_TYPE; TYPE space_constraint_type = ENUMERATION OF (sc_equal, sc_subspace, sc_member); END_TYPE; TYPE repackage_options = ENUMERATION OF (ro_nochange, ro_wrap_as_tuple, ro_unwrap_tuple); END_TYPE; TYPE extension_options = ENUMERATION OF (eo_none, eo_cont, eo_cont_right, eo_cont_left); END_TYPE; TYPE maths_enum_atom = SELECT (elementary_space_enumerators, ordering_type, lower_upper, symmetry_type, elementary_function_enumerators, open_closed, space_constraint_type, repackage_options, extension_options); END_TYPE; TYPE dotted_express_identifier = STRING; WHERE syntax: dotted_identifiers_syntax(SELF); END_TYPE; TYPE express_identifier = dotted_express_identifier; WHERE syntax: dot_count(SELF) = 0; END_TYPE; TYPE product_space = SELECT (uniform_product_space, listed_product_space); END_TYPE; TYPE tuple_space = SELECT (product_space, extended_tuple_space); END_TYPE; TYPE maths_space_or_function = SELECT (maths_space, maths_function); END_TYPE; TYPE real_interval = SELECT (real_interval_from_min, real_interval_to_max, finite_real_interval, elementary_space); WHERE WR1: NOT ('ELEMENTARY_SPACE' IN stripped_typeof(SELF)) OR (SELF\elementary_space.space_id = es_reals); END_TYPE; ENTITY quantifier_expression ABSTRACT SUPERTYPE SUBTYPE OF (multiple_arity_generic_expression); variables : LIST [1:?] OF UNIQUE generic_variable; WHERE WR1: SIZEOF (QUERY (vrbl <* variables | NOT (vrbl IN SELF\multiple_arity_generic_expression.operands))) = 0; WR2: SIZEOF (QUERY (vrbl <* variables | NOT ((schema_prefix + 'BOUND_VARIABLE_SEMANTICS') IN TYPEOF (vrbl.interpretation.semantics)))) = 0; END_ENTITY; ENTITY dependent_variable_definition SUBTYPE OF (unary_generic_expression); name : label; description : text; END_ENTITY; ENTITY bound_variable_semantics SUBTYPE OF (variable_semantics); END_ENTITY; ENTITY free_variable_semantics SUBTYPE OF (variable_semantics); END_ENTITY; ENTITY complex_number_literal SUBTYPE OF (generic_literal); real_part : REAL; imag_part : REAL; END_ENTITY; ENTITY logical_literal SUBTYPE OF (generic_literal); lit_value : LOGICAL; END_ENTITY; ENTITY binary_literal SUBTYPE OF (generic_literal); lit_value : BINARY; END_ENTITY; ENTITY maths_enum_literal SUBTYPE OF (generic_literal); lit_value : maths_enum_atom; END_ENTITY; ENTITY real_tuple_literal SUBTYPE OF (generic_literal); lit_value : LIST [1:?] OF REAL; END_ENTITY; ENTITY integer_tuple_literal SUBTYPE OF (generic_literal); lit_value : LIST [1:?] OF INTEGER; END_ENTITY; ENTITY atom_based_literal SUBTYPE OF (generic_literal); lit_value : atom_based_value; END_ENTITY; ENTITY maths_tuple_literal SUBTYPE OF (generic_literal); lit_value : LIST OF maths_value; END_ENTITY; ENTITY maths_variable SUBTYPE OF (generic_variable); values_space : maths_space; name : label; WHERE WR1: expression_is_constant(values_space); END_ENTITY; ENTITY maths_real_variable SUBTYPE OF (maths_variable, real_numeric_variable); WHERE WR1: subspace_of_es(SELF\maths_variable.values_space,es_reals); END_ENTITY; ENTITY maths_integer_variable SUBTYPE OF (maths_variable, int_numeric_variable); WHERE WR1: subspace_of_es(SELF\maths_variable.values_space,es_integers); END_ENTITY; ENTITY maths_boolean_variable SUBTYPE OF (maths_variable, boolean_variable); WHERE WR1: subspace_of_es(SELF\maths_variable.values_space,es_booleans); END_ENTITY; ENTITY maths_string_variable SUBTYPE OF (maths_variable, string_variable); WHERE WR1: subspace_of_es(SELF\maths_variable.values_space,es_strings); END_ENTITY; ENTITY function_application SUBTYPE OF (multiple_arity_generic_expression); func : maths_function_select; arguments : LIST [1:?] OF maths_expression; DERIVE SELF\multiple_arity_generic_expression.operands : LIST [2:?] OF generic_expression := [convert_to_maths_function(func)] + convert_to_operands(arguments); WHERE WR1: function_applicability(func, arguments); END_ENTITY; ENTITY maths_space ABSTRACT SUPERTYPE OF (ONEOF (elementary_space, finite_integer_interval, integer_interval_from_min, integer_interval_to_max, finite_real_interval, real_interval_from_min, real_interval_to_max, cartesian_complex_number_region, polar_complex_number_region, finite_space, uniform_product_space, listed_product_space, extended_tuple_space, function_space)) SUBTYPE OF (generic_expression); END_ENTITY; ENTITY elementary_space SUBTYPE OF (maths_space, generic_literal); space_id : elementary_space_enumerators; END_ENTITY; ENTITY finite_integer_interval SUBTYPE OF (maths_space, generic_literal); min : INTEGER; max : INTEGER; DERIVE size : positive_integer := max - min + 1; WHERE WR1: min <= max; END_ENTITY; ENTITY integer_interval_from_min SUBTYPE OF (maths_space, generic_literal); min : INTEGER; END_ENTITY; ENTITY integer_interval_to_max SUBTYPE OF (maths_space, generic_literal); max : INTEGER; END_ENTITY; ENTITY finite_real_interval SUBTYPE OF (maths_space, generic_literal); min : REAL; min_closure : open_closed; max : REAL; max_closure : open_closed; WHERE WR1: min < max; END_ENTITY; ENTITY real_interval_from_min SUBTYPE OF (maths_space, generic_literal); min : REAL; min_closure : open_closed; END_ENTITY; ENTITY real_interval_to_max SUBTYPE OF (maths_space, generic_literal); max : REAL; max_closure : open_closed; END_ENTITY; ENTITY cartesian_complex_number_region SUBTYPE OF (maths_space, generic_literal); real_constraint : real_interval; imag_constraint : real_interval; WHERE WR1: min_exists(real_constraint) OR max_exists(real_constraint) OR min_exists(imag_constraint) OR max_exists(imag_constraint); END_ENTITY; ENTITY polar_complex_number_region SUBTYPE OF (maths_space, generic_literal); centre : complex_number_literal; distance_constraint : real_interval; direction_constraint : finite_real_interval; WHERE WR1: min_exists(distance_constraint) AND (real_min(distance_constraint) >= 0.0); WR2: {-PI <= direction_constraint.min < PI}; WR3: direction_constraint.max - direction_constraint.min <= 2.0*PI; WR4: (direction_constraint.max - direction_constraint.min < 2.0*PI) OR (direction_constraint.min_closure = open); WR5: (direction_constraint.max - direction_constraint.min < 2.0*PI) OR (direction_constraint.max_closure = open) OR (direction_constraint.min = -PI); WR6: (real_min(distance_constraint) > 0.0) OR max_exists(distance_constraint) OR (direction_constraint.max - direction_constraint.min < 2.0*PI) OR (direction_constraint.max_closure = open); END_ENTITY; ENTITY finite_space SUBTYPE OF (maths_space, generic_literal); members : SET OF maths_value; WHERE WR1: VALUE_UNIQUE(members); WR2: SIZEOF (QUERY (expr <* QUERY (member <* members | 'ISO13584_GENERIC_EXPRESSIONS_SCHEMA.GENERIC_EXPRESSION' IN TYPEOF (member)) | NOT expression_is_constant(expr))) = 0; WR3: no_cyclic_space_reference(SELF, []); END_ENTITY; ENTITY uniform_product_space SUBTYPE OF (maths_space, generic_literal); base : maths_space; exponent : positive_integer; WHERE WR1: expression_is_constant(base); WR2: no_cyclic_space_reference(SELF, []); WR3: base <> the_empty_space; END_ENTITY; ENTITY listed_product_space SUBTYPE OF (maths_space, generic_literal); factors : LIST OF maths_space; WHERE WR1: SIZEOF (QUERY (space <* factors | NOT (expression_is_constant(space)))) = 0; WR2: no_cyclic_space_reference(SELF, []); WR3: NOT (the_empty_space IN factors); END_ENTITY; ENTITY extended_tuple_space SUBTYPE OF (maths_space, generic_literal); base : product_space; extender : maths_space; WHERE WR1: expression_is_constant(base) AND expression_is_constant(extender); WR2: no_cyclic_space_reference(SELF, []); WR3: extender <> the_empty_space; END_ENTITY; ENTITY function_space SUBTYPE OF (maths_space, generic_literal); domain_constraint : space_constraint_type; domain_argument : maths_space; range_constraint : space_constraint_type; range_argument : maths_space; WHERE WR1: expression_is_constant(domain_argument) AND expression_is_constant(range_argument); WR2: (domain_argument <> the_empty_space) AND (range_argument <> the_empty_space); WR3: (domain_constraint <> sc_member) OR NOT member_of(the_empty_space,domain_argument); WR4: (range_constraint <> sc_member) OR NOT member_of(the_empty_space,range_argument); WR5: NOT (any_space_satisfies(domain_constraint,domain_argument) AND any_space_satisfies(range_constraint,range_argument)); END_ENTITY; ENTITY maths_function ABSTRACT SUPERTYPE OF (ONEOF (finite_function, constant_function, selector_function, elementary_function, restriction_function, repackaging_function, reindexed_array_function, series_composed_function, parallel_composed_function, explicit_table_function, homogeneous_linear_function, general_linear_function, b_spline_basis, b_spline_function, rationalize_function, partial_derivative_function, definite_integral_function, abstracted_expression_function, expression_denoted_function, imported_point_function, imported_curve_function, imported_surface_function, imported_volume_function, application_defined_function)) SUBTYPE OF (generic_expression); DERIVE domain : tuple_space := derive_function_domain(SELF); range : tuple_space := derive_function_range(SELF); END_ENTITY; ENTITY finite_function SUBTYPE OF (maths_function, generic_literal); pairs : SET [1:?] OF LIST [2:2] OF maths_value; WHERE WR1: VALUE_UNIQUE(list_selected_components(pairs, 1)); END_ENTITY; ENTITY constant_function SUBTYPE OF (maths_function, generic_literal); sole_output : maths_value; source_of_domain : maths_space_or_function; WHERE WR1: no_cyclic_domain_reference(source_of_domain, [SELF]); WR2: expression_is_constant(domain_from(source_of_domain)); END_ENTITY; ENTITY selector_function SUBTYPE OF (maths_function, generic_literal); selector : input_selector; source_of_domain : maths_space_or_function; WHERE WR1: no_cyclic_domain_reference(source_of_domain, [SELF]); WR2: expression_is_constant(domain_from(source_of_domain)); END_ENTITY; ENTITY elementary_function SUBTYPE OF (maths_function, generic_literal); func_id : elementary_function_enumerators; END_ENTITY; ENTITY restriction_function SUBTYPE OF (maths_function, unary_generic_expression); SELF\unary_generic_expression.operand : maths_space; END_ENTITY; ENTITY repackaging_function SUBTYPE OF (maths_function, unary_generic_expression); SELF\unary_generic_expression.operand : maths_function; input_repack : repackage_options; output_repack : repackage_options; selected_output : nonnegative_integer; WHERE WR1: (input_repack <> ro_wrap_as_tuple) OR ((space_dimension(operand.domain) = 1) AND ((schema_prefix + 'TUPLE_SPACE') IN TYPEOF (factor1(operand.domain)))); WR2: (output_repack <> ro_unwrap_tuple) OR ((space_dimension(operand.range) = 1) AND ((schema_prefix + 'TUPLE_SPACE') IN TYPEOF (factor1(operand.range)))); WR3: selected_output <= space_dimension( repackage( operand.range, output_repack)); END_ENTITY; ENTITY reindexed_array_function SUBTYPE OF (maths_function, unary_generic_expression); SELF\unary_generic_expression.operand : maths_function; starting_indices : LIST [1:?] OF INTEGER; WHERE WR1: function_is_array(SELF\unary_generic_expression.operand); WR2: SIZEOF(starting_indices) = SIZEOF(shape_of_array( SELF\unary_generic_expression.operand)); END_ENTITY; ENTITY series_composed_function SUBTYPE OF (maths_function, multiple_arity_generic_expression); SELF\multiple_arity_generic_expression.operands : LIST [2:?] of maths_function; WHERE WR1: composable_sequence(SELF\multiple_arity_generic_expression.operands); END_ENTITY; ENTITY parallel_composed_function SUBTYPE OF (maths_function, multiple_arity_generic_expression); source_of_domain : maths_space_or_function; prep_functions : LIST [1:?] OF maths_function; final_function : maths_function_select; DERIVE SELF\multiple_arity_generic_expression.operands : LIST [2:?] of generic_expression := convert_to_operands_prcmfn(source_of_domain, prep_functions, final_function); WHERE WR1: no_cyclic_domain_reference(source_of_domain, [SELF]); WR2: expression_is_constant(domain_from(source_of_domain)); WR3: parallel_composed_function_domain_check(domain_from(source_of_domain), prep_functions); WR4: parallel_composed_function_composability_check(prep_functions, final_function); END_ENTITY; ENTITY explicit_table_function ABSTRACT SUPERTYPE OF (ONEOF (listed_real_data, listed_integer_data, listed_logical_data, listed_string_data, listed_complex_number_data, listed_data, externally_listed_data, linearized_table_function, basic_sparse_matrix)) SUBTYPE OF (maths_function); index_base : zero_or_one; shape : LIST [1:?] OF positive_integer; END_ENTITY; ENTITY listed_real_data SUBTYPE OF (explicit_table_function, generic_literal); values : LIST [1:?] OF REAL; DERIVE self\explicit_table_function.shape : LIST [1:?] OF positive_integer := [SIZEOF (values)]; END_ENTITY; ENTITY listed_integer_data SUBTYPE OF (explicit_table_function, generic_literal); values : LIST [1:?] OF INTEGER; DERIVE self\explicit_table_function.shape : LIST [1:?] OF positive_integer := [SIZEOF (values)]; END_ENTITY; ENTITY listed_logical_data SUBTYPE OF(explicit_table_function, generic_literal); values : LIST [1:?] OF LOGICAL; DERIVE self\explicit_table_function.shape : LIST [1:?] OF positive_integer := [SIZEOF (values)]; END_ENTITY; ENTITY listed_string_data SUBTYPE OF (explicit_table_function, generic_literal); values : LIST [1:?] OF STRING; DERIVE self\explicit_table_function.shape : LIST [1:?] OF positive_integer := [SIZEOF (values)]; END_ENTITY; ENTITY listed_complex_number_data SUBTYPE OF (explicit_table_function, generic_literal); values : LIST [2:?] OF REAL; DERIVE self\explicit_table_function.shape : LIST [1:?] OF positive_integer := [SIZEOF (values)/2]; WHERE WR1: NOT ODD (SIZEOF (values)); END_ENTITY; ENTITY listed_data SUBTYPE OF (explicit_table_function, generic_literal); values : LIST [1:?] OF maths_value; value_range : maths_space; DERIVE SELF\explicit_table_function.shape : LIST [1:?] OF positive_integer := [SIZEOF (values)]; WHERE WR1: expression_is_constant(value_range); WR2: SIZEOF (QUERY (val <* values | NOT (member_of( val, value_range)))) = 0; END_ENTITY; ENTITY externally_listed_data SUBTYPE OF (explicit_table_function, generic_literal, externally_defined_item); value_range : maths_space; WHERE WR1: expression_is_constant(value_range); END_ENTITY; ENTITY linearized_table_function SUPERTYPE OF (ONEOF (standard_table_function, regular_table_function, triangular_matrix, symmetric_matrix, banded_matrix)) SUBTYPE OF (explicit_table_function, unary_generic_expression); SELF\unary_generic_expression.operand : maths_function; first : integer; DERIVE source : maths_function := SELF\unary_generic_expression.operand; WHERE WR1: function_is_1d_array(source); WR2: member_of(first, source.domain); END_ENTITY; ENTITY standard_table_function SUBTYPE OF (linearized_table_function); order : ordering_type; WHERE WR1: extremal_position_check(SELF); END_ENTITY; ENTITY regular_table_function SUBTYPE OF (linearized_table_function); increments : LIST [1:?] OF INTEGER; WHERE WR1: SIZEOF (increments) = SIZEOF (self\explicit_table_function.shape); WR2: extremal_position_check(self); END_ENTITY; ENTITY triangular_matrix SUBTYPE OF (linearized_table_function); default_entry : maths_value; lo_up : lower_upper; order : ordering_type; WHERE WR1: SIZEOF (SELF\explicit_table_function.shape) = 2; WR2: member_of(default_entry, SELF\maths_function.range); END_ENTITY; ENTITY strict_triangular_matrix SUBTYPE OF (triangular_matrix); main_diagonal_value : maths_value; END_ENTITY; ENTITY symmetric_matrix SUBTYPE OF (linearized_table_function); symmetry : symmetry_type; triangle : lower_upper; order : ordering_type; WHERE WR1: SIZEOF (SELF\explicit_table_function.shape) = 2; WR2: SELF\explicit_table_function.shape[1] = SELF\explicit_table_function.shape[2]; WR3: NOT (symmetry = skew) OR ( (space_dimension(SELF\linearized_table_function.source.range) = 1) AND subspace_of_es(factor1(SELF\linearized_table_function.source.range), es_numbers)); WR4: NOT ((symmetry = hermitian) OR (symmetry = skew_hermitian)) OR ( (space_dimension(SELF\linearized_table_function.source.range) = 1) AND subspace_of_es(factor1(SELF\linearized_table_function.source.range), es_complex_numbers)); END_ENTITY; ENTITY symmetric_banded_matrix SUBTYPE OF (symmetric_matrix); default_entry : maths_value; above : nonnegative_integer; WHERE WR1: member_of(default_entry, factor1(SELF\linearized_table_function.source.range)); END_ENTITY; ENTITY banded_matrix SUBTYPE OF (linearized_table_function); default_entry : maths_value; below : integer; above : integer; order : ordering_type; WHERE WR1: SIZEOF (self\explicit_table_function.shape) = 2; WR2: -below <= above; WR3: member_of(default_entry, factor1(SELF\linearized_table_function.source.range)); END_ENTITY; ENTITY basic_sparse_matrix SUBTYPE OF (explicit_table_function, multiple_arity_generic_expression); SELF\multiple_arity_generic_expression.operands : LIST [3:3] OF maths_function; default_entry : maths_value; order : ordering_type; DERIVE index : maths_function := SELF\multiple_arity_generic_expression.operands[1]; loc : maths_function := SELF\multiple_arity_generic_expression.operands[2]; val : maths_function := SELF\multiple_arity_generic_expression.operands[3]; WHERE WR1: function_is_1d_table(index); WR2: function_is_1d_table(loc); WR3: function_is_1d_table(val); WR4: check_sparse_index_domain(index.domain, index_base, shape, order); WR5: check_sparse_index_to_loc(index.range, loc.domain); WR6: loc.domain = val.domain; WR7: check_sparse_loc_range(loc.range, index_base, shape, order); WR8: member_of(default_entry, val.range); END_ENTITY; ENTITY homogeneous_linear_function SUBTYPE OF (maths_function, unary_generic_expression); SELF\unary_generic_expression.operand : maths_function; sum_index : one_or_two; DERIVE mat : maths_function := SELF\unary_generic_expression.operand; WHERE WR1: function_is_2d_table(mat); WR2: (space_dimension(mat.range) = 1) AND subspace_of_es(factor1(mat.range),es_numbers); END_ENTITY; ENTITY general_linear_function SUBTYPE OF (maths_function, unary_generic_expression); SELF\unary_generic_expression.operand : maths_function; sum_index : one_or_two; DERIVE mat : maths_function := SELF\unary_generic_expression.operand; WHERE WR1: function_is_2d_table(mat); WR2: (space_dimension(mat.range) = 1) AND subspace_of_es(factor1(mat.range),es_numbers); END_ENTITY; ENTITY b_spline_basis SUBTYPE OF (maths_function, generic_literal); degree : nonnegative_integer; repeated_knots : LIST [2:?] OF REAL; DERIVE order : positive_integer := degree + 1; num_basis : positive_integer := SIZEOF (repeated_knots) - order; WHERE WR1: num_basis >= order; WR2: nondecreasing(repeated_knots); WR3: repeated_knots[order] < repeated_knots[num_basis+1]; END_ENTITY; ENTITY b_spline_function SUBTYPE OF (maths_function, unary_generic_expression); SELF\unary_generic_expression.operand : maths_function; basis : LIST [1:?] OF b_spline_basis; DERIVE coef : maths_function := SELF\unary_generic_expression.operand; WHERE WR1: function_is_table(coef); WR2: (space_dimension(coef.range) = 1) AND (number_superspace_of(factor1(coef.range)) = the_reals); WR3: SIZEOF (basis) <= SIZEOF (shape_of_array(coef)); WR4: compare_basis_and_coef(basis, coef); END_ENTITY; ENTITY rationalize_function SUBTYPE OF (maths_function, unary_generic_expression); SELF\unary_generic_expression.operand : maths_function; DERIVE fun : maths_function := SELF\unary_generic_expression.operand; WHERE WR1: (space_dimension(fun.domain) = 1) AND (space_dimension(fun.range) = 1); WR2: number_tuple_subspace_check(factor1(fun.range)); WR3: space_dimension(factor1(fun.range)) > 1; END_ENTITY; ENTITY partial_derivative_function SUBTYPE OF (maths_function, unary_generic_expression); SELF\unary_generic_expression.operand : maths_function; d_variables : LIST [1:?] OF input_selector; extension : extension_options; DERIVE derivand : maths_function := SELF\unary_generic_expression.operand; WHERE WR1: space_is_continuum (derivand.range); WR2: partial_derivative_check (derivand.domain, d_variables); END_ENTITY; ENTITY partial_derivative_expression SUBTYPE OF (unary_generic_expression); d_variables : LIST [1:?] OF maths_variable; extension : extension_options; DERIVE derivand : generic_expression := SELF\unary_generic_expression.operand; WHERE WR1: has_values_space (derivand); WR2: space_is_continuum (values_space_of (derivand)); WR3: SIZEOF (QUERY (vbl <* d_variables | (NOT subspace_of (values_space_of (vbl), the_reals)) AND (NOT subspace_of (values_space_of (vbl), the_complex_numbers)) )) = 0; END_ENTITY; ENTITY definite_integral_function SUBTYPE OF (maths_function, unary_generic_expression); SELF\unary_generic_expression.operand : maths_function; variable_of_integration : input_selector; lower_limit_neg_infinity : BOOLEAN; upper_limit_pos_infinity : BOOLEAN; DERIVE integrand : maths_function := SELF\unary_generic_expression.operand; WHERE WR1: space_is_continuum (integrand.range); WR2: definite_integral_check (integrand.domain, variable_of_integration, lower_limit_neg_infinity, upper_limit_pos_infinity); END_ENTITY; ENTITY definite_integral_expression SUBTYPE OF (quantifier_expression); lower_limit_neg_infinity : BOOLEAN; upper_limit_pos_infinity : BOOLEAN; DERIVE integrand : generic_expression := SELF\multiple_arity_generic_expression.operands[1]; variable_of_integration : maths_variable := SELF\multiple_arity_generic_expression.operands[2]; SELF\quantifier_expression.variables : LIST [1:1] OF UNIQUE generic_variable := [variable_of_integration]; WHERE WR1: has_values_space (integrand); WR2: space_is_continuum (values_space_of (integrand)); WR3: definite_integral_expr_check (SELF\multiple_arity_generic_expression.operands, lower_limit_neg_infinity, upper_limit_pos_infinity); END_ENTITY; ENTITY abstracted_expression_function SUBTYPE OF (maths_function, quantifier_expression); DERIVE SELF\quantifier_expression.variables : LIST [1:?] OF UNIQUE generic_variable := remove_first(SELF\multiple_arity_generic_expression.operands); expr : generic_expression := SELF\multiple_arity_generic_expression.operands[1]; WHERE WR1: SIZEOF (QUERY ( operand <* SELF\multiple_arity_generic_expression.operands | NOT ( has_values_space( operand)))) = 0; END_ENTITY; ENTITY expression_denoted_function SUBTYPE OF (maths_function, unary_generic_expression); DERIVE expr : generic_expression := SELF\unary_generic_expression.operand; WHERE WR1: (schema_prefix + 'FUNCTION_SPACE') IN TYPEOF (values_space_of(expr)); END_ENTITY; ENTITY imported_point_function SUBTYPE OF (maths_function, generic_literal); geometry : point; END_ENTITY; ENTITY imported_curve_function SUBTYPE OF (maths_function, generic_literal); geometry : curve; parametric_domain : tuple_space; WHERE WR1: expression_is_constant(parametric_domain); END_ENTITY; ENTITY imported_surface_function SUBTYPE OF (maths_function, generic_literal); geometry : surface; parametric_domain : tuple_space; WHERE WR1: expression_is_constant(parametric_domain); END_ENTITY; ENTITY imported_volume_function SUBTYPE OF (maths_function, generic_literal); geometry : volume; parametric_domain : tuple_space; WHERE WR1: expression_is_constant(parametric_domain); END_ENTITY; ENTITY application_defined_function SUBTYPE OF (maths_function); explicit_domain : tuple_space; explicit_range : tuple_space; parameters : LIST OF maths_value; WHERE WR1: expression_is_constant(explicit_domain); WR2: expression_is_constant(explicit_range); END_ENTITY; ENTITY mathematical_description; described : maths_expression; describing : STRING; encoding : label; END_ENTITY; FUNCTION all_members_of_es(sv : SET OF maths_value; es : elementary_space_enumerators) : LOGICAL; CONSTANT base_types : SET OF STRING := ['NUMBER','COMPLEX_NUMBER_LITERAL','REAL', 'INTEGER','LOGICAL','BOOLEAN','STRING','BINARY','MATHS_SPACE', 'MATHS_FUNCTION','LIST','ELEMENTARY_SPACE_ENUMERATORS','ORDERING_TYPE', 'LOWER_UPPER','SYMMETRY_TYPE','ELEMENTARY_FUNCTION_ENUMERATORS', 'OPEN_CLOSED','SPACE_CONSTRAINT_TYPE','REPACKAGE_OPTIONS', 'EXTENSION_OPTIONS']; END_CONSTANT; LOCAL v : maths_value; key_type : STRING := ''; types : SET OF STRING; ge : generic_expression; cum : LOGICAL := TRUE; vspc : maths_space; END_LOCAL; IF NOT EXISTS (sv) OR NOT EXISTS (es) THEN RETURN (FALSE); END_IF; CASE es OF es_numbers : key_type := 'NUMBER'; es_complex_numbers : key_type := 'COMPLEX_NUMBER_LITERAL'; es_reals : key_type := 'REAL'; es_integers : key_type := 'INTEGER'; es_logicals : key_type := 'LOGICAL'; es_booleans : key_type := 'BOOLEAN'; es_strings : key_type := 'STRING'; es_binarys : key_type := 'BINARY'; es_maths_spaces : key_type := 'MATHS_SPACE'; es_maths_functions : key_type := 'MATHS_FUNCTION'; es_generics : RETURN (TRUE); END_CASE; REPEAT i := 1 TO SIZEOF (sv); IF NOT EXISTS (sv[i]) THEN RETURN (FALSE); END_IF; v := simplify_maths_value(sv[i]); types := stripped_typeof(v); IF key_type IN types THEN SKIP; END_IF; IF (es = es_numbers) AND ('COMPLEX_NUMBER_LITERAL' IN types) THEN SKIP; END_IF; IF SIZEOF (base_types * types) > 0 THEN RETURN (FALSE); END_IF; -- Must be a generic_expression which doesn't simplify and which is not a -- complex_number_literal, maths_space, or maths_function. ge := v; IF has_values_space(ge) THEN vspc := values_space_of(ge); IF NOT subspace_of_es(vspc,es) THEN IF NOT compatible_spaces(vspc,make_elementary_space(es)) THEN RETURN (FALSE); END_IF; cum := UNKNOWN; END_IF; ELSE cum := UNKNOWN; END_IF; IF cum = FALSE THEN RETURN (FALSE); END_IF; END_REPEAT; RETURN (cum); END_FUNCTION; -- all_members_of_es FUNCTION any_space_satisfies(sc : space_constraint_type; spc : maths_space) : BOOLEAN; LOCAL spc_id : elementary_space_enumerators; END_LOCAL; IF (sc = sc_equal) OR NOT ('ELEMENTARY_SPACE' IN stripped_typeof(spc)) THEN RETURN (FALSE); END_IF; spc_id := spc\elementary_space.space_id; IF sc = sc_subspace THEN RETURN (bool(spc_id = es_generics)); END_IF; IF sc = sc_member THEN RETURN (bool((spc_id = es_generics) OR (spc_id = es_maths_spaces))); END_IF; -- Should be unreachable. RETURN (?); END_FUNCTION; -- any_space_satisfies FUNCTION assoc_product_space(ts1, ts2 : tuple_space) : tuple_space; LOCAL types1 : SET OF STRING := stripped_typeof (ts1); types2 : SET OF STRING := stripped_typeof (ts2); up1, up2 : uniform_product_space := make_uniform_product_space(the_reals,1); lp1, lp2, lps : listed_product_space := the_zero_tuple_space; et1, et2, ets : extended_tuple_space := the_tuples; use_up1, use_up2, use_lp1, use_lp2 : BOOLEAN; factors : LIST OF maths_space := []; tspace : tuple_space; END_LOCAL; -- Identify type of first operand IF 'UNIFORM_PRODUCT_SPACE' IN types1 THEN up1 := ts1; use_up1 := true; use_lp1 := false; ELSE IF 'LISTED_PRODUCT_SPACE' IN types1 THEN lp1 := ts1; use_up1 := false; use_lp1 := true; ELSE IF NOT ('EXTENDED_TUPLE_SPACE' IN types1) THEN -- Unreachable when this function was written. RETURN (?); END_IF; et1 := ts1; use_up1 := false; use_lp1 := false; END_IF; END_IF; -- Identify type of second operand IF 'UNIFORM_PRODUCT_SPACE' IN types2 THEN up2 := ts2; use_up2 := true; use_lp2 := false; ELSE IF 'LISTED_PRODUCT_SPACE' IN types2 THEN lp2 := ts2; use_up2 := false; use_lp2 := true; ELSE IF NOT ('EXTENDED_TUPLE_SPACE' IN types2) THEN -- Unreachable when this function was written. RETURN (?); END_IF; et2 := ts2; use_up2 := false; use_lp2 := false; END_IF; END_IF; -- Construction for each combination of cases IF use_up1 THEN IF use_up2 THEN IF up1.base = up2.base THEN tspace := make_uniform_product_space(up1.base, up1.exponent + up2.exponent); ELSE factors := [up1.base : up1.exponent, up2.base : up2.exponent]; tspace := make_listed_product_space(factors); END_IF; ELSE IF use_lp2 THEN -- Avoid compiler confusion by breaking into two lines. factors := [up1.base : up1.exponent]; factors := factors + lp2.factors; tspace := make_listed_product_space(factors); ELSE tspace := assoc_product_space(up1, et2.base); tspace := make_extended_tuple_space(tspace, et2.extender); END_IF; END_IF; ELSE IF use_lp1 THEN IF use_up2 THEN -- Avoid compiler confusion by breaking into two lines. factors := [up2.base : up2.exponent]; factors := lp1.factors + factors; tspace := make_listed_product_space(factors); ELSE IF use_lp2 THEN tspace := make_listed_product_space(lp1.factors + lp2.factors); ELSE tspace := assoc_product_space(lp1, et2.base); tspace := make_extended_tuple_space(tspace, et2.extender); END_IF; END_IF; ELSE IF use_up2 THEN IF et1.extender = up2.base THEN tspace := assoc_product_space(et1.base, up2); tspace := make_extended_tuple_space(tspace, et1.extender); ELSE -- No subtype is available to represent this cartesian product. RETURN (?); END_IF; ELSE IF use_lp2 THEN factors := lp2.factors; REPEAT i := 1 TO SIZEOF (factors); IF et1.extender <> factors[i] THEN -- No subtype available to represent this cartesian product. RETURN (?); END_IF; END_REPEAT; tspace := assoc_product_space(et1.base, lp2); tspace := make_extended_tuple_space(tspace, et1.extender); ELSE IF et1.extender = et2.extender THEN -- Next line may assign indeterminate (?) to tspace. tspace := assoc_product_space(et1, et2.base); ELSE -- No subtype available to represent this cartesian product. RETURN (?); END_IF; END_IF; END_IF; END_IF; END_IF; RETURN (tspace); END_FUNCTION; -- assoc_product_space FUNCTION atan2(y, x : REAL) : REAL; LOCAL r : REAL; END_LOCAL; IF (y = 0.0) AND (x = 0.0) THEN RETURN (?); END_IF; r := atan(y,x); IF x < 0.0 THEN IF y < 0.0 THEN r := r - PI; ELSE r := r + PI; END_IF; END_IF; RETURN (r); END_FUNCTION; -- atan2 FUNCTION bool(lgcl: LOGICAL) : BOOLEAN; IF NOT EXISTS (lgcl) THEN RETURN (FALSE); END_IF; IF lgcl <> TRUE THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; -- bool FUNCTION check_sparse_index_domain(idxdom : tuple_space; base : zero_or_one; shape : LIST [1:?] OF positive_integer; order : ordering_type) : BOOLEAN; LOCAL mthspc : maths_space; interval : finite_integer_interval; i : INTEGER; END_LOCAL; mthspc := factor1(idxdom); -- A consequence of WR1 of basic_sparse_matrix is that here we need only -- consider the case that mthspc is a finite integer interval and is the only -- factor space of idxdom. interval := mthspc; IF order = by_rows THEN i := 1; ELSE i := 2; END_IF; RETURN (bool((interval.min <= base) AND (interval.max >= base + shape[i]))); -- The index function is evaluated at (base+shape[i]) when determining the -- upper search bound for entries of the last row or column, respectively. END_FUNCTION; -- check_sparse_index_domain; FUNCTION check_sparse_loc_range(locrng : tuple_space; base : zero_or_one; shape : LIST [1:?] OF positive_integer; order : ordering_type) : BOOLEAN; LOCAL mthspc : maths_space; interval : finite_integer_interval; i : INTEGER; END_LOCAL; IF space_dimension(locrng) <> 1 THEN RETURN (FALSE); END_IF; mthspc := factor1(locrng); IF NOT ((schema_prefix + 'FINITE_INTEGER_INTERVAL') IN TYPEOF (mthspc)) THEN RETURN (FALSE); END_IF; interval := mthspc; IF order = by_rows THEN i := 2; ELSE i := 1; END_IF; RETURN (bool((interval.min >= base) AND (interval.max <= base + shape[i] - 1))); END_FUNCTION; -- check_sparse_loc_range; FUNCTION check_sparse_index_to_loc(index_range, loc_domain : tuple_space) : BOOLEAN; LOCAL temp : maths_space; idx_rng_itvl, loc_dmn_itvl : finite_integer_interval; END_LOCAL; temp := factor1 (index_range); IF (schema_prefix + 'TUPLE_SPACE') IN TYPEOF (temp) THEN temp := factor1 (temp); END_IF; IF NOT ((schema_prefix + 'FINITE_INTEGER_INTERVAL') IN TYPEOF (temp)) THEN RETURN (FALSE); END_IF; idx_rng_itvl := temp; temp := factor1 (loc_domain); IF (schema_prefix + 'TUPLE_SPACE') IN TYPEOF (temp) THEN temp := factor1 (temp); END_IF; IF NOT ((schema_prefix + 'FINITE_INTEGER_INTERVAL') IN TYPEOF (temp)) THEN RETURN (FALSE); END_IF; loc_dmn_itvl := temp; RETURN (bool((loc_dmn_itvl.min <= idx_rng_itvl.min) AND (idx_rng_itvl.max <= loc_dmn_itvl.max+1))); END_FUNCTION; -- check_sparse_index_to_loc FUNCTION compare_basis_and_coef(basis : LIST [1:?] OF b_spline_basis; coef : maths_function) : BOOLEAN; LOCAL shape : LIST OF positive_integer; END_LOCAL; IF NOT EXISTS (basis) OR NOT EXISTS (coef) THEN RETURN (FALSE); END_IF; shape := shape_of_array(coef); IF NOT EXISTS (shape) THEN RETURN (FALSE); END_IF; IF SIZEOF (shape) < SIZEOF (basis) THEN RETURN (FALSE); END_IF; REPEAT i := 1 TO SIZEOF (basis); IF (basis[i].num_basis = shape[i]) <> TRUE THEN RETURN (FALSE); END_IF; END_REPEAT; RETURN (TRUE); END_FUNCTION; -- compare_basis_and_coef FUNCTION compare_list_and_value(lv : LIST OF GENERIC:G; op : elementary_function_enumerators; v : GENERIC:G) : BOOLEAN; IF NOT EXISTS (lv) OR NOT EXISTS (op) OR NOT EXISTS (v) THEN RETURN (FALSE); END_IF; REPEAT i := 1 TO SIZEOF (lv); IF NOT compare_values(lv[i], op, v) THEN RETURN (FALSE); END_IF; END_REPEAT; RETURN (TRUE); END_FUNCTION; -- compare_list_and_value FUNCTION compare_values(v1 : GENERIC:G; op : elementary_function_enumerators; v2 : GENERIC:G) : BOOLEAN; -- This algorithm assumes a comparison between "incompatible" types will -- produce the indeterminate value (or UNKNOWN?). LOCAL logl : LOGICAL := UNKNOWN; END_LOCAL; IF NOT EXISTS (v1) OR NOT EXISTS (op) OR NOT EXISTS (v2) THEN RETURN (FALSE); END_IF; CASE op OF ef_eq_i : logl := (v1 = v2); ef_ne_i : logl := (v1 <> v2); ef_gt_i : logl := (v1 > v2); ef_lt_i : logl := (v1 < v2); ef_ge_i : logl := (v1 >= v2); ef_le_i : logl := (v1 <= v2); END_CASE; IF EXISTS (logl) THEN IF logl = TRUE THEN RETURN (TRUE); END_IF; END_IF; RETURN (FALSE); END_FUNCTION; -- compare_values FUNCTION compatible_complex_number_regions(sp1, sp2 : maths_space) : BOOLEAN; LOCAL typenames : SET OF string := stripped_typeof (sp1); crgn1, crgn2 : cartesian_complex_number_region; prgn1, prgn2, prgn1c2, prgn2c1 : polar_complex_number_region; sp1_is_crgn, sp2_is_crgn : BOOLEAN; END_LOCAL; IF 'CARTESIAN_COMPLEX_NUMBER_REGION' IN typenames THEN sp1_is_crgn := TRUE; crgn1 := sp1; ELSE IF 'POLAR_COMPLEX_NUMBER_REGION' IN typenames THEN sp1_is_crgn := FALSE; prgn1 := sp1; ELSE -- Improper usage: Default response is to assume compatibility. RETURN (TRUE); END_IF; END_IF; typenames := stripped_typeof (sp2); IF 'CARTESIAN_COMPLEX_NUMBER_REGION' IN typenames THEN sp2_is_crgn := TRUE; crgn2 := sp2; ELSE IF 'POLAR_COMPLEX_NUMBER_REGION' IN typenames THEN sp2_is_crgn := FALSE; prgn2 := sp2; ELSE -- Improper usage: Default response is to assume compatibility. RETURN (TRUE); END_IF; END_IF; IF sp1_is_crgn AND sp2_is_crgn THEN -- two cartesian regions RETURN (compatible_intervals(crgn1.real_constraint, crgn2.real_constraint) AND compatible_intervals(crgn1.imag_constraint, crgn2.imag_constraint)); END_IF; IF NOT sp1_is_crgn AND NOT sp2_is_crgn AND (prgn1.centre.real_part = prgn2.centre.real_part) AND (prgn1.centre.imag_part = prgn2.centre.imag_part) THEN -- two polar regions with common centre IF NOT compatible_intervals(prgn1.distance_constraint, prgn2.distance_constraint) THEN RETURN (FALSE); END_IF; IF compatible_intervals(prgn1.direction_constraint, prgn2.direction_constraint) THEN RETURN (TRUE); END_IF; -- Deal with direction ambiguity by 2 pi. IF (prgn1.direction_constraint.max > PI) AND (prgn2.direction_constraint.max < PI) THEN RETURN (compatible_intervals(prgn2.direction_constraint, make_finite_real_interval(-PI,open,prgn1.direction_constraint.max-2.0*PI, prgn1.direction_constraint.max_closure))); END_IF; IF (prgn2.direction_constraint.max > PI) AND (prgn1.direction_constraint.max < PI) THEN RETURN (compatible_intervals(prgn1.direction_constraint, make_finite_real_interval(-PI,open,prgn2.direction_constraint.max-2.0*PI, prgn2.direction_constraint.max_closure))); END_IF; RETURN (FALSE); END_IF; -- Make do with imperfect tests for remaining cases. IF sp1_is_crgn AND NOT sp2_is_crgn THEN crgn2 := enclose_pregion_in_cregion(prgn2); prgn1 := enclose_cregion_in_pregion(crgn1,prgn2.centre); RETURN (compatible_complex_number_regions(crgn1,crgn2) AND compatible_complex_number_regions(prgn1,prgn2)); END_IF; IF NOT sp1_is_crgn AND sp2_is_crgn THEN crgn1 := enclose_pregion_in_cregion(prgn1); prgn2 := enclose_cregion_in_pregion(crgn2,prgn1.centre); RETURN (compatible_complex_number_regions(crgn1,crgn2) AND compatible_complex_number_regions(prgn1,prgn2)); END_IF; -- Two polar regions with different centres prgn1c2 := enclose_pregion_in_pregion(prgn1,prgn2.centre); prgn2c1 := enclose_pregion_in_pregion(prgn2,prgn1.centre); RETURN (compatible_complex_number_regions(prgn1,prgn2c1) AND compatible_complex_number_regions(prgn1c2,prgn2)); END_FUNCTION; -- compatible_complex_number_regions FUNCTION compatible_es_values(esval1, esval2 : elementary_space_enumerators) : BOOLEAN; LOCAL esval1_is_numeric, esval2_is_numeric : LOGICAL; END_LOCAL; IF (esval1 = esval2) OR (esval1 = es_generics) OR (esval2 = es_generics) THEN RETURN (TRUE); END_IF; esval1_is_numeric := (esval1 >= es_numbers) AND (esval1 <= es_integers); esval2_is_numeric := (esval2 >= es_numbers) AND (esval2 <= es_integers); IF (esval1_is_numeric AND (esval2 = es_numbers)) OR (esval2_is_numeric AND (esval1 = es_numbers)) THEN RETURN (TRUE); END_IF; IF esval1_is_numeric XOR esval2_is_numeric THEN RETURN (FALSE); END_IF; IF ((esval1 = es_logicals) AND (esval2 = es_booleans)) OR ((esval1 = es_booleans) AND (esval2 = es_logicals)) THEN RETURN (TRUE); END_IF; -- All other cases are incompatible RETURN (FALSE); END_FUNCTION; -- compatible_es_values FUNCTION compatible_intervals(sp1, sp2 : maths_space) : BOOLEAN; LOCAL amin, amax : REAL; END_LOCAL; IF min_exists(sp1) AND max_exists(sp2) THEN amin := real_min(sp1); amax := real_max(sp2); IF amin > amax THEN RETURN (FALSE); END_IF; IF amin = amax THEN RETURN (min_included(sp1) AND max_included(sp2)); END_IF; END_IF; IF min_exists(sp2) AND max_exists(sp1) THEN amin := real_min(sp2); amax := real_max(sp1); IF amin > amax THEN RETURN (FALSE); END_IF; IF amin = amax THEN RETURN (min_included(sp2) AND max_included(sp1)); END_IF; END_IF; RETURN (TRUE); END_FUNCTION; -- compatible_intervals FUNCTION compatible_spaces(sp1, sp2 : maths_space) : BOOLEAN; LOCAL types1 : SET OF STRING := stripped_typeof (sp1); types2 : SET OF STRING := stripped_typeof (sp2); lgcl : LOGICAL := UNKNOWN; m, n : INTEGER; s1, s2 : maths_space; END_LOCAL; IF 'FINITE_SPACE' IN types1 THEN REPEAT i := 1 TO SIZEOF (sp1\finite_space.members); lgcl := member_of(sp1\finite_space.members[i], sp2); IF lgcl <> FALSE THEN RETURN (TRUE); END_IF; END_REPEAT; RETURN (FALSE); END_IF; IF 'FINITE_SPACE' IN types2 THEN REPEAT i := 1 TO SIZEOF (sp2\finite_space.members); lgcl := member_of(sp2\finite_space.members[i], sp1); IF lgcl <> FALSE THEN RETURN (TRUE); END_IF; END_REPEAT; RETURN (FALSE); END_IF; IF 'ELEMENTARY_SPACE' IN types1 THEN IF sp1\elementary_space.space_id = es_generics THEN RETURN (TRUE); END_IF; IF 'ELEMENTARY_SPACE' IN types2 THEN RETURN (compatible_es_values(sp1\elementary_space.space_id, sp2\elementary_space.space_id)); END_IF; IF ('FINITE_INTEGER_INTERVAL' IN types2) OR ('INTEGER_INTERVAL_FROM_MIN' IN types2) OR ('INTEGER_INTERVAL_TO_MAX' IN types2) THEN RETURN (compatible_es_values(sp1\elementary_space.space_id, es_integers)); END_IF; IF ('FINITE_REAL_INTERVAL' IN types2) OR ('REAL_INTERVAL_FROM_MIN' IN types2) OR ('REAL_INTERVAL_TO_MAX' IN types2) THEN RETURN (compatible_es_values(sp1\elementary_space.space_id, es_reals)); END_IF; IF ('CARTESIAN_COMPLEX_NUMBER_REGION' IN types2) OR ('POLAR_COMPLEX_NUMBER_REGION' IN types2) THEN RETURN (compatible_es_values(sp1\elementary_space.space_id, es_complex_numbers)); END_IF; IF 'TUPLE_SPACE' IN types2 THEN RETURN (FALSE); END_IF; IF 'FUNCTION_SPACE' IN types2 THEN RETURN (bool(sp1\elementary_space.space_id = es_maths_functions)); END_IF; -- Should be unreachable. RETURN (TRUE); END_IF; IF 'ELEMENTARY_SPACE' IN types2 THEN IF sp2\elementary_space.space_id = es_generics THEN RETURN (TRUE); END_IF; IF ('FINITE_INTEGER_INTERVAL' IN types1) OR ('INTEGER_INTERVAL_FROM_MIN' IN types1) OR ('INTEGER_INTERVAL_TO_MAX' IN types1) THEN RETURN (compatible_es_values(sp2\elementary_space.space_id, es_integers)); END_IF; IF ('FINITE_REAL_INTERVAL' IN types1) OR ('REAL_INTERVAL_FROM_MIN' IN types1) OR ('REAL_INTERVAL_TO_MAX' IN types1) THEN RETURN (compatible_es_values(sp2\elementary_space.space_id, es_reals)); END_IF; IF ('CARTESIAN_COMPLEX_NUMBER_REGION' IN types1) OR ('POLAR_COMPLEX_NUMBER_REGION' IN types1) THEN RETURN (compatible_es_values(sp2\elementary_space.space_id, es_complex_numbers)); END_IF; IF 'TUPLE_SPACE' IN types1 THEN RETURN (FALSE); END_IF; IF 'FUNCTION_SPACE' IN types1 THEN RETURN (bool(sp2\elementary_space.space_id = es_maths_functions)); END_IF; -- Should be unreachable. RETURN (TRUE); END_IF; IF subspace_of_es(sp1,es_integers) THEN -- Note that sp1 finite already handled. IF subspace_of_es(sp2,es_integers) THEN -- Note that sp2 finite already handled. RETURN (compatible_intervals(sp1,sp2)); END_IF; RETURN (FALSE); END_IF; IF subspace_of_es(sp2,es_integers) THEN RETURN (FALSE); END_IF; IF subspace_of_es(sp1,es_reals) THEN -- Note that sp1 finite already handled. IF subspace_of_es(sp2,es_reals) THEN -- Note that sp2 finite already handled. RETURN (compatible_intervals(sp1,sp2)); END_IF; RETURN (FALSE); END_IF; IF subspace_of_es(sp2,es_reals) THEN RETURN (FALSE); END_IF; IF subspace_of_es(sp1,es_complex_numbers) THEN -- Note sp1 finite already handled. IF subspace_of_es(sp2,es_complex_numbers) THEN -- Note sp2 finite already handled. RETURN (compatible_complex_number_regions(sp1,sp2)); END_IF; RETURN (FALSE); END_IF; IF subspace_of_es(sp2,es_complex_numbers) THEN RETURN (FALSE); END_IF; IF 'UNIFORM_PRODUCT_SPACE' IN types1 THEN IF 'UNIFORM_PRODUCT_SPACE' IN types2 THEN IF sp1\uniform_product_space.exponent <> sp2\uniform_product_space.exponent THEN RETURN (FALSE); END_IF; RETURN (compatible_spaces(sp1\uniform_product_space.base, sp2\uniform_product_space.base)); END_IF; IF 'LISTED_PRODUCT_SPACE' IN types2 THEN n := SIZEOF (sp2\listed_product_space.factors); IF sp1\uniform_product_space.exponent <> n THEN RETURN (FALSE); END_IF; REPEAT i := 1 TO n; IF NOT compatible_spaces(sp1\uniform_product_space.base, sp2\listed_product_space.factors[i]) THEN RETURN (FALSE); END_IF; END_REPEAT; RETURN (TRUE); END_IF; IF 'EXTENDED_TUPLE_SPACE' IN types2 THEN m := sp1\uniform_product_space.exponent; n := space_dimension(sp2\extended_tuple_space.base); IF m < n THEN RETURN (FALSE); END_IF; IF m = n THEN RETURN (compatible_spaces(sp1, sp2\extended_tuple_space.base)); END_IF; RETURN (compatible_spaces(sp1, assoc_product_space( sp2\extended_tuple_space.base, make_uniform_product_space( sp2\extended_tuple_space.extender, m - n)))); END_IF; IF 'FUNCTION_SPACE' IN types2 THEN RETURN (FALSE); END_IF; -- Should be unreachable. RETURN (TRUE); END_IF; IF 'LISTED_PRODUCT_SPACE' IN types1 THEN n := SIZEOF (sp1\listed_product_space.factors); IF 'UNIFORM_PRODUCT_SPACE' IN types2 THEN IF n <> sp2\uniform_product_space.exponent THEN RETURN (FALSE); END_IF; REPEAT i := 1 TO n; IF NOT compatible_spaces(sp2\uniform_product_space.base, sp1\listed_product_space.factors[i]) THEN RETURN (FALSE); END_IF; END_REPEAT; RETURN (TRUE); END_IF; IF 'LISTED_PRODUCT_SPACE' IN types2 THEN IF n <> SIZEOF (sp2\listed_product_space.factors) THEN RETURN (FALSE); END_IF; REPEAT i := 1 TO n; IF NOT compatible_spaces(sp1\listed_product_space.factors[i], sp2\listed_product_space.factors[i]) THEN RETURN (FALSE); END_IF; END_REPEAT; RETURN (TRUE); END_IF; IF 'EXTENDED_TUPLE_SPACE' IN types2 THEN m := space_dimension(sp2\extended_tuple_space.base); IF n < m THEN RETURN (FALSE); END_IF; IF n = m THEN RETURN (compatible_spaces(sp1, sp2\extended_tuple_space.base)); END_IF; RETURN (compatible_spaces(sp1, assoc_product_space( sp2\extended_tuple_space.base, make_uniform_product_space( sp2\extended_tuple_space.extender, n - m)))); END_IF; IF (schema_prefix + 'FUNCTION_SPACE') IN types2 THEN RETURN (FALSE); END_IF; -- Should be unreachable. RETURN (TRUE); END_IF; IF 'EXTENDED_TUPLE_SPACE' IN types1 THEN IF ('UNIFORM_PRODUCT_SPACE' IN types2) OR ('LISTED_PRODUCT_SPACE' IN types2) THEN RETURN (compatible_spaces(sp2, sp1)); END_IF; IF 'EXTENDED_TUPLE_SPACE' IN types2 THEN IF NOT compatible_spaces(sp1\extended_tuple_space.extender, sp2\extended_tuple_space.extender) THEN RETURN (FALSE); END_IF; n := space_dimension(sp1\extended_tuple_space.base); m := space_dimension(sp2\extended_tuple_space.base); IF n < m THEN RETURN (compatible_spaces(assoc_product_space(sp1\extended_tuple_space.base, make_uniform_product_space(sp1\extended_tuple_space.extender, m - n)), sp2\extended_tuple_space.base)); END_IF; IF n = m THEN RETURN (compatible_spaces(sp1\extended_tuple_space.base, sp2\extended_tuple_space.base)); END_IF; IF n > m THEN RETURN (compatible_spaces(sp1\extended_tuple_space.base, assoc_product_space(sp2\extended_tuple_space.base, make_uniform_product_space(sp2\extended_tuple_space.extender, n - m)))); END_IF; END_IF; IF 'FUNCTION_SPACE' IN types2 THEN RETURN (FALSE); END_IF; -- Should be unreachable. RETURN (TRUE); END_IF; IF 'FUNCTION_SPACE' IN types1 THEN IF 'FUNCTION_SPACE' IN types2 THEN s1 := sp1\function_space.domain_argument; s2 := sp2\function_space.domain_argument; CASE sp1\function_space.domain_constraint OF sc_equal : BEGIN CASE sp2\function_space.domain_constraint OF sc_equal : lgcl := subspace_of(s1, s2) AND subspace_of(s2, s1); sc_subspace : lgcl := subspace_of(s1, s2); sc_member : lgcl := member_of(s1, s2); END_CASE; END; sc_subspace :BEGIN CASE sp2\function_space.domain_constraint OF sc_equal : lgcl := subspace_of(s2, s1); sc_subspace : lgcl := compatible_spaces(s1, s2); sc_member : lgcl := UNKNOWN; END_CASE; END; sc_member :BEGIN CASE sp2\function_space.domain_constraint OF sc_equal : lgcl := member_of(s2, s1); sc_subspace : lgcl := UNKNOWN; sc_member : lgcl := compatible_spaces(s1, s2); END_CASE; END; END_CASE; IF lgcl = FALSE THEN RETURN (FALSE); END_IF; s1 := sp1\function_space.range_argument; s2 := sp2\function_space.range_argument; CASE sp1\function_space.range_constraint OF sc_equal : BEGIN CASE sp2\function_space.range_constraint OF sc_equal : lgcl := subspace_of(s1, s2) AND subspace_of(s2, s1); sc_subspace : lgcl := subspace_of(s1, s2); sc_member : lgcl := member_of(s1, s2); END_CASE; END; sc_subspace :BEGIN CASE sp2\function_space.range_constraint OF sc_equal : lgcl := subspace_of(s2, s1); sc_subspace : lgcl := compatible_spaces(s1, s2); sc_member : lgcl := UNKNOWN; END_CASE; END; sc_member :BEGIN CASE sp2\function_space.range_constraint OF sc_equal : lgcl := member_of(s2, s1); sc_subspace : lgcl := UNKNOWN; sc_member : lgcl := compatible_spaces(s1, s2); END_CASE; END; END_CASE; IF lgcl = FALSE THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_IF; -- Should be unreachable. RETURN (TRUE); END_IF; -- Should be unreachable. RETURN (TRUE); END_FUNCTION; -- compatible_spaces FUNCTION composable_sequence(operands : LIST [2:?] OF maths_function) : BOOLEAN; REPEAT i := 1 TO SIZEOF (operands) - 1; IF NOT compatible_spaces (operands[i].range, operands[i+1].domain) THEN RETURN (FALSE); END_IF; END_REPEAT; RETURN (TRUE); END_FUNCTION; -- composable_sequence FUNCTION convert_to_literal(val : maths_atom) : generic_literal; LOCAL types : SET OF STRING := TYPEOF (val); END_LOCAL; IF 'INTEGER' IN types THEN RETURN (make_int_literal (val)); END_IF; IF 'REAL' IN types THEN RETURN (make_real_literal (val)); END_IF; IF 'BOOLEAN' IN types THEN RETURN (make_boolean_literal (val)); END_IF; IF 'STRING' IN types THEN RETURN (make_string_literal (val)); END_IF; IF 'LOGICAL' IN types THEN RETURN (make_logical_literal (val)); END_IF; IF 'BINARY' IN types THEN RETURN (make_binary_literal (val)); END_IF; IF (schema_prefix + 'MATHS_ENUM_ATOM') IN types THEN RETURN (make_maths_enum_literal (val)); END_IF; -- Should be unreachable RETURN (?); END_FUNCTION; -- convert_to_literal FUNCTION convert_to_maths_function(func : maths_function_select) : maths_function; LOCAL efenum : elementary_function_enumerators; mthfun : maths_function; END_LOCAL; IF (schema_prefix + 'MATHS_FUNCTION') IN TYPEOF (func) THEN mthfun := func; ELSE efenum := func; mthfun := make_elementary_function (efenum); END_IF; RETURN (mthfun); END_FUNCTION; -- convert_to_maths_function FUNCTION convert_to_maths_value(val : GENERIC:G) : maths_value; LOCAL types : SET OF STRING := TYPEOF (val); ival : maths_integer; rval : maths_real; nval : maths_number; tfval : maths_boolean; lval : maths_logical; sval : maths_string; bval : maths_binary; tval : maths_tuple := the_empty_maths_tuple; mval : maths_value; END_LOCAL; IF (schema_prefix + 'MATHS_VALUE') IN types THEN RETURN (val); END_IF; IF 'INTEGER' IN types THEN ival := val; RETURN (ival); END_IF; IF 'REAL' IN types THEN rval := val; RETURN (rval); END_IF; IF 'NUMBER' IN types THEN nval := val; RETURN (nval); END_IF; IF 'BOOLEAN' IN types THEN tfval := val; RETURN (tfval); END_IF; IF 'LOGICAL' IN types THEN lval := val; RETURN (lval); END_IF; IF 'STRING' IN types THEN sval := val; RETURN (sval); END_IF; IF 'BINARY' IN types THEN bval := val; RETURN (bval); END_IF; IF 'LIST' IN types THEN REPEAT i := 1 TO SIZEOF (val); mval := convert_to_maths_value (val[i]); IF NOT EXISTS (mval) THEN RETURN (?); END_IF; INSERT (tval, mval, i-1); END_REPEAT; RETURN (tval); END_IF; RETURN (?); END_FUNCTION; -- convert_to_maths_value FUNCTION convert_to_operand(val : maths_value) : generic_expression; LOCAL types : SET OF STRING := stripped_typeof (val); END_LOCAL; -- Use intermediate variables of appropriate declared types to help the compilers. IF 'GENERIC_EXPRESSION' IN types THEN RETURN (val); END_IF; IF 'MATHS_ATOM' IN types THEN RETURN (convert_to_literal (val)); END_IF; IF 'ATOM_BASED_VALUE' IN types THEN RETURN (make_atom_based_literal(val)); END_IF; IF 'MATHS_TUPLE' IN types THEN RETURN (make_maths_tuple_literal(val)); END_IF; -- Should be unreachable RETURN (?); END_FUNCTION; -- convert_to_operand FUNCTION convert_to_operands(values : AGGREGATE OF maths_value) : LIST OF generic_expression; LOCAL operands : LIST OF generic_expression := []; loc : INTEGER := 0; END_LOCAL; IF NOT EXISTS (values) THEN RETURN (?); END_IF; REPEAT i := LOINDEX (values) TO HIINDEX (values); INSERT (operands, convert_to_operand (values[i]), loc); loc := loc + 1; END_REPEAT; RETURN (operands); END_FUNCTION; -- convert_to_operands FUNCTION convert_to_operands_prcmfn(srcdom : maths_space_or_function; prepfun : LIST OF maths_function; finfun : maths_function_select) : LIST [2:?] OF generic_expression; LOCAL operands : LIST OF generic_expression := []; END_LOCAL; INSERT (operands, srcdom, 0); REPEAT i := 1 TO SIZEOF (prepfun); INSERT (operands, prepfun[i], i); END_REPEAT; INSERT (operands, convert_to_maths_function (finfun), SIZEOF (prepfun)+1); RETURN (operands); END_FUNCTION; -- convert_to_operands_prcmfn FUNCTION definite_integral_check(domain : tuple_space; vrblint : input_selector; lowerinf : BOOLEAN; upperinf : BOOLEAN) : BOOLEAN; LOCAL domn : tuple_space := domain; fspc : maths_space; dim : nonnegative_integer; k : positive_integer; END_LOCAL; IF (space_dimension (domain) = 1) AND ((schema_prefix + 'TUPLE_SPACE') IN TYPEOF (factor1 (domain))) THEN domn := factor1 (domain); END_IF; dim := space_dimension (domn); k := vrblint; IF k > dim THEN RETURN (FALSE); END_IF; fspc := factor_space (domn, k); IF NOT ((schema_prefix + 'REAL_INTERVAL') IN TYPEOF (fspc)) THEN RETURN (FALSE); END_IF; IF lowerinf AND min_exists (fspc) THEN RETURN (FALSE); END_IF; IF upperinf AND max_exists (fspc) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; -- definite_integral_check FUNCTION definite_integral_expr_check(operands : LIST [2:?] OF generic_expression; lowerinf : BOOLEAN; upperinf : BOOLEAN) : BOOLEAN; LOCAL nops : INTEGER := 2; vspc : maths_space; dim : nonnegative_integer; k : positive_integer; bspc : maths_space; END_LOCAL; IF NOT lowerinf THEN nops := nops + 1; END_IF; IF NOT upperinf THEN nops := nops + 1; END_IF; IF SIZEOF (operands) <> nops THEN RETURN (FALSE); END_IF; IF NOT ('GENERIC_VARIABLE' IN stripped_typeof(operands[2])) THEN RETURN (FALSE); END_IF; IF NOT has_values_space (operands[2]) THEN RETURN (FALSE); END_IF; vspc := values_space_of (operands[2]); IF NOT ('REAL_INTERVAL' IN stripped_typeof(vspc)) THEN RETURN (FALSE); END_IF; IF lowerinf THEN IF min_exists (vspc) THEN RETURN (FALSE); END_IF; k := 3; ELSE IF NOT has_values_space (operands[3]) THEN RETURN (FALSE); END_IF; bspc := values_space_of (operands[3]); IF NOT compatible_spaces (bspc, vspc) THEN RETURN (FALSE); END_IF; k := 4; END_IF; IF upperinf THEN IF max_exists (vspc) THEN RETURN (FALSE); END_IF; ELSE IF NOT has_values_space (operands[k]) THEN RETURN (FALSE); END_IF; bspc := values_space_of (operands[k]); IF NOT compatible_spaces (bspc, vspc) THEN RETURN (FALSE); END_IF; END_IF; RETURN (TRUE); END_FUNCTION; -- definite_integral_expr_check FUNCTION derive_definite_integral_domain(igrl : definite_integral_function) : tuple_space; -- Internal utility function: FUNCTION process_product_space(spc : product_space; idx, prefix : INTEGER; vdomn : maths_space) : product_space; LOCAL uspc : uniform_product_space; expnt : INTEGER; factors : LIST OF maths_space; END_LOCAL; IF (schema_prefix + 'UNIFORM_PRODUCT_SPACE') IN TYPEOF (spc) THEN uspc := spc; expnt := uspc.exponent + prefix; IF idx <= uspc.exponent THEN expnt := expnt - 1; END_IF; IF expnt = 0 THEN RETURN (make_listed_product_space([])); ELSE RETURN (make_uniform_product_space(uspc.base,expnt)); END_IF; ELSE factors := spc\listed_product_space.factors; IF idx <= SIZEOF (factors) THEN REMOVE (factors, idx); END_IF; IF prefix > 0 THEN INSERT (factors, vdomn, 0); IF prefix > 1 THEN INSERT (factors, vdomn, 0); END_IF; END_IF; RETURN (make_listed_product_space(factors)); END_IF; END_FUNCTION; -- process_product_space -- Resume body of derive_definite_integral_domain function LOCAL idomn : tuple_space := igrl.integrand.domain; types : SET OF STRING := TYPEOF (idomn); idx : INTEGER := igrl.variable_of_integration; tupled : BOOLEAN := bool(((space_dimension(idomn) = 1) AND ((schema_prefix + 'TUPLE_SPACE') IN types))); prefix : INTEGER := 0; espc : extended_tuple_space; vdomn : maths_space; END_LOCAL; IF tupled THEN idomn := factor1(idomn); types := TYPEOF (idomn); END_IF; IF igrl.lower_limit_neg_infinity THEN prefix := prefix + 1; END_IF; IF igrl.upper_limit_pos_infinity THEN prefix := prefix + 1; END_IF; vdomn := factor_space(idomn,idx); IF (schema_prefix + 'EXTENDED_TUPLE_SPACE') IN types THEN espc := idomn; idomn := make_extended_tuple_space(process_product_space(espc.base,idx, prefix,vdomn),espc.extender); ELSE idomn := process_product_space(idomn,idx,prefix,vdomn); END_IF; IF tupled THEN RETURN (one_tuples_of(idomn)); ELSE RETURN (idomn); END_IF; END_FUNCTION; -- derive_definite_integral_domain FUNCTION derive_elementary_function_domain(ef_val : elementary_function_enumerators) : tuple_space; IF NOT EXISTS (ef_val) THEN RETURN (?); END_IF; CASE ef_val OF ef_and : RETURN (make_extended_tuple_space (the_zero_tuple_space, the_logicals)); ef_or : RETURN (make_extended_tuple_space (the_zero_tuple_space, the_logicals)); ef_not : RETURN (make_uniform_product_space (the_logicals, 1)); ef_xor : RETURN (make_uniform_product_space (the_logicals, 2)); ef_negate_i : RETURN (make_uniform_product_space (the_integers, 1)); ef_add_i : RETURN (the_integer_tuples); ef_subtract_i : RETURN (make_uniform_product_space (the_integers, 2)); ef_multiply_i : RETURN (the_integer_tuples); ef_divide_i : RETURN (make_uniform_product_space (the_integers, 2)); ef_mod_i : RETURN (make_uniform_product_space (the_integers, 2)); ef_exponentiate_i : RETURN (make_uniform_product_space (the_integers, 2)); ef_eq_i : RETURN (make_uniform_product_space (the_integers, 2)); ef_ne_i : RETURN (make_uniform_product_space (the_integers, 2)); ef_gt_i : RETURN (make_uniform_product_space (the_integers, 2)); ef_lt_i : RETURN (make_uniform_product_space (the_integers, 2)); ef_ge_i : RETURN (make_uniform_product_space (the_integers, 2)); ef_le_i : RETURN (make_uniform_product_space (the_integers, 2)); ef_abs_i : RETURN (make_uniform_product_space (the_integers, 1)); ef_if_i : RETURN (make_listed_product_space ([the_logicals, the_integers, the_integers])); ef_negate_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_reciprocal_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_add_r : RETURN (the_real_tuples); ef_subtract_r : RETURN (make_uniform_product_space (the_reals, 2)); ef_multiply_r : RETURN (the_real_tuples); ef_divide_r : RETURN (make_uniform_product_space (the_reals, 2)); ef_mod_r : RETURN (make_uniform_product_space (the_reals, 2)); ef_exponentiate_r : RETURN (make_listed_product_space ([the_nonnegative_reals, the_reals])); ef_exponentiate_ri : RETURN (make_listed_product_space ([the_reals, the_integers])); ef_eq_r : RETURN (make_uniform_product_space (the_reals, 2)); ef_ne_r : RETURN (make_uniform_product_space (the_reals, 2)); ef_gt_r : RETURN (make_uniform_product_space (the_reals, 2)); ef_lt_r : RETURN (make_uniform_product_space (the_reals, 2)); ef_ge_r : RETURN (make_uniform_product_space (the_reals, 2)); ef_le_r : RETURN (make_uniform_product_space (the_reals, 2)); ef_abs_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_acos_r : RETURN (make_uniform_product_space (the_neg1_one_interval, 1)); ef_asin_r : RETURN (make_uniform_product_space (the_neg1_one_interval, 1)); ef_atan2_r : RETURN (make_uniform_product_space (the_reals, 2)); ef_cos_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_exp_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_ln_r : RETURN (make_uniform_product_space (the_nonnegative_reals, 1)); ef_log2_r : RETURN (make_uniform_product_space (the_nonnegative_reals, 1)); ef_log10_r : RETURN (make_uniform_product_space (the_nonnegative_reals, 1)); ef_sin_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_sqrt_r : RETURN (make_uniform_product_space (the_nonnegative_reals, 1)); ef_tan_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_if_r : RETURN (make_listed_product_space ([the_logicals, the_reals, the_reals])); ef_negate_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_reciprocal_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_add_c : RETURN (the_complex_tuples); ef_subtract_c : RETURN (make_uniform_product_space (the_complex_numbers, 2)); ef_multiply_c : RETURN (the_complex_tuples); ef_divide_c : RETURN (make_uniform_product_space (the_complex_numbers, 2)); ef_exponentiate_c : RETURN (make_uniform_product_space (the_complex_numbers, 2)); ef_exponentiate_ci : RETURN (make_listed_product_space ([the_complex_numbers, the_integers])); ef_eq_c : RETURN (make_uniform_product_space (the_complex_numbers, 2)); ef_ne_c : RETURN (make_uniform_product_space (the_complex_numbers, 2)); ef_conjugate_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_abs_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_arg_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_cos_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_exp_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_ln_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_sin_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_sqrt_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_tan_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_if_c : RETURN (make_listed_product_space ([the_logicals, the_complex_numbers, the_complex_numbers])); ef_subscript_s : RETURN (make_listed_product_space ([the_strings, the_integers])); ef_eq_s : RETURN (make_uniform_product_space (the_strings, 2)); ef_ne_s : RETURN (make_uniform_product_space (the_strings, 2)); ef_gt_s : RETURN (make_uniform_product_space (the_strings, 2)); ef_lt_s : RETURN (make_uniform_product_space (the_strings, 2)); ef_ge_s : RETURN (make_uniform_product_space (the_strings, 2)); ef_le_s : RETURN (make_uniform_product_space (the_strings, 2)); ef_subsequence_s : RETURN (make_listed_product_space ([the_strings, the_integers, the_integers])); ef_concat_s : RETURN (make_extended_tuple_space (the_zero_tuple_space, the_strings)); ef_size_s : RETURN (make_uniform_product_space (the_strings, 1)); ef_format : RETURN (make_listed_product_space ([the_numbers, the_strings])); ef_value : RETURN (make_uniform_product_space (the_strings, 1)); ef_like : RETURN (make_uniform_product_space (the_strings, 2)); ef_if_s : RETURN (make_listed_product_space ([the_logicals, the_strings, the_strings])); ef_subscript_b : RETURN (make_listed_product_space ([the_binarys, the_integers])); ef_eq_b : RETURN (make_uniform_product_space (the_binarys, 2)); ef_ne_b : RETURN (make_uniform_product_space (the_binarys, 2)); ef_gt_b : RETURN (make_uniform_product_space (the_binarys, 2)); ef_lt_b : RETURN (make_uniform_product_space (the_binarys, 2)); ef_ge_b : RETURN (make_uniform_product_space (the_binarys, 2)); ef_le_b : RETURN (make_uniform_product_space (the_binarys, 2)); ef_subsequence_b : RETURN (make_listed_product_space ([the_binarys, the_integers, the_integers])); ef_concat_b : RETURN (make_extended_tuple_space (the_zero_tuple_space, the_binarys)); ef_size_b : RETURN (make_uniform_product_space (the_binarys, 1)); ef_if_b : RETURN (make_listed_product_space ([the_logicals, the_binarys, the_binarys])); ef_subscript_t : RETURN (make_listed_product_space ([the_tuples, the_integers])); ef_eq_t : RETURN (make_uniform_product_space (the_tuples, 2)); ef_ne_t : RETURN (make_uniform_product_space (the_tuples, 2)); ef_concat_t : RETURN (make_extended_tuple_space (the_zero_tuple_space, the_tuples)); ef_size_t : RETURN (make_uniform_product_space (the_tuples, 1)); ef_entuple : RETURN (the_tuples); ef_detuple : RETURN (make_uniform_product_space (the_generics, 1)); ef_insert : RETURN (make_listed_product_space ([the_tuples, the_generics, the_integers])); ef_remove : RETURN (make_listed_product_space ([the_tuples, the_integers])); ef_if_t : RETURN (make_listed_product_space ([the_logicals, the_tuples, the_tuples])); ef_sum_it : RETURN (make_uniform_product_space (the_integer_tuples, 1)); ef_product_it : RETURN (make_uniform_product_space (the_integer_tuples, 1)); ef_add_it : RETURN (make_extended_tuple_space (the_integer_tuples, the_integer_tuples)); ef_subtract_it : RETURN (make_uniform_product_space (the_integer_tuples, 2)); ef_scalar_mult_it : RETURN (make_listed_product_space ([the_integers, the_integer_tuples])); ef_dot_prod_it : RETURN (make_uniform_product_space (the_integer_tuples, 2)); ef_sum_rt : RETURN (make_uniform_product_space (the_real_tuples, 1)); ef_product_rt : RETURN (make_uniform_product_space (the_real_tuples, 1)); ef_add_rt : RETURN (make_extended_tuple_space (the_real_tuples, the_real_tuples)); ef_subtract_rt : RETURN (make_uniform_product_space (the_real_tuples, 2)); ef_scalar_mult_rt : RETURN (make_listed_product_space ([the_reals, the_real_tuples])); ef_dot_prod_rt : RETURN (make_uniform_product_space (the_real_tuples, 2)); ef_norm_rt : RETURN (make_uniform_product_space (the_real_tuples, 1)); ef_sum_ct : RETURN (make_uniform_product_space (the_complex_tuples, 1)); ef_product_ct : RETURN (make_uniform_product_space (the_complex_tuples, 1)); ef_add_ct : RETURN (make_extended_tuple_space (the_complex_tuples, the_complex_tuples)); ef_subtract_ct : RETURN (make_uniform_product_space (the_complex_tuples, 2)); ef_scalar_mult_ct : RETURN (make_listed_product_space ([the_complex_numbers, the_complex_tuples])); ef_dot_prod_ct : RETURN (make_uniform_product_space (the_complex_tuples, 2)); ef_norm_ct : RETURN (make_uniform_product_space (the_complex_tuples, 1)); ef_if : RETURN (make_listed_product_space ([the_logicals, the_generics, the_generics])); ef_ensemble : RETURN (the_tuples); ef_member_of : RETURN (make_listed_product_space ([the_generics, the_maths_spaces])); OTHERWISE : RETURN (?); END_CASE; END_FUNCTION; -- derive_elementary_function_domain FUNCTION derive_elementary_function_range(ef_val : elementary_function_enumerators) : tuple_space; IF NOT EXISTS (ef_val) THEN RETURN (?); END_IF; CASE ef_val OF ef_and : RETURN (make_uniform_product_space (the_logicals, 1)); ef_or : RETURN (make_uniform_product_space (the_logicals, 1)); ef_not : RETURN (make_uniform_product_space (the_logicals, 1)); ef_xor : RETURN (make_uniform_product_space (the_logicals, 2)); ef_negate_i : RETURN (make_uniform_product_space (the_integers, 1)); ef_add_i : RETURN (make_uniform_product_space (the_integers, 1)); ef_subtract_i : RETURN (make_uniform_product_space (the_integers, 1)); ef_multiply_i : RETURN (make_uniform_product_space (the_integers, 1)); ef_divide_i : RETURN (make_uniform_product_space (the_integers, 1)); ef_mod_i : RETURN (make_uniform_product_space (the_integers, 1)); ef_exponentiate_i : RETURN (make_uniform_product_space (the_integers, 1)); ef_eq_i : RETURN (make_uniform_product_space (the_logicals, 1)); ef_ne_i : RETURN (make_uniform_product_space (the_logicals, 1)); ef_gt_i : RETURN (make_uniform_product_space (the_logicals, 1)); ef_lt_i : RETURN (make_uniform_product_space (the_logicals, 1)); ef_ge_i : RETURN (make_uniform_product_space (the_logicals, 1)); ef_le_i : RETURN (make_uniform_product_space (the_logicals, 1)); ef_abs_i : RETURN (make_uniform_product_space (the_integers, 1)); ef_if_i : RETURN (make_uniform_product_space (the_integers, 1)); ef_negate_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_reciprocal_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_add_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_subtract_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_multiply_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_divide_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_mod_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_exponentiate_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_exponentiate_ri : RETURN (make_uniform_product_space (the_reals, 1)); ef_eq_r : RETURN (make_uniform_product_space (the_logicals, 1)); ef_ne_r : RETURN (make_uniform_product_space (the_logicals, 1)); ef_gt_r : RETURN (make_uniform_product_space (the_logicals, 1)); ef_lt_r : RETURN (make_uniform_product_space (the_logicals, 1)); ef_ge_r : RETURN (make_uniform_product_space (the_logicals, 1)); ef_le_r : RETURN (make_uniform_product_space (the_logicals, 1)); ef_abs_r : RETURN (make_uniform_product_space (the_nonnegative_reals, 1)); ef_acos_r : RETURN (make_uniform_product_space (the_zero_pi_interval, 1)); ef_asin_r : RETURN (make_uniform_product_space (the_neghalfpi_halfpi_interval, 1)); ef_atan2_r : RETURN (make_uniform_product_space (the_negpi_pi_interval, 1)); ef_cos_r : RETURN (make_uniform_product_space (the_neg1_one_interval, 1)); ef_exp_r : RETURN (make_uniform_product_space (the_nonnegative_reals, 1)); ef_ln_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_log2_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_log10_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_sin_r : RETURN (make_uniform_product_space (the_neg1_one_interval, 1)); ef_sqrt_r : RETURN (make_uniform_product_space (the_nonnegative_reals, 1)); ef_tan_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_if_r : RETURN (make_uniform_product_space (the_reals, 1)); ef_negate_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_reciprocal_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_add_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_subtract_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_multiply_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_divide_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_exponentiate_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_exponentiate_ci : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_eq_c : RETURN (make_uniform_product_space (the_logicals, 1)); ef_ne_c : RETURN (make_uniform_product_space (the_logicals, 1)); ef_conjugate_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_abs_c : RETURN (make_uniform_product_space (the_nonnegative_reals, 1)); ef_arg_c : RETURN (make_uniform_product_space (the_negpi_pi_interval, 1)); ef_cos_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_exp_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_ln_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_sin_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_sqrt_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_tan_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_if_c : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_subscript_s : RETURN (make_uniform_product_space (the_strings, 1)); ef_eq_s : RETURN (make_uniform_product_space (the_logicals, 1)); ef_ne_s : RETURN (make_uniform_product_space (the_logicals, 1)); ef_gt_s : RETURN (make_uniform_product_space (the_logicals, 1)); ef_lt_s : RETURN (make_uniform_product_space (the_logicals, 1)); ef_ge_s : RETURN (make_uniform_product_space (the_logicals, 1)); ef_le_s : RETURN (make_uniform_product_space (the_logicals, 1)); ef_subsequence_s : RETURN (make_uniform_product_space (the_strings, 1)); ef_concat_s : RETURN (make_uniform_product_space (the_strings, 1)); ef_size_s : RETURN (make_uniform_product_space (the_integers, 1)); ef_format : RETURN (make_uniform_product_space (the_strings, 1)); ef_value : RETURN (make_uniform_product_space (the_reals, 1)); ef_like : RETURN (make_uniform_product_space (the_booleans, 1)); ef_if_s : RETURN (make_uniform_product_space (the_strings, 1)); ef_subscript_b : RETURN (make_uniform_product_space (the_binarys, 1)); ef_eq_b : RETURN (make_uniform_product_space (the_logicals, 1)); ef_ne_b : RETURN (make_uniform_product_space (the_logicals, 1)); ef_gt_b : RETURN (make_uniform_product_space (the_logicals, 1)); ef_lt_b : RETURN (make_uniform_product_space (the_logicals, 1)); ef_ge_b : RETURN (make_uniform_product_space (the_logicals, 1)); ef_le_b : RETURN (make_uniform_product_space (the_logicals, 1)); ef_subsequence_b : RETURN (make_uniform_product_space (the_binarys, 1)); ef_concat_b : RETURN (make_uniform_product_space (the_binarys, 1)); ef_size_b : RETURN (make_uniform_product_space (the_integers, 1)); ef_if_b : RETURN (make_uniform_product_space (the_binarys, 1)); ef_subscript_t : RETURN (make_uniform_product_space (the_generics, 1)); ef_eq_t : RETURN (make_uniform_product_space (the_logicals, 1)); ef_ne_t : RETURN (make_uniform_product_space (the_logicals, 1)); ef_concat_t : RETURN (make_uniform_product_space (the_tuples, 1)); ef_size_t : RETURN (make_uniform_product_space (the_integers, 1)); ef_entuple : RETURN (make_uniform_product_space (the_tuples, 1)); ef_detuple : RETURN (the_tuples); ef_insert : RETURN (make_uniform_product_space (the_tuples, 1)); ef_remove : RETURN (make_uniform_product_space (the_tuples, 1)); ef_if_t : RETURN (make_uniform_product_space (the_tuples, 1)); ef_sum_it : RETURN (make_uniform_product_space (the_integers, 1)); ef_product_it : RETURN (make_uniform_product_space (the_integers, 1)); ef_add_it : RETURN (make_uniform_product_space (the_integer_tuples, 1)); ef_subtract_it : RETURN (make_uniform_product_space (the_integer_tuples, 1)); ef_scalar_mult_it : RETURN (make_uniform_product_space (the_integer_tuples, 1)); ef_dot_prod_it : RETURN (make_uniform_product_space (the_integers, 1)); ef_sum_rt : RETURN (make_uniform_product_space (the_reals, 1)); ef_product_rt : RETURN (make_uniform_product_space (the_reals, 1)); ef_add_rt : RETURN (make_uniform_product_space (the_real_tuples, 1)); ef_subtract_rt : RETURN (make_uniform_product_space (the_real_tuples, 1)); ef_scalar_mult_rt : RETURN (make_uniform_product_space (the_real_tuples, 1)); ef_dot_prod_rt : RETURN (make_uniform_product_space (the_reals, 1)); ef_norm_rt : RETURN (make_uniform_product_space (the_reals, 1)); ef_sum_ct : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_product_ct : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_add_ct : RETURN (make_uniform_product_space (the_complex_tuples, 1)); ef_subtract_ct : RETURN (make_uniform_product_space (the_complex_tuples, 1)); ef_scalar_mult_ct : RETURN (make_uniform_product_space (the_complex_tuples, 1)); ef_dot_prod_ct : RETURN (make_uniform_product_space (the_complex_numbers, 1)); ef_norm_ct : RETURN (make_uniform_product_space (the_nonnegative_reals, 1)); ef_if : RETURN (make_uniform_product_space (the_generics, 1)); ef_ensemble : RETURN (make_uniform_product_space (the_maths_spaces, 1)); ef_member_of : RETURN (make_uniform_product_space (the_logicals, 1)); OTHERWISE : RETURN (?); END_CASE; END_FUNCTION; -- derive_elementary_function_range FUNCTION derive_finite_function_domain(pairs : SET [1:?] OF LIST [2:2] OF maths_value) : tuple_space; LOCAL result : SET OF maths_value := []; END_LOCAL; -- An ambiguity in ISO 10303-11:1994 pages 99-101 leaves the result of the following -- three lines ambiguous in those cases where an operand is simultaneously a member -- of the base type and the aggregate type. -- REPEAT i := 1 TO SIZEOF (pairs); -- result := result + pairs[i][1]; -- END_REPEAT; -- The next line unions an empty set and the desired list to get the desired set. result := result + list_selected_components (pairs, 1); RETURN (one_tuples_of (make_finite_space (result))); END_FUNCTION; -- derive_finite_function_domain FUNCTION derive_finite_function_range(pairs : SET [1:?] OF LIST [2:2] OF maths_value) : tuple_space; LOCAL result : SET OF maths_value := []; END_LOCAL; -- An ambiguity in ISO 10303-11:1994 pages 99-101 leaves the result of the following -- three lines ambiguous in those cases where an operand is simultaneously a member -- of the base type and the aggregate type. -- REPEAT i := 1 TO SIZEOF (pairs); -- result := result + pairs[i][2]; -- END_REPEAT; -- The next line unions an empty set and the desired list to get the desired set. result := result + list_selected_components (pairs, 2); RETURN (one_tuples_of (make_finite_space (result))); END_FUNCTION; -- derive_finite_function_range FUNCTION derive_function_domain(func : maths_function) : tuple_space; LOCAL typenames : SET OF STRING := stripped_typeof(func); tspace : tuple_space := make_listed_product_space ([]); shape : LIST OF positive_integer; sidxs : LIST OF INTEGER := [0]; itvl : finite_integer_interval; factors : LIST OF finite_integer_interval := []; is_uniform : BOOLEAN := TRUE; END_LOCAL; IF 'FINITE_FUNCTION' IN typenames THEN RETURN (derive_finite_function_domain (func\finite_function.pairs)); END_IF; IF 'CONSTANT_FUNCTION' IN typenames THEN RETURN (domain_from (func\constant_function.source_of_domain)); END_IF; IF 'SELECTOR_FUNCTION' IN typenames THEN RETURN (domain_from (func\selector_function.source_of_domain)); END_IF; IF 'ELEMENTARY_FUNCTION' IN typenames THEN RETURN (derive_elementary_function_domain (func\elementary_function.func_id)); END_IF; IF 'RESTRICTION_FUNCTION' IN typenames THEN RETURN (one_tuples_of (func\restriction_function.operand)); END_IF; IF 'REPACKAGING_FUNCTION' IN typenames THEN IF func\repackaging_function.input_repack = ro_nochange THEN RETURN (func\repackaging_function.operand.domain); END_IF; IF func\repackaging_function.input_repack = ro_wrap_as_tuple THEN RETURN (factor1 (func\repackaging_function.operand.domain)); END_IF; IF func\repackaging_function.input_repack = ro_unwrap_tuple THEN RETURN (one_tuples_of (func\repackaging_function.operand.domain)); END_IF; -- Unreachable, as there is no other possible value for input_repack. RETURN (?); END_IF; IF 'REINDEXED_ARRAY_FUNCTION' IN typenames THEN shape := shape_of_array(func\unary_generic_expression.operand); sidxs := func\reindexed_array_function.starting_indices; REPEAT i := 1 TO SIZEOF (shape); itvl := make_finite_integer_interval (sidxs[i], sidxs[i]+shape[i]-1); INSERT (factors, itvl, i-1); IF shape[i] <> shape[1] THEN is_uniform := FALSE; END_IF; END_REPEAT; IF is_uniform THEN RETURN (make_uniform_product_space (factors[1], SIZEOF (shape))); END_IF; RETURN (make_listed_product_space (factors)); END_IF; IF 'SERIES_COMPOSED_FUNCTION' IN typenames THEN RETURN (func\series_composed_function.operands[1].domain); END_IF; IF 'PARALLEL_COMPOSED_FUNCTION' IN typenames THEN RETURN (domain_from (func\parallel_composed_function.source_of_domain)); END_IF; IF 'EXPLICIT_TABLE_FUNCTION' IN typenames THEN shape := func\explicit_table_function.shape; sidxs[1] := func\explicit_table_function.index_base; REPEAT i := 1 TO SIZEOF (shape); itvl := make_finite_integer_interval (sidxs[1], sidxs[1]+shape[i]-1); INSERT (factors, itvl, i-1); IF shape[i] <> shape[1] THEN is_uniform := FALSE; END_IF; END_REPEAT; IF is_uniform THEN RETURN (make_uniform_product_space (factors[1], SIZEOF (shape))); END_IF; RETURN (make_listed_product_space (factors)); END_IF; IF 'HOMOGENEOUS_LINEAR_FUNCTION' IN typenames THEN RETURN (one_tuples_of (make_uniform_product_space (factor1 (func\homogeneous_linear_function.mat.range), func\homogeneous_linear_function.mat\explicit_table_function.shape [func\homogeneous_linear_function.sum_index]))); END_IF; IF 'GENERAL_LINEAR_FUNCTION' IN typenames THEN RETURN (one_tuples_of (make_uniform_product_space (factor1 (func\general_linear_function.mat.range), func\general_linear_function.mat\explicit_table_function.shape [func\general_linear_function.sum_index] - 1))); END_IF; IF 'B_SPLINE_BASIS' IN typenames THEN RETURN (one_tuples_of (make_finite_real_interval (func\b_spline_basis.repeated_knots[func\b_spline_basis.order], closed, func\b_spline_basis.repeated_knots[func\b_spline_basis.num_basis+1], closed))); END_IF; IF 'B_SPLINE_FUNCTION' IN typenames THEN REPEAT i := 1 TO SIZEOF (func\b_spline_function.basis); tspace := assoc_product_space (tspace, func\b_spline_function.basis[i].domain); END_REPEAT; RETURN (one_tuples_of (tspace)); END_IF; IF 'RATIONALIZE_FUNCTION' IN typenames THEN RETURN (func\rationalize_function.fun.domain); END_IF; IF 'PARTIAL_DERIVATIVE_FUNCTION' IN typenames THEN RETURN (func\partial_derivative_function.derivand.domain); END_IF; IF 'DEFINITE_INTEGRAL_FUNCTION' IN typenames THEN RETURN (derive_definite_integral_domain(func)); END_IF; IF 'ABSTRACTED_EXPRESSION_FUNCTION' IN typenames THEN REPEAT i := 1 TO SIZEOF (func\abstracted_expression_function.variables); tspace := assoc_product_space (tspace, one_tuples_of (values_space_of (func\abstracted_expression_function.variables[i]))); END_REPEAT; RETURN (tspace); END_IF; IF 'EXPRESSION_DENOTED_FUNCTION' IN typenames THEN RETURN (values_space_of (func\expression_denoted_function.expr)\function_space. domain_argument); END_IF; IF 'IMPORTED_POINT_FUNCTION' IN typenames THEN RETURN (one_tuples_of (make_listed_product_space ([]))); END_IF; IF 'IMPORTED_CURVE_FUNCTION' IN typenames THEN RETURN (func\imported_curve_function.parametric_domain); END_IF; IF 'IMPORTED_SURFACE_FUNCTION' IN typenames THEN RETURN (func\imported_surface_function.parametric_domain); END_IF; IF 'IMPORTED_VOLUME_FUNCTION' IN typenames THEN RETURN (func\imported_volume_function.parametric_domain); END_IF; IF 'APPLICATION_DEFINED_FUNCTION' IN typenames THEN RETURN (func\application_defined_function.explicit_domain); END_IF; -- Unreachable, as no other subtypes of maths_function are permissible without -- first modifying this function to account for them. RETURN (?); END_FUNCTION; -- derive_function_domain FUNCTION derive_function_range(func : maths_function) : tuple_space; LOCAL typenames : SET OF STRING := stripped_typeof(func); tspace : tuple_space := make_listed_product_space ([]); m, n : nonnegative_integer := 0; END_LOCAL; IF 'FINITE_FUNCTION' IN typenames THEN RETURN (derive_finite_function_range (func\finite_function.pairs)); END_IF; IF 'CONSTANT_FUNCTION' IN typenames THEN RETURN (one_tuples_of (make_finite_space ([func\constant_function.sole_output]))); END_IF; IF 'SELECTOR_FUNCTION' IN typenames THEN tspace := func.domain; IF (space_dimension(tspace) = 1) AND ((schema_prefix + 'TUPLE_SPACE') IN TYPEOF (tspace)) THEN tspace := factor1 (tspace); END_IF; RETURN (one_tuples_of (factor_space (tspace, func\selector_function.selector))); END_IF; IF 'ELEMENTARY_FUNCTION' IN typenames THEN RETURN (derive_elementary_function_range (func\elementary_function.func_id)); END_IF; IF 'RESTRICTION_FUNCTION' IN typenames THEN RETURN (one_tuples_of (func\restriction_function.operand)); END_IF; IF 'REPACKAGING_FUNCTION' IN typenames THEN tspace := func\repackaging_function.operand.range; IF func\repackaging_function.output_repack = ro_wrap_as_tuple THEN tspace := one_tuples_of (tspace); END_IF; IF func\repackaging_function.output_repack = ro_unwrap_tuple THEN tspace := factor1 (tspace); END_IF; IF func\repackaging_function.selected_output > 0 THEN tspace := one_tuples_of (factor_space (tspace, func\repackaging_function.selected_output)); END_IF; RETURN (tspace); END_IF; IF 'REINDEXED_ARRAY_FUNCTION' IN typenames THEN RETURN (func\unary_generic_expression.operand\maths_function.range); END_IF; IF 'SERIES_COMPOSED_FUNCTION' IN typenames THEN RETURN (func\series_composed_function.operands[SIZEOF (func\series_composed_function.operands)].range); END_IF; IF 'PARALLEL_COMPOSED_FUNCTION' IN typenames THEN RETURN (func\parallel_composed_function.final_function.range); END_IF; IF 'EXPLICIT_TABLE_FUNCTION' IN typenames THEN IF 'LISTED_REAL_DATA' IN typenames THEN RETURN (one_tuples_of (the_reals)); END_IF; IF 'LISTED_INTEGER_DATA' IN typenames THEN RETURN (one_tuples_of (the_integers)); END_IF; IF 'LISTED_LOGICAL_DATA' IN typenames THEN RETURN (one_tuples_of (the_logicals)); END_IF; IF 'LISTED_STRING_DATA' IN typenames THEN RETURN (one_tuples_of (the_strings)); END_IF; IF 'LISTED_COMPLEX_NUMBER_DATA' IN typenames THEN RETURN (one_tuples_of (the_complex_numbers)); END_IF; IF 'LISTED_DATA' IN typenames THEN RETURN (one_tuples_of (func\listed_data.value_range)); END_IF; IF 'EXTERNALLY_LISTED_DATA' IN typenames THEN RETURN (one_tuples_of (func\externally_listed_data.value_range)); END_IF; IF 'LINEARIZED_TABLE_FUNCTION' IN typenames THEN RETURN (func\linearized_table_function.source.range); END_IF; IF 'BASIC_SPARSE_MATRIX' IN typenames THEN RETURN (func\basic_sparse_matrix.val.range); END_IF; -- Unreachable, as no other subtypes of explicit_table_function are permissible -- without first modifying this function to account for them. RETURN (?); END_IF; IF 'HOMOGENEOUS_LINEAR_FUNCTION' IN typenames THEN RETURN (one_tuples_of (make_uniform_product_space (factor1 (func\homogeneous_linear_function.mat.range), func\homogeneous_linear_function.mat\explicit_table_function.shape [3 - func\homogeneous_linear_function.sum_index]))); END_IF; IF 'GENERAL_LINEAR_FUNCTION' IN typenames THEN RETURN (one_tuples_of (make_uniform_product_space (factor1 (func\general_linear_function.mat.range), func\general_linear_function.mat\explicit_table_function.shape [3 - func\general_linear_function.sum_index]))); END_IF; IF 'B_SPLINE_BASIS' IN typenames THEN RETURN (one_tuples_of (make_uniform_product_space (the_reals, func\b_spline_basis.num_basis))); END_IF; IF 'B_SPLINE_FUNCTION' IN typenames THEN tspace := factor1 (func\b_spline_function.coef.domain); m := SIZEOF (func\b_spline_function.basis); n := space_dimension (tspace); IF m = n THEN RETURN (one_tuples_of (the_reals)); END_IF; IF m = n - 1 THEN RETURN (one_tuples_of (make_uniform_product_space (the_reals, factor_space (tspace, n)\finite_integer_interval.size))); END_IF; tspace := extract_factors (tspace, m+1, n); RETURN (one_tuples_of (make_function_space (sc_equal, tspace, sc_subspace, number_superspace_of (func\b_spline_function.coef.range)))); END_IF; IF 'RATIONALIZE_FUNCTION' IN typenames THEN tspace := factor1 (func\rationalize_function.fun.range); n := space_dimension (tspace); RETURN (one_tuples_of (make_uniform_product_space (number_superspace_of ( factor1 (tspace)), n-1))); END_IF; IF 'PARTIAL_DERIVATIVE_FUNCTION' IN typenames THEN RETURN (drop_numeric_constraints ( func\partial_derivative_function.derivand.range)); END_IF; IF 'DEFINITE_INTEGRAL_FUNCTION' IN typenames THEN RETURN (drop_numeric_constraints ( func\definite_integral_function.integrand.range)); END_IF; IF 'ABSTRACTED_EXPRESSION_FUNCTION' IN typenames THEN RETURN (one_tuples_of(values_space_of(func\abstracted_expression_function.expr))); END_IF; IF 'EXPRESSION_DENOTED_FUNCTION' IN typenames THEN RETURN (values_space_of (func\expression_denoted_function.expr)\function_space. range_argument); END_IF; IF 'IMPORTED_POINT_FUNCTION' IN typenames THEN RETURN (one_tuples_of (make_uniform_product_space (the_reals, dimension_of (func\imported_point_function.geometry)))); END_IF; IF 'IMPORTED_CURVE_FUNCTION' IN typenames THEN RETURN (one_tuples_of (make_uniform_product_space (the_reals, dimension_of (func\imported_curve_function.geometry)))); END_IF; IF 'IMPORTED_SURFACE_FUNCTION' IN typenames THEN RETURN (one_tuples_of (make_uniform_product_space (the_reals, dimension_of (func\imported_surface_function.geometry)))); END_IF; IF 'IMPORTED_VOLUME_FUNCTION' IN typenames THEN RETURN (one_tuples_of (make_uniform_product_space (the_reals, dimension_of (func\imported_volume_function.geometry)))); END_IF; IF 'APPLICATION_DEFINED_FUNCTION' IN typenames THEN RETURN (func\application_defined_function.explicit_range); END_IF; -- Unreachable, as no other subtypes of maths_function are permissible without -- first modifying this function to account for them. RETURN (?); END_FUNCTION; -- derive_function_range FUNCTION domain_from(ref : maths_space_or_function) : tuple_space; LOCAL typenames : SET OF STRING := stripped_typeof(ref); func : maths_function; END_LOCAL; IF NOT EXISTS (ref) THEN RETURN (?); END_IF; IF 'TUPLE_SPACE' IN typenames THEN RETURN (ref); END_IF; IF 'MATHS_SPACE' IN typenames THEN RETURN (one_tuples_of (ref)); END_IF; func := ref; IF 'CONSTANT_FUNCTION' IN typenames THEN RETURN (domain_from (func\constant_function.source_of_domain)); END_IF; IF 'SELECTOR_FUNCTION' IN typenames THEN RETURN (domain_from (func\selector_function.source_of_domain)); END_IF; IF 'PARALLEL_COMPOSED_FUNCTION' IN typenames THEN RETURN (domain_from (func\parallel_composed_function.source_of_domain)); END_IF; RETURN (func.domain); END_FUNCTION; -- domain_from FUNCTION dot_count(str : STRING) : INTEGER; LOCAL n : INTEGER := 0; END_LOCAL; REPEAT i := 1 TO LENGTH (str); IF str[i] = '.' THEN n := n + 1; END_IF; END_REPEAT; RETURN (n); END_FUNCTION; -- dot_count FUNCTION dotted_identifiers_syntax(str : STRING) : BOOLEAN; LOCAL k : positive_integer; m : positive_integer; END_LOCAL; IF NOT EXISTS (str) THEN RETURN (FALSE); END_IF; k := parse_express_identifier (str, 1); IF k = 1 THEN RETURN (FALSE); END_IF; REPEAT WHILE k <= LENGTH (str); IF (str[k] <> '.') OR (k = LENGTH (str)) THEN RETURN (FALSE); END_IF; m := parse_express_identifier (str, k+1); IF m = k + 1 THEN RETURN (FALSE); END_IF; k := m; END_REPEAT; RETURN (TRUE); END_FUNCTION; -- dotted_identifiers_syntax FUNCTION drop_numeric_constraints(spc : maths_space) : maths_space; LOCAL typenames : SET OF STRING := stripped_typeof(spc); tspc : listed_product_space; factors : LIST OF maths_space := []; xspc : extended_tuple_space; END_LOCAL; IF 'UNIFORM_PRODUCT_SPACE' IN typenames THEN RETURN (make_uniform_product_space (drop_numeric_constraints ( spc\uniform_product_space.base), spc\uniform_product_space.exponent)); END_IF; IF 'LISTED_PRODUCT_SPACE' IN typenames THEN tspc := spc; REPEAT i := 1 TO SIZEOF (tspc.factors); INSERT (factors, drop_numeric_constraints (tspc.factors[i]), i-1); END_REPEAT; RETURN (make_listed_product_space (factors)); END_IF; IF 'EXTENDED_TUPLE_SPACE' IN typenames THEN xspc := spc; RETURN (make_extended_tuple_space (drop_numeric_constraints (xspc.base), drop_numeric_constraints (xspc.extender))); END_IF; IF subspace_of_es (spc, es_numbers) THEN RETURN (number_superspace_of (spc)); END_IF; RETURN (spc); END_FUNCTION; -- drop_numeric_constraints FUNCTION enclose_cregion_in_pregion(crgn : cartesian_complex_number_region; centre : complex_number_literal) : polar_complex_number_region; -- Find equivalent direction in range -PI < a <= PI. FUNCTION angle(a : REAL) : REAL; REPEAT WHILE a > PI; a := a - 2.0*PI; END_REPEAT; REPEAT WHILE a <= -PI; a := a + 2.0*PI; END_REPEAT; RETURN (a); END_FUNCTION; -- Determine whether a real is strictly within a real interval FUNCTION strictly_in(z : REAL; zitv : real_interval) : LOGICAL; RETURN ((NOT min_exists(zitv) OR (z > real_min(zitv))) AND (NOT max_exists(zitv) OR (z < real_max(zitv)))); END_FUNCTION; -- Include direction in minmax collection PROCEDURE angle_minmax( ab, a : REAL; a_in : BOOLEAN; VAR amin, amax : REAL; VAR amin_in, amax_in : BOOLEAN); a := angle(a - ab); IF amin = a THEN amin_in := amin_in OR a_in; END_IF; IF amin > a THEN amin := a; amin_in := a_in; END_IF; IF amax = a THEN amax_in := amax_in OR a_in; END_IF; IF amax < a THEN amax := a; amax_in := a_in; END_IF; END_PROCEDURE; -- Include distance in max collection PROCEDURE range_max( r : REAL; incl : BOOLEAN; VAR rmax : REAL; VAR rmax_in : BOOLEAN); IF rmax = r THEN rmax_in := rmax_in OR incl; END_IF; IF rmax < r THEN rmax := r; rmax_in := incl; END_IF; END_PROCEDURE; -- Include distance in min collection PROCEDURE range_min( r : REAL; incl : BOOLEAN; VAR rmin : REAL; VAR rmin_in : BOOLEAN); IF rmin = r THEN rmin_in := rmin_in OR incl; END_IF; IF (rmin < 0.0) OR (rmin > r) THEN rmin := r; rmin_in := incl; END_IF; END_PROCEDURE; LOCAL xitv, yitv : real_interval; is_xmin, is_xmax, is_ymin, is_ymax : BOOLEAN; xmin, xmax, ymin, ymax, xc, yc : REAL := 0.0; xmin_in, xmax_in, ymin_in, ymax_in : BOOLEAN := FALSE; rmin, rmax : REAL := -1.0; amin : REAL := 4.0; amax : REAL := -4.0; rmax_exists, outside : BOOLEAN := TRUE; rmin_in, rmax_in, amin_in, amax_in : BOOLEAN := FALSE; ab, a, r : REAL := 0.0; incl : BOOLEAN; ritv : real_interval; aitv : finite_real_interval; minclo, maxclo : open_closed := open; END_LOCAL; IF NOT EXISTS (crgn) OR NOT EXISTS (centre) THEN RETURN (?); END_IF; -- Extract elementary input information xitv := crgn.real_constraint; yitv := crgn.imag_constraint; xc := centre.real_part; yc := centre.imag_part; is_xmin := min_exists(xitv); is_xmax := max_exists(xitv); is_ymin := min_exists(yitv); is_ymax := max_exists(yitv); IF is_xmin THEN xmin := real_min(xitv); xmin_in := min_included(xitv); END_IF; IF is_xmax THEN xmax := real_max(xitv); xmax_in := max_included(xitv); END_IF; IF is_ymin THEN ymin := real_min(yitv); ymin_in := min_included(yitv); END_IF; IF is_ymax THEN ymax := real_max(yitv); ymax_in := max_included(yitv); END_IF; rmax_exists := is_xmin AND is_xmax AND is_ymin AND is_ymax; -- Identify base direction with respect to which all relevant directions lie -- within +/- 0.5*PI, or that the centre lies properly inside crgn. IF is_xmin AND (xc <= xmin) THEN ab := 0.0; ELSE IF is_ymin AND (yc <= ymin) THEN ab := 0.5*PI; ELSE IF is_ymax AND (yc >= ymax) THEN ab := -0.5*PI; ELSE IF is_xmax AND (xc >= xmax) THEN ab := PI; ELSE outside := FALSE; END_IF; END_IF; END_IF; END_IF; IF NOT outside AND NOT rmax_exists THEN RETURN (?); -- No enclosing polar region exists (requires whole plane) END_IF; -- Identify any closest point on a side but not a corner. IF is_xmin AND (xc <= xmin) AND strictly_in(yc,yitv) THEN rmin := xmin - xc; rmin_in := xmin_in; ELSE IF is_ymin AND (yc <= ymin) AND strictly_in(xc,xitv) THEN rmin := ymin - yc; rmin_in := ymin_in; ELSE IF is_ymax AND (yc >= ymax) AND strictly_in(xc,xitv) THEN rmin := yc - ymax; rmin_in := ymax_in; ELSE IF is_xmax AND (xc >= xmax) AND strictly_in(yc,yitv) THEN rmin := xc - xmax; rmin_in := xmax_in; END_IF; END_IF; END_IF; END_IF; IF is_xmin THEN IF is_ymin THEN -- Consider lower left corner r := SQRT((xmin-xc)**2 + (ymin-yc)**2); incl := xmin_in AND ymin_in; IF rmax_exists THEN range_max(r,incl,rmax,rmax_in); END_IF; IF outside THEN IF r > 0.0 THEN range_min(r,incl,rmin,rmin_in); a := angle(atan2(ymin-yc,xmin-xc) - ab); IF xc = xmin THEN incl := xmin_in; END_IF; IF yc = ymin THEN incl := ymin_in; END_IF; angle_minmax(ab,a,incl,amin,amax,amin_in,amax_in); ELSE -- Centre at lower left corner rmin := 0.0; rmin_in := xmin_in AND ymin_in; amin := angle(0.0-ab); amin_in := ymin_in; amax := angle(0.5*PI-ab); amax_in := xmin_in; END_IF; END_IF; ELSE IF xc <= xmin THEN -- Consider points near (xmin, -infinity) angle_minmax(ab,-0.5*PI,(xc=xmin) AND xmin_in,amin,amax,amin_in,amax_in); END_IF; END_IF; IF NOT is_ymax AND (xc <= xmin) THEN -- Consider points near (xmin, +infinity) angle_minmax(ab,0.5*PI,(xc=xmin) AND xmin_in,amin,amax,amin_in,amax_in); END_IF; END_IF; IF is_ymin THEN IF is_xmax THEN -- Consider lower right corner r := SQRT((xmax-xc)**2 + (ymin-yc)**2); incl := xmax_in AND ymin_in; IF rmax_exists THEN range_max(r,incl,rmax,rmax_in); END_IF; IF outside THEN IF r > 0.0 THEN range_min(r,incl,rmin,rmin_in); a := angle(atan2(ymin-yc,xmax-xc) - ab); IF xc = xmax THEN incl := xmax_in; END_IF; IF yc = ymin THEN incl := ymin_in; END_IF; angle_minmax(ab,a,incl,amin,amax,amin_in,amax_in); ELSE -- Centre at lower right corner rmin := 0.0; rmin_in := xmax_in AND ymin_in; amin := angle(0.5*PI-ab); amin_in := ymin_in; amax := angle(PI-ab); amax_in := xmax_in; END_IF; END_IF; ELSE IF yc <= ymin THEN -- Consider points near (+infinity, ymin) angle_minmax(ab,0.0,(yc=ymin) AND ymin_in,amin,amax,amin_in,amax_in); END_IF; END_IF; IF NOT is_xmin AND (yc <= ymin) THEN -- Consider points near (-infinity, ymin) angle_minmax(ab,PI,(yc=ymin) AND ymin_in,amin,amax,amin_in,amax_in); END_IF; END_IF; IF is_xmax THEN IF is_ymax THEN -- Consider upper right corner r := SQRT((xmax-xc)**2 + (ymax-yc)**2); incl := xmax_in AND ymax_in; IF rmax_exists THEN range_max(r,incl,rmax,rmax_in); END_IF; IF outside THEN IF r > 0.0 THEN range_min(r,incl,rmin,rmin_in); a := angle(atan2(ymax-yc,xmax-xc) - ab); IF xc = xmax THEN incl := xmax_in; END_IF; IF yc = ymax THEN incl := ymax_in; END_IF; angle_minmax(ab,a,incl,amin,amax,amin_in,amax_in); ELSE -- Centre at lower left corner rmin := 0.0; rmin_in := xmax_in AND ymax_in; amin := angle(-PI-ab); amin_in := ymax_in; amax := angle(-0.5*PI-ab); amax_in := xmax_in; END_IF; END_IF; ELSE IF xc >= xmax THEN -- Consider points near (xmax, +infinity) angle_minmax(ab,0.5*PI,(xc=xmax) AND xmax_in,amin,amax,amin_in,amax_in); END_IF; END_IF; IF NOT is_ymin AND (xc >= xmax) THEN -- Consider points near (xmax, -infinity) angle_minmax(ab,-0.5*PI,(xc=xmax) AND xmax_in,amin,amax,amin_in,amax_in); END_IF; END_IF; IF is_ymax THEN IF is_xmin THEN -- Consider upper left corner r := SQRT((xmin-xc)**2 + (ymax-yc)**2); incl := xmin_in AND ymax_in; IF rmax_exists THEN range_max(r,incl,rmax,rmax_in); END_IF; IF outside THEN IF r > 0.0 THEN range_min(r,incl,rmin,rmin_in); a := angle(atan2(ymax-yc,xmin-xc) - ab); IF xc = xmin THEN incl := xmin_in; END_IF; IF yc = ymax THEN incl := ymax_in; END_IF; angle_minmax(ab,a,incl,amin,amax,amin_in,amax_in); ELSE -- Centre at lower right corner rmin := 0.0; rmin_in := xmin_in AND ymax_in; amin := angle(0.5*PI-ab); amin_in := ymax_in; amax := angle(PI-ab); amax_in := xmin_in; END_IF; END_IF; ELSE IF yc >= ymax THEN -- Consider points near (-infinity, ymax) angle_minmax(ab,PI,(yc=ymax) AND ymax_in,amin,amax,amin_in,amax_in); END_IF; END_IF; IF NOT is_xmax AND (yc >= ymax) THEN -- Consider points near (+infinity, ymax) angle_minmax(ab,0.0,(yc=ymax) AND ymax_in,amin,amax,amin_in,amax_in); END_IF; END_IF; IF outside THEN -- Change direction origin from ab back to zero amin := angle(amin+ab); IF amin = PI THEN amin := -PI; END_IF; amax := angle(amax+ab); IF amax <= amin THEN amax := amax + 2.0*PI; END_IF; ELSE amin := -PI; amin_in := FALSE; amax := PI; amax_in := FALSE; END_IF; IF amin_in THEN minclo := closed; END_IF; IF amax_in THEN maxclo := closed; END_IF; aitv := make_finite_real_interval(amin,minclo,amax,maxclo); minclo := open; IF rmin_in THEN minclo := closed; END_IF; IF rmax_exists THEN maxclo := open; IF rmax_in THEN maxclo := closed; END_IF; ritv := make_finite_real_interval(rmin,minclo,rmax,maxclo); ELSE ritv := make_real_interval_from_min(rmin,minclo); END_IF; RETURN (make_polar_complex_number_region(centre,ritv,aitv)); END_FUNCTION; -- enclose_cregion_in_pregion FUNCTION enclose_pregion_in_cregion(prgn : polar_complex_number_region) : cartesian_complex_number_region; PROCEDURE nearest_good_direction(acart : REAL; aitv : finite_real_interval; VAR a : REAL; VAR a_in : BOOLEAN); a := acart; a_in := TRUE; IF a < aitv.min THEN -- a+2.0*PI > aitv.min automatically! IF a+2.0*PI < aitv.max THEN RETURN; END_IF; IF a+2.0*PI = aitv.max THEN a_in := max_included(aitv); RETURN; END_IF; ELSE IF a = aitv.min THEN a_in := min_included(aitv); RETURN; ELSE IF a < aitv.max THEN RETURN; ELSE IF a = aitv.max THEN a_in := max_included(aitv); RETURN; END_IF; END_IF; END_IF; END_IF; IF COS(acart - aitv.max) >= COS(acart - aitv.min) THEN a := aitv.max; a_in := max_included(aitv); ELSE a := aitv.min; a_in := min_included(aitv); END_IF; END_PROCEDURE; LOCAL xc, yc, xmin, xmax, ymin, ymax : REAL := 0.0; ritv, xitv, yitv : real_interval; aitv : finite_real_interval; xmin_exists, xmax_exists, ymin_exists, ymax_exists : BOOLEAN; xmin_in, xmax_in, ymin_in, ymax_in : BOOLEAN := FALSE; a, r : REAL := 0.0; a_in : BOOLEAN := FALSE; min_clo, max_clo : open_closed := open; END_LOCAL; IF NOT EXISTS (prgn) THEN RETURN (?); END_IF; -- Extract elementary input data xc := prgn.centre.real_part; yc := prgn.centre.imag_part; ritv := prgn.distance_constraint; aitv := prgn.direction_constraint; -- Determine xmin data nearest_good_direction(PI,aitv,a,a_in); IF COS(a) >= 0.0 THEN xmin_exists := TRUE; xmin := xc + real_min(ritv)*COS(a); xmin_in := a_in AND (min_included(ritv) OR (COS(a) = 0.0)); ELSE IF max_exists(ritv) THEN xmin_exists := TRUE; xmin := xc + real_max(ritv)*COS(a); xmin_in := a_in AND max_included(ritv); ELSE xmin_exists := FALSE; END_IF; END_IF; -- Determine xmax data nearest_good_direction(0.0,aitv,a,a_in); IF COS(a) <= 0.0 THEN xmax_exists := TRUE; xmax := xc + real_min(ritv)*COS(a); xmax_in := a_in AND (min_included(ritv) OR (COS(a) = 0.0)); ELSE IF max_exists(ritv) THEN xmax_exists := TRUE; xmax := xc + real_max(ritv)*COS(a); xmax_in := a_in AND max_included(ritv); ELSE xmax_exists := FALSE; END_IF; END_IF; -- Determine ymin data nearest_good_direction(-0.5*PI,aitv,a,a_in); IF SIN(a) >= 0.0 THEN ymin_exists := TRUE; ymin := yc + real_min(ritv)*SIN(a); ymin_in := a_in AND (min_included(ritv) OR (SIN(a) = 0.0)); ELSE IF max_exists(ritv) THEN ymin_exists := TRUE; ymin := yc + real_max(ritv)*SIN(a); ymin_in := a_in AND max_included(ritv); ELSE ymin_exists := FALSE; END_IF; END_IF; -- Determine ymax data nearest_good_direction(0.5*PI,aitv,a,a_in); IF SIN(a) <= 0.0 THEN ymax_exists := TRUE; ymax := yc + real_min(ritv)*SIN(a); ymax_in := a_in AND (min_included(ritv) OR (SIN(a) = 0.0)); ELSE IF max_exists(ritv) THEN ymax_exists := TRUE; ymax := yc + real_max(ritv)*SIN(a); ymax_in := a_in AND max_included(ritv); ELSE ymax_exists := FALSE; END_IF; END_IF; -- Construct result IF NOT (xmin_exists OR xmax_exists OR ymin_exists OR ymax_exists) THEN RETURN (?); -- No finite boundaries exist END_IF; -- Construct real_constraint IF xmin_exists THEN IF xmin_in THEN min_clo := closed; ELSE min_clo := open; END_IF; IF xmax_exists THEN IF xmax_in THEN max_clo := closed; ELSE max_clo := open; END_IF; xitv := make_finite_real_interval(xmin,min_clo,xmax,max_clo); ELSE xitv := make_real_interval_from_min(xmin,min_clo); END_IF; ELSE IF xmax_exists THEN IF xmax_in THEN max_clo := closed; ELSE max_clo := open; END_IF; xitv := make_real_interval_to_max(xmax,max_clo); ELSE xitv := the_reals; END_IF; END_IF; -- Construct imag_constraint IF ymin_exists THEN IF ymin_in THEN min_clo := closed; ELSE min_clo := open; END_IF; IF ymax_exists THEN IF ymax_in THEN max_clo := closed; ELSE max_clo := open; END_IF; yitv := make_finite_real_interval(ymin,min_clo,ymax,max_clo); ELSE yitv := make_real_interval_from_min(ymin,min_clo); END_IF; ELSE IF ymax_exists THEN IF ymax_in THEN max_clo := closed; ELSE max_clo := open; END_IF; yitv := make_real_interval_to_max(ymax,max_clo); ELSE yitv := the_reals; END_IF; END_IF; -- Construct cartesian region RETURN (make_cartesian_complex_number_region(xitv,yitv)); END_FUNCTION; -- enclose_pregion_in_cregion FUNCTION enclose_pregion_in_pregion(prgn : polar_complex_number_region; centre : complex_number_literal) : polar_complex_number_region; -- Find equivalent direction in range -PI < a <= PI. FUNCTION angle(a : REAL) : REAL; REPEAT WHILE a > PI; a := a - 2.0*PI; END_REPEAT; REPEAT WHILE a <= -PI; a := a + 2.0*PI; END_REPEAT; RETURN (a); END_FUNCTION; -- Find proper limits for direction interval PROCEDURE angle_range(VAR amin, amax : REAL); amin := angle(amin); IF amin = PI THEN amin := -PI; END_IF; amax := angle(amax); IF amax <= amin THEN amax := amax + 2.0*PI; END_IF; END_PROCEDURE; -- Determine whether a direction is strictly within a direction interval FUNCTION strictly_in(a : REAL; aitv : finite_real_interval) : LOGICAL; a := angle(a); RETURN ({aitv.min < a < aitv.max} OR {aitv.min < a+2.0*PI < aitv.max}); END_FUNCTION; -- Find min and max and related inclusion booleans among four candidates, -- using a base direction chosen to ensure the algebraic comparisons are valid. PROCEDURE find_aminmax( ab,a0,a1,a2,a3 : REAL; in0,in1,in2,in3 : BOOLEAN; VAR amin,amax : REAL; VAR amin_in,amax_in : BOOLEAN); LOCAL a : REAL; END_LOCAL; amin := angle(a0-ab); amin_in := in0; amax := amin; amax_in := in0; a := angle(a1-ab); IF a = amin THEN amin_in := amin_in OR in1; END_IF; IF a < amin THEN amin := a; amin_in := in1; END_IF; IF a = amax THEN amax_in := amax_in OR in1; END_IF; IF a > amax THEN amax := a; amax_in := in1; END_IF; a := angle(a2-ab); IF a = amin THEN amin_in := amin_in OR in2; END_IF; IF a < amin THEN amin := a; amin_in := in2; END_IF; IF a = amax THEN amax_in := amax_in OR in2; END_IF; IF a > amax THEN amax := a; amax_in := in2; END_IF; a := angle(a3-ab); IF a = amin THEN amin_in := amin_in OR in3; END_IF; IF a < amin THEN amin := a; amin_in := in3; END_IF; IF a = amax THEN amax_in := amax_in OR in3; END_IF; IF a > amax THEN amax := a; amax_in := in3; END_IF; amin := amin+ab; amax := amax+ab; angle_range(amin,amax); END_PROCEDURE; LOCAL ritp, ritv : real_interval; aitp, aitv : finite_real_interval; xp, yp, xc, yc, rmax, rmin, amin, amax, rc, acp, apc : REAL := 0.0; rmax_in, rmin_in, amin_in, amax_in : BOOLEAN := FALSE; rmxp, rmnp, x, y, r, a, ab, r0, a0, r1, a1, r2, a2, r3, a3 : REAL := 0.0; in0, in1, in2, in3, inn : BOOLEAN := FALSE; minclo, maxclo : open_closed := open; END_LOCAL; -- Extract elementary input information IF NOT EXISTS (prgn) OR NOT EXISTS (centre) THEN RETURN (?); END_IF; xp := prgn.centre.real_part; yp := prgn.centre.imag_part; ritp := prgn.distance_constraint; aitp := prgn.direction_constraint; xc := centre.real_part; yc := centre.imag_part; IF (xc = xp) AND (yc = yp) THEN RETURN (prgn); END_IF; rc := SQRT((xp-xc)**2 + (yp-yc)**2); acp := atan2(yp-yc,xp-xc); apc := atan2(yc-yp,xc-xp); rmnp := real_min(ritp); -- Analyse cases by existence of max distance and direction limits IF max_exists(ritp) THEN rmxp := real_max(ritp); IF aitp.max - aitp.min = 2.0*PI THEN -- annulus or disk, with or without slot or puncture inn := NOT max_included(aitp); -- slot exists; a := angle(aitp.min); -- slot direction rmax := rc+rmxp; rmax_in := max_included(ritp); IF inn AND (acp = a) THEN rmax_in := FALSE; END_IF; IF rc > rmxp THEN a0 := ASIN(rmxp/rc); amin := angle(acp-a0); amin_in := max_included(ritp); IF amin = PI THEN amin := -PI; END_IF; amax := angle(acp+a0); amax_in := amin_in; IF amax < amin THEN amax := amax + 2.0*PI; END_IF; rmin := rc-rmxp; rmin_in := amin_in; IF inn THEN -- slotted case IF apc = a THEN rmin_in := FALSE; END_IF; IF angle(amin+0.5*PI) = a THEN amin_in := FALSE; END_IF; IF angle(amax-0.5*PI) = a THEN amax_in := FALSE; END_IF; END_IF; ELSE IF rc = rmxp THEN amin := angle(acp-0.5*PI); amin_in := FALSE; IF amin = PI THEN amin := -PI; END_IF; amax := angle(acp+0.5*PI); amax_in := FALSE; IF amax < amin THEN amax := amax + 2.0*PI; END_IF; rmin := 0.0; rmin_in := max_included(ritp); IF inn AND (apc = a) THEN rmin_in := FALSE; END_IF; ELSE IF rc > rmnp THEN IF inn AND (apc = a) THEN -- in the slot rmin := 0.0; rmin_in := FALSE; amin := aitp.min; amin_in := FALSE; amax