--DCubicsSub.mesa
--m.stone April 1, 1981 9:53 PM
-- Last Edited by: Stone, March 15, 1983 3:26 pm

DIRECTORY
 Real: FROM "Real",
 Inline: FROM "Inline",
 SplineDefs: FROM "SplineDefs";

DCubicsSub: PROGRAM IMPORTS Real,Inline EXPORTS SplineDefs =
BEGIN OPEN SplineDefs;

Vals: TYPE=
RECORD[Fx: LONG INTEGER, Cx: LONG INTEGER, Fy: LONG INTEGER, Cy: LONG INTEGER];
PutPt: PROCEDURE[SplineDefs.ScrPt];

scaler: LONG INTEGER ← 200000B;
tol: LONG INTEGER ← scaler/2;

DisplayCubic: PUBLIC PROCEDURE
 [coeffs: Coeffs,
MoveTo: PROCEDURE[SplineDefs.ScrPt],
DrawTo: PROCEDURE[SplineDefs.ScrPt]] =
BEGIN
ONE: REAL ← 1; E2: REAL ← 100;
pt: ScrPt;
val0,val1: Vals;
--set initial values. assume t0=0, t1=1 deltaT**2=1
--F[0], F[1], C ← deltaT^2*(6at+2b)/2
val0 ← Vals[Real.RoundLI[scaler*coeffs.t0[X]],
  Real.RoundLI[scaler*coeffs.t2[X]],
  Real.RoundLI[scaler*coeffs.t0[Y]],
  Real.RoundLI[scaler*coeffs.t2[Y]]];
val1 ← Vals[Real.RoundLI[scaler*(coeffs.t3[X]+coeffs.t2[X]+coeffs.t1[X]+coeffs.t0[X])],
  Real.RoundLI[scaler*(3*coeffs.t3[X]+coeffs.t2[X])],
  Real.RoundLI[scaler*(coeffs.t3[Y]+coeffs.t2[Y]+coeffs.t1[Y]+coeffs.t0[Y])],
  Real.RoundLI[scaler*(3*coeffs.t3[Y]+coeffs.t2[Y])] ];
--do first MoveTo
pt[X] ← DoubleToInt[val0.Fx];
pt[Y] ← DoubleToInt[val0.Fy];
MoveTo[pt];
PutPt ← DrawTo;
DrawCurve[val0, val1];
pt[X] ← DoubleToInt[val1.Fx]; --seems to be necessary
pt[Y] ← DoubleToInt[val1.Fy];
DrawTo[pt];
END;

--recursive subdivision
DrawCurve: PROCEDURE[val1: Vals, val2: Vals ]=
BEGIN
x1,x2,y1,y2: INTEGER;
pt: ScrPt;
DO
x1 ← DoubleToInt[val1.Fx]; x2 ← DoubleToInt[val2.Fx];
y1 ← DoubleToInt[val1.Fy];
y2 ← DoubleToInt[val2.Fy];
SELECT TRUE FROM
(ABS[val1.Cx] < tol AND ABS[val1.Cy] < tol AND ABS[val2.Cx] < tol AND ABS[val2.Cy] < tol) => BEGIN
 pt ← [x2,y2]; --compiler error if use constuctor in arg list
 PutPt[pt];
RETURN;
END;
(ABS[x1-x2] <=1 AND ABS[y1-y2] <=1) => BEGIN
 pt ← [x2,y2]; --compiler error if use constuctor in arg list
 PutPt[pt];
RETURN;
END;
ENDCASE => BEGIN
 valc: Vals;
 val1.Cx 𡤍oubleHalve[DoubleHalve[ val1.Cx]]; val2.Cx ← DoubleHalve[DoubleHalve[val2.Cx]];
 valc.Cx ← DoubleHalve[(val1.Cx+val2.Cx)];
 valc.Fx ← DoubleHalve[val1.Fx+val2.Fx] - valc.Cx;
 val1.Cy 𡤍oubleHalve[DoubleHalve[ val1.Cy]]; val2.Cy ← DoubleHalve[DoubleHalve[val2.Cy]];
 valc.Cy ← DoubleHalve[(val1.Cy+val2.Cy)];
 valc.Fy ← DoubleHalve[val1.Fy+val2.Fy] - valc.Cy;
 DrawCurve[val1,valc];
 val1 ←valc; --instead of a second call to DrawCurve
END;
ENDLOOP;
END;


--round a Double to an INTEGER
DoubleToInt: PROCEDURE[double: LONG INTEGER] RETURNS[i: INTEGER] =
INLINE BEGIN OPEN Inline;
i ← HighHalf[double]+(IF CARDINAL[LowHalf[double]] > 77777B THEN 1 ELSE 0);
END;

DoubleHalve: PROCEDURE [dint: LONG INTEGER] RETURNS [dintover2: LONG INTEGER] =
INLINE BEGIN OPEN Inline;
ln: LongNumber; ln.li ← dint;
ln.lowbits ← BITSHIFT[ln.lowbits,-1] + (IF ln.highbits MOD 2 = 1 THEN 100000B ELSE 0);
ln.highbits ← BITSHIFT[ln.highbits,-1] + (IF ln.highbits > 77777B THEN 100000B ELSE 0);
dintover2 ← ln.li;
END;

END.
(635)\1111i18I1481b1B343b1B