Overview Schemas Index

MATHEMATICAL_FUNCTIONS_SCHEMA (jsdai.SMathematical_functions_schema)


FUNCTION simplify_generic_expression
          (expr : generic_expression) : maths_value;

FUNCTION restore_unary(expr : unary_generic_expression;
                         opnd : generic_expression) : generic_expression;
    expr.operand := opnd;
    RETURN  (expr);
  END_FUNCTION;  -- restore_unary
  FUNCTION  restore_binary(expr       : binary_generic_expression;
                          opd1, opd2 : generic_expression) : generic_expression;
    expr.operands[1] := opd1;
    expr.operands[2] := opd2;
    RETURN  (expr);
  END_FUNCTION;  -- restore_binary
  FUNCTION  restore_mulary(expr : multiple_arity_generic_expression;
                          ops  : LIST  OF  generic_expression) : generic_expression;
    expr.operands := ops;
    RETURN  (expr);
  END_FUNCTION;  -- restore_mulary
  FUNCTION make_number_literal(nmb : NUMBER) : generic_literal;
    IF  'INTEGER' IN  TYPEOF  (nmb) THEN   RETURN  (make_int_literal(nmb));  END_IF;
    RETURN  (make_real_literal(nmb));
  END_FUNCTION;  -- make_number_literal;
  LOCAL
    types : SET OF  STRING := stripped_typeof (expr);
    v1, v2 : maths_value;
    vlist : LIST  OF  maths_value := [];
    op1, op2 : generic_expression;
    oplist : LIST  OF  generic_expression := [];
    opnds : LIST [2:?] OF  generic_expression;
    n, m : INTEGER;
    finfun : maths_function_select;
    boo : BOOLEAN;
    str : STRING;
    nmb : NUMBER;
  END_LOCAL;
  -- Unwrap the elementary kinds OF  literals
  IF  'INT_LITERAL' IN  types THEN
    RETURN  (convert_to_maths_value (expr\int_literal.the_value));
  END_IF;
  IF  'REAL_LITERAL' IN  types THEN
    RETURN  (convert_to_maths_value (expr\real_literal.the_value));
  END_IF;
  IF  'BOOLEAN_LITERAL' IN  types THEN
    RETURN  (convert_to_maths_value (expr\boolean_literal.the_value));
  END_IF;
  IF  'STRING_LITERAL' IN  types THEN
    RETURN  (convert_to_maths_value (expr\string_literal.the_value));
  END_IF;
  IF  'COMPLEX_NUMBER_LITERAL' IN  types THEN
    RETURN  (expr);  -- No simpler expression available
  END_IF;
  IF  'LOGICAL_LITERAL' IN  types THEN
    RETURN  (convert_to_maths_value (expr\logical_literal.lit_value));
  END_IF;
  IF  'BINARY_LITERAL' IN  types THEN
    RETURN  (convert_to_maths_value (expr\binary_literal.lit_value));
  END_IF;
  IF  'MATHS_ENUM_LITERAL' IN  types THEN
    RETURN  (expr\maths_enum_literal.lit_value);
  END_IF;
  IF  'REAL_TUPLE_LITERAL' IN  types THEN
    RETURN  (convert_to_maths_value (expr\real_tuple_literal.lit_value));
  END_IF;
  IF  'INTEGER_TUPLE_LITERAL' IN  types THEN
    RETURN  (convert_to_maths_value (expr\integer_tuple_literal.lit_value));
  END_IF;
  IF  'ATOM_BASED_LITERAL' IN  types THEN
    RETURN  (expr\atom_based_literal.lit_value);
  END_IF;
  IF  'MATHS_TUPLE_LITERAL' IN  types THEN
    RETURN  (convert_to_maths_value (expr\maths_tuple_literal.lit_value));
  END_IF;
  -- Simplify one special class OF  literals
  IF  'MATHS_SPACE' IN  types THEN
    RETURN  (simplify_maths_space(expr));
  END_IF;
  -- Simplify one special kind OF  expression
  IF  'FUNCTION_APPLICATION' IN  types THEN
    RETURN  (simplify_function_application(expr));
  END_IF;
  -- Separate AND  simplify the operands
  IF  'UNARY_GENERIC_EXPRESSION' IN  types THEN
    v1 := simplify_generic_expression(expr\unary_generic_expression.operand);
    op1 := convert_to_operand(v1);
  END_IF;
  IF  'BINARY_GENERIC_EXPRESSION' IN  types THEN
    v1 := simplify_generic_expression(expr\binary_generic_expression.operands[1]);
    op1 := convert_to_operand(v1);
    v2 := simplify_generic_expression(expr\binary_generic_expression.operands[2]);
    op2 := convert_to_operand(v2);
  END_IF;
  IF  'MULTIPLE_ARITY_GENERIC_EXPRESSION' IN  types THEN
    opnds := expr\multiple_arity_generic_expression.operands;
    REPEAT  i := 1 TO  SIZEOF  (opnds);
      v1 := simplify_generic_expression(opnds[i]);
      INSERT  (vlist, v1, i-1);
      INSERT  (oplist, convert_to_operand(v1), i-1);
    END_REPEAT;
  END_IF;
  -- Simplify the one kind OF  maths_function which derives its operands.
  IF  'PARALLEL_COMPOSED_FUNCTION' IN  types THEN
    v1 := vlist[1];
    n := SIZEOF  (vlist);
    finfun := vlist[n];
    REMOVE  (vlist, n);
    REMOVE  (vlist, 1);
    RETURN  (make_parallel_composed_function(v1,vlist,finfun));
  END_IF;
  -- Simplify individual kinds OF expressions.  It is NOT  necessary TO  cover all cases.
  IF  ('ABS_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (ABS(v1)));
  END_IF;
  IF  ('ACOS_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (ACOS(v1)));
  END_IF;
  IF  'AND_EXPRESSION' IN  types THEN
    REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
      IF  'BOOLEAN' IN  TYPEOF  (vlist[i]) THEN
        boo := vlist[i];
        IF  NOT boo THEN   RETURN  (convert_to_maths_value(FALSE));  END_IF;
        REMOVE  (oplist, i);
      END_IF;
    END_REPEAT;
    IF  SIZEOF  (oplist) = 0 THEN   RETURN  (convert_to_maths_value(TRUE));  END_IF;
    IF  SIZEOF  (oplist) = 1 THEN   RETURN  (oplist[1]);  END_IF;
  END_IF;
  IF  ('ASIN_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (ASIN(v1)));
  END_IF;
  IF  ('ATAN_EXPRESSION' IN  types) AND
    ('NUMBER' IN  TYPEOF  (v1)) AND  ('NUMBER' IN  TYPEOF  (v2)) THEN
    RETURN  (convert_to_maths_value (ATAN(v1,v2)));
  END_IF;
  IF  ('COMPARISON_EXPRESSION' IN  types) AND  (
    (('NUMBER' IN  TYPEOF  (v1)) AND  ('NUMBER' IN  TYPEOF  (v2))) OR
    (('STRING' IN  TYPEOF  (v1)) AND  ('STRING' IN  TYPEOF  (v2))) OR
    (('BOOLEAN' IN  TYPEOF  (v1)) AND  ('BOOLEAN' IN  TYPEOF  (v2))) ) THEN
    IF       'COMPARISON_EQUAL'         IN  types THEN   boo := bool(v1 = v2);
    ELSE  IF  'COMPARISON_GREATER'       IN  types THEN   boo := bool(v1 > v2);
    ELSE  IF  'COMPARISON_GREATER_EQUAL' IN  types THEN   boo := bool(v1 >= v2);
    ELSE  IF  'COMPARISON_LESS'          IN  types THEN   boo := bool(v1 < v2);
    ELSE  IF  'COMPARISON_LESS_EQUAL'    IN  types THEN   boo := bool(v1 <= v2);
    ELSE  IF  'COMPARISON_NOT_EQUAL'     IN  types THEN   boo := bool(v1 <> v2);
    ELSE  IF  'LIKE_EXPRESSION'          IN  types THEN   boo := bool(v1 LIKE v2);
    ELSE   RETURN  (?);  -- Unreachable
    END_IF;  END_IF;  END_IF;  END_IF;  END_IF;  END_IF;  END_IF;
    RETURN  (convert_to_maths_value (boo));
  END_IF;
  IF  'CONCAT_EXPRESSION' IN  types THEN
    str := '';
    REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
      IF  'STRING' IN  TYPEOF  (vlist[i]) THEN
        str := vlist[i] + str;
        REMOVE  (oplist, i);
      ELSE IF  LENGTH(str) > 0 THEN
        INSERT  (oplist, make_string_literal(str), i);
        str := '';
      END_IF;  END_IF;
    END_REPEAT;
    IF  SIZEOF  (oplist) = 0 THEN   RETURN  (convert_to_maths_value(str));  END_IF;
    IF  LENGTH(str) > 0 THEN   INSERT  (oplist, make_string_literal(str), 0);  END_IF;
    IF  SIZEOF  (oplist) = 1 THEN   RETURN  (oplist[1]);  END_IF;
  END_IF;
  IF  ('COS_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (COS(v1)));
  END_IF;
  IF  ('DIV_EXPRESSION' IN  types) AND
    ('NUMBER' IN  TYPEOF  (v1)) AND  ('NUMBER' IN  TYPEOF  (v2)) THEN
    RETURN  (convert_to_maths_value (v1 DIV v2));
  END_IF;
  IF  'EQUALS_EXPRESSION' IN  types THEN
    opnds := expr\binary_generic_expression.operands;
    RETURN  (convert_to_maths_value (opnds[1] :=: opnds[2]));
  END_IF;
  IF  ('EXP_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (EXP(v1)));
  END_IF;
  IF  ('FORMAT_EXPRESSION' IN  types) AND
    ('NUMBER' IN  TYPEOF  (v1)) AND  ('STRING' IN  TYPEOF  (v2)) THEN
    RETURN  (convert_to_maths_value (FORMAT(v1,v2)));
  END_IF;
  IF  ('INDEX_EXPRESSION' IN  types) AND
    ('STRING' IN  TYPEOF  (v1)) AND  ('NUMBER' IN  TYPEOF  (v2)) THEN
    str := v1;  n := v2;
    RETURN  (convert_to_maths_value (str[n]));
  END_IF;
  IF  ('INT_VALUE_EXPRESSION' IN  types) AND  ('STRING' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (VALUE(v1)));
  END_IF;
  IF  'INTERVAL_EXPRESSION' IN  types THEN
    str := '';
    IF  'NUMBER'  IN  TYPEOF  (vlist[1]) THEN  str := 'NUMBER';   END_IF;
    IF  'STRING'  IN  TYPEOF  (vlist[1]) THEN  str := 'STRING';   END_IF;
    IF  'BOOLEAN' IN  TYPEOF  (vlist[1]) THEN  str := 'BOOLEAN';  END_IF;
    IF  (LENGTH (str) > 0) AND  (str IN  TYPEOF  (vlist[2])) AND
      (str IN  TYPEOF  (vlist[3])) THEN
      RETURN  (convert_to_maths_value ({vlist[1] <= vlist[2] <= vlist[3]}));
    END_IF;
  END_IF;
  IF  ('LENGTH_EXPRESSION' IN  types) AND  ('STRING' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (LENGTH(v1)));
  END_IF;
  IF  ('LOG_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (LOG(v1)));
  END_IF;
  IF  ('LOG10_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (LOG10(v1)));
  END_IF;
  IF  ('LOG2_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (LOG2(v1)));
  END_IF;
  IF  'MAXIMUM_EXPRESSION' IN  types THEN
    boo := FALSE;
    REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
      IF  'NUMBER' IN  TYPEOF  (vlist[i]) THEN
        IF  boo THEN
          IF  nmb < vlist[i] THEN   nmb := vlist[i];  END_IF;
        ELSE
          nmb := vlist[i];  boo := TRUE;
        END_IF;
        REMOVE  (oplist, i);
      END_IF;
    END_REPEAT;
    IF  SIZEOF  (oplist) = 0 THEN   RETURN  (convert_to_maths_value(nmb));  END_IF;
    IF  boo THEN   INSERT  (oplist, make_number_literal(nmb), 0);  END_IF;
  END_IF;
  IF  'MINIMUM_EXPRESSION' IN  types THEN
    boo := FALSE;
    REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
      IF  'NUMBER' IN  TYPEOF  (vlist[i]) THEN
        IF  boo THEN
          IF  nmb > vlist[i] THEN   nmb := vlist[i];  END_IF;
        ELSE
          nmb := vlist[i];  boo := TRUE;
        END_IF;
        REMOVE  (oplist, i);
      END_IF;
    END_REPEAT;
    IF  SIZEOF  (oplist) = 0 THEN   RETURN  (convert_to_maths_value(nmb));  END_IF;
    IF  boo THEN   INSERT  (oplist, make_number_literal(nmb), 0);  END_IF;
  END_IF;
  IF  ('MINUS_EXPRESSION' IN  types) AND
    ('NUMBER' IN  TYPEOF  (v1)) AND  ('NUMBER' IN  TYPEOF  (v2)) THEN
    RETURN  (convert_to_maths_value (v1 - v2));
  END_IF;
  IF  ('MOD_EXPRESSION' IN  types) AND
    ('NUMBER' IN  TYPEOF  (v1)) AND  ('NUMBER' IN  TYPEOF  (v2)) THEN
    RETURN  (convert_to_maths_value (v1 MOD v2));
  END_IF;
  IF  'MULT_EXPRESSION' IN  types THEN
    nmb := 1;
    REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
      IF  'NUMBER' IN  TYPEOF  (vlist[i]) THEN
        nmb := nmb * vlist[i];
        REMOVE  (oplist, i);
      END_IF;
    END_REPEAT;
    IF  SIZEOF  (oplist) = 0 THEN   RETURN  (convert_to_maths_value(nmb));  END_IF;
    IF  nmb <> 1 THEN   INSERT  (oplist, make_number_literal(nmb), 0);  END_IF;
    IF  SIZEOF  (oplist) = 1 THEN   RETURN  (oplist[1]);  END_IF;
  END_IF;
  IF  ('NOT_EXPRESSION' IN  types) AND  ('BOOLEAN' IN  TYPEOF  (v1)) THEN
    boo := v1;
    RETURN  (convert_to_maths_value (NOT(boo)));
  END_IF;
  IF  ('ODD_EXPRESSION' IN  types) AND  ('INTEGER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (ODD(v1)));
  END_IF;
  IF  'OR_EXPRESSION' IN  types THEN
    REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
      IF  'BOOLEAN' IN  TYPEOF  (vlist[i]) THEN
        boo := vlist[i];
        IF  boo THEN   RETURN  (convert_to_maths_value(TRUE));  END_IF;
        REMOVE  (oplist, i);
      END_IF;
    END_REPEAT;
    IF  SIZEOF  (oplist) = 0 THEN   RETURN  (convert_to_maths_value(FALSE));  END_IF;
    IF  SIZEOF  (oplist) = 1 THEN   RETURN  (oplist[1]);  END_IF;
  END_IF;
  IF  'PLUS_EXPRESSION' IN  types THEN
    nmb := 0;
    REPEAT i := SIZEOF  (vlist) TO 1 BY -1;
      IF  'NUMBER' IN  TYPEOF  (vlist[i]) THEN
        nmb := nmb + vlist[i];
        REMOVE (oplist, i);
      END_IF;
    END_REPEAT;
    IF  SIZEOF  (oplist) = 0 THEN   RETURN  (convert_to_maths_value(nmb));  END_IF;
    IF  nmb <> 0 THEN   INSERT (oplist, make_number_literal(nmb), 0);  END_IF;
    IF  SIZEOF (oplist) = 1 THEN  RETURN  (oplist[1]);  END_IF;
  END_IF;
  IF  ('POWER_EXPRESSION' IN  types) AND
    ('NUMBER' IN  TYPEOF  (v1)) AND  ('NUMBER' IN  TYPEOF  (v2)) THEN
    RETURN  (convert_to_maths_value (v1 ** v2));
  END_IF;
  IF  ('SIN_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (SIN(v1)));
  END_IF;
  IF  ('SLASH_EXPRESSION' IN  types) AND
    ('NUMBER' IN  TYPEOF  (v1)) AND  ('NUMBER' IN  TYPEOF  (v2)) THEN
    RETURN  (convert_to_maths_value (v1 / v2));
  END_IF;
  IF  ('SQUARE_ROOT_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (SQRT(v1)));
  END_IF;
  IF  ('SUBSTRING_EXPRESSION' IN  types) AND
    ('STRING' IN  TYPEOF  (vlist[1])) AND  ('NUMBER' IN  TYPEOF  (vlist[2])) AND
    ('NUMBER' IN  TYPEOF  (vlist[3])) THEN
    str := vlist[1];  n := vlist[2];  m := vlist[3];
    RETURN  (convert_to_maths_value (str[n:m]));
  END_IF;
  IF  ('TAN_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (TAN(v1)));
  END_IF;
  IF  ('UNARY_MINUS_EXPRESSION' IN  types) AND  ('NUMBER' IN  TYPEOF  (v1)) THEN
    nmb := v1;
    RETURN  (convert_to_maths_value (-nmb));
  END_IF;
  IF  ('VALUE_EXPRESSION' IN  types) AND  ('STRING' IN  TYPEOF  (v1)) THEN
    RETURN  (convert_to_maths_value (VALUE(v1)));
  END_IF;
  IF  ('XOR_EXPRESSION' IN  types) AND
    ('BOOLEAN' IN  TYPEOF  (v1)) AND ('BOOLEAN' IN  TYPEOF (v2)) THEN
    RETURN  (convert_to_maths_value (v1 XOR v2));
  END_IF;
  -- No special simplification defined, RETURN  same WITH simplified operands.
  IF  'UNARY_GENERIC_EXPRESSION' IN  types THEN
    RETURN  (restore_unary(expr,op1));
  END_IF;
  IF  'BINARY_GENERIC_EXPRESSION' IN  types THEN
    RETURN  (restore_binary(expr,op1,op2));
  END_IF;
  IF 'MULTIPLE_ARITY_GENERIC_EXPRESSION' IN types THEN
    RETURN  (restore_mulary(expr,oplist));
  END_IF;
  -- Should be unreachable, but FOR safety, RETURN  unsimplified expression.
  RETURN (expr);

END_FUNCTION; -- simplify_generic_expression

public class FSimplify_generic_expression
          public static Value run(SdaiContext _context, Value expr)