PolynomialsImpl.mesa
Last Edited by: Arnon, June 10, 1985 4:19:22 pm PDT
DIRECTORY
Rope,
Basics,
Atom,
Ascii,
Convert,
IO,
RemoteAlgebra,
MathExpr,
MathConstructors,
AlgebraClasses,
Structures,
Variables,
Sets,
Ints,
Points,
Sequences,
VariableSequences,
DistribPolys,
Matrices,
Polynomials;
PolynomialsImpl: CEDAR PROGRAM
IMPORTS Rope, Convert, IO, RemoteAlgebra, MathConstructors, AlgebraClasses, Structures, Variables, Sets, Ints, Sequences, VariableSequences, DistribPolys, Matrices
EXPORTS Polynomials =
BEGIN OPEN AC: AlgebraClasses, VARS: Variables, VARSEQ: VariableSequences, SEQ: Sequences, DP: DistribPolys, MAT: Matrices, Polynomials;
Types
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Object: TYPE = AC.Object;
Method: TYPE = AC.Method;
Errors
SyntaxError: PUBLIC ERROR [reason: ATOM] = CODE;
BadElementStructure: PUBLIC ERROR [elementStructure: Object] = CODE;
CantInvertError: PUBLIC ERROR [elementStructure: Object] = CODE;
TypeError: PUBLIC ERROR [message: ATOM ← $Unspecified] = CODE;
OperationError: PUBLIC ERROR [message: ATOM ← $Unspecified] = CODE;
Polynomial Structure Ops
MakePolynomialStructure: PUBLIC AC.PolynomialStructureConstructor ~ {
baseCoeffRing, strictCoeffRing: Object;
strictVariable: VARS.Variable;
allVariables: VARSEQ.VariableSequence;
polynomialRingData: PolynomialRingData;
vData: SEQ.SequenceData ← NARROW[variableSeq.data];
IF vData.lengthPlus1 - 1 > 1 THEN {
strictCoeffRing ← MakePolynomialStructure[coeffRing, SEQ.DeleteLast[variableSeq] ];
strictVariable ← SEQ.Last[variableSeq];
}
ELSE {
strictCoeffRing ← coeffRing;
strictVariable ← SEQ.First[variableSeq];
};
IF IsPolynomialStructure[strictCoeffRing] THEN { -- polynomials over polynomials, or not?
data: PolynomialRingData ← NARROW[strictCoeffRing.data];
baseCoeffRing ← data.baseCoeffRing;
allVariables ← SEQ.Append[data.allVariables, strictVariable]
}
ELSE {
baseCoeffRing ← strictCoeffRing;
allVariables ← SEQ.MakeSequence[LIST[strictVariable], VARSEQ.VariableSequences];
};
polynomialRingData ← NEW[PolynomialRingDataRec ← [
coeffRing: strictCoeffRing,
variable: strictVariable,
baseCoeffRing: baseCoeffRing,
allVariables: allVariables
] ];
polynomialStructure ← NEW[AC.ObjectRec ← [
flavor: Structure,
class: NIL,
data: polynomialRingData
] ];
polynomialStructure.name ← ShortPrintName[polynomialStructure];
SELECT TRUE FROM
AC.IsCategory[strictCoeffRing, ring] => polynomialStructure.class ← polynomialsOverCommRingClass;
AC.IsCategory[strictCoeffRing, algebra] => polynomialStructure.class ← polynomialsOverCommRingClass;
AC.IsCategory[strictCoeffRing, field] => polynomialStructure.class ← polynomialsOverOrderedCommFieldClass;
AC.IsCategory[strictCoeffRing, divisionAlgebra] => polynomialStructure.class ← polynomialsOverOrderedCommFieldClass; -- probably wrong, since probably the divisionAlgebra is noncommutative
ENDCASE => polynomialStructure.class ← polynomialClass;
};
PrintName: PUBLIC AC.PrintNameProc = {
data: PolynomialRingData ← NARROW[structure.data];
RETURN[Rope.Cat[
"Polynomials in ",
VARSEQ.VariableSequenceToRope[data.variable],
" over ",
data.coeffRing.class.printName[data.coeffRing]
] ];
};
ShortPrintName: PUBLIC AC.PrintNameProc = {
data: PolynomialRingData ← NARROW[structure.data];
shortPrintNameMethod: Method ← AC.LookupMethodInStructure[$shortPrintName, data.baseCoeffRing];
RETURN[Rope.Concat[
NARROW[AC.ApplyNoLkpNoRecastRef[shortPrintNameMethod,LIST[data.baseCoeffRing] ] ],
Sequences.ToRope[data.allVariables]
] ];
};
Characteristic: PUBLIC AC.StructureRankOp = {
data: PolynomialRingData ← NARROW[structure.data];
RETURN[ data.coeffRing.class.characteristic[data.coeffRing] ]
};
IsPolynomialStructure: PUBLIC AC.UnaryPredicate = {
IF ~arg.flavor = Structure THEN RETURN[FALSE];
RETURN[ AC.LookupMethodInStructure[$polynomialStructure, arg]#NIL ]
};
Conversion and IO
Recast: PUBLIC AC.BinaryOp = {
Args are a StructureElement and a Structure
destPolyRing: Object ← secondArg;
destPolyRingData: PolynomialRingData ← NARROW[destPolyRing.data];
destFromRopeMethod: Method ← AC.LookupMethodInStructure[$fromRope, destPolyRing];
destBaseCoeffRing: Object ← destPolyRingData.baseCoeffRing;
destBaseCanRecastMethod: Method ← AC.LookupMethodInStructure[$canRecast, destBaseCoeffRing];
destBaseRecastMethod: Method ← AC.LookupMethodInStructure[$recast, destBaseCoeffRing];
refBOOL: REF BOOL;
sourceStructure: Object ← firstArg.class;
variable: Object ← firstArg;
sourceRope: ROPE;
reCastSource: Object;
Already in this structure
IF AC.StructureEqual[sourceStructure, destPolyRing] THEN RETURN[firstArg];
Source Object to recast is a variable as an elt of a SingleSetStructure
IF Sets.IsVariable[firstArg] THEN { -- recast as an element of Variables Structure
variable ← Sets.UnderlyingSetUniverseEltFromSSSElt[firstArg];
sourceStructure ← variable.class;
};
Source Object to recast is a variable as an elt of VARS.IsVariables
IF VARS.IsVariables[sourceStructure] THEN {
Check that variable occurs in destination Structure's allVars
sourceVarsSubset: BOOLSEQ.IsSubset[SEQ.MakeSequence[LIST[variable], VARSEQ.VariableSequences], destPolyRingData.allVariables];
IF NOT sourceVarsSubset THEN RETURN[NIL];
Do secondArg.class.FromRope[firstArg.class.ToRope[firstArg] ]; avoids having to get into firstArg's internals and possibly introduce new variables
sourceRope ← NARROW[AC.ApplyLkpNoRecastRef[$toRope, sourceStructure, LIST[variable]]];
RETURN[AC.ApplyFromRopeMethod[destFromRopeMethod, sourceRope, destPolyRing] ];
};
Object to recast is a polynomial
IF IsPolynomialStructure[sourceStructure] THEN {
sourcePolyRingData: PolynomialRingData ← NARROW[sourceStructure.data];
sourceBaseCoeffRing: Object ← sourcePolyRingData.baseCoeffRing;
Check that sourceStructure's allVars are a subset of destination Structure's allVars
sourceVarsSubset: BOOL ← Sequences.IsSubset[sourcePolyRingData.allVariables, destPolyRingData.allVariables];
IF NOT sourceVarsSubset THEN RETURN[NIL];
Check that canRecast source baseCoeffRing to dest baseCoeffRing
refBOOL ← NARROW[AC.ApplyNoLkpNoRecastRef[destBaseCanRecastMethod, LIST[sourceBaseCoeffRing, destBaseCoeffRing] ] ];
IF NOT refBOOL^ THEN RETURN[NIL];
Do secondArg.class.FromRope[firstArg.class.ToRope[firstArg] ]; avoids having to get into firstArg's internals and possibly reorder, possibly introduce new variables
sourceRope ← NARROW[AC.ApplyLkpNoRecastRef[$toRope, sourceStructure, LIST[firstArg]]];
RETURN[AC.ApplyFromRopeMethod[destFromRopeMethod, sourceRope, destPolyRing] ];
};
Source Object to recast NOT a polynomial; Check if canRecast sourceStructure to dest baseCoeffRing; If so, do it, and return as a constant monomial
refBOOL ← NARROW[AC.ApplyNoLkpNoRecastRef[destBaseCanRecastMethod, LIST[sourceStructure, destBaseCoeffRing] ] ];
IF refBOOL^ THEN {
sourceRope ← NARROW[AC.ApplyLkpNoRecastRef[$toRope, sourceStructure, LIST[firstArg]]];
RETURN[AC.ApplyFromRopeMethod[destFromRopeMethod, sourceRope, destPolyRing] ];
};
-- This way works for univariate, but not multivariate, polynomials
reCastSource ← AC.ApplyNoLkpNoRecastObject[destBaseRecastMethod, LIST[firstArg, destBaseCoeffRing] ];
RETURN[ Monomial[reCastSource, NEW[CARDINAL ← 0], destPolyRing] ];
--
Can't do it
RETURN[NIL];
};
CanRecast: PUBLIC AC.BinaryPredicate = {
Args are either [Structure, Structure] or [StructureElement, Structure]
destPolyRing: Object ← secondArg;
destPolyRingData: PolynomialRingData ← NARROW[destPolyRing.data];
destBaseCoeffRing: Object ← destPolyRingData.baseCoeffRing;
destBaseCanRecastMethod: Method ← AC.LookupMethodInStructure[$canRecast, destBaseCoeffRing];
refBOOL: REF BOOL;
sourceStructure: Object ← IF firstArg.flavor = StructureElement THEN firstArg.class ELSE IF firstArg.flavor = Structure THEN firstArg ELSE ERROR;
variable: Object ← firstArg;
variableList: LIST OF Object ← NIL;
IF AC.StructureEqual[sourceStructure, destPolyRing] THEN RETURN[TRUE]; -- nothing to do
Source Object to recast is a variable as an elt of a SingleSetStructure
IF firstArg.flavor=StructureElement AND Sets.IsVariable[firstArg] THEN { -- recast as an element of Variables Structure
variable ← Sets.UnderlyingSetUniverseEltFromSSSElt[firstArg];
sourceStructure ← variable.class;
variableList← LIST[variable];
}
Source Object to recast is a SingleSetStructure; check whether underlying set consists of a single variable; if so, make it the arg
ELSE IF firstArg.flavor=Structure AND Sets.IsSingleSetStructure[firstArg] THEN {
thisSetStructureData: Sets.SingleSetStructureData ← NARROW[firstArg.data];
thisSetStructureUnderlyingSet: Object ← thisSetStructureData.underlyingSet;
underlyingSetData: Sets.SetData;
IF NOT AC.StructureEqual[thisSetStructureUnderlyingSet.class, Sets.VariableSets] THEN RETURN[FALSE];
underlyingSetData ← NARROW[thisSetStructureUnderlyingSet.data];
variableList← underlyingSetData;
variable ← underlyingSetData.first;
sourceStructure ← variable.class;
};
Source Object to recast is one or more variables
IF VARS.IsVariables[sourceStructure] THEN {
Check that variable occurs in destination Structure's allVars
sourceVarsSubset: BOOL;
IF variable.flavor # StructureElement THEN RETURN[FALSE]; -- can't check since don't have any concrete variables, i.e.VARS.Variables is not recastable to a particular poly ring
IF variableList=NIL THEN variableList ← LIST[variable];
sourceVarsSubset ← Sequences.IsSubset[SEQ.MakeSequence[variableList, VARSEQ.VariableSequences], destPolyRingData.allVariables];
RETURN[sourceVarsSubset];
};
Source Object to recast is a polynomial
IF IsPolynomialStructure[sourceStructure] THEN {
sourcePolyRingData: PolynomialRingData ← NARROW[sourceStructure.data];
sourceBaseCoeffRing: Object ← sourcePolyRingData.baseCoeffRing;
Check that source Structure's allVars are a subset of destination Structure's allVars
sourceVarsSubset: BOOL ← Sequences.IsSubset[sourcePolyRingData.allVariables, destPolyRingData.allVariables];
IF NOT sourceVarsSubset THEN RETURN[FALSE];
Check that canRecast source baseCoeffRing to dest baseCoeffRing
refBOOL ← NARROW[AC.ApplyNoLkpNoRecastRef[destBaseCanRecastMethod, LIST[sourceBaseCoeffRing, destBaseCoeffRing] ] ];
RETURN[refBOOL^];
};
Source Object to recast NOT a polynomial; Check if canRecast sourceStructure to dest baseCoeffRing
refBOOL ← NARROW[AC.ApplyNoLkpNoRecastRef[destBaseCanRecastMethod, LIST[sourceStructure, destBaseCoeffRing] ] ];
RETURN[refBOOL^];
};
ToExpr: PUBLIC AC.ToExprOp = {
data: PolynomialRingData ← NARROW[in.class.data];
dIn: DP.DPolynomial ← DPolyFromPoly[in];
addend, sum: MathExpr.EXPR;
V: VARSEQ.VariableSequence ← data.allVariables;
coeffRing: Object ← data.baseCoeffRing;
firstTerm: BOOLTRUE;
trivialMonomial, firstOccurringVar: BOOL;
thisVar: MathExpr.EXPR;
coeff, coeffAbs: AC.Object;
degreeVec: DP.DegreeVector;
coeffSign: Basics.Comparison;
exponent, index: CARDINAL;
one: AC.Object ← AC.ApplyLkpNoRecastObject[$one, coeffRing, LIST[coeffRing] ];
equalMethod: Method ← AC.LookupMethodInStructure[$eqFormula, coeffRing];
toExprMethod: Method ← AC.LookupMethodInStructure[$toExpr, coeffRing];
isOrdered: BOOLAC.HasProperty[coeffRing, $ordered];
signMethod, absMethod: Method;
CreateDTerm: PROC[firstTerm: BOOL] ~ {
[coeff, degreeVec] ← dIn.first;
IF isOrdered THEN {
coeffSign ← AC.ApplyCompareToZeroMethod[signMethod, coeff];
coeffAbs ← AC.ApplyNoLkpNoRecastObject[absMethod, LIST[coeff] ]
}
ELSE { -- for unordered coeffRing, act as though coeff is positive
coeffSign ← greater;
coeffAbs ← coeff;
};
trivialMonomial ← TRUE;
firstOccurringVar ← TRUE;
degreeVec ← DP.DVReverse[degreeVec];
WHILE degreeVec#NIL DO
trivialMonomial ← FALSE;
exponent ← degreeVec.first; degreeVec ← degreeVec.rest;
index ← degreeVec.first; degreeVec ← degreeVec.rest;
IF exponent>1 THEN
thisVar ← MathConstructors.MakePow[
VARS.ToExpr[SEQ.Select[V, Ints.FromINT[index] ] ],
MathConstructors.MakeInt[Convert.RopeFromCard[exponent]]
]
ELSE
thisVar ← VARS.ToExpr[SEQ.Select[V, Ints.FromINT[index] ] ];
IF firstOccurringVar THEN addend ← thisVar ELSE
addend ← MathConstructors.MakeProduct[addend, thisVar];
firstOccurringVar ← FALSE;
ENDLOOP;
IF NOT trivialMonomial THEN {
IF NOT AC.ApplyPredNoLkpNoRecast[equalMethod, LIST[coeffAbs, one] ] THEN
addend ← MathConstructors.MakeProduct[NARROW[AC.ApplyNoLkpNoRecastRef[toExprMethod, LIST[coeffAbs] ] ], addend]
}
ELSE addend ← NARROW[AC.ApplyNoLkpNoRecastRef[toExprMethod, LIST[coeffAbs] ] ];
IF firstTerm AND coeffSign = less THEN
addend ← MathConstructors.MakeNegation[addend];
};
IF isOrdered THEN {
signMethod ← AC.LookupMethodInStructure[$sign, coeffRing];
absMethod ← AC.LookupMethodInStructure[$abs, coeffRing];
};
IF dIn = DP.ZeroDPoly THEN RETURN[MathConstructors.MakeInt["0"] ];
CreateDTerm[TRUE]; -- first term
sum ← addend;
dIn ← dIn.rest;
WHILE dIn # NIL DO
CreateDTerm[FALSE]; -- not first term
IF coeffSign = greater THEN
sum ← MathConstructors.MakeSum[sum, addend] -- (((a+b)+c)+d)+ ...
ELSE
sum ← MathConstructors.MakeDifference[sum, addend];
dIn ← dIn.rest;
ENDLOOP;
RETURN[sum];
};
LegalFirstChar: PUBLIC AC.LegalFirstCharOp = {
Legal first char of polynomial is either legal first char of coefficient, or first char of some variable (this all with reference to distributed rep)
data: PolynomialRingData ← NARROW[structure.data];
firstCharMethod: Method ← AC.LookupMethodInStructure[$legalFirstChar, data.baseCoeffRing];
IF AC.ApplyLegalFirstCharMethod[firstCharMethod, char, data.baseCoeffRing] THEN RETURN[TRUE];
RETURN[VARSEQ.VariableFirstChar[char, data.allVariables] ];
};
Read: PUBLIC AC.ReadOp = {
data: PolynomialRingData ← NARROW[structure.data];
dPoly: DP.DPolynomial;
termChar: CHAR;
[dPoly, termChar] ← DP.ReadDPoly[in, data.allVariables, data.baseCoeffRing];
RETURN[ PolyFromDPoly[dPoly, structure] ];
};
FromRope: PUBLIC AC.FromRopeOp = {
stream: IO.STREAMIO.RIS[in];
out ← Read[stream, structure];
};
ToRope: PUBLIC AC.ToRopeOp ~ {
data: PolynomialRingData ← NARROW[in.class.data];
out ← DP.DPolyToRope[DPolyFromPoly[in], data.allVariables, data.baseCoeffRing, NIL];
};
ToIndexRope: PUBLIC AC.ToRopeOp ~ {
out ← "Pol";
};
Write: PUBLIC AC.WriteOp ~ {
IO.PutRope[ stream, ToRope[in] ]
};
PolyToRope: PUBLIC PROC [in: Polynomial, termRope: Rope.ROPENIL] RETURNS [out: Rope.ROPE] = {
data: PolynomialRingData ← NARROW[in.class.data];
out ← DP.DPolyToRope[DPolyFromPoly[in], data.allVariables, data.baseCoeffRing, termRope];
};
WritePoly: PUBLIC PROC [in: Polynomial, out: IO.STREAM, termRope: Rope.ROPENIL] = {
out.PutF["\n %g \n", IO.rope[PolyToRope[in, termRope]] ];
};
PolyFromDPoly: PUBLIC PROC [in: DP.DPolynomial, polynomialRing: Object] RETURNS [out: Polynomial] = {
polyRingData: PolynomialRingData ← NARROW[polynomialRing.data];
coeffRing: Object ← polyRingData.coeffRing;
zero: AC.Object ← AC.ApplyLkpNoRecastObject[$zero, polynomialRing, LIST[polynomialRing] ];
allVarsData: SEQ.SequenceData ← NARROW[polyRingData.allVariables.data];
numVars: CARDINAL = allVarsData.lengthPlus1 - 1;
termDegree: CARDINAL; -- degree in main variable of current (output) term
outTermDCoefficient: DP.DPolynomial; -- output term coefficient, still in DP rep
outTermCoefficient: AC.Object; -- output term coefficient, converted to P rep
outTerm: Term; -- completed output term
outTerms, outTermsPointer: LIST OF Term ← NIL;
IF in = DP.ZeroDPoly THEN RETURN[zero];
WHILE in#NIL DO
termDegree ← DP.DVDegree[in.first.degreeVector, numVars]; -- degree in main variable
IF numVars > 1 THEN {
outTermDCoefficient ← LIST[ [in.first.coefficient, DP.DVRemoveMainVariablePower[in.first.degreeVector, numVars] ] ];
in ← in.rest;
WHILE in#NIL AND DP.DVDegree[in.first.degreeVector, numVars] = termDegree DO
outTermDCoefficient ← CONS[ [in.first.coefficient, DP.DVRemoveMainVariablePower[in.first.degreeVector, numVars] ], outTermDCoefficient];
in ← in.rest;
ENDLOOP;
outTermDCoefficient ← DP.DPReverse[ outTermDCoefficient ];
outTermCoefficient ← PolyFromDPoly[ outTermDCoefficient, coeffRing ];
}
ELSE {
outTermCoefficient ← in.first.coefficient;
in ← in.rest;
};
outTerm ← NEW[TermRec ← [
exponent: termDegree,
coefficient: outTermCoefficient
] ];
IF outTerms # NIL THEN outTermsPointer ← outTermsPointer.rest ← LIST[outTerm]
ELSE outTerms ← outTermsPointer ← LIST[outTerm];
ENDLOOP;
RETURN[ NEW[AC.ObjectRec ← [flavor: StructureElement, class: polynomialRing, data: outTerms]] ]
};
DPolyFromPoly: PUBLIC PROC [in: Polynomial] RETURNS [out: DP.DPolynomial] ~ {
polyRingData: PolynomialRingData ← NARROW[in.class.data];
allVarsData: SEQ.SequenceData ← NARROW[polyRingData.allVariables.data];
numVars: CARDINAL = allVarsData.lengthPlus1 - 1;
inTerms: LIST OF Term ← NARROW[in.data];
inTermDegree: CARDINAL; -- degree in main variable of current (input) term
inTermDPolynomial: DP.DPolynomial;
singleVariableIndex: CARDINAL = 1;
ok: BOOL;
degreeVec: DP.DegreeVector;
IF IsZero[in] THEN RETURN[DP.ZeroDPoly];
out ← DP.ZeroDPoly;
WHILE inTerms # NIL DO
inTermDegree ← inTerms.first.exponent;
IF numVars > 1 THEN {
inTermDPolynomial ← DPolyFromPoly[NARROW[inTerms.first.coefficient, Polynomial]];
WHILE inTermDPolynomial#NIL DO
out ← CONS[ [ inTermDPolynomial.first.coefficient, DP.DVAddMainVariablePower[inTermDPolynomial.first.degreeVector, numVars, inTermDegree] ], out];
inTermDPolynomial ← inTermDPolynomial.rest;
ENDLOOP;
}
ELSE {
[ok, degreeVec] ← DP.DVInsertVariablePower[singleVariableIndex, inTermDegree, NIL];
IF NOT ok THEN ERROR;
out ← CONS[ [inTerms.first.coefficient, degreeVec], out];
};
inTerms ← inTerms.rest;
ENDLOOP;
out ← DP.DPReverse[out];
};
Constructors
Monomial: PUBLIC AC.BinaryImbedOp = {
structureData: PolynomialRingData ← NARROW[structure.data];
coeffRing: Object ← structureData.coeffRing;
refExp: REF CARDINALNARROW[data2];
exp: CARDINAL ← refExp^;
equalMethod: Method ← AC.LookupMethodInStructure[$eqFormula, coeffRing];
zero: AC.Object ← AC.ApplyLkpNoRecastObject[$zero, coeffRing, LIST[coeffRing] ];
IF NOT AC.StructureEqual[data1.class, coeffRing] THEN TypeError[]; -- check that we really are constructing an element of polynomialRing
IF AC.ApplyPredNoLkpNoRecast[equalMethod, LIST[data1, zero] ] THEN -- check for zero coeff
RETURN[ NEW[AC.ObjectRec ← [
flavor: StructureElement,
class: structure,
data: NIL
] ] ]
ELSE {
outTerm: Term ← NEW[TermRec ← [exponent: exp, coefficient: data1] ];
outTerms: LIST OF Term ← LIST[outTerm];
RETURN[ NEW[AC.ObjectRec ← [
flavor: StructureElement,
class: structure,
data: outTerms
] ] ];
};
};
Selectors
LeadingCoefficient: PUBLIC AC.UnaryOp ~ {
data: PolynomialRingData ← NARROW[arg.class.data];
coeffRing: Object ← data.coeffRing;
polyData: PolynomialData;
IF IsZero[arg] THEN RETURN[AC.ApplyLkpNoRecastObject[$zero, coeffRing, LIST[coeffRing] ]];
polyData ← NARROW[arg.data];
RETURN[polyData.first.coefficient];
};
Degree: PUBLIC AC.ElementRankOp ~ {
polyData: PolynomialData;
IF IsZero[arg] THEN RETURN[0];
polyData ← NARROW[arg.data];
RETURN[polyData.first.exponent];
};
Reductum: PUBLIC AC.UnaryOp ~ {
polyData: PolynomialData;
IF IsZero[arg] THEN RETURN[arg];
polyData ← NARROW[arg.data];
RETURN[ NEW[AC.ObjectRec ← [flavor: StructureElement, class: arg.class, data: polyData.rest] ] ];
};
Arithmetic
Zero: PUBLIC AC.NullaryOp = {
RETURN[ NEW[ AC.ObjectRec ← [flavor: StructureElement, class: structure, data: NIL]] ]
};
One: PUBLIC AC.NullaryOp = {
data: PolynomialRingData ← NARROW[structure.data];
RETURN[ Monomial[AC.ApplyLkpNoRecastObject[$one, data.coeffRing, LIST[data.coeffRing] ], NEW[CARDINAL ← 0], structure] ];
};
Add: PUBLIC AC.BinaryOp ~ {
data: PolynomialRingData ← NARROW[firstArg.class.data];
coeffRing: Object ← data.coeffRing;
zero: AC.Object ← AC.ApplyLkpNoRecastObject[$zero, coeffRing, LIST[coeffRing] ];
addMethod: Method ← AC.LookupMethodInStructure[$sum, coeffRing];
equalMethod: Method ← AC.LookupMethodInStructure[$eqFormula, coeffRing];
inTerms1: LIST OF Term ← NARROW[firstArg.data];
inTerms2: LIST OF Term ← NARROW[secondArg.data];
outTerms, outTermsPointer, tail: LIST OF Term ← NIL;
outTerm: Term;
termToAdd: BOOL;
IF IsZero[firstArg] THEN RETURN[secondArg];
IF IsZero[secondArg] THEN RETURN[firstArg];
WHILE inTerms1 # NIL AND inTerms2 # NIL DO
termToAdd ← TRUE;
SELECT inTerms1.first.exponent FROM
< inTerms2.first.exponent => {
outTerm ← inTerms2.first;
inTerms2 ← inTerms2.rest;
};
> inTerms2.first.exponent => {
outTerm ← inTerms1.first;
inTerms1 ← inTerms1.rest;
};
= inTerms2.first.exponent => {
coeff: AC.Object ← AC.ApplyNoLkpNoRecastObject[addMethod, LIST[inTerms1.first.coefficient, inTerms2.first.coefficient] ];
IF NOT AC.ApplyPredNoLkpNoRecast[equalMethod,LIST[coeff, zero] ] THEN
outTerm ← NEW[TermRec ← [
exponent: inTerms2.first.exponent,
coefficient: coeff
] ]
ELSE
termToAdd ← FALSE;
inTerms1 ← inTerms1.rest;
inTerms2 ← inTerms2.rest;
};
ENDCASE;
IF termToAdd THEN {
IF outTerms # NIL THEN outTermsPointer ← outTermsPointer.rest ← LIST[outTerm]
ELSE outTerms ← outTermsPointer ← LIST[outTerm];
};
ENDLOOP;
IF inTerms1 = NIL THEN tail ← inTerms2 ELSE tail ← inTerms1;
IF outTerms # NIL THEN outTermsPointer.rest ← tail
ELSE outTerms ← tail;
RETURN[ NEW[AC.ObjectRec ← [flavor: StructureElement, class: firstArg.class, data: outTerms] ] ];
};
Negate: PUBLIC AC.UnaryOp ~ {
data: PolynomialRingData ← NARROW[arg.class.data];
coeffRing: Object ← data.coeffRing;
negateMethod: Method ← AC.LookupMethodInStructure[$negation, coeffRing];
inTerms: LIST OF Term ← NARROW[arg.data];
outTerms, outTermsPointer: LIST OF Term ← NIL;
outTerm: Term;
IF IsZero[arg] THEN RETURN[arg];
WHILE inTerms # NIL DO
outTerm ← NEW[TermRec ← [
exponent: inTerms.first.exponent,
coefficient: AC.ApplyNoLkpNoRecastObject[negateMethod, LIST[inTerms.first.coefficient] ]
] ];
IF outTerms # NIL THEN outTermsPointer ← outTermsPointer.rest ← LIST[outTerm]
ELSE outTerms ← outTermsPointer ← LIST[outTerm];
inTerms ← inTerms.rest;
ENDLOOP;
RETURN[ NEW[AC.ObjectRec ← [flavor: StructureElement, class: arg.class, data: outTerms] ] ];
};
Subtract: PUBLIC AC.BinaryOp ~ {
RETURN[ Add[ firstArg, Negate[ secondArg] ] ];
};
Multiply: PUBLIC AC.BinaryOp ~ {
Does not assume that coefficient multiplication is commutative
data: PolynomialRingData ← NARROW[firstArg.class.data];
coeffRing: Object ← data.coeffRing;
zeroPoly: AC.Object ← AC.ApplyLkpNoRecastObject[$zero, firstArg.class, LIST[firstArg.class] ];
productMethod: Method ← AC.LookupMethodInStructure[$product, coeffRing];
inTerms1: LIST OF Term ← NARROW[firstArg.data];
inTerms2: LIST OF Term ← NARROW[secondArg.data];
outSummand: Polynomial;
outSummandTerms, outSummandTermsPointer: LIST OF Term;
outSummandTerm: Term;
scratchInTerms1: LIST OF Term;
result ← zeroPoly;
IF IsZero[firstArg] OR IsZero[secondArg] THEN RETURN[result];
WHILE inTerms2 # NIL DO
outSummandTerms ← outSummandTermsPointer ← NIL;
scratchInTerms1 ← inTerms1;
WHILE scratchInTerms1 # NIL DO
coeff: AC.Object ← AC.ApplyNoLkpNoRecastObject[productMethod, LIST[
scratchInTerms1.first.coefficient,
inTerms2.first.coefficient
] ];
outSummandTerm ← NEW[TermRec ← [
exponent: scratchInTerms1.first.exponent + inTerms2.first.exponent,
coefficient: coeff
] ];
IF outSummandTerms # NIL THEN outSummandTermsPointer ← outSummandTermsPointer.rest ← LIST[outSummandTerm]
ELSE outSummandTerms ← outSummandTermsPointer ← LIST[outSummandTerm];
scratchInTerms1 ← scratchInTerms1.rest;
ENDLOOP;
outSummand ← NEW[AC.ObjectRec ← [flavor: StructureElement, class: firstArg.class, data: outSummandTerms]];
result ← Add[result, outSummand];
inTerms2 ← inTerms2.rest;
ENDLOOP;
};
ObjectAndIntDesired: PUBLIC AC.UnaryToListOp ~ {
RETURN[ LIST[arg, Ints.Ints] ]; -- arg assumed to be a Structure
};
Power: PUBLIC AC.BinaryOp ~ { -- this simple algorithm is Structure independent
power: INT ← Ints.ToINT[secondArg];
structure: Object ← firstArg.class;
one: Object ← AC.ApplyLkpNoRecastObject[$one, structure, LIST[structure] ];
productMethod: Method ← AC.LookupMethodInStructure[$product, structure];
IF power < 0 THEN {
invertMethod: Method ← AC.LookupMethodInStructure[$invert, structure];
temp: Object;
IF invertMethod = NIL THEN ERROR;
temp ← Power[firstArg, Ints.FromINT[ABS[power] ] ];
RETURN[AC.ApplyNoLkpNoRecastObject[invertMethod, LIST[temp] ] ];
};
IF power = 0 THEN RETURN[one];
result ← firstArg;
FOR i:INT IN [2..power] DO
result ← AC.ApplyNoLkpNoRecastObject[productMethod, LIST[firstArg, result] ];
ENDLOOP;
};
Differentiate: PUBLIC AC.BinaryOp ~ {
Simple or partial differentiation. firstArg is polynomial, secondArg is variable. firstArg is reordered to make secondArg its main variable, then partially differentiated, then result reordered back to original firstArg Structure.
Assumes that CARDINAL exponent values can be imbedded in coeffRing, in particular, that coeffRing.class.fromRope[Convert.RopeFromCard[arg.data.first.exponent]] works.
reorderedArg: Object ← NewMainVariable[firstArg, secondArg];
data: PolynomialRingData ← NARROW[reorderedArg.class.data];
coeffRing: Object ← data.coeffRing;
fromRopeMethod: Method ← AC.LookupMethodInStructure[$fromRope, coeffRing];
productMethod: Method ← AC.LookupMethodInStructure[$product, coeffRing];
inTerms: LIST OF Term ← NARROW[reorderedArg.data];
outTerms, outTermsPointer: LIST OF Term ← NIL;
outTerm: Term;
reorderedResult: Object;
IF Degree[reorderedArg] = 0 THEN RETURN[Zero[firstArg.class] ];
If we are here, variable of diff occurs in both firstArg and reorderedArg, result of diff will be nonzero, and we know we can recast back into firstArg Structure
WHILE inTerms # NIL AND inTerms.first.exponent > 0 DO
imbeddedExp: AC.Object ← AC.ApplyFromRopeMethod[fromRopeMethod, Convert.RopeFromCard[inTerms.first.exponent,10, FALSE], coeffRing];
newCoeff: AC.Object ← AC.ApplyNoLkpNoRecastObject[productMethod, LIST[imbeddedExp, inTerms.first.coefficient] ];
outTerm ← NEW[TermRec ← [exponent: inTerms.first.exponent-1, coefficient: newCoeff] ];
IF outTerms # NIL THEN outTermsPointer ← outTermsPointer.rest ← LIST[outTerm]
ELSE outTerms ← outTermsPointer ← LIST[outTerm];
inTerms ← inTerms.rest;
ENDLOOP;
reorderedResult ← NEW[AC.ObjectRec ← [flavor: StructureElement, class: reorderedArg.class, data: outTerms] ];
RETURN[ Recast[reorderedResult, firstArg.class] ];
};
IndefIntegrate: PUBLIC AC.BinaryOp ~ {
Indefinite integration. firstArg is polynomial, secondArg is variable. firstArg is reordered to make secondArg its main variable, then integrated, then result reordered back to original firstArg Structure.
Constant of integration set to zero.
Currently (some superClass of) coeffRing must have a fraction method, i.e. be a field, and its DesiredArgStructures proc must be able to recast elements of coeffRing. I.e. current proc won't work for multivariate integrands.
Assumes that CARDINAL exponent values can be imbedded in coeffRing, in particular, that coeffRing.class.fromRope[Convert.RopeFromCard[arg.data.first.exponent]] works.
reorderedArg: Object ← NewMainVariable[firstArg, secondArg];
data: PolynomialRingData ← NARROW[reorderedArg.class.data];
coeffRing: Object ← data.coeffRing;
variable: Object ← data.variable;
fromRopeMethod: Method ← AC.LookupMethodInStructure[$fromRope, coeffRing];
fractionMethod: Method ← AC.LookupMethodInStructure[$fraction, coeffRing];
inTerms: LIST OF Term ← NARROW[reorderedArg.data];
outTerms, outTermsPointer: LIST OF Term ← NIL;
newCoeff: AC.Object;
outTerm: Term;
reorderedResult: Object;
IF Degree[reorderedArg] = 0 THEN RETURN[Zero[firstArg.class] ];
IF fractionMethod=NIL THEN RETURN[firstArg]; -- do nothing if no fraction method
If we are here, variable of int occurs in both firstArg and reorderedArg, result of int will be nonzero, and we know we can recast back into firstArg Structure
WHILE inTerms # NIL AND (inTerms.first.exponent > 0 OR inTerms.first.exponent = 0) DO
imbeddedExp: AC.Object ← AC.ApplyFromRopeMethod[fromRopeMethod, Convert.RopeFromCard[inTerms.first.exponent+1,10, FALSE], coeffRing];
newCoeff ← AC.ApplyNoLkpRecastObject[fractionMethod, coeffRing, LIST[inTerms.first.coefficient, imbeddedExp] ]; -- Recast since fraction method may be coming from superClass; if so, coeffRing arg will be bogus, but need the placeholder
outTerm ← NEW[TermRec ← [exponent: inTerms.first.exponent+1, coefficient: newCoeff] ];
IF outTerms # NIL THEN outTermsPointer ← outTermsPointer.rest ← LIST[outTerm]
ELSE outTerms ← outTermsPointer ← LIST[outTerm];
inTerms ← inTerms.rest;
ENDLOOP;
reorderedResult ← NEW[AC.ObjectRec ← [
flavor: StructureElement,
class: MakePolynomialStructure[newCoeff.class, SEQ.MakeSequence[LIST[variable], VARSEQ.VariableSequences] ],
data: outTerms
] ]; -- pick up possible new quotient structure for (new) coefficients
RETURN[ reorderedResult ]; -- return with possibly reordered variables
};
MainVarEval: PUBLIC AC.BinaryOp ~ {
data: PolynomialRingData ← NARROW[firstArg.class.data];
productMethod: Method ← AC.LookupMethodInStructure[$product, coeffRing];
sumMethod: Method ← AC.LookupMethodInStructure[$sum, coeffRing];
coeffRing: Object ← data.coeffRing;
zero: AC.Object ← AC.ApplyLkpNoRecastObject[$zero, coeffRing, LIST[coeffRing] ];
inTerms: LIST OF Term ← NARROW[firstArg.data];
IF NOT AC.StructureEqual[secondArg.class, coeffRing] THEN TypeError[];
IF IsZero[firstArg] THEN RETURN[zero];
result ← inTerms.first.coefficient;
WHILE inTerms.rest # NIL DO
degreeDelta: CARDINAL ← DegreeDelta[inTerms];
newAddend: AC.Object ← AC.ApplyNoLkpNoRecastObject[productMethod, LIST[result, Power[secondArg, Ints.FromINT[degreeDelta] ] ] ];
inTerms ← inTerms.rest;
result ← AC.ApplyNoLkpNoRecastObject[sumMethod, LIST[newAddend, inTerms.first.coefficient] ];
ENDLOOP;
result ← AC.ApplyNoLkpNoRecastObject[productMethod, LIST[result, Power[secondArg, Ints.FromINT[inTerms.first.exponent] ] ] ];
RETURN[ result ];
};
AllVarEval: PUBLIC AC.BinaryOp ~ {
data: PolynomialRingData ← NARROW[firstArg.class.data];
baseCoeffRing: Object ← data.baseCoeffRing;
removeMain: Points.Point;
mainCood: AC.Object;
pointData: Points.PointData ← NARROW[secondArg.data];
inTerms: LIST OF Term ← NARROW[firstArg.data];
coeff: Polynomial;
IF NOT pointData.dimensionPlus1 = data.allVariables.lengthPlus1 THEN OperationError[$BadPointLength];
IF pointData.dimensionPlus1 - 1 = 1 THEN {
at: AC.Object ← NARROW[secondArg.data, Points.PointData][1];
RETURN[MainVarEval[firstArg, at] ];
};
removeMain ← Points.RemoveMainCood[secondArg];
mainCood ← Points.MainCood[secondArg]; -- element of baseCoeffRing
IF NOT baseCoeffRing.class.isElementOf[mainCood, baseCoeffRing] THEN TypeError[];
IF IsZero[firstArg] THEN RETURN[baseCoeffRing.class.zero[baseCoeffRing] ];
coeff ← NARROW[inTerms.first.coefficient];
result ← AllVarEval[coeff, removeMain]; -- element of baseCoeffRing
WHILE inTerms.rest # NIL DO
degreeDelta: CARDINAL ← DegreeDelta[inTerms];
newAddend: AC.Object ← baseCoeffRing.class.multiply[result, Power[mainCood, Ints.FromINT[degreeDelta] ] ];
inTerms ← inTerms.rest;
coeff ← NARROW[inTerms.first.coefficient];
result ← baseCoeffRing.class.add[newAddend, AllVarEval[coeff, removeMain] ];
ENDLOOP;
result ← baseCoeffRing.class.multiply[result, Power[mainCood, Ints.FromINT[inTerms.first.exponent] ] ];
RETURN[ result ];
};
Subst: PUBLIC AC.BinaryOp ~ {
polyRing: Object ← firstArg.class;
data: PolynomialRingData ← NARROW[polyRing.data];
inTerms: LIST OF Term ← NARROW[firstArg.data];
IF NOT polyRing.class.isElementOf[secondArg, polyRing] THEN TypeError[];
IF IsZero[firstArg] THEN RETURN[firstArg];
result ← Monomial[inTerms.first.coefficient, NEW[CARDINAL ← 0], polyRing]; -- lift coefficient
WHILE inTerms.rest # NIL DO
degreeDelta: CARDINAL ← DegreeDelta[inTerms];
trailCoeff: Polynomial;
newAddend: Polynomial ← NARROW[polyRing.class.multiply[result, Power[secondArg, Ints.FromINT[degreeDelta] ] ] ];
inTerms ← inTerms.rest;
trailCoeff ← Monomial[inTerms.first.coefficient, NEW[CARDINAL ← 0], polyRing]; -- lift
result ← NARROW[ polyRing.class.add[newAddend, trailCoeff] ];
ENDLOOP;
result ← NARROW[ polyRing.class.multiply[result, Power[secondArg, Ints.FromINT[inTerms.first.exponent] ] ] ];
RETURN[ result ];
};
DegreeDelta: PUBLIC PROC [terms: LIST OF Term] RETURNS [CARDINAL] ~ {
IF terms = NIL THEN RETURN[0];
IF terms.rest = NIL THEN RETURN[terms.first.exponent];
RETURN[terms.first.exponent - terms.rest.first.exponent];
};
SylvesterMatrix: PUBLIC AC.BinaryOp ~ {
data: PolynomialRingData ← NARROW[firstArg.class.data];
coeffRing: Object ← data.coeffRing;
degree1: CARDINAL ← Degree[firstArg];
degree2: CARDINAL ← Degree[secondArg];
size: CARDINAL ← degree1 + degree2;
rows: MAT.RowSeq ← NEW[MAT.RowSeqRec[size]];
zero: AC.Object ← AC.ApplyLkpNoRecastObject[$zero, coeffRing, LIST[coeffRing] ];
matrixStructure: Object ← MAT.MakeMatrixStructure[coeffRing, size, size];
IF degree1 = 0 AND degree2 = 0 THEN RETURN[NIL]; -- undefined in this case
IF degree1 = 0 THEN {
IF IsZero[firstArg] THEN
RETURN[NARROW[MAT.DiagonalMatrix[zero, matrixStructure] ] ]
ELSE {
polyData: PolynomialData ← NARROW[firstArg.data];
RETURN[NARROW[MAT.DiagonalMatrix[polyData.first.coefficient, matrixStructure] ] ];
};
};
IF degree2 = 0 THEN {
IF IsZero[secondArg] THEN
RETURN[NARROW[MAT.DiagonalMatrix[zero, matrixStructure] ] ]
ELSE {
polyData: PolynomialData ← NARROW[secondArg.data];
RETURN[NARROW[MAT.DiagonalMatrix[polyData.first.coefficient, matrixStructure] ] ];
};
};
FOR i:NAT IN [1..degree2] DO
row: Matrices.Row ← NEW[Matrices.RowRec[size]];
in1Terms: LIST OF Term ← NARROW[firstArg.data];
FOR j:NAT IN [1..i-1] DO
row[j] ← zero;
ENDLOOP;
row[i] ← in1Terms.first.coefficient;
WHILE in1Terms.rest # NIL DO
degreeDelta: CARDINAL ← DegreeDelta[in1Terms];
FOR j: NAT IN [1..degreeDelta-1] DO
row[i+degree1-in1Terms.first.exponent+j] ← zero;
ENDLOOP;
in1Terms ← in1Terms.rest;
row[i+degree1-in1Terms.first.exponent] ← in1Terms.first.coefficient;
ENDLOOP;
FOR j: NAT IN [1..in1Terms.first.exponent+(degree2-i)] DO
row[size+1-j] ← zero;
ENDLOOP;
rows[i] ← row;
ENDLOOP;
FOR i:NAT IN [1..degree1] DO
row: Matrices.Row ← NEW[Matrices.RowRec[size]];
in2Terms: LIST OF Term ← NARROW[secondArg.data];
FOR j:NAT IN [1..i-1] DO
row[j] ← zero;
ENDLOOP;
row[i] ← in2Terms.first.coefficient;
WHILE in2Terms.rest # NIL DO
degreeDelta: CARDINAL ← DegreeDelta[in2Terms];
FOR j: NAT IN [1..degreeDelta-1] DO
row[i+degree2-in2Terms.first.exponent+j] ← zero;
ENDLOOP;
in2Terms ← in2Terms.rest;
row[i+degree2-in2Terms.first.exponent] ← in2Terms.first.coefficient;
ENDLOOP;
FOR j: NAT IN [1..in2Terms.first.exponent+(degree1-i)] DO
row[size+1-j] ← zero;
ENDLOOP;
rows[degree2+i] ← row;
ENDLOOP;
result ← NEW[AC.ObjectRec ← [flavor: StructureElement, class: matrixStructure, data: rows] ];
};
Resultant: PUBLIC AC.BinaryOp ~ {
sylvesterMatrix: MAT.Matrix ← SylvesterMatrix[firstArg, secondArg];
RETURN[MAT.Determinant[sylvesterMatrix] ];
};
GCD: PUBLIC AC.BinaryOp ~ {
polyRingData: PolynomialRingData ← NARROW[firstArg.class.data];
allVariables: Object ← polyRingData.allVariables;
varRope: ROPENARROW[AC.ApplyLkpNoRecastRef[$toRope, allVariables.class, LIST[allVariables] ] ];
resultStream: IO.STREAM ← RemoteAlgebra.SAC2PolynomialBinaryOp[varRope, ToRope[firstArg], ToRope[secondArg] ];
RETURN[Read[resultStream, firstArg.class] ];
};
Remainder: PUBLIC AC.BinaryOp ~ {
newDividend: Polynomial ← firstArg;
polyRingData: PolynomialRingData ← NARROW[firstArg.class.data];
coeffRing: Object ← polyRingData.coeffRing;
fractionMethod: Method ← AC.LookupMethodInStructure[$fraction, coeffRing];
IF NOT AC.IsCategory[coeffRing, field] AND AC.IsCategory[coeffRing, divisionAlgebra] THEN TypeError[];
WHILE Degree[newDividend] >= Degree[secondArg] DO
coeff: AC.Object ← AC.ApplyNoLkpNoRecastObject[fractionMethod, LIST[LeadingCoefficient[newDividend], LeadingCoefficient[secondArg] ] ];
degreeDelta: CARDINAL ← Degree[newDividend] - Degree[secondArg];
multiplier: Polynomial ← Monomial[coeff, NEW[CARDINAL ← degreeDelta], firstArg.class];
product: Polynomial ← Multiply[multiplier, secondArg];
newDividend ← Subtract[newDividend, product];
ENDLOOP;
RETURN[newDividend];
};
Comparison
Equal: PUBLIC AC.EqualityOp ~ {
RETURN[IsZero[Subtract[firstArg, secondArg] ] ];
};
IsZero: PUBLIC AC.UnaryPredicate ~ {
RETURN[AC.HasProperty[arg.class, $polynomialStructure] AND arg.data = NIL] };
Sign: PUBLIC AC.CompareToZeroOp ~ {
data: PolynomialRingData ← NARROW[arg.class.data];
polyData: PolynomialData;
IF NOT arg.class.class.ordered THEN TypeError[$UnorderedStructure];
IF IsZero[arg] THEN RETURN[equal]; -- needed since arg.data = NIL for zero poly
polyData ← NARROW[arg.data];
RETURN[data.coeffRing.class.sign[polyData.first.coefficient] ];
};
Abs: PUBLIC AC.UnaryOp ~ {
IF NOT arg.class.class.ordered THEN TypeError[$UnorderedStructure];
IF Sign[arg] = less THEN RETURN[Negate[arg]] ELSE RETURN[arg];
};
Compare: PUBLIC AC.BinaryCompareOp ~ {
IF NOT firstArg.class.class.ordered THEN TypeError[$UnorderedStructure];
RETURN[Sign[ Subtract[firstArg, secondArg] ]];
};
Utility
ObjectAndVariableDesired: PUBLIC AC.UnaryToListOp ~ {
RETURN[ LIST[arg, Variables.Variables] ]; -- arg assumed to be a polynomial Structure
};
NewMainVariable: PUBLIC AC.BinaryOp ~ {
firstArg is polynomial, secondArg is a Variable that may or may not occur in firstArg's allVariables. result is firstArg with reordered variables so that secondArg is new main variable. Order of other variables is preserved
polyRingData: PolynomialRingData ← NARROW[firstArg.class.data];
allVars: VARSEQ.VariableSequence ← polyRingData.allVariables;
reorderedVars: VARSEQ.VariableSequence ← VARSEQ.NewMainVariable[allVars, secondArg];
newStruct: Object ← MakePolynomialStructure[polyRingData.baseCoeffRing, reorderedVars];
RETURN[ Recast[firstArg, newStruct] ];
};
Start Code
polynomialsOverCommOrderedRingClass: PUBLIC AC.StructureClass ** Old ** NEW[AC.StructureClassRec ← [
characteristic: ClassCharacteristic,
isElementOf: AC.defaultElementOfProc,
integralDomain: TRUE, -- not necessarily accurate; need separate classrecs
gcdDomain: FALSE, -- not necessarily accurate; need separate classrecs
gcd: NIL, -- should have a poly gcd proc here when appropriate
euclideanDomain: FALSE,
] ];
polynomialClass: AC.Object ← AC.MakeClass["polynomialClass", NIL, NIL];
polynomialsOverCommRingClass: AC.Object ← AC.MakeClass["polynomialsOverCommRingClass", polynomialClass, NIL];
subclass[polynomialClass]
polynomialsOverOrderedCommRingClass: AC.Object ← AC.MakeClass["polynomialsOverOrderedCommRingClass", polynomialsOverCommRingClass, NIL];
subclass[polynomialsOverCommRingClass]
polynomialsOverOrderedCommFieldClass: AC.Object ← AC.MakeClass["polynomialsOverOrderedCommFieldClass", polynomialsOverOrderedCommRingClass, NIL];
subclass[polynomialsOverOrderedCommRingClass]
polynomialsOverNonCommRingClass: AC.Object ← AC.MakeClass["polynomialsOverNonCommRingClass", polynomialClass, NIL];
subclass[polynomialClass]; this is e.g. for polynomials with matrix coefficients
polynomialStructureMethod: Method ← AC.MakeMethod[Value, FALSE, NIL, NIL, "polynomialStructure"];
groupCategoryMethod: Method ← AC.MakeMethod[Value, FALSE, NEW[AC.Category ← group], NIL, "group"];
ringCategoryMethod: Method ← AC.MakeMethod[Value, FALSE, NEW[AC.Category ← ring], NIL, "ring"];
euclideanDomainMethod: Method ← AC.MakeMethod[Value, FALSE, NIL, NIL, "euclideanDomain"];
orderedMethod: Method ← AC.MakeMethod[Value, FALSE, NIL, NIL, "ordered"];
commutativeMethod: Method ← AC.MakeMethod[Value, FALSE, NIL, NIL, "commutative"];
shortPrintNameMethod: Method ← AC.MakeMethod[ToRopeOp, FALSE, NEW[AC.ToRopeOp ← ShortPrintName], NIL, "shortPrintName"];
recastMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Recast], NIL, "recast"];
canRecastMethod: Method ← AC.MakeMethod[BinaryPredicate, TRUE, NEW[AC.BinaryPredicate ← CanRecast], NIL, "canRecast"];
toExprMethod: Method ← AC.MakeMethod[ToExprOp, FALSE, NEW[AC.ToExprOp ← ToExpr], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "toExpr"];
fromRopeMethod: Method ← AC.MakeMethod[FromRopeOp, TRUE, NEW[AC.FromRopeOp ← FromRope], NIL, "fromRope"];
readMethod: Method ← AC.MakeMethod[ReadOp, FALSE, NEW[AC.ReadOp ← Read], NIL, "read"];
toRopeMethod: Method ← AC.MakeMethod[ToRopeOp, FALSE, NEW[AC.ToRopeOp ← ToRope], NIL, "toRope"];
monomialMethod: Method ← AC.MakeMethod[BinaryImbedOp, FALSE, NEW[AC.BinaryImbedOp ← Monomial], NIL, "monomial"];
leadingCoeffMethod: Method ← AC.MakeMethod[UnaryOp, TRUE, NEW[AC.UnaryOp ← LeadingCoefficient], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "leadingCoeff"];
degreeMethod: Method ← AC.MakeMethod[ElementRankOp, TRUE, NEW[AC.ElementRankOp ← Degree], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "degree"];
reductumMethod: Method ← AC.MakeMethod[UnaryOp, TRUE, NEW[AC.UnaryOp ← Reductum], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "reductum"];
parenMethod: Method ← AC.MakeMethod[UnaryOp, FALSE, NEW[AC.UnaryOp ← AC.Copy], NIL, "paren"];
zeroMethod: Method ← AC.MakeMethod[NullaryOp, FALSE, NEW[AC.NullaryOp ← Zero], NIL, "zero"];
oneMethod: Method ← AC.MakeMethod[NullaryOp, FALSE, NEW[AC.NullaryOp ← One], NIL, "one"];
sumMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Add], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "sum"];
negationMethod: Method ← AC.MakeMethod[UnaryOp, TRUE, NEW[AC.UnaryOp ← Negate], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "negation"];
differenceMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Subtract], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "difference"];
productMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Multiply], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "product"];
powerMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Power], NEW[AC.UnaryToListOp ← ObjectAndIntDesired], "power"];
derivativeMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Differentiate], NEW[AC.UnaryToListOp ← ObjectAndVariableDesired], "derivative"];
partialDerivativeMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Differentiate], NEW[AC.UnaryToListOp ← ObjectAndVariableDesired], "partialDerivative"];
indefIntMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← IndefIntegrate], NEW[AC.UnaryToListOp ← ObjectAndVariableDesired], "indefiniteIntegrate"];
newMainVariableMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← NewMainVariable], NEW[AC.UnaryToListOp ← ObjectAndVariableDesired], "newMainVarialbe"];
mainVarEvalMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← MainVarEval], NIL, "mainVarEval"];
allVarEvalMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← AllVarEval], NIL, "allVarEval"];
substMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Subst], NIL, "substitute"];
sylvesterMatrixMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← SylvesterMatrix], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "sylvesterMatrix"];
resultantMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Resultant], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "resultant"];
gcdMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← GCD], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "gcd"];
remainderMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Remainder], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "remainder"];
equalMethod: Method ← AC.MakeMethod[BinaryPredicate, TRUE, NEW[AC.BinaryPredicate ← Equal], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "equals"];
makePolynomialStructureMethod: Method ← AC.MakeMethod[PolynomialStructureConstructor, FALSE, NEW[AC.PolynomialStructureConstructor ← MakePolynomialStructure], NIL, "makePolynomialStructure"];
AC.AddMethodToClass[$polynomialStructure, polynomialStructureMethod, polynomialClass];
AC.AddMethodToClass[$category, groupCategoryMethod, polynomialClass];
AC.AddMethodToClass[$shortPrintName, shortPrintNameMethod, polynomialClass];
AC.AddMethodToClass[$recast, recastMethod, polynomialClass];
AC.AddMethodToClass[$canRecast, canRecastMethod, polynomialClass];
AC.AddMethodToClass[$toExpr, toExprMethod, polynomialClass];
AC.AddMethodToClass[$fromRope, fromRopeMethod, polynomialClass];
AC.AddMethodToClass[$read, readMethod, polynomialClass];
AC.AddMethodToClass[$toRope, toRopeMethod, polynomialClass];
AC.AddMethodToClass[$monomial, monomialMethod, polynomialClass];
AC.AddMethodToClass[$leadingCoeff, leadingCoeffMethod, polynomialClass];
AC.AddMethodToClass[$degree, degreeMethod, polynomialClass];
AC.AddMethodToClass[$reductum, reductumMethod, polynomialClass];
AC.AddMethodToClass[$paren, parenMethod, polynomialClass];
AC.AddMethodToClass[$zero, zeroMethod, polynomialClass];
AC.AddMethodToClass[$one, oneMethod, polynomialClass];
AC.AddMethodToClass[$sum, sumMethod, polynomialClass];
AC.AddMethodToClass[$negation, negationMethod, polynomialClass];
AC.AddMethodToClass[$difference, differenceMethod, polynomialClass];
AC.AddMethodToClass[$eqFormula, equalMethod, polynomialClass];
AC.AddMethodToClass[$newMainVariable, newMainVariableMethod, polynomialClass];
AC.AddMethodToClass[$category, ringCategoryMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$commutative, commutativeMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$product, productMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$pow, powerMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$dDx, derivativeMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$partialDeriv, partialDerivativeMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$indefInt, indefIntMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$mainVarEval, mainVarEvalMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$allVarEval, allVarEvalMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$subst, substMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$sylvesterMatrix, sylvesterMatrixMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$resultant, resultantMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$gcd, gcdMethod, polynomialsOverCommRingClass];
AC.AddMethodToClass[$ordered, orderedMethod, polynomialsOverOrderedCommRingClass];
AC.AddMethodToClass[$euclideanDomain, euclideanDomainMethod, polynomialsOverOrderedCommFieldClass];
AC.AddMethodToClass[$remainder, remainderMethod, polynomialsOverOrderedCommFieldClass];
AC.AddMethodToClass[$makePolynomialStructure, makePolynomialStructureMethod, Structures.StructuresClass];
AC.AddMethodToClass[$Polynomials, makePolynomialStructureMethod, Structures.StructuresClass];
END.