arithmetic/src/algebra/polynomial/PolynomialFmtLex.mg


GENERIC MODULE PolynomialFmtLex(R, RF, VF);
Arithmetic for Modula-3, see doc for details

IMPORT Rd, Wr, TextWr, Thread;
IMPORT Fmt AS F;
IMPORT Lex AS L;
IMPORT FloatMode;
FROM FmtLexSupport IMPORT Precedence;

<* UNUSED *>
CONST
  Module = "PolynomialFmtLex.";

PROCEDURE Fmt (x: T; READONLY style := FmtStyle{}; ): TEXT
  RAISES {Thread.Alerted, Wr.Failure} =
  (* Generate a text object for the polynomial poly, in form:
     T3{a0,a1,a2} *)
  VAR wr := NEW(TextWr.T).init();
  BEGIN
    Wr.PutText(wr, "Polynomial" & F.Int(NUMBER(x^)) & "{");
    FOR i := FIRST(x^) TO LAST(x^) DO
      Wr.PutText(wr, RF.Fmt(x[i], style.elemStyle));
      IF i # LAST(x^) THEN Wr.PutText(wr, ", "); END;
    END;
    Wr.PutText(wr, "}");
    RETURN TextWr.ToText(wr);
  END Fmt;

PROCEDURE Tex (                      x     : T;
                            READONLY style       := TexStyle{};
               <* UNUSED *>          within      := Precedence.Sum; ): TEXT
  RAISES {Thread.Alerted, Wr.Failure} =

  PROCEDURE TexPower (i: CARDINAL; ): TEXT =
    BEGIN
      RETURN RF.Tex(x[i], style.elemStyle, Precedence.Product) & " "
               & style.var & "^{" & F.Int(i) & "}";
    END TexPower;

  PROCEDURE TexSimplePower (i: CARDINAL; ): TEXT =
    BEGIN
      IF i = 0 THEN
        RETURN RF.Tex(x[i], style.elemStyle, Precedence.Sum);
      ELSIF i = 1 THEN
        RETURN RF.Tex(x[i], style.elemStyle, Precedence.Product) & " "
                 & style.var;
      ELSE
        RETURN TexPower(i);
      END;
    END TexSimplePower;

  PROCEDURE TexCoefficient (i: CARDINAL; ): TEXT =
    BEGIN
      RETURN RF.Tex(x[i], style.elemStyle, Precedence.Sum);
    END TexCoefficient;

  TYPE TexCoefProc = PROCEDURE (i: CARDINAL; ): TEXT;

  PROCEDURE TexMonomial
    (texCoef: TexCoefProc; i: CARDINAL; reqSep: BOOLEAN)
    RAISES {Thread.Alerted, Wr.Failure} =
    BEGIN
      IF NOT (TexFlag.OmitZero IN style.flags AND R.IsZero(x[i])) THEN
        IF reqSep THEN Wr.PutText(wr, sep); END;
        Wr.PutText(wr, texCoef(i));
      END;
    END TexMonomial;

  PROCEDURE LoopForward (texCoef: TexCoefProc)
    RAISES {Thread.Alerted, Wr.Failure} =
    BEGIN
      FOR i := FIRST(x^) TO LAST(x^) DO
        TexMonomial(texCoef, i, i > FIRST(x^))
      END;
    END LoopForward;

  PROCEDURE LoopBackward (texCoef: TexCoefProc)
    RAISES {Thread.Alerted, Wr.Failure} =
    BEGIN
      FOR i := LAST(x^) TO FIRST(x^) BY -1 DO
        TexMonomial(texCoef, i, i < LAST(x^))
      END;
    END LoopBackward;

  PROCEDURE Loop (texCoef: TexCoefProc)
    RAISES {Thread.Alerted, Wr.Failure} =
    BEGIN
      IF NUMBER(x^) = 0 THEN
        IF TexFlag.PowerSum IN style.flags THEN
          Wr.PutText(wr, RF.Tex(R.Zero, style.elemStyle, Precedence.Sum));
          (* ELSE we output () as vector notation *)
        END;
      ELSE
        IF TexFlag.Reverse IN style.flags THEN
          LoopBackward(texCoef);
        ELSE
          LoopForward(texCoef);
        END;
      END;
    END Loop;

  VAR
    wr        := TextWr.New();
    sep: TEXT;

  BEGIN
    <* ASSERT NOT (NUMBER(x^) > 1 AND R.IsZero(x[LAST(x^)])) *>
    IF TexFlag.PowerSum IN style.flags THEN
      sep := "+";
      IF TexFlag.SimplePower IN style.flags THEN
        Loop(TexSimplePower);
      ELSE
        Loop(TexPower);
      END;
    ELSE
      <* ASSERT NOT TexFlag.SimplePower IN style.flags *>
      sep := ",";
      Wr.PutText(wr, "\\left(");
      Loop(TexCoefficient);
    END;

    IF NOT TexFlag.PowerSum IN style.flags THEN
      Wr.PutText(wr, "\\right)\n");
    END;
    RETURN TextWr.ToText(wr);
  END Tex;

PROCEDURE Lex (rd: Rd.T; READONLY style: LexStyle; ): T
  RAISES {L.Error, FloatMode.Trap, Rd.Failure, Thread.Alerted} =
  BEGIN
    RETURN VF.Lex(rd, VF.LexStyle{
                        sep := style.sep, elemStyle := style.elemStyle});
  END Lex;

BEGIN
END PolynomialFmtLex.