Overview Schemas Index

MATHEMATICAL_FUNCTIONS_SCHEMA (jsdai.SMathematical_functions_schema)


FUNCTION simplify_function_application
          (expr : function_application) : maths_value;

FUNCTION ctmv(x : GENERIC:G) : maths_value;
    RETURN  (convert_to_maths_value(x));
  END_FUNCTION;  -- LOCAL  abbreviation FOR  convert_to_maths_value function
  PROCEDURE parts(       c : complex_number_literal;
                  VAR x, y : REAL);
    x := c.real_part;  y := c.imag_part;
  END_PROCEDURE;  -- parts
  FUNCTION  makec(x, y : REAL) : complex_number_literal;
    RETURN  (make_complex_number_literal(x,y));
  END_FUNCTION;  -- LOCAL abbreviation FOR make_complex_number_literal function
  FUNCTION good_t(v  : maths_value;
                  tn : STRING) : BOOLEAN;
    LOCAL
      tpl : LIST  OF  maths_value;
    END_LOCAL;
    IF  'LIST' IN  TYPEOF  (v) THEN
      tpl := v;
      REPEAT  i := 1 TO  SIZEOF  (tpl);
        IF  NOT  (tn IN  TYPEOF  (tpl[i])) THEN   RETURN  (FALSE);  END_IF;
      END_REPEAT;
      RETURN  (TRUE);
    END_IF;
    RETURN  (FALSE);
  END_FUNCTION;  -- good_t
  CONSTANT
    cnlit : STRING  := schema_prefix + 'COMPLEX_NUMBER_LITERAL';
  END_CONSTANT;
  LOCAL
    types : SET  OF  STRING := stripped_typeof(expr.func);
    ef_val : elementary_function_enumerators;
    is_elementary : BOOLEAN := FALSE;
    v, v1, v2, v3 : maths_value;
    vlist : LIST  OF  maths_value := [];
    gexpr : generic_expression;
    pairs : SET [1:?] OF  LIST  [2:2] OF  maths_value;
    boo : BOOLEAN;
    lgc, cum : LOGICAL;
    j, k, n : INTEGER;
    p, q, r, s, t, u : REAL;
    str, st2 : STRING;
    bin, bi2 : BINARY;
    tpl, tp2 : LIST  OF  maths_value;
    mem :SET OF maths_value := [];
  END_LOCAL;
  REPEAT  i := 1 TO  SIZEOF  (expr.arguments);
    v := simplify_maths_value(expr.arguments[i]);
    INSERT  (vlist, v, i-1);
  END_REPEAT;
  IF  SIZEOF  (vlist) >= 1 THEN   v1 := vlist[1];  END_IF;
  IF  SIZEOF  (vlist) >= 2 THEN   v2 := vlist[2];  END_IF;
  IF  SIZEOF  (vlist) >= 3 THEN   v3 := vlist[3];  END_IF;
  IF  'ELEMENTARY_FUNCTION_ENUMERATORS' IN  types THEN
    ef_val := expr.func;
    is_elementary := TRUE;
  END_IF;
  IF  'ELEMENTARY_FUNCTION' IN  types THEN
    ef_val := expr.func\elementary_function.func_id;
    is_elementary := TRUE;
  END_IF;
  IF  is_elementary THEN
    CASE ef_val OF
    ef_and : BEGIN
      cum := TRUE;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'LOGICAL' IN  TYPEOF  (vlist[i]) THEN
          lgc := vlist[i];  cum := cum AND  lgc;
          IF  lgc = FALSE  THEN   RETURN  (ctmv(FALSE));  END_IF;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(cum));  END_IF;
      IF  cum <> TRUE  THEN   INSERT  (vlist, ctmv(cum), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_or : BEGIN
      cum := FALSE;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'LOGICAL' IN  TYPEOF  (vlist[i]) THEN
          lgc := vlist[i];  cum := cum OR  lgc;
          IF  lgc = TRUE THEN   RETURN  (ctmv(TRUE));  END_IF;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(cum));  END_IF;
      IF  cum <> FALSE  THEN   INSERT  (vlist, ctmv(cum), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_not :
      IF  'LOGICAL' IN  TYPEOF  (v1) THEN   lgc := v1;  RETURN  (ctmv(NOT lgc));  END_IF;
    ef_xor : BEGIN
      IF  'LOGICAL' IN  TYPEOF  (v1) THEN
        lgc := v1;
        IF  'LOGICAL' IN  TYPEOF  (v2) THEN   cum := v2;  RETURN  (ctmv(lgc XOR cum));
        ELSE  IF  lgc = FALSE  THEN   RETURN  (ctmv(v2));
        ELSE  IF  lgc = UNKNOWN  THEN   RETURN  (ctmv(UNKNOWN));
        ELSE   RETURN  (make_function_application(ef_not,[v2]));
        END_IF;  END_IF;  END_IF;
      ELSE  IF  'LOGICAL' IN  TYPEOF  (v2) THEN
        lgc := v2;
        IF  lgc = FALSE THEN   RETURN  (ctmv(v1));
        ELSE  IF  lgc = UNKNOWN  THEN   RETURN  (ctmv(UNKNOWN));
        ELSE   RETURN  (make_function_application(ef_not,[v1]));
        END_IF;  END_IF;
      END_IF;  END_IF;
      END;
    ef_negate_i :
      IF  'INTEGER' IN  TYPEOF  (v1) THEN   j := v1;  RETURN  (ctmv(-j));  END_IF;
    ef_add_i : BEGIN
      j := 0;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'INTEGER' IN  TYPEOF  (vlist[i]) THEN
          k := vlist[i];  j := j + k;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(j));  END_IF;
      IF  j <> 0 THEN   INSERT  (vlist, ctmv(j), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_subtract_i :
      IF  ('INTEGER' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        j := v1;  k := v2;  RETURN  (ctmv(j - k));
      END_IF;
    ef_multiply_i : BEGIN
      j := 1;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'INTEGER' IN  TYPEOF  (vlist[i]) THEN
          k := vlist[i];  j := j * k;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(j));  END_IF;
      IF  j <> 1 THEN   INSERT  (vlist, ctmv(j), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_divide_i :
      IF  ('INTEGER' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        j := v1;  k := v2;  RETURN  (ctmv(j DIV  k));
      END_IF;
    ef_mod_i :
      IF  ('INTEGER' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        j := v1;  k := v2;  RETURN  (ctmv(j MOD k));
      END_IF;
    ef_exponentiate_i :
      IF  ('INTEGER' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        j := v1;  k := v2;  n := 1;
        REPEAT  i := 1 TO  ABS(k);  n := n * j;  END_REPEAT;
        IF  k < 0 THEN   n := 1 DIV  n;  END_IF;
        RETURN  (ctmv(n));
      END_IF;
    ef_eq_i :
      IF  ('INTEGER' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        j := v1;  k := v2;  RETURN  (ctmv(j = k));
      END_IF;
    ef_ne_i :
      IF  ('INTEGER' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        j := v1;  k := v2;  RETURN  (ctmv(j <> k));
      END_IF;
    ef_gt_i :
      IF  ('INTEGER' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        j := v1;  k := v2;  RETURN  (ctmv(j > k));
      END_IF;
    ef_lt_i :
      IF  ('INTEGER' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        j := v1;  k := v2;  RETURN  (ctmv(j < k));
      END_IF;
    ef_ge_i :
      IF  ('INTEGER' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        j := v1;  k := v2;  RETURN  (ctmv(j >= k));
      END_IF;
    ef_le_i :
      IF  ('INTEGER' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        j := v1;  k := v2;  RETURN  (ctmv(j <= k));
      END_IF;
    ef_abs_i :
      IF  'INTEGER' IN  TYPEOF  (v1) THEN   j := v1;  RETURN  (ctmv(ABS(j)));  END_IF;
    ef_max_i : BEGIN
      boo := FALSE;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'INTEGER' IN  TYPEOF  (vlist[i]) THEN
          IF  boo THEN   k := vlist[i];  IF  k > j THEN   j := k;  END_IF;
          ELSE   j := vlist[i];  boo := TRUE;  END_IF;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(j));  END_IF;
      IF  boo THEN   INSERT  (vlist, ctmv(j), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_min_i : BEGIN
      boo := FALSE;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'INTEGER' IN  TYPEOF  (vlist[i]) THEN
          IF  boo THEN   k := vlist[i];  IF  k < j THEN   j := k;  END_IF;
          ELSE   j := vlist[i];  boo := TRUE;  END_IF;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(j));  END_IF;
      IF  boo THEN   INSERT  (vlist, ctmv(j), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    -- ef_if_i : combined WITH  ef_if
    ef_negate_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(-r));  END_IF;
    ef_reciprocal_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(1.0/r));  END_IF;
    ef_add_r : BEGIN
      r := 0.0;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'REAL' IN  TYPEOF  (vlist[i]) THEN
          s := vlist[i];  r := r + s;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(r));  END_IF;
      IF  r <> 0.0 THEN   INSERT  (vlist, ctmv(r), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_subtract_r :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  RETURN  (ctmv(r - s));
      END_IF;
    ef_multiply_r : BEGIN
      r := 1.0;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'REAL' IN  TYPEOF  (vlist[i]) THEN
          s := vlist[i];  r := r * s;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(r));  END_IF;
      IF  r <> 1.0 THEN   INSERT  (vlist, ctmv(r), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_divide_r :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  RETURN  (ctmv(r / s));
      END_IF;
    ef_mod_r :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  t := r/s;  j := t DIV 1;
        IF  (t < 0.0) AND  (j <> t) THEN   j := j - 1;  END_IF;
        RETURN  (ctmv(r - j * s));
      END_IF;
    ef_exponentiate_r :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  RETURN  (ctmv(r ** s));
      END_IF;
    ef_exponentiate_ri :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        r := v1;  k := v2;  t := 1.0;
        REPEAT  i := 1 TO  ABS(k);  t := t * r;  END_REPEAT;
        IF  k < 0 THEN   t := 1.0/t;  END_IF;
        RETURN  (ctmv(t));
      END_IF;
    ef_eq_r :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  RETURN  (ctmv(r = s));
      END_IF;
    ef_ne_r :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  RETURN  (ctmv(r <> s));
      END_IF;
    ef_gt_r :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  RETURN  (ctmv(r > s));
      END_IF;
    ef_lt_r :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  RETURN  (ctmv(r < s));
      END_IF;
    ef_ge_r :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  RETURN  (ctmv(r >= s));
      END_IF;
    ef_le_r :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  RETURN  (ctmv(r <= s));
      END_IF;
    ef_abs_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(ABS(r)));  END_IF;
    ef_max_r : BEGIN
      boo := FALSE;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'REAL' IN  TYPEOF  (vlist[i]) THEN
          IF  boo THEN   s := vlist[i];  IF  s > r THEN   r := s;  END_IF;
          ELSE   r := vlist[i];  boo := TRUE;  END_IF;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(r));  END_IF;
      IF  boo THEN   INSERT  (vlist, ctmv(r), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_min_r : BEGIN
      boo := FALSE;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'REAL' IN  TYPEOF  (vlist[i]) THEN
          IF  boo THEN   s := vlist[i];  IF  s < r THEN   r := s;  END_IF;
          ELSE   r := vlist[i];  boo := TRUE;  END_IF;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(r));  END_IF;
      IF  boo THEN   INSERT  (vlist, ctmv(r), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_acos_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(ACOS(r)));  END_IF;
    ef_asin_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(ASIN(r)));  END_IF;
    ef_atan2_r :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  RETURN  (ctmv(atan2(r,s)));
      END_IF;
    ef_cos_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(COS(r)));  END_IF;
    ef_exp_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(EXP(r)));  END_IF;
    ef_ln_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(LOG(r)));  END_IF;
    ef_log2_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(LOG2(r)));  END_IF;
    ef_log10_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(LOG10(r)));  END_IF;
    ef_sin_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(SIN(r)));  END_IF;
    ef_sqrt_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(SQRT(r)));  END_IF;
    ef_tan_r :
      IF  'REAL' IN  TYPEOF  (v1) THEN   r := v1;  RETURN  (ctmv(TAN(r)));  END_IF;
    -- ef_if_r : combined WITH  ef_if
    ef_form_c :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  ('REAL' IN  TYPEOF  (v2)) THEN
        r := v1;  s := v2;  RETURN  (makec(r,s));
      END_IF;
    ef_rpart_c :
      IF  cnlit IN  TYPEOF  (v1) THEN
        RETURN  (ctmv(v1\complex_number_literal.real_part));
      END_IF;
    ef_ipart_c :
      IF  cnlit IN  TYPEOF  (v1) THEN
        RETURN  (ctmv(v1\complex_number_literal.imag_part));
      END_IF;
    ef_negate_c :
      IF  cnlit IN  TYPEOF  (v1) THEN   parts(v1,p,q);  RETURN  (makec(-p,-q));  END_IF;
    ef_reciprocal_c :
      IF  cnlit IN  TYPEOF  (v1) THEN
        parts(v1,p,q);  t := p*p + q*q;  RETURN  (makec(p/t,-q/t));
      END_IF;
    ef_add_c : BEGIN
      p := 0.0;  q := 0.0;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  cnlit IN  TYPEOF  (vlist[i]) THEN
          parts(vlist[i],r,s);  p := p + r;  q := q + s;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (makec(p,q));  END_IF;
      IF  p*p+q*q <> 0.0 THEN   INSERT  (vlist, makec(p,q), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_subtract_c :
      IF  (cnlit IN  TYPEOF  (v1)) AND  (cnlit IN  TYPEOF  (v2)) THEN
        parts(v1,p,q);  parts(v2,r,s);  RETURN  (makec(p-r,q-s));
      END_IF;
    ef_multiply_c : BEGIN
      p := 1.0;  q := 0.0;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  cnlit IN  TYPEOF  (vlist[i]) THEN
          parts(vlist[i],r,s);  p := p*r-q*s;  q := p*s+q*r;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (makec(p,q));  END_IF;
      IF  (p <> 1.0) OR  (q <> 0.0) THEN   INSERT  (vlist, makec(p,q), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_divide_c :
      IF  (cnlit IN  TYPEOF  (v1)) AND  (cnlit IN  TYPEOF  (v2)) THEN
        parts(v1,p,q);  parts(v2,r,s);  t := r*r+s*s;
        RETURN  (makec((p*r+q*s)/t,(q*r-p*s)/t));
      END_IF;
    ef_exponentiate_c :
      IF  (cnlit IN  TYPEOF  (v1)) AND  (cnlit IN  TYPEOF  (v2)) THEN
        parts(v1,p,q);  parts(v2,r,s);  t := 0.5*LOG(p*p+q*q);  u := atan2(q,p);
        p := r*t-s*u;  q := r*u+s*t;  r := EXP(p);
        RETURN  (makec(r*COS(q),r*SIN(q)));
      END_IF;
    ef_exponentiate_ci :
      IF  (cnlit IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        parts(v1,p,q);  k := v2;  r := 1.0;  s := 0.0;
        REPEAT  i := 1 TO  ABS(k);  r := p*r-q*s;  s := p*s+q*r;  END_REPEAT;
        IF  k < 0 THEN   t := r*r+s*s;  r := r/t;  s := -s/t;  END_IF;
        RETURN  (makec(r,s));
      END_IF;
    ef_eq_c :
      IF  (cnlit IN  TYPEOF  (v1)) AND  (cnlit IN  TYPEOF  (v2)) THEN
        parts(v1,p,q);  parts(v2,r,s);  RETURN  (ctmv((p = r) AND  (q = s)));
      END_IF;
    ef_ne_c :
      IF  (cnlit IN  TYPEOF  (v1)) AND  (cnlit IN  TYPEOF  (v2)) THEN
        parts(v1,p,q);  parts(v2,r,s);  RETURN  (ctmv((p <> r) OR (q <> s)));
      END_IF;
    ef_conjugate_c :
      IF  cnlit IN  TYPEOF  (v1) THEN   parts(v1,p,q);  RETURN  (makec(p,-q));  END_IF;
    ef_abs_c :
      IF  cnlit IN  TYPEOF  (v1) THEN
        parts(v1,p,q);  RETURN  (ctmv(SQRT(p*p+q*q)));
      END_IF;
    ef_arg_c :
      IF  cnlit IN  TYPEOF  (v1) THEN
        parts(v1,p,q);  RETURN  (ctmv(atan2(q,p)));
      END_IF;
    ef_cos_c :
      IF  cnlit IN  TYPEOF  (v1) THEN
        parts(v1,p,q);  t := 0.5*EXP(-q);  u := 0.5*EXP(q);
        RETURN  (makec((t+u)*COS(p),(t-u)*SIN(p)));
      END_IF;
    ef_exp_c :
      IF  cnlit IN  TYPEOF  (v1) THEN
        parts(v1,p,q);  RETURN  (makec(EXP(p)*COS(q),EXP(p)*SIN(q)));
      END_IF;
    ef_ln_c :
      IF  cnlit IN  TYPEOF  (v1) THEN
        parts(v1,p,q);  RETURN  (makec(0.5*LOG(p*p+q*q),atan2(q,p)));
      END_IF;
    ef_sin_c :
      IF  cnlit IN  TYPEOF  (v1) THEN
        parts(v1,p,q);  t := 0.5*EXP(-q);  u := 0.5*EXP(q);
        RETURN  (makec((t+u)*SIN(p),(u-t)*COS(p)));
      END_IF;
    ef_sqrt_c :
      IF  cnlit IN  TYPEOF  (v1) THEN
        parts(v1,p,q);  t := SQRT(SQRT(p*p+q*q));  u := 0.5*atan2(q,p);
        RETURN  (makec(t*COS(u),t*SIN(u)));
      END_IF;
    ef_tan_c :
      IF  cnlit IN  TYPEOF  (v1) THEN
        parts(v1,p,q);  t := EXP(2.0*q) + EXP(-2.0*q) + 2.0*COS(2.0*p);
        RETURN  (makec(2.0*SIN(2.0*p)/t,(EXP(-2.0*q)-EXP(2.0*q))/t));
      END_IF;
    -- ef_if_c : combined WITH  ef_if
    ef_subscript_s :
      IF  ('STRING' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        str := v1;  k := v2;  RETURN  (ctmv(str[k]));
      END_IF;
    ef_eq_s :
      IF  ('STRING' IN  TYPEOF  (v1)) AND  ('STRING' IN  TYPEOF  (v2)) THEN
        str := v1;  st2 := v2;  RETURN  (ctmv(str = st2));
      END_IF;
    ef_ne_s :
      IF  ('STRING' IN  TYPEOF  (v1)) AND  ('STRING' IN  TYPEOF  (v2)) THEN
        str := v1;  st2 := v2;  RETURN  (ctmv(str <> st2));
      END_IF;
    ef_gt_s :
      IF  ('STRING' IN  TYPEOF  (v1)) AND  ('STRING' IN  TYPEOF  (v2)) THEN
        str := v1;  st2 := v2;  RETURN  (ctmv(str > st2));
      END_IF;
    ef_lt_s :
      IF  ('STRING' IN  TYPEOF  (v1)) AND  ('STRING' IN  TYPEOF  (v2)) THEN
        str := v1;  st2 := v2;  RETURN  (ctmv(str < st2));
      END_IF;
    ef_ge_s :
      IF  ('STRING' IN  TYPEOF  (v1)) AND  ('STRING' IN  TYPEOF  (v2)) THEN
        str := v1;  st2 := v2;  RETURN  (ctmv(str >= st2));
      END_IF;
    ef_le_s :
      IF  ('STRING' IN  TYPEOF  (v1)) AND  ('STRING' IN  TYPEOF  (v2)) THEN
        str := v1;  st2 := v2;  RETURN  (ctmv(str <= st2));
      END_IF;
    ef_subsequence_s :
      IF  ('STRING' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) AND
        ('INTEGER' IN  TYPEOF  (v3)) THEN
        str := v1;  j := v2;  k := v3;  RETURN  (ctmv(str[j:k]));
      END_IF;
    ef_concat_s : BEGIN
      str := '';
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'STRING' IN  TYPEOF  (vlist[i]) THEN
          st2 := vlist[i];  str := str + st2;
          REMOVE  (vlist, i);
        ELSE  IF  str <> '' THEN
          INSERT  (vlist, ctmv(str), i);
          str := '';
        END_IF;  END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(str));  END_IF;
      IF  str <> '' THEN   INSERT  (vlist, ctmv(str), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_size_s :
      IF  'STRING' IN  TYPEOF  (v1) THEN   str:=v1;  RETURN  (ctmv(LENGTH(str)));  END_IF;
    ef_format :
      IF  ('NUMBER' IN  TYPEOF  (v1)) AND  ('STRING' IN  TYPEOF  (v2)) THEN
        RETURN  (ctmv(FORMAT(v1,v2)));
      END_IF;
    ef_value :
      IF  'STRING' IN  TYPEOF  (v1) THEN   str:=v1;  RETURN  (ctmv(VALUE(str)));  END_IF;
    ef_like :
      IF  ('STRING' IN  TYPEOF  (v1)) AND  ('STRING' IN  TYPEOF  (v2)) THEN
        RETURN  (ctmv(v1 LIKE v2));
      END_IF;
    -- ef_if_s : combined WITH  ef_if
    ef_subscript_b :
      IF  ('BINARY' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        bin := v1;  k := v2;  RETURN  (ctmv(bin[k]));
      END_IF;
    ef_eq_b :
      IF  ('BINARY' IN  TYPEOF  (v1)) AND  ('BINARY' IN  TYPEOF  (v2)) THEN
        bin := v1;  bi2 := v2;  RETURN  (ctmv(bin = bi2));
      END_IF;
    ef_ne_b :
      IF  ('BINARY' IN  TYPEOF  (v1)) AND  ('BINARY' IN  TYPEOF  (v2)) THEN
        bin := v1;  bi2 := v2;  RETURN  (ctmv(bin <> bi2));
      END_IF;
    ef_gt_b :
      IF  ('BINARY' IN  TYPEOF  (v1)) AND  ('BINARY' IN  TYPEOF  (v2)) THEN
        bin := v1;  bi2 := v2;  RETURN  (ctmv(bin > bi2));
      END_IF;
    ef_lt_b :
      IF  ('BINARY' IN  TYPEOF  (v1)) AND  ('BINARY' IN  TYPEOF  (v2)) THEN
        bin := v1;  bi2 := v2;  RETURN  (ctmv(bin < bi2));
      END_IF;
    ef_ge_b :
      IF  ('BINARY' IN  TYPEOF  (v1)) AND  ('BINARY' IN  TYPEOF  (v2)) THEN
        bin := v1;  bi2 := v2;  RETURN  (ctmv(bin >= bi2));
      END_IF;
    ef_le_b :
      IF  ('BINARY' IN  TYPEOF  (v1)) AND  ('BINARY' IN  TYPEOF  (v2)) THEN
        bin := v1;  bi2 := v2;  RETURN  (ctmv(bin <= bi2));
      END_IF;
    ef_subsequence_b :
      IF  ('BINARY' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) AND
        ('INTEGER' IN  TYPEOF  (v3)) THEN
        bin := v1;  j := v2;  k := v3;  RETURN  (ctmv(bin[j:k]));
      END_IF;
    ef_concat_b : BEGIN
      boo := FALSE;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'BINARY' IN  TYPEOF  (vlist[i]) THEN
          IF  boo THEN   bi2 := vlist[i];  bin := bin + bi2;
          ELSE          bin := vlist[i];  boo := TRUE;  END_IF;
          REMOVE  (vlist, i);
        ELSE  IF  boo THEN
          INSERT  (vlist, ctmv(bin), i);
          boo := FALSE;
        END_IF;  END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(bin));  END_IF;
      IF  boo THEN   INSERT  (vlist, ctmv(bin), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_size_b :
      IF  'BINARY' IN  TYPEOF  (v1) THEN   bin:=v1;  RETURN  (ctmv(BLENGTH(bin)));  END_IF;
    -- ef_if_b : combined WITH  ef_if
    ef_subscript_t :
      IF  ('LIST' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        tpl := v1;  k := v2;  RETURN  (ctmv(tpl[k]));
      END_IF;
    ef_eq_t :
      IF  ('LIST' IN  TYPEOF  (v1)) AND  ('LIST' IN  TYPEOF  (v2)) THEN
        lgc := equal_maths_values(v1,v2);
        IF  lgc <> UNKNOWN  THEN   RETURN  (ctmv(lgc));  END_IF;
      END_IF;
    ef_ne_t :
      IF  ('LIST' IN  TYPEOF  (v1)) AND  ('LIST' IN  TYPEOF  (v2)) THEN
        lgc := equal_maths_values(v1,v2);
        IF  lgc <> UNKNOWN  THEN   RETURN  (ctmv(NOT lgc));  END_IF;
      END_IF;
    ef_concat_t : BEGIN
      tpl := [];
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  'STRING' IN  TYPEOF  (vlist[i]) THEN
          tp2 := vlist[i];  tpl := tpl + tp2;
          REMOVE  (vlist, i);
        ELSE  IF  SIZEOF  (tpl) <> 0 THEN
          INSERT  (vlist, ctmv(tpl), i);
          tpl := [];
        END_IF;  END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(tpl));  END_IF;
      IF  SIZEOF  (tpl) <> 0 THEN   INSERT  (vlist, ctmv(tpl), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_size_t :
      IF  'LIST' IN  TYPEOF  (v1) THEN   tpl:=v1;  RETURN  (ctmv(SIZEOF(tpl)));  END_IF;
    ef_entuple :
      RETURN  (ctmv(vlist));
    ef_detuple :  -- This can have multiple outputs, but the expression only
                  -- denotes the first.
      IF  'LIST' IN  TYPEOF  (v1) THEN   tpl:=v1;  RETURN  (ctmv(tpl[1]));  END_IF;
    ef_insert :
      IF  ('LIST' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v3)) THEN
        tpl := v1;  k := v3;  INSERT  (tpl, v2, k);  RETURN  (ctmv(tpl));
      END_IF;
    ef_remove :
      IF  ('LIST' IN  TYPEOF  (v1)) AND  ('INTEGER' IN  TYPEOF  (v2)) THEN
        tpl := v1;  k := v2;  REMOVE  (tpl, k);  RETURN  (ctmv(tpl));
      END_IF;
    -- ef_if_t : combined WITH ef_if
    ef_sum_it :
      IF  good_t(v1,'INTEGER') THEN
        tpl := v1;  j := 0;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  j := j + tpl[i];  END_REPEAT;
        RETURN  (ctmv(j));
      END_IF;
    ef_product_it :
      IF  good_t(v1,'INTEGER') THEN
        tpl := v1;  j := 1;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  j := j * tpl[i];  END_REPEAT;
        RETURN  (ctmv(j));
      END_IF;
    ef_add_it : BEGIN
      boo := FALSE;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  good_t(vlist[i],'INTEGER') THEN
          IF  NOT  boo THEN   tpl := vlist[i];  boo := TRUE;
          ELSE
            tp2 := vlist[i];
            IF  SIZEOF  (tpl) <> SIZEOF  (tp2) THEN   RETURN  (?);  END_IF;
            REPEAT  l := 1 TO  SIZEOF  (tpl);  tpl[j] := tpl[j] + tp2[j];  END_REPEAT;
          END_IF;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(tpl));  END_IF;
      IF  boo THEN   INSERT  (vlist, ctmv(tpl), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_subtract_it :
      IF  good_t(v1,'INTEGER') AND  good_t(v2,'INTEGER') THEN
        tpl := v1;  tp2 := v2;
        IF  SIZEOF  (tpl) <> SIZEOF  (tp2) THEN   RETURN  (?);  END_IF;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  tpl[i] := tpl[i] - tp2[i];  END_REPEAT;
        RETURN  (ctmv(tpl));
      END_IF;
    ef_scalar_mult_it :
      IF  ('INTEGER' IN  TYPEOF  (v1)) AND  good_t(v2,'INTEGER') THEN
        j := v1;  tpl := v2;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  tpl[i] := j * tpl[i];  END_REPEAT;
        RETURN  (ctmv(tpl));
      END_IF;
    ef_dot_prod_it :
      IF  good_t(v1,'INTEGER') AND  good_t(v2,'INTEGER') THEN
        tpl := v1;  tp2 := v2;  j := 0;
        IF  SIZEOF  (tpl) <> SIZEOF  (tp2) THEN   RETURN  (?);  END_IF;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  j := j + tpl[i] * tp2[i];  END_REPEAT;
        RETURN  (ctmv(j));
      END_IF;
    ef_sum_rt :
      IF  good_t(v1,'REAL') THEN
        tpl := v1;  r := 0.0;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  r := r + tpl[i];  END_REPEAT;
        RETURN  (ctmv(r));
      END_IF;
    ef_product_rt :
      IF  good_t(v1,'REAL') THEN
        tpl := v1;  r := 1.0;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  r := r * tpl[i];  END_REPEAT;
        RETURN  (ctmv(r));
      END_IF;
    ef_add_rt : BEGIN
      boo := FALSE;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY  -1;
        IF  good_t(vlist[i],'REAL') THEN
          IF  NOT  boo THEN   tpl := vlist[i];  boo := TRUE;
          ELSE
            tp2 := vlist[i];
            IF  SIZEOF  (tpl) <> SIZEOF  (tp2) THEN   RETURN  (?);  END_IF;
            REPEAT  l := 1 TO  SIZEOF  (tpl);  tpl[j] := tpl[j] + tp2[j];  END_REPEAT;
          END_IF;
          REMOVE  (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(tpl));  END_IF;
      IF  boo THEN   INSERT  (vlist, ctmv(tpl), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_subtract_rt :
      IF  good_t(v1,'REAL') AND  good_t(v2,'REAL') THEN
        tpl := v1;  tp2 := v2;
        IF  SIZEOF  (tpl) <> SIZEOF  (tp2) THEN   RETURN  (?);  END_IF;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  tpl[i] := tpl[i] - tp2[i];  END_REPEAT;
        RETURN  (ctmv(tpl));
      END_IF;
    ef_scalar_mult_rt :
      IF  ('REAL' IN  TYPEOF  (v1)) AND  good_t(v2,'REAL') THEN
        r := v1;  tpl := v2;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  tpl[i] := r * tpl[i];  END_REPEAT;
        RETURN  (ctmv(tpl));
      END_IF;
    ef_dot_prod_rt :
      IF  good_t(v1,'REAL') AND  good_t(v2,'REAL') THEN
        tpl := v1;  tp2 := v2;  r := 0;
        IF  SIZEOF  (tpl) <> SIZEOF  (tp2) THEN   RETURN  (?);  END_IF;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  r := r + tpl[i] * tp2[i];  END_REPEAT;
        RETURN  (ctmv(r));
      END_IF;
    ef_norm_rt :
      IF  good_t(v1,'REAL') THEN
        tpl := v1;  r := 0.0;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  r := r + tpl[i]*tpl[i];  END_REPEAT;
        RETURN  (ctmv(SQRT(r)));
      END_IF;
    ef_sum_ct :
      IF  good_t(v1,cnlit) THEN
        tpl := v1;  p := 0.0;  q := 0.0;
        REPEAT  i:=1 TO  SIZEOF  (tpl);  parts(tpl[i],r,s);  p:=p+r;  q:=q+s;  END_REPEAT;
        RETURN  (makec(p,q));
      END_IF;
    ef_product_ct :
      IF  good_t(v1,cnlit) THEN
        tpl := v1;  p := 1.0;  q := 0.0;
        REPEAT  i := 1 TO  SIZEOF  (tpl);
          parts(tpl[i],r,s);  p := p*r-q*s;  q := p*s+q*r;
        END_REPEAT;
        RETURN  (makec(p,q));
      END_IF;
    ef_add_ct : BEGIN
      boo := FALSE;
      REPEAT  i := SIZEOF  (vlist) TO  1 BY -1;
        IF  good_t(vlist[i],cnlit) THEN
          IF  NOT boo THEN   tpl := vlist[i];  boo := TRUE;
          ELSE
            tp2 := vlist[i];
            IF  SIZEOF  (tpl) <> SIZEOF  (tp2) THEN   RETURN  (?);  END_IF;
            REPEAT  l := 1 TO  SIZEOF  (tpl);
              parts(tpl[j],p,q); parts(tp2[j],r,s);  tpl[j] := makec(p+r,q+s);
            END_REPEAT;
          END_IF;
          REMOVE (vlist, i);
        END_IF;
      END_REPEAT;
      IF  SIZEOF  (vlist) = 0 THEN   RETURN  (ctmv(tpl));  END_IF;
      IF  boo THEN   INSERT (vlist, ctmv(tpl), 0);  END_IF;
      IF  SIZEOF  (vlist) = 1 THEN   RETURN  (vlist[1]);  END_IF;
      END;
    ef_subtract_ct :
      IF  good_t(v1,cnlit) AND  good_t(v2,cnlit) THEN
        tpl := v1;  tp2 := v2;
        IF  SIZEOF  (tpl) <> SIZEOF  (tp2) THEN   RETURN  (?);  END_IF;
        REPEAT  i := 1 TO  SIZEOF  (tpl);
          parts(tpl[i],p,q);  parts(tp2[i],r,s);  tpl[i] := makec(p-r,q-s);
        END_REPEAT;
        RETURN  (ctmv(tpl));
      END_IF;
    ef_scalar_mult_ct :
      IF  (cnlit IN  TYPEOF  (v1)) AND  good_t(v2,cnlit) THEN
        parts(v1,p,q);  tpl := v2;
        REPEAT  i := 1 TO  SIZEOF  (tpl);
          parts(tpl[i],r,s);  tpl[i] := makec(p*r-q*s,p*s+q*r);
        END_REPEAT;
        RETURN  (ctmv(tpl));
      END_IF;
    ef_dot_prod_ct :
      IF  good_t(v1,cnlit) AND good_t(v2,cnlit) THEN
        tpl := v1;  tp2 := v2;  t := 0.0;  u := 0.0;
        IF  SIZEOF  (tpl) <> SIZEOF  (tp2) THEN   RETURN  (?);  END_IF;
        REPEAT  i := 1 TO  SIZEOF  (tpl);
          parts(tpl[i],p,q);  parts(tp2[i],r,s);  t := t + p*r+q*s;  u := u + q*r-p*s;
        END_REPEAT;
        RETURN  (makec(t,u));
      END_IF;
    ef_norm_ct :
      IF  good_t(v1,cnlit) THEN
        tpl := v1;  r := 0.0;
        REPEAT  i := 1 TO  SIZEOF  (tpl);  parts(tpl[i],p,q);  r:=r+p*p+q*q;  END_REPEAT;
        RETURN  (ctmv(SQRT(r)));
      END_IF;
    ef_if, ef_if_i, ef_if_r, ef_if_c, ef_if_s, ef_if_b, ef_if_t :
      IF  'LOGICAL' IN  TYPEOF  (v1) THEN
        lgc := v1;  IF  lgc THEN   RETURN  (v2);  ELSE  RETURN  (v3);  END_IF;
      END_IF;
    ef_ensemble :   -- (mem + vlist) effectively converts LIST TO  set
      RETURN  (make_finite_space(mem + vlist));
    ef_member_of :
      IF  (schema_prefix + 'MATHS_SPACE') IN  TYPEOF (v2) THEN
        lgc := member_of(v1,v2);
        IF  lgc <> UNKNOWN THEN  RETURN  (ctmv(lgc));  END_IF;
      END_IF;
    END_CASE;
    RETURN  (make_function_application(expr.func,vlist));
  END_IF;
  IF  'ABSTRACTED_EXPRESSION_FUNCTION' IN  types THEN
    gexpr := substitute(expr.func\abstracted_expression_function.expr,
      expr.func\quantifier_expression.variables,vlist);
    RETURN  (simplify_generic_expression(gexpr));
  END_IF;
  IF  'FINITE_FUNCTION' IN types THEN
    pairs := expr.func\finite_function.pairs;
    REPEAT i := 1 TO SIZEOF (pairs);
      IF equal_maths_values(vlist[1],pairs[i][1]) THEN
        RETURN  (simplify_maths_value(pairs[i][2]));
      END_IF;
    END_REPEAT;
    RETURN  (make_function_application(expr.func,vlist));
  END_IF;
  RETURN (expr);

END_FUNCTION; -- simplify_function_application

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