Overview Schemas Index

MATHEMATICAL_FUNCTIONS_SCHEMA (jsdai.SMathematical_functions_schema)


FUNCTION enclose_pregion_in_pregion
          (prgn : polar_complex_number_region, centre : complex_number_literal) : polar_complex_number_region;

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 := aitp.max;               amax_in := FALSE;
        ELSE
          rmin := 0.0;                    rmin_in := TRUE;
          amin := -PI;                    amin_in := FALSE;
          amax := PI;                     amax_in := TRUE;
        END_IF;
      ELSE
        rmin := rmnp-rc;                  rmin_in := min_included(ritp);
        amin := -PI;                      amin_in := FALSE;
        amax := PI;                       amax_in := TRUE;
        IF  inn THEN   -- Special cases when aligned WITH  slot
          IF  apc = a THEN
                                          rmin_in := FALSE;
            amin := aitp.min;             amin_in := FALSE;
            amax := aitp.max;             amax_in := FALSE;
          ELSE  IF  acp = a THEN
            amin := aitp.min;             amin_in := FALSE;
            amax := aitp.max;             amax_in := FALSE;
          END_IF;  END_IF;
        END_IF;
      END_IF;  END_IF;  END_IF;
    ELSE   -- direction range < 2*PI
      -- Compute data FOR  corners WITH  respect TO  xc,yc
      x := xp + rmxp*cos(aitp.min) - xc;
      y := yp + rmxp*sin(aitp.min) - yc;
      r0 := SQRT(x**2 + y**2);
      in0 := max_included(ritp) AND  min_included(aitp);
      IF  r0 <> 0.0 THEN   a0 := atan2(y,x);  END_IF;
      x := xp + rmxp*cos(aitp.max) - xc;
      y := yp + rmxp*sin(aitp.max) - yc;
      r1 := SQRT(x**2 + y**2);
      in1 := max_included(ritp) AND  max_included(aitp);
      IF  r1 <> 0.0 THEN   a1 := atan2(y,x);  END_IF;
      x := xp + rmnp*cos(aitp.max) - xc;
      y := yp + rmnp*sin(aitp.max) - yc;
      r2 := SQRT(x**2 + y**2);
      in2 := min_included(ritp) AND  max_included(aitp);
      IF  r2 <> 0.0 THEN   a2 := atan2(y,x);  ELSE   a2 := a1;  in2 := in1;  END_IF;
      IF  r1 = 0.0 THEN   a1 := a2;  in1 := in2;  END_IF;
      x := xp + rmnp*cos(aitp.min) - xc;
      y := yp + rmnp*sin(aitp.min) - yc;
      r3 := SQRT(x**2 + y**2);
      in3 := min_included(ritp) AND  min_included(aitp);
      IF  r3 <> 0.0 THEN   a3 := atan2(y,x);  ELSE   a3 := a0;  in3 := in0;  END_IF;
      IF  r0 = 0.0 THEN   a0 := a3;  in0 := in3;  END_IF;
      IF  rmnp = 0.0 THEN   in2 := min_included(ritp);  in3 := in2;  END_IF;
      IF  (apc = angle(aitp.min)) OR  (acp = angle(aitp.min)) THEN
        in0 := min_included(aitp);
        in3 := in0;
      ELSE  IF  (apc = angle(aitp.max)) OR  (acp = angle(aitp.max)) THEN
        in1 := max_included(aitp);
        in2 := in1;
      END_IF;  END_IF;
      -- Find rmax
      IF  strictly_in(acp,aitp) THEN
        rmax := rc+rmxp;                  rmax_in := max_included(ritp);
      ELSE
        rmax := r0;                       rmax_in := in0;
        IF  rmax = r1 THEN                  rmax_in := rmax_in OR  in1;  END_IF;
        IF  rmax < r1 THEN   rmax := r1;    rmax_in := in1;             END_IF;
        IF  rmax = r2 THEN                  rmax_in := rmax_in OR  in2;  END_IF;
        IF  rmax < r2 THEN   rmax := r2;    rmax_in := in2;             END_IF;
        IF  rmax = r3 THEN                  rmax_in := rmax_in OR  in3;  END_IF;
        IF  rmax < r3 THEN   rmax := r3;    rmax_in := in3;             END_IF;
      END_IF;
      -- Find rmin
      IF  strictly_in(apc,aitp) THEN
        IF  rc >= rmxp THEN
          rmin := rc-rmxp;                rmin_in := max_included(ritp);
        ELSE  IF  rc <= rmnp THEN
          rmin := rmnp-rc;                rmin_in := min_included(ritp);
        ELSE
          rmin := 0.0;                    rmin_in := TRUE;
        END_IF;  END_IF;
      ELSE
        rmin := r0;                       rmin_in := in0;
        a := apc-aitp.min;
        r := rc*COS(a);
        IF  {rmnp < r < rmxp} THEN   -- USE  nearest point on line segment
          rmin := rc*SIN(ABS(a));         rmin_in := min_included(aitp);
        END_IF;
        a := apc-aitp.max;
        r := rc*COS(a);
        IF  {rmnp < r < rmxp} THEN   -- try nearest point on line segment
          r := rc*SIN(ABS(a));            inn := max_included(aitp);
          IF  r = rmin THEN                 rmin_in := rmin_in OR  inn;  END_IF;
          IF  r < rmin THEN   rmin := r;    rmin_in := inn;             END_IF;
        END_IF;
        IF  r1 = rmin THEN                  rmin_in := rmin_in OR  in1;  END_IF;
        IF  r1 < rmin THEN   rmin := r1;    rmin_in := in1;             END_IF;
        IF  r2 = rmin THEN                  rmin_in := rmin_in OR  in2;  END_IF;
        IF  r2 < rmin THEN   rmin := r2;    rmin_in := in2;             END_IF;
        IF  r3 = rmin THEN                  rmin_in := rmin_in OR  in3;  END_IF;
        IF  r3 < rmin THEN   rmin := r3;    rmin_in := in3;             END_IF;
      END_IF;
      -- Find amin AND  amax, initially WITH  respect TO  base direction ab.
      IF  rc >= rmxp THEN   -- outside outer circle
        ab := acp;
        find_aminmax(ab,a0,a1,a2,a3,in0,in1,in2,in3,amin,amax,amin_in,amax_in);
        a := ACOS(rmxp/rc);
        IF  strictly_in(apc-a,aitp) THEN
          amin := ab-ASIN(rmxp/rc);       amin_in := max_included(ritp);
        END_IF;
        IF  strictly_in(apc+a,aitp) THEN
          amax := ab+ASIN(rmxp/rc);       amax_in := max_included(ritp);
        END_IF;
        angle_range(amin,amax);
      ELSE  IF  rc > rmnp THEN
        ab := angle(0.5*(aitp.min+aitp.max));  -- REFERENCE  direction
        find_aminmax(ab,a0,a1,a2,a3,in0,in1,in2,in3,amin,amax,amin_in,amax_in);
      ELSE
        -- Using base direction midway IN  prgn, compute all directions using
        -- values which ensure a3 < a2 AND  a0 < a1 algebraically.
        ab := angle(0.5*(aitp.min+aitp.max));  -- REFERENCE  direction
        a0 := angle(a0-ab);
        a1 := angle(a1-ab);
        a2 := angle(a2-ab);
        a3 := angle(a3-ab);
        IF  a3 > a2 THEN   a2 := a2 + 2.0*PI;  END_IF;
        IF  a0 > a1 THEN   a0 := a0 + 2.0*PI;  END_IF;
        IF  a3 < a0 THEN   amin := a3;      amin_in := in3;
        ELSE              amin := a0;      amin_in := in0;  END_IF;
        IF  a2 > a1 THEN   amax := a2;      amax_in := in2;
        ELSE              amax := a1;      amax_in := in1;  END_IF;
        IF  (amax - amin > 2.0*PI) OR
          ((amax - amin = 2.0*PI) AND  (amin_in OR  amax_in)) THEN
          -- Cannot see out
          amin := -PI;                    amin_in := FALSE;
          amax := PI;                     amax_in := TRUE;
        ELSE
          amin := amin + ab;
          amax := amax + ab;
          angle_range(amin,amax);
        END_IF;
      END_IF;  END_IF;
    END_IF;
    IF  rmin_in THEN   minclo := closed;  END_IF;
    IF  rmax_in THEN   maxclo := closed;  END_IF;
    ritv := make_finite_real_interval(rmin,minclo,rmax,maxclo);
  ELSE   -- NOT  max_exists(ritp)
    IF  (rc > rmnp) AND  strictly_in(apc,aitp) THEN
      RETURN  (?);  -- No pregion exists.  (Would require whole plane.)
    END_IF;
    IF  aitp.max - aitp.min = 2.0*PI THEN
      -- complement OF disk, WITH  OR  without slot
      a := angle(aitp.min);  -- slot direction
      IF  rc > rmnp THEN   -- already excluded IF  NOT  aligned WITH  slot
        IF  max_included(aitp) THEN
          RETURN  (?);  -- No pregion exists.  (Would require whole plane.)
        END_IF;
        rmin := 0.0;                      rmin_in := FALSE;
        amin := aitp.min;                 amin_in := FALSE;
        amax := aitp.max;                 amax_in := FALSE;
      ELSE
        rmin := rmnp-rc;                  rmin_in := min_included(ritp);
        amin := -PI;                      amin_in := FALSE;
        amax := PI;                       amax_in := TRUE;
        IF  NOT max_included(aitp) THEN   -- Special cases when aligned WITH  slot
          IF  apc = a THEN
                                          rmin_in := FALSE;
            amin := aitp.min;             amin_in := FALSE;
            amax := aitp.max;             amax_in := FALSE;
          ELSE  IF  acp = a THEN
            amin := aitp.min;             amin_in := FALSE;
            amax := aitp.max;             amax_in := FALSE;
          END_IF;  END_IF;
        END_IF;
      END_IF;
    ELSE   -- direction range < 2*PI
      -- Compute data FOR corners WITH respect TO xc,yc (two at infinity)
      a0 := angle(aitp.min);
      in0 := FALSE;
      a1 := angle(aitp.max);
      in1 := FALSE;
      x := xp + rmnp*cos(aitp.max) - xc;
      y := yp + rmnp*sin(aitp.max) - yc;
      r2 := SQRT(x**2 + y**2);
      in2 := min_included(ritp) AND  max_included(aitp);
      IF  r2 <> 0.0 THEN   a2 := atan2(y,x);  ELSE   a2 := a1;  in2 := in1;  END_IF;
      x := xp + rmnp*cos(aitp.min) - xc;
      y := yp + rmnp*sin(aitp.min) - yc;
      r3 := SQRT(x**2 + y**2);
      in3 := min_included(ritp) AND  min_included(aitp);
      IF  r3 <> 0.0 THEN   a3 := atan2(y,x);  ELSE   a3 := a0;  in3 := in0;  END_IF;
      IF  rmnp = 0.0 THEN   in2 := min_included(ritp);  in3 := in2;  END_IF;
      IF  (apc = angle(aitp.min)) OR  (acp = angle(aitp.min)) THEN
        in0 := min_included(aitp);
        in3 := in0;
      ELSE  IF  (apc = angle(aitp.max)) OR  (acp = angle(aitp.max)) THEN
        in1 := max_included(aitp);
        in2 := in1;
      END_IF;  END_IF;
      -- Find rmin
      IF  strictly_in(apc,aitp) THEN
        rmin := rmnp-rc;                  rmin_in := min_included(ritp);
      ELSE
        rmin := r2;                       rmin_in := in2;
        a := apc-aitp.min;
        r := rc*COS(a);
        IF  rmnp < r THEN   -- USE nearest point on aitp.min ray
          rmin := rc*SIN(ABS(a));         rmin_in := min_included(aitp);
        END_IF;
        a := apc-aitp.max;
        r := rc*COS(a);
        IF  rmnp < r THEN   -- try nearest point on aitp.max ray
          r := rc*SIN(ABS(a));            inn := max_included(aitp);
          IF  r = rmin THEN                 rmin_in := rmin_in OR  inn;  END_IF;
          IF  r < rmin THEN   rmin := r;    rmin_in := inn;             END_IF;
        END_IF;
        IF  r3 = rmin THEN                  rmin_in := rmin_in OR  in3;  END_IF;
        IF  r3 < rmin THEN   rmin := r3;    rmin_in := in3;             END_IF;
      END_IF;
      -- Find amin AND  amax
      ab := angle(0.5*(aitp.min+aitp.max));  -- REFERENCE direction
      IF  rc > rmnp THEN
        find_aminmax(ab,a0,a1,a2,a3,in0,in1,in2,in3,amin,amax,amin_in,amax_in);
      ELSE
        -- Using base direction midway IN prgn, compute all directions using
        -- values which ensure a3 < a2 AND  a0 < a1 algebraically.
        a0 := angle(a0-ab);
        a1 := angle(a1-ab);
        a2 := angle(a2-ab);
        a3 := angle(a3-ab);
        IF  a3 > a2 THEN   a2 := a2 + 2.0*PI;  END_IF;
        IF  a0 > a1 THEN   a0 := a0 + 2.0*PI;  END_IF;
        IF  a3 < a0 THEN   amin := a3;      amin_in := in3;
        ELSE              amin := a0;      amin_in := in0;  END_IF;
        IF  a2 > a1 THEN   amax := a2;      amax_in := in2;
        ELSE             amax := a1;      amax_in := in1;  END_IF;
        IF  (amax - amin > 2.0*PI) OR
          ((amax - amin = 2.0*PI) AND  (amin_in OR amax_in)) THEN
          -- Cannot see out
          amin := -PI;                    amin_in := FALSE;
          amax := PI;                     amax_in := TRUE;
          IF  (rmin = 0.0) AND rmin_in THEN
            RETURN  (?);  -- No pregion exists.  (Would require whole plane.)
          END_IF;
        ELSE
          amin := amin + ab;
          amax := amax + ab;
          angle_range(amin,amax);
        END_IF;
      END_IF;
    END_IF;
    IF  rmin_in THEN   minclo := closed;  END_IF;
    ritv := make_real_interval_from_min(rmin,minclo);
  END_IF;
  minclo := open;  maxclo := open;
  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);
  -- Construct polar region
  RETURN (make_polar_complex_number_region(centre,ritv,aitv));

END_FUNCTION; -- enclose_pregion_in_pregion

public class FEnclose_pregion_in_pregion
          public static Value run(SdaiContext _context, Value prgn, Value centre)