'From Squeak 2.0 of May 22, 1998 on 29 August 1998 at 7:46:36 pm'! Object subclass: #AlgebraicVariety instanceVariableNames: 'system parametrization ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Ideals'! Object subclass: #Ideal instanceVariableNames: 'generators ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Ideals'! Object subclass: #IdealGenerator instanceVariableNames: 'contents ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Ideals'! IdealGenerator subclass: #GroebnerBasis instanceVariableNames: 'ordering ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Ideals'! Ideal subclass: #IdealWithGroebner instanceVariableNames: 'groebner ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Ideals'! Magnitude subclass: #Infinity instanceVariableNames: 'sign ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Kernel'! Object subclass: #Monomial instanceVariableNames: 'literal coefficient ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Polynomials'! Object subclass: #MonomialLiteral instanceVariableNames: 'contents ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Polynomials'! Object subclass: #MonomialOrdering instanceVariableNames: 'indeterminates weighs ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Polynomials'! Object subclass: #MultiPolynomialDivisor instanceVariableNames: 'dividend divisors ordering quotients remainder done ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Polynomials'! Object subclass: #Polynomial instanceVariableNames: 'monomials ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Polynomials'! Object subclass: #PolynomialDivisor instanceVariableNames: 'dividend divisor quotient remainder done ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Polynomials'! Object subclass: #PolynomialEquation instanceVariableNames: 'polynomial ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Ideals'! Object subclass: #PolynomialPseudoDivisor instanceVariableNames: 'dividend divisor indeterminate quotient remainder done ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Polynomials'! Object subclass: #PolynomialSystem instanceVariableNames: 'equations ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Ideals'! Object subclass: #RationalFunction instanceVariableNames: 'numerator denominator ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Kernel'! Object subclass: #RationalParametrization instanceVariableNames: 'contents ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Ideals'! Object subclass: #Tuple instanceVariableNames: 'contents ' classVariableNames: '' poolDictionaries: '' category: 'Mathematics-Kernel'! !Object methodsFor: 'testing' stamp: 'len 12/13/97 02:25'! isInfinity "Answer true if the receiver is infinity." ^ false! ! !Object methodsFor: 'testing' stamp: 'len 1/24/98 13:43'! isMonomial "Answer true if the receiver is a monomial." ^ false! ! !Object methodsFor: 'testing' stamp: 'len 11/24/97 20:46'! isMonomialLiteral "Answer true if the receiver is a monomial literal." ^ false! ! !Object methodsFor: 'testing' stamp: 'len 1/20/98 01:46'! isPolynomial "Answer true if the receiver is a polynomial." ^ false! ! !Object methodsFor: 'testing' stamp: 'pdm 6/20/1998 19:57'! isRationalFunction ^ false! ! !Object methodsFor: 'testing' stamp: 'len 11/28/97 02:08'! isTuple "Answer true if the receiver is a Tuple." ^ false! ! !AlgebraicVariety commentStamp: 'pdm 8/29/1998 19:46' prior: 0! My instances represent the solutions of systems of polynomial equations over an algebrically closed field. For an example try this: (here the variety is finite) | x y | x _ Polynomial x. y _ Polynomial y. AlgebraicVariety system: (PolynomialSystem new add: (x*x eq: 1); add: (y*y - (x*x) eq: 3); yourself). Or this one: (here the variety is empty) AlgebraicVariety system: (PolynomialSystem new add: ((Polynomial continuantOfOrder: 2) eq: 0); add: ((Polynomial continuantOfOrder: 3) eq: 0); yourself). You can also create AlgebraicVarieties sending the message #solutions to an equation or a system of polynomial equations. For instance: | x y | x _ Polynomial x. y _ Polynomial y. ((y eq: 0), (x*x - 1 eq: 0)) solutions. Note that the last sentence is equivalent to: (y eq: 0) solutions intersect: (x*x - 1 eq: 0) solutions. ! !AlgebraicVariety methodsFor: 'accessing-private' stamp: 'pdm 8/17/1998 19:47'! parametrization: aRationalParametrization parametrization _ aRationalParametrization! ! !AlgebraicVariety methodsFor: 'accessing-private' stamp: 'pdm 3/9/98 16:29'! system: aPolynomialSystem system _ aPolynomialSystem! ! !AlgebraicVariety methodsFor: 'accessing' stamp: 'pdm 8/17/1998 19:47'! parametrization ^ parametrization! ! !AlgebraicVariety methodsFor: 'accessing' stamp: 'pdm 8/17/1998 19:49'! system "Answer the polynomial system that defines the receiver." system isNil ifTrue: [system _ parametrization implicit]. ^ system! ! !AlgebraicVariety methodsFor: 'arithmetic' stamp: 'pdm 8/17/1998 20:01'! intersect: anAlgebraicVariety "Answer the intersection between the receiver and the argument." ^ self class system: (self system copy addAll: anAlgebraicVariety system; yourself)! ! !AlgebraicVariety methodsFor: 'testing' stamp: 'pdm 3/9/98 16:29'! includes: aTuple "Answer true if the receiver includes the argument." ^ self system isSolution: aTuple! ! !AlgebraicVariety methodsFor: 'testing' stamp: 'pdm 3/9/98 16:30'! isEmpty "Answer true if the receiver is empty. Ref. Algorithmic Algebra, B. Mishra, pag. 142-145." | ideal | ideal _ Ideal new. self system do: [:each | ideal add: each polynomial]. ideal groebner do: [:each | (each isConstant and: [each isNull not]) ifTrue: [^ true]]. ^ false! ! !AlgebraicVariety methodsFor: 'printing' stamp: 'pdm 8/17/1998 19:46'! printOn: aStream "Print a representation of the receiver on the stream aStream." super printOn: aStream. aStream nextPutAll: ' given by '; print: (parametrization notNil ifTrue: [parametrization] ifFalse: [system])! ! !AlgebraicVariety class methodsFor: 'instance creation' stamp: 'pdm 8/17/1998 19:55'! parametrization: aRationalParametrization "Answer a new instance of the receiver representing the algebraic variety given by aRationalParametrization." ^ self new parametrization: aRationalParametrization! ! !AlgebraicVariety class methodsFor: 'instance creation' stamp: 'pdm 8/17/1998 19:53'! system: aPolynomialSystem "Answer a new instance of the receiver representing the solutions of the system of equations aPolynomialSystem." ^ self new system: aPolynomialSystem! ! !Ideal commentStamp: 'pdm 8/29/1998 19:46' prior: 0! My instances represent ideals of polynomials generated by a finite basis. For an examples try this: | ideal x y | x _ Polynomial x. y _ Polynomial y. ideal _ IdealGenerator new add: x*x; add: y*2 + x; yourself. ideal includes: (x + y) squared. ! !Ideal methodsFor: 'accessing-private' stamp: 'pdm 3/22/98 17:19'! generators: aCollection generators _ aCollection! ! !Ideal methodsFor: 'accessing' stamp: 'pdm 3/22/98 17:24'! generators "Answer a generators set of the receiver." ^ generators! ! !Ideal methodsFor: 'arithmetic' stamp: 'pdm 3/22/98 17:32'! * anIdeal "Answer the product of the receiver by the argument." | prodgen | prodgen _ self generators class new. self generators do: [:each | anIdeal generators do: [:other | prodgen add: each * other]]. ^ self class generators: prodgen! ! !Ideal methodsFor: 'arithmetic' stamp: 'pdm 3/22/98 17:22'! + anIdeal "Answer the sum of the receiver and the argument." ^ self class generators: (self generators copy addAll: anIdeal generators; yourself)! ! !Ideal methodsFor: 'comparing' stamp: 'pdm 3/22/98 17:25'! <= anIdeal "Answer true if the receiver is included in the argument." self generators do: [:each | (anIdeal includes: each) ifFalse: [^ false]]. ^ true! ! !Ideal methodsFor: 'comparing' stamp: 'pdm 3/7/98 19:41'! = anIdeal "Answer true if the receiver is equal to the argument." ^ self <= anIdeal and: [anIdeal <= self]! ! !Ideal methodsFor: 'comparing' stamp: 'pdm 3/7/98 19:52'! >= anIdeal "Answer true if the argument is included in the receiver." ^ anIdeal <= self! ! !Ideal methodsFor: 'comparing' stamp: 'pdm 3/7/98 19:45'! hash "Answer the hash of the receiver." ^ 0! ! !Ideal methodsFor: 'testing' stamp: 'pdm 3/22/98 17:41'! includes: anObject "Answer true if the receiver includes the argument." self subclassResponsibility! ! !Ideal methodsFor: 'testing' stamp: 'pdm 3/9/98 16:32'! isNull "Answer true if the receiver is the null ideal." self do: [:each | each isNull ifFalse: [^ false]]. ^ true! ! !Ideal methodsFor: 'copying' stamp: 'pdm 3/22/98 17:22'! copy "Answer a copy of the receiver." ^ self class generators: self generators copy! ! !Ideal methodsFor: 'printing' stamp: 'pdm 3/9/98 16:32'! printOn: aStream "Print a representation of the receiver on the stream aStream." | first | aStream nextPut: $<. first _ true. self do: [:each | first ifFalse: [aStream nextPutAll: ', ']. aStream print: each. first _ false]. aStream nextPut: $>! ! !Ideal class methodsFor: 'instance creation' stamp: 'pdm 3/22/98 17:45'! generators: anIdealGenerator "Answer a new instance of the receiver with the generators given by the argument." ^ self new generators: anIdealGenerator! ! !IdealGenerator methodsFor: 'initialization' stamp: 'len 2/6/98 11:01'! initialize self contents: OrderedCollection new! ! !IdealGenerator methodsFor: 'accessing-private' stamp: 'len 2/6/98 11:02'! contents ^ contents! ! !IdealGenerator methodsFor: 'accessing-private' stamp: 'pdm 3/9/98 16:33'! contents: aCollection contents _ aCollection! ! !IdealGenerator methodsFor: 'accessing' stamp: 'pdm 4/19/98 18:27'! add: anObject "Add the argument to the receiver. Answer the argument." ^ self contents add: anObject! ! !IdealGenerator methodsFor: 'accessing' stamp: 'pdm 3/9/98 16:33'! addAll: aCollection "Add the elements in the argument to the receiver. Answer the argument. " aCollection do: [:each | self add: each]. ^ aCollection! ! !IdealGenerator methodsFor: 'accessing' stamp: 'pdm 3/9/98 16:34'! at: anInteger "Answer the anInteger-th element in the receiver." ^ self contents at: anInteger! ! !IdealGenerator methodsFor: 'accessing' stamp: 'pdm 3/9/98 16:34'! at: anInteger put: anObject "Change the anInteger-th element in the receiver to be anObject. Answer anObject." ^ self contents at: anInteger put: anObject! ! !IdealGenerator methodsFor: 'accessing' stamp: 'pdm 3/9/98 16:34'! first "Answer the first element in the receiver." ^ self at: 1! ! !IdealGenerator methodsFor: 'accessing' stamp: 'pdm 3/9/98 16:34'! indexOf: anObject "Answer the index of the argument in the receiver." | answer | answer _ 1. self do: [:each | each = anObject ifTrue: [^ answer]. answer _ answer + 1]. self errorNotFound! ! !IdealGenerator methodsFor: 'accessing' stamp: 'pdm 3/9/98 16:34'! size "Answer the number of elements in the receiver." ^ self contents size! ! !IdealGenerator methodsFor: 'enumerating' stamp: 'pdm 3/9/98 16:35'! collect: aBlock "Answer a copy of the receiver with the elements mapped by aBlock. " | answer | answer _ self class new. self do: [:each | answer add: (aBlock value: each)]. ^ answer! ! !IdealGenerator methodsFor: 'enumerating' stamp: 'pdm 3/9/98 16:35'! do: aBlock "Enumerate the elements in the receiver." 1 to: self size do: [:each | aBlock value: (self at: each)]! ! !IdealGenerator methodsFor: 'enumerating' stamp: 'pdm 3/9/98 16:35'! select: aBlock "Answer the subset of the receiver satistying aBlock." | answer | answer _ self class new. self do: [:each | (aBlock value: each) ifTrue: [answer add: each]]. ^ answer! ! !IdealGenerator methodsFor: 'testing' stamp: 'pdm 3/9/98 16:35'! includes: anObject "Answer true if the receiver includes the argument." self do: [:each | each = anObject ifTrue: [^ true]]. ^ false! ! !IdealGenerator methodsFor: 'testing' stamp: 'pdm 3/9/98 16:35'! isEmpty "Answer true if the receiver is empty." ^ self size = 1! ! !IdealGenerator methodsFor: 'copying' stamp: 'pdm 3/9/98 16:35'! copy "Answer a copy of the receiver." ^ self class new addAll: self; yourself! ! !IdealGenerator methodsFor: 'copying' stamp: 'pdm 3/9/98 16:35'! copyWithout: anObject "Answer a copy of the receiver without anObject." ^ self select: [:each | each ~= anObject]! ! !IdealGenerator methodsFor: 'printing' stamp: 'pdm 3/9/98 16:36'! printOn: aStream "Print a representation of the receiver on the stream aStream." | first | aStream nextPut: ${. first _ true. self do: [:each | first ifFalse: [aStream nextPutAll: ', ']. aStream print: each. first _ false]. aStream nextPut: $}! ! !GroebnerBasis commentStamp: 'pdm 8/29/1998 19:46' prior: 0! My instances represent Groebner basis of a given ideal. For an example, try this: | x y grlex f1 f2 basis | x _ Polynomial x. y _ Polynomial y. grlex _ MonomialOrdering tlex: #(1 2). f1 _ x**3 - (2*x*y). f2 _ x**2*y - (2*y*y) + x. basis _ IdealGenerator new add: f1; add: f2; yourself. GroebnerBasis from: basis ordering: grlex ! !GroebnerBasis methodsFor: 'accessing-private' stamp: 'pdm 8/17/1998 20:48'! ordering: aMonomialOrdering "Change the monomial ordering of the receiver." ordering _ aMonomialOrdering! ! !GroebnerBasis methodsFor: 'accessing' stamp: 'pdm 4/19/98 18:23'! minimal "Answer the minimal Groebner basis of the receiver." | monics leadings goods answer | monics _ self collect: [:each | each / (self ordering headOf: each) coefficient]. leadings _ (1 to: monics size) collect: [:each | (self ordering headOf: (monics at: each)) literal]. goods _ (1 to: monics size) asSet. 1 to: monics size do: [:each | (goods detect: [:one | each ~= one and: [(leadings at: one) divides: (leadings at: each)]] ifNone: []) notNil ifTrue: [goods remove: each]]. answer _ self class new. goods do: [:each | answer add: (monics at: each)]. ^ answer! ! !GroebnerBasis methodsFor: 'accessing' stamp: 'pdm 3/9/98 16:30'! ordering "Answer the monomial ordering of the receiver." ^ ordering! ! !GroebnerBasis methodsFor: 'accessing' stamp: 'pdm 4/19/98 17:13'! remainderOf: aPolynomial "Answer the remainder of the argument when divided by the receiver. " ^ (MultiPolynomialDivisor divide: aPolynomial by: self ordering: self ordering) remainder! ! !GroebnerBasis methodsFor: 'testing' stamp: 'pdm 3/7/98 17:36'! isMinimal "Answer true if the receiver is a minimal Groebner basis." | id | id _ self first identityCoefficient. self do: [:each | (self ordering headOf: each) coefficient ~= id ifTrue: [^ false]]. self do: [:each | ((Ideal basis: (self copyWithout: each)) includes: (self ordering headOf: each) asPolynomial) ifTrue: [^ false]]. ^ true! ! !GroebnerBasis methodsFor: 'testing' stamp: 'pdm 3/9/98 16:31'! isReduced "Answer true if the receiver is a reduced Groebner basis." | id ideal | id _ self first identityCoefficient. self do: [:each | (self ordering headOf: each) coefficient ~= id ifTrue: [^ false]]. self do: [:each | ideal _ Ideal basis: (self copyWithout: each). each do: [:other | (ideal includes: other asPolynomial) ifTrue: [^ false]]]. ^ true! ! !GroebnerBasis methodsFor: 'copying' stamp: 'pdm 3/9/98 16:31'! copy "Answer a copy of the reciever." ^ super copy ordering: self ordering! ! !IdealGenerator class methodsFor: 'instance creation' stamp: 'len 2/6/98 11:11'! new ^ super new initialize! ! !GroebnerBasis class methodsFor: 'instance creation' stamp: 'pdm 3/7/98 19:14'! from: anIdealBasis "Answer a new instance of the receiver representing a Groebner basis obtainded from anIdealBasis" | indets | indets _ Set new. anIdealBasis do: [:each | indets addAll: each indeterminates]. ^ self from: anIdealBasis ordering: (MonomialOrdering lex: indets asSortedCollection)! ! !GroebnerBasis class methodsFor: 'instance creation' stamp: 'pdm 4/19/98 17:24'! from: anIdealGenerator ordering: aMonomialOrdering "Answer a new instance of the receiver representing a Groebner basis obtainded from anIdealGenerator operating with the ordering aMonomialOrdering." | answer next rem lcm p q hp hq | answer _ self new ordering: aMonomialOrdering; addAll: anIdealGenerator; yourself. [next _ OrderedCollection new. 1 to: answer size do: [:each | each + 1 to: answer size do: [:other | p _ answer at: each. q _ answer at: other. hp _ aMonomialOrdering headOf: p. hq _ aMonomialOrdering headOf: q. lcm _ hp literal lcm: hq literal. rem _ answer remainderOf: p * lcm / hp - (q * lcm / hq). rem isNull ifFalse: [next add: rem]]]. (answer addAll: next) isEmpty] whileFalse. ^ answer! ! !IdealWithGroebner methodsFor: 'accessing-private' stamp: 'pdm 3/22/98 17:37'! groebner: aGroebnerBasis "Change the instance variable." groebner _ aGroebnerBasis! ! !IdealWithGroebner methodsFor: 'accessing-private' stamp: 'pdm 3/22/98 17:37'! privateGroebner "Answer the instance variable." ^ groebner! ! !IdealWithGroebner methodsFor: 'accessing' stamp: 'pdm 3/22/98 17:37'! groebner "Answer a groebner basis of the receiver." self privateGroebner isNil ifTrue: [self groebner: (GroebnerBasis from: self generators)]. ^ self privateGroebner! ! !IdealWithGroebner methodsFor: 'testing' stamp: 'pdm 3/22/98 17:40'! includes: aPolynomial "Answer true if the receiver includes aPolynomial. (Ideal Membership Problem)." ^ (self groebner remainderOf: aPolynomial) isNull! ! !IdealWithGroebner class methodsFor: 'instance creation' stamp: 'pdm 3/22/98 17:51'! groebnerBasis: aGroebnerBasis "Answer a new instance of the receiver with Groebner basis aGroebnerBasis. " ^ (self generators: aGroebnerBasis) groebner: aGroebnerBasis! ! !Infinity commentStamp: 'pdm 8/29/1998 19:46' prior: 0! My instances represent the real +infinity or -infinity. For some examples try these: Infinity positive * Infinity negative. Infinity positive * 2. Infinity positive - 7811234871239847. Infinity negative / -199. Infinity positive reciprocal. Infinity positive > Infinity negative. Infinity negative < -19238479182374598172349871234. Infinity negative > 0. Infinity negative min: Infinity positive. The following are examples of undeterminations (they produce an error): Infinity positive + Infinity negative. Infinity positive * 0. Infinity positive / Infinity positive. Infinity positive raisedToInteger: 0. ! !Infinity methodsFor: 'accessing-private' stamp: 'len 10/9/97 20:16'! sign: anInteger sign _ anInteger! ! !Infinity methodsFor: 'accessing' stamp: 'len 10/9/97 20:17'! sign "Answer the sign of the receiver." ^ sign! ! !Infinity methodsFor: 'arithmetic' stamp: 'len 11/14/97 14:49'! * anObject "Answer the product of the receiver by the argument." anObject = 0 ifTrue: [^ self errorUndetermined]. ^ self class sign: self sign * anObject sign! ! !Infinity methodsFor: 'arithmetic' stamp: 'len 12/13/97 02:26'! + anObject "Answer the sum of the receiver and the argument." (anObject isInfinity and: [self sign ~= anObject sign]) ifTrue: [^ self errorUndetermined]. ^ self! ! !Infinity methodsFor: 'arithmetic' stamp: 'len 11/12/97 21:30'! - anObject "Answer the difference between the receiver and the argument." ^ self + anObject negated! ! !Infinity methodsFor: 'arithmetic' stamp: 'len 10/9/97 20:24'! / anObject "Answer the division of the receiver by the argument." ^ self * anObject reciprocal! ! !Infinity methodsFor: 'arithmetic' stamp: 'len 11/12/97 21:31'! negated "Answer a copy of the receiver with the sign changed." ^ self class sign: self sign negated! ! !Infinity methodsFor: 'arithmetic' stamp: 'len 10/17/97 04:11'! raisedToInteger: anInteger "Answer the receiver raised to the integer anInteger." anInteger = 0 ifTrue: [^ self errorUndetermined]. anInteger negative ifTrue: [^ 0]. ^ anInteger odd ifTrue: [self] ifFalse: [self negated]! ! !Infinity methodsFor: 'arithmetic' stamp: 'len 11/12/97 21:32'! reciprocal "Answer zero. (1 / self)" ^ 0! ! !Infinity methodsFor: 'arithmetic' stamp: 'len 10/17/97 04:09'! squared "Answer the square of the receiver." ^ self class positive! ! !Infinity methodsFor: 'comparing' stamp: 'len 12/13/97 02:26'! < anObject "Answer true if the receiver is lower than the argument." anObject isInfinity ifTrue: [^ self sign < anObject sign]. ^ self negative! ! !Infinity methodsFor: 'comparing' stamp: 'len 11/14/97 14:35'! = anObject "Answer true if the receiver equals the argument." ^ self class == anObject class and: [self sign = anObject sign]! ! !Infinity methodsFor: 'comparing' stamp: 'len 12/13/97 02:26'! > anObject "Answer true if the receiver is greater than the argument." anObject isInfinity ifTrue: [^ self sign > anObject sign]. ^ self positive! ! !Infinity methodsFor: 'comparing' stamp: 'len 11/14/97 14:35'! hash "Answer the hash value of the receiver." ^ self sign hash! ! !Infinity methodsFor: 'testing' stamp: 'len 12/13/97 02:25'! isInfinity "Answer true if the receiver is infinity." ^ true! ! !Infinity methodsFor: 'testing' stamp: 'len 11/14/97 14:50'! negative "Answer true if the receiver is negative." ^ self sign negative! ! !Infinity methodsFor: 'testing' stamp: 'len 11/14/97 14:50'! positive "Answer true if the receiver is positive." ^ self sign positive! ! !Infinity methodsFor: 'testing' stamp: 'len 11/14/97 14:51'! strictlyPositive "Answer true if the receiver is strictly positive." ^ self positive! ! !Infinity methodsFor: 'private' stamp: 'len 10/9/97 20:29'! errorUndetermined ^ self error: 'undetermined'! ! !Infinity methodsFor: 'printing' stamp: 'len 10/9/97 20:13'! printOn: aStream "Print a representation of the receiver on the stream aStream." self negative ifTrue: [aStream nextPut: $-]. aStream nextPutAll: 'infinity'! ! !Infinity class methodsFor: 'instance creation' stamp: 'len 10/17/97 04:07'! negative "Answer a new instance of the receiver representing -infinity." ^ self sign: -1! ! !Infinity class methodsFor: 'instance creation' stamp: 'len 10/17/97 04:07'! positive "Answer a new instance of the receiver representing +infinity." ^ self sign: 1! ! !Infinity class methodsFor: 'instance creation' stamp: 'len 10/9/97 20:27'! sign: anInteger "Answer a new instance of the receiver with sign anInteger." ^ self new sign: anInteger! ! !Monomial commentStamp: 'pdm 8/29/1998 19:46' prior: 0! My instances represent monomials in one or many variables. Each Monomial has a coefficient and a MonomialLiteral (power product). ! !Monomial methodsFor: 'accessing-private'! coefficient: value coefficient _ value ! ! !Monomial methodsFor: 'accessing-private'! literal: aLiteral literal _ aLiteral ! ! !Monomial methodsFor: 'accessing' stamp: 'len 10/18/97 02:13'! coefficient "Answer the coefficient of the receiver." ^ coefficient ! ! !Monomial methodsFor: 'accessing' stamp: 'len 11/6/97 20:58'! indeterminates "Answer the indeterminates of the receiver." ^ self literal indeterminates! ! !Monomial methodsFor: 'accessing' stamp: 'len 10/18/97 02:13'! literal "Answer the literal part of the receiver." ^ literal ! ! !Monomial methodsFor: 'arithmetic' stamp: 'len 1/24/98 13:46'! * anObject "Answer the product of the receiver by the argument." anObject isMonomial ifTrue: [^ self class coefficient: self coefficient * anObject coefficient literal: self literal * anObject literal]. anObject isMonomialLiteral ifTrue: [^ self class coefficient: self coefficient literal: self literal * anObject]. anObject isPolynomial ifTrue: [^ self asPolynomial * anObject]. ^ self class coefficient: self coefficient * anObject literal: self literal! ! !Monomial methodsFor: 'arithmetic' stamp: 'len 2/5/98 20:06'! + anObject "Answer the sum of the receiver with the argument." (anObject isMonomial and: [anObject literal = self literal]) ifTrue: [^ self class coefficient: self coefficient + anObject coefficient literal: self literal]. ^ self asPolynomial + anObject! ! !Monomial methodsFor: 'arithmetic' stamp: 'len 11/23/97 00:30'! - anObject "Answer the difference between the receiver with the argument." ^ self + anObject negated! ! !Monomial methodsFor: 'arithmetic' stamp: 'len 1/24/98 13:47'! / anObject "Answer the exact division of the receiver by the argument." anObject isMonomial ifTrue: [^ self class coefficient: self coefficient / anObject coefficient literal: self literal / anObject literal]. anObject isMonomialLiteral ifTrue: [^ self class coefficient: self coefficient literal: self literal / anObject]. anObject isPolynomial ifTrue: [^ self asPolynomial / anObject]. ^ self class coefficient: self coefficient / anObject literal: self literal! ! !Monomial methodsFor: 'arithmetic' stamp: 'len 10/18/97 02:14'! negated "Answer the additive inverse of the receiver." ^ self class coefficient: self coefficient negated literal: self literal! ! !Monomial methodsFor: 'operations' stamp: 'len 10/18/97 02:15'! degree "Answer the degree of the receiver." ^ self isNull ifTrue: [Infinity negative] ifFalse: [self literal degree]! ! !Monomial methodsFor: 'operations' stamp: 'len 10/18/97 02:15'! degreeIn: anInteger "Answer the degree of the receiver in the anInteger-th indeterminate." ^ self isNull ifTrue: [Infinity negative] ifFalse: [self literal degreeIn: anInteger]! ! !Monomial methodsFor: 'operations' stamp: 'len 11/22/97 19:53'! derivative "Answer the derivative of the receiver." ^ self derivativeIn: 1! ! !Monomial methodsFor: 'operations' stamp: 'len 1/27/98 23:29'! derivativeIn: anInteger "Answer the derivative of the receiver in the anInteger-th indeterminate." | degree | (degree _ self degreeIn: anInteger) <= 0 ifTrue: [^ self null]. ^ self class coefficient: self coefficient * degree literal: (self literal copy at: anInteger put: degree - 1; yourself)! ! !Monomial methodsFor: 'operations' stamp: 'len 11/23/97 00:57'! valueAt: anObject "Answer the value of the receiver at the argument." ^ self coefficient * (self literal valueAt: anObject)! ! !Monomial methodsFor: 'comparing' stamp: 'len 9/1/97 19:16'! = aMonomial "Answer true if the receiver equals the argument." ^ self class == aMonomial class and: [aMonomial literal = self literal and: [aMonomial coefficient = self coefficient]]! ! !Monomial methodsFor: 'comparing' stamp: 'len 9/1/97 19:17'! hash "Answer the hash value for the receiver." ^ self literal hash + self coefficient hash ! ! !Monomial methodsFor: 'testing' stamp: 'len 9/1/97 19:17'! isConstant "Answer true if the receiver is constant." ^ self isNull or: [self degree = 0]! ! !Monomial methodsFor: 'testing' stamp: 'len 1/24/98 13:42'! isMonomial "Answer true if the receiver is a monomial." ^ true! ! !Monomial methodsFor: 'testing' stamp: 'len 9/1/97 19:17'! isNull "Answer true if the receiver is the null monomial." ^ self coefficient isNull ! ! !Monomial methodsFor: 'testing' stamp: 'len 11/23/97 01:20'! isUnivariateIn: anInteger "Answer true if the receiver is an univariate monomial in the anInteger-th indeterminate." ^ (self degreeIn: anInteger) = self degree! ! !Monomial methodsFor: 'converting' stamp: 'len 1/24/98 13:48'! adaptFraction: aFraction "If I am involved in arithmetic with a Fraction, convert the Fraction." ^ self identity * aFraction! ! !Monomial methodsFor: 'converting' stamp: 'len 7/12/97 23:06'! adaptInteger: anInteger "If I am involved in arithmetic with an Integer, convert the Integer." ^ self identity * anInteger! ! !Monomial methodsFor: 'converting' stamp: 'len 1/24/98 13:48'! adaptToFraction "If I am involved in arithmetic with a Fraction, do not convert me." ^self! ! !Monomial methodsFor: 'converting'! adaptToInteger "If I am involved in arithmetic with an Integer, do not convert me." ^self! ! !Monomial methodsFor: 'converting' stamp: 'len 10/20/97 00:28'! asPolynomial "Convert the receiver to a polynomial." ^ self class polynomialClass fromMonomial: self! ! !Monomial methodsFor: 'converting' stamp: 'len 11/23/97 01:13'! univariateIn: anInteger "Answer the receiver as univariate monomial in the anInteger-th indeterminate." | d | ^ (d _ self degreeIn: anInteger) < self degree ifTrue: [self class coefficient: (self copyWithout: anInteger) asPolynomial literal: (self literal class x: anInteger to: d)] ifFalse: [self]! ! !Monomial methodsFor: 'copying' stamp: 'len 10/22/97 01:31'! complete: anInteger with: anotherInteger "Answer a copy of the receiver of degree anInteger completing with a power of anotherInteger." ^ self class coefficient: self coefficient literal: (self literal complete: anInteger with: anotherInteger)! ! !Monomial methodsFor: 'copying' stamp: 'len 2/6/98 13:29'! copy "Answer a copy of the receiver." ^ self class coefficient: self coefficient literal: self literal copy! ! !Monomial methodsFor: 'copying' stamp: 'len 10/22/97 21:49'! copyWithout: anInteger "Answer a copy of the receiver with the anInteger-th indeterminate removed." ^ self class coefficient: self coefficient literal: (self literal copyWithout: anInteger)! ! !Monomial methodsFor: 'constants' stamp: 'len 11/7/97 06:28'! identity "Answer the monomial that is the constant identity." ^ self class coefficient: self coefficient identity literal: self literal class identity! ! !Monomial methodsFor: 'constants' stamp: 'len 11/7/97 06:28'! null "Answer the monomial that is the constant null." ^ self class coefficient: self coefficient null literal: self literal class identity! ! !Monomial methodsFor: 'printing-private' stamp: 'len 11/23/97 01:53'! printCoefficientOn: aStream "Print the coefficient of the receiver on the stream aStream." | string numeric | string _ self coefficient printString. string first = $- ifTrue: [aStream nextPut: $-. string _ self coefficient negated printString]. numeric _ (string detect: [ :each | each isDigit not] ifNone: []) isNil. aStream nextPutAll: ((numeric or: [string first = $(]) ifTrue: [string] ifFalse: ['(', string, ')'])! ! !Monomial methodsFor: 'printing' stamp: 'len 9/1/97 19:21'! printOn: aStream "Print a representation of the receiver on the stream aStream." | coef | coef _ self coefficient. self isConstant ifTrue: [self printCoefficientOn: aStream. ^ self]. coef = coef identity ifFalse: [ coef = coef identity negated ifTrue: [aStream nextPut: $-] ifFalse: [self printCoefficientOn: aStream]]. self literal printOn: aStream! ! !Monomial methodsFor: 'printing' stamp: 'len 9/1/97 19:21'! printOn: aStream withNames: aDictionary "Print a representation of the receiver on the stream aStream using the the names in aDictionary for the indeterminates." | coef | coef _ self coefficient. self isConstant ifTrue: [self printCoefficientOn: aStream. ^ self]. coef = coef identity ifFalse: [ coef = coef identity negated ifTrue: [aStream nextPut: $-] ifFalse: [self printCoefficientOn: aStream]]. self literal printOn: aStream withNames: aDictionary! ! !Monomial class methodsFor: 'instance creation' stamp: 'len 11/22/97 19:46'! coefficient: anObject degree: anInteger "Answer an instance of the receiver representing the monomial of degree anInteger with argument anObject." ^ self x: 1 to: anInteger coefficient: anObject! ! !Monomial class methodsFor: 'instance creation' stamp: 'len 10/18/97 02:11'! coefficient: anObject literal: aMonomialLiteral "Answer a new instance of the receiver with coefficient anObject and literal aMonomialLiteral." ^ self new coefficient: anObject; literal: aMonomialLiteral! ! !Monomial class methodsFor: 'instance creation' stamp: 'len 2/5/98 00:38'! constant: anObject "Answer an instance of the receiver representing the constant anObject." ^ self coefficient: anObject literal: self monomialLiteralClass identity! ! !Monomial class methodsFor: 'instance creation' stamp: 'len 11/22/97 19:46'! degree: anInteger coefficient: anObject "Answer an instance of the receiver representing the monomial of degree anInteger with argument anObject." ^ self coefficient: anObject degree: anInteger! ! !Monomial class methodsFor: 'instance creation' stamp: 'len 10/22/97 01:33'! literal: aMonomialLiteral coefficient: anObject "Answer a new instance of the receiver with coefficient anObject and literal aMonomialLiteral." ^ self coefficient: anObject; literal: aMonomialLiteral! ! !Monomial class methodsFor: 'instance creation' stamp: 'len 10/22/97 01:36'! x: anInteger "Answer an instance of the receiver representing monomial with the sole anInteger-th indeterminate with degree 1 and with coefficient 1." ^ self x: anInteger coefficient: self identityCoefficient! ! !Monomial class methodsFor: 'instance creation' stamp: 'len 10/22/97 01:36'! x: anInteger coefficient: anObject "Answer an instance of the receiver representing monomial with the sole anInteger-th indeterminate with degree 1 and with coefficient anObject." ^ self x: anInteger to: 1 coefficient: anObject! ! !Monomial class methodsFor: 'instance creation' stamp: 'len 10/22/97 01:37'! x: anInteger to: anotherInteger "Answer an instance of the receiver representing monomial with the sole anInteger-th indeterminate with degree 1 and with coefficient 1." ^ self x: anInteger to: anotherInteger coefficient: self identityCoefficient! ! !Monomial class methodsFor: 'instance creation' stamp: 'len 2/5/98 00:38'! x: anInteger to: anotherInteger coefficient: anObject "Answer an instance of the receiver representing monomial with the sole anInteger-th indeterminate raised to anotherInteger and with coefficient anObject." ^ self coefficient: anObject literal: (self monomialLiteralClass x: anInteger to: anotherInteger)! ! !Monomial class methodsFor: 'constants' stamp: 'len 9/1/97 21:25'! identityCoefficient ^ 1! ! !Monomial class methodsFor: 'constants' stamp: 'len 9/1/97 21:25'! nullCoefficient ^ 0! ! !Monomial class methodsFor: 'related classes' stamp: 'len 2/5/98 00:37'! monomialLiteralClass ^ MonomialLiteral! ! !Monomial class methodsFor: 'related classes' stamp: 'len 11/23/97 00:13'! polynomialClass ^ Polynomial! ! !MonomialLiteral commentStamp: 'pdm 8/29/1998 19:46' prior: 0! My instances represent power products of one or many variables, i.e. the literal part of monomials. ! !MonomialLiteral methodsFor: 'initialization' stamp: 'pdm 5/1/98 14:56'! initialize: anInteger self contents: ((1 to: anInteger) collect: [:each | 0])! ! !MonomialLiteral methodsFor: 'accessing-private' stamp: 'len 10/18/97 02:06'! contents ^ contents! ! !MonomialLiteral methodsFor: 'accessing-private' stamp: 'pdm 5/1/98 14:52'! contents: anArray contents _ anArray! ! !MonomialLiteral methodsFor: 'accessing' stamp: 'len 12/4/97 00:51'! at: anInteger "Answer the exponent of the anInteger-th indeterminate." ^ (anInteger <= self size and: [anInteger > 0]) ifTrue: [self contents at: anInteger] ifFalse: [0]! ! !MonomialLiteral methodsFor: 'accessing' stamp: 'len 1/27/98 23:28'! at: anInteger put: anotherInteger "Set the exponent of the anInteger-th indeterminate to anotherInteger. Answer anotherInteger." anInteger > self size ifTrue: [ anInteger = 0 ifTrue: [^ anotherInteger] ifFalse: [self contents: self contents, ((self size + 1 to: anInteger) collect: [ :each | 0])]]. anInteger < 1 ifTrue: [^ anotherInteger ~= 0 ifTrue: [self halt] ifFalse: [anotherInteger]]. ^ self contents at: anInteger put: anotherInteger! ! !MonomialLiteral methodsFor: 'accessing' stamp: 'len 11/6/97 20:36'! indeterminates "Answer the indeterminates of the receiver." ^ 1 to: self size! ! !MonomialLiteral methodsFor: 'accessing' stamp: 'len 10/22/97 22:31'! lastIndeterminate "Answer the leading indeterminate of the receiver (the last indeterminate effectively present)." | answer | answer _ 0. self do: [ :each | answer _ answer max: each]. ^ answer! ! !MonomialLiteral methodsFor: 'accessing' stamp: 'len 11/6/97 20:35'! size "Answer the number of indeterminates of the receiver." ^ self contents size! ! !MonomialLiteral methodsFor: 'arithmetic' stamp: 'len 11/6/97 20:49'! * aMonomialLiteral "Answer the product of the receiver by the argument." | answer | (self size < aMonomialLiteral size) ifTrue: [^ aMonomialLiteral * self]. answer _ self copy. aMonomialLiteral do: [ :each | answer at: each put: (self at: each) + (aMonomialLiteral at: each)]. ^ answer! ! !MonomialLiteral methodsFor: 'arithmetic' stamp: 'len 10/18/97 19:02'! / aMonomialLiteral "Answer the exact division of the receiver by the argument." | answer | answer _ self copy. aMonomialLiteral do: [ :each | (answer at: each put: (self at: each) - (aMonomialLiteral at: each)) negative ifTrue: [^ self error: 'not exact division']]. ^ answer! ! !MonomialLiteral methodsFor: 'enumerating' stamp: 'len 11/6/97 20:30'! do: aBlock "Enumerate the indeterminates of the receiver." (1 to: self size) do: [ :each | (self at: each) = 0 ifFalse: [aBlock value: each]]! ! !MonomialLiteral methodsFor: 'mathematical functions' stamp: 'len 11/6/97 20:30'! gcd: aMonomialLiteral "Answer the greatest common divisor of the receiver and the argument." | answer | answer _ self class new: self size. self do: [ :each | answer at: each put: ((self at: each) min: (aMonomialLiteral at: each))]. ^ answer! ! !MonomialLiteral methodsFor: 'mathematical functions' stamp: 'len 1/27/98 23:31'! lcm: aMonomialLiteral "Answer the least common multiple of the receiver and the argument." | answer max | answer _ self class new: (max _ self size max: aMonomialLiteral size). (1 to: max) do: [ :each | answer at: each put: ((self at: each) max: (aMonomialLiteral at: each))]. ^ answer! ! !MonomialLiteral methodsFor: 'operations' stamp: 'len 10/18/97 01:53'! degree "Answer the degree of the receiver. By the degree is meant the sum of the powers to which the indererminates appear." | answer | answer _ 0. self do: [ :each | answer _ answer + (self at: each)]. ^ answer! ! !MonomialLiteral methodsFor: 'operations' stamp: 'len 10/18/97 02:01'! degreeIn: anInteger "Answer the degree of the receiver in the indeterminate given by the argument, i.e. the power to which the indeterminate appears." ^ self at: anInteger! ! !MonomialLiteral methodsFor: 'operations' stamp: 'len 12/13/97 05:24'! valueAt: anObject "Answer the value of the receiver at the argument." | answer next | 1 to: anObject size do: [ :each | next _ (anObject at: each) raisedToInteger: (self at: each). answer _ answer isNil ifTrue: [next] ifFalse: [next * answer]]. ^ answer! ! !MonomialLiteral methodsFor: 'comparing' stamp: 'len 10/22/97 23:58'! < aMonomialLiteral "Answer the receiver is below the argument." ^ (self >= aMonomialLiteral) not! ! !MonomialLiteral methodsFor: 'comparing' stamp: 'len 10/23/97 00:00'! <= aMonomialLiteral "Answer the receiver is below or equal to the argument." ^ (self > aMonomialLiteral) not! ! !MonomialLiteral methodsFor: 'comparing' stamp: 'len 10/18/97 02:04'! = aMonomialLiteral "Answer true if the receiver equals the argument." self degree = aMonomialLiteral degree ifFalse: [^ false]. self do: [ :each | (self at: each) = (aMonomialLiteral at: each) ifFalse: [^ false]]. ^ true! ! !MonomialLiteral methodsFor: 'comparing' stamp: 'len 2/5/98 00:46'! > aMonomialLiteral "Answer true if the receiver is greater than the argument in the total lexicographic ordering." | n m | (n _ self degree) > (m _ aMonomialLiteral degree) ifTrue: [^ true]. n < m ifTrue: [^ false]. 1 to: (self lastIndeterminate max: aMonomialLiteral lastIndeterminate) do: [ :each | (self at: each) < (aMonomialLiteral at: each) ifTrue: [^ false]. (self at: each) > (aMonomialLiteral at: each) ifTrue: [^ true]]. ^ false! ! !MonomialLiteral methodsFor: 'comparing' stamp: 'len 2/5/98 00:46'! >= aMonomialLiteral "Answer true if the receiver is greater than or equal to the argument in the total lexicographic ordering." | n m | (n _ self degree) > (m _ aMonomialLiteral degree) ifTrue: [^ true]. n < m ifTrue: [^ false]. 1 to: (self lastIndeterminate max: aMonomialLiteral lastIndeterminate) do: [ :each | (self at: each) < (aMonomialLiteral at: each) ifTrue: [^ false]. (self at: each) > (aMonomialLiteral at: each) ifTrue: [^ true]]. ^ true! ! !MonomialLiteral methodsFor: 'comparing' stamp: 'len 10/18/97 02:05'! hash "Answer the hash value of the receiver." | sum | sum _ 0. self do: [ :each | sum _ (self at: each) * each + sum]. ^ sum hash! ! !MonomialLiteral methodsFor: 'testing' stamp: 'len 10/18/97 20:22'! divides: aMonomialLiteral "Answer true if the receiver divedes the argument." self do: [ :each | (aMonomialLiteral at: each) < (self at: each) ifTrue: [^ false]]. ^ true! ! !MonomialLiteral methodsFor: 'testing' stamp: 'len 10/23/97 04:14'! isMonomialLiteral "Answer true if the receiver is a monomial literal." ^ true! ! !MonomialLiteral methodsFor: 'copying' stamp: 'len 10/22/97 01:31'! complete: anInteger with: anotherInteger "Answer a copy of the receiver of degree anInteger completing with a power of the indeterminate anotherInteger." | deg | (deg _ self degree) = anInteger ifTrue: [^ self]. ^ self copy at: anotherInteger put: (anInteger - deg + (self at: anotherInteger)); yourself! ! !MonomialLiteral methodsFor: 'copying' stamp: 'len 11/6/97 20:53'! copy ^ self class new contents: self contents copy! ! !MonomialLiteral methodsFor: 'copying' stamp: 'len 10/22/97 01:29'! copyWithout: anInteger "Answer a copy of the receiver with the anInteger-th indeterminate removed." ^ self copy at: anInteger put: 0; yourself! ! !MonomialLiteral methodsFor: 'copying' stamp: 'len 10/22/97 01:28'! copyWithoutAll: aCollection "Answer a copy of the receiver with all the indeterminates in the argument removed." | answer | answer _ self copy. aCollection do: [ :each | answer at: each put: 0]. ^ answer! ! !MonomialLiteral methodsFor: 'printing-private' stamp: 'len 12/21/97 20:53'! defaultNames "Answer the default names for the indeterminates." ^ self class defaultNames! ! !MonomialLiteral methodsFor: 'printing' stamp: 'len 7/13/97 00:44'! printOn: aStream "Print a representation of the receiver on the stream aStream." self printOn: aStream withNames: self defaultNames! ! !MonomialLiteral methodsFor: 'printing' stamp: 'len 1/27/98 23:27'! printOn: aStream withNames: namesDictionary "Print a representation of the receiver on the stream aStream using the names in namesDictionary for the indeterminates." | exp | self degree = 0 ifTrue: [aStream print: 1. ^ self]. (self indeterminates select: [ :each | (self at: each) > 0]) asSortedCollection do: [ :each | aStream nextPutAll: (namesDictionary at: each ifAbsent: ['{x', each printString, '}']). (exp _ (self degreeIn: each) printString) = '1' ifFalse: [aStream nextPut: $^. exp size = 1 ifTrue: [aStream nextPutAll: exp] ifFalse: [aStream nextPut: ${; nextPutAll: exp; nextPut: $}]]]! ! !MonomialLiteral class methodsFor: 'instance creation' stamp: 'len 11/7/97 06:17'! identity "Answer the identity literal (i.e., the literal without indeterminates)." ^ self new: 0! ! !MonomialLiteral class methodsFor: 'instance creation' stamp: 'len 11/6/97 20:09'! new: anInteger "Answer a new instance of the receiver representing the empty literal of anInteger indeterminates." ^ self new initialize: anInteger! ! !MonomialLiteral class methodsFor: 'instance creation' stamp: 'len 10/23/97 22:37'! new: anInteger x: anotherInteger "Answer a new instance of the receiver representing the a literal of anInteger indeterminates, one of those (the anotherInteger-th) is effectively present with degree 1." ^ self new: anInteger x: anInteger to: 1! ! !MonomialLiteral class methodsFor: 'instance creation' stamp: 'len 10/23/97 22:38'! new: anInteger x: anotherInteger to: thirthInteger "Answer a new instance of the receiver representing the a literal of anInteger indeterminates, one of those (the anotherInteger-th) is effectively present with degree thirthInteger." ^ (self new: anInteger) at: anotherInteger put: thirthInteger; yourself! ! !MonomialLiteral class methodsFor: 'instance creation' stamp: 'len 10/22/97 01:38'! x: anInteger "Answer a new instance of the receiver with only one indeterminate: the argument." ^ self x: anInteger to: 1! ! !MonomialLiteral class methodsFor: 'instance creation' stamp: 'len 11/7/97 06:25'! x: anInteger to: anotherInteger "Answer a new instance of the receiver with only one indeterminate, anInteger, raised to anotherInteger." ^ self new: anInteger x: anInteger to: anotherInteger! ! !MonomialLiteral class methodsFor: 'related classes' stamp: 'len 11/22/97 19:58'! monomialClass ^ Monomial! ! !MonomialLiteral class methodsFor: 'constants' stamp: 'pdm 5/1/98 14:57'! defaultNames "Answer the default names for the indeterminates." | names last | last _ 0. MonomialLiteral allSubInstancesDo: [:each | last _ last max: each size]. last <= 3 ifTrue: [^ Dictionary with: 1 -> #x with: 2 -> #y with: 3 -> #z]. names _ Dictionary new. 1 to: last do: [:each | names add: each -> ('{x' , each printString , '}')]. ^ names! ! !MonomialOrdering commentStamp: 'pdm 8/29/1998 19:46' prior: 0! My instances are orderings for the monomial literals. For literals in n variables, there are n!! (n factorial) orderings, and in certain aplications, such Groebner bases, it's desirable to easily construct new monomial orderings. Each MonomialOrdering fix the ordering of the variables mantaining an ordered collection with them. Furthermore, each MonomialOrdering posseses a list of "weights", which are n-tuples (if there are n variables), and these "weights" fix the ordering of all the literals. Let's take a look at the way "weights" work. Suppose you have two literals: a = x1^a1 x2^a2 ... xn^an b = x1^b1 x2^b2 ... xn^bn where some of the ai or bi may be 0. And suppose the variables are ordered x1 < x2 < ... < xn. If we are asked for the truth of a < b, we enumerate the weights and for each one, (w1, w2, ..., wn) we do: asum = a1 w1 + a2 w2 + ... + an wn, bsum = b1 w1 + b2 w2 + ... + bn wn; if asum < bsum, then a < b; if asum > bsum, then a > b; if asum = bsum, we continue with the next weight, until there are no more weights (then, a should equal b...). There is a theorem claiming that for any monomial ordering in a finite number of variables, there are a collection of weights which models that ordering. So, with this scheme we are able to contruct any ordering. If looking for examples, see the class method category named 'examples'. ! !MonomialOrdering methodsFor: 'accessing-private' stamp: 'len 2/2/98 01:23'! indeterminates: aCollection indeterminates _ aCollection! ! !MonomialOrdering methodsFor: 'accessing-private' stamp: 'len 2/5/98 01:14'! weighs: aCollectionOfTuples weighs _ aCollectionOfTuples! ! !MonomialOrdering methodsFor: 'accessing' stamp: 'len 2/3/98 00:54'! headOf: aPolynomial "Answer the head of the argument." | answer | aPolynomial do: [ :each | answer _ (answer isNil or: [self is: each literal gneq: answer literal]) ifTrue: [each] ifFalse: [answer]]. ^ answer! ! !MonomialOrdering methodsFor: 'accessing' stamp: 'len 2/2/98 01:23'! indeterminates "Answer the indeterminates of the receiver." ^ indeterminates! ! !MonomialOrdering methodsFor: 'accessing' stamp: 'len 2/18/98 18:56'! is: aLiteral gneq: bLiteral "Answer true if the first argument is greater than the second." | left right a b | left _ Tuple dimension: self indeterminates size fromBlock: [ :each | aLiteral at: (self indeterminates at: each)]. right _ Tuple dimension: self indeterminates size fromBlock: [ :each | bLiteral at: (self indeterminates at: each)]. self weighs do: [ :each | (a _ each scalar: left) > (b _ each scalar: right) ifTrue: [^ true]. a < b ifTrue: [^ false]]. ^ false! ! !MonomialOrdering methodsFor: 'accessing' stamp: 'len 2/2/98 02:18'! weighs "Answer the weighs of the receiver." ^ weighs! ! !MonomialOrdering methodsFor: 'arithmetic' stamp: 'len 2/5/98 01:15'! * aMonomialOrdering "Answer the product of the recever by the argument." | newWeighs null | newWeighs _ OrderedCollection new. null _ aMonomialOrdering weighs first null. self weighs do: [ :each | newWeighs add: each, null]. null _ self weighs first null. aMonomialOrdering weighs do: [ :each | newWeighs add: null, each]. ^ self class indeterminates: self indeterminates, aMonomialOrdering indeterminates weighs: newWeighs! ! !MonomialOrdering methodsFor: 'arithmetic' stamp: 'len 2/5/98 01:18'! , aMonomialOrdering "Answer the concatenation of the recever and the argument." self indeterminates = aMonomialOrdering indeterminates ifFalse: [^ self halt]. ^ self class indeterminates: self indeterminates weighs: (self weighs copy addAll: aMonomialOrdering weighs)! ! !MonomialOrdering methodsFor: 'arithmetic' stamp: 'len 2/3/98 02:09'! inverse "Answer the inverse of the receiver." ^ self class indeterminates: self indeterminates reversed weighs: self weighs! ! !MonomialOrdering methodsFor: 'arithmetic' stamp: 'len 2/3/98 02:09'! reverse "Answer the reverse of the receiver." ^ self class indeterminates: self indeterminates weighs: (self weighs collect: [ :each | each negated])! ! !MonomialOrdering methodsFor: 'printing' stamp: 'len 2/3/98 02:01'! print: aPolynomial ^ (aPolynomial copy monomials: (aPolynomial monomials asSortedCollection: [ :each :other | self is: each literal gneq: other literal])) printString! ! !MonomialOrdering methodsFor: 'printing' stamp: 'len 2/3/98 01:27'! printOn: aStream "Print a representation of the receiver on the stream aStream." aStream nextPutAll: self class name; space. self indeterminates do: [ :each | aStream nextPutAll: ' {x', each printString, '} ']. self weighs do: [ :each | aStream print: each; space]! ! !MonomialOrdering class methodsFor: 'instance creation' stamp: 'len 2/5/98 01:13'! indeterminates: aCollection weighs: aCollectionOfTuples "Answer a new instance of the receiver with the indeterminates and weighs given by the arguments." ^ self new indeterminates: aCollection; weighs: aCollectionOfTuples! ! !MonomialOrdering class methodsFor: 'examples' stamp: 'len 2/3/98 01:39'! lex: aCollection "Answer the lexicographic order with the indeterminates of aCollection." | weighs n | n _ aCollection size. weighs _ (1 to: n) collect: [ :each | (Tuple null: n) at: each put: 1; yourself]. ^ self indeterminates: aCollection weighs: weighs! ! !MonomialOrdering class methodsFor: 'examples' stamp: 'len 2/3/98 01:38'! revlex: aCollection "Answer the reverse lexicographic ordering with the indeterminates of aCollection." ^ (self lex: aCollection) reverse! ! !MonomialOrdering class methodsFor: 'examples' stamp: 'len 2/3/98 02:16'! tlex: aCollection "Answer the total (or graded) lexicographic ordering with the indeterminates of aCollection." | weighs | weighs _ OrderedCollection new. weighs add: (Tuple dimension: aCollection size fromBlock: [ :each | 1]). weighs addAll: (self lex: aCollection) weighs. ^ self indeterminates: aCollection weighs: weighs! ! !MonomialOrdering class methodsFor: 'examples' stamp: 'len 2/3/98 02:17'! trevlex: aCollection "Answer the total (or graded) reverse lexicographic ordering with the indeterminates of aCollection." | weighs | weighs _ OrderedCollection new. weighs add: (Tuple dimension: aCollection size fromBlock: [ :each | 1]). weighs addAll: (self revlex: aCollection) weighs. ^ self indeterminates: aCollection weighs: weighs! ! !MultiPolynomialDivisor methodsFor: 'initialization' stamp: 'len 1/24/98 11:58'! divide: aPolynomial by: aTupleOfPolynomials self dividend: aPolynomial. self divisors: aTupleOfPolynomials. self done: false! ! !MultiPolynomialDivisor methodsFor: 'accessing-private' stamp: 'len 1/24/98 11:59'! done: aBoolean done _ aBoolean! ! !MultiPolynomialDivisor methodsFor: 'accessing-private' stamp: 'len 1/24/98 12:00'! quotients: aTupleOfPolynomials quotients _ aTupleOfPolynomials! ! !MultiPolynomialDivisor methodsFor: 'accessing-private' stamp: 'len 1/24/98 12:00'! remainder: aPolynomial remainder _ aPolynomial ! ! !MultiPolynomialDivisor methodsFor: 'accessing' stamp: 'len 1/24/98 12:04'! dividend "Answer the dividend of the receiver." ^ dividend! ! !MultiPolynomialDivisor methodsFor: 'accessing' stamp: 'len 1/24/98 12:04'! dividend: aPolynomial dividend _ aPolynomial. self done: false! ! !MultiPolynomialDivisor methodsFor: 'accessing' stamp: 'len 1/24/98 12:04'! divisors "Answer the divisors of the receiver." ^ divisors! ! !MultiPolynomialDivisor methodsFor: 'accessing' stamp: 'len 1/24/98 12:04'! divisors: aTupleOfPolynomials divisors _ aTupleOfPolynomials. self done: false! ! !MultiPolynomialDivisor methodsFor: 'accessing' stamp: 'len 1/24/98 11:59'! done "Answer true if the quotient and the remainder have been computed." ^ done! ! !MultiPolynomialDivisor methodsFor: 'accessing' stamp: 'len 2/5/98 01:06'! ordering "Answer the monomial ordering used by the receiver." ^ ordering! ! !MultiPolynomialDivisor methodsFor: 'accessing' stamp: 'len 2/5/98 01:06'! ordering: aMonomialOrdering "Change the monomial ordering used by the receiver." ordering _ aMonomialOrdering! ! !MultiPolynomialDivisor methodsFor: 'accessing' stamp: 'len 1/24/98 12:05'! quotients "Answer the quotients of the receiver." self divide. ^ quotients! ! !MultiPolynomialDivisor methodsFor: 'accessing' stamp: 'len 1/24/98 12:05'! remainder "Answer the remainder of the receiver." self divide. ^ remainder! ! !MultiPolynomialDivisor methodsFor: 'operations' stamp: 'pdm 4/19/98 17:16'! divide "Perform the division algorithm computing quotients and remainder." | p s null quots rem index fi q headp headfi | self done ifTrue: [^ self]. null _ self dividend null. rem _ null. quots _ (1 to: self divisors size) collect: [ :each | null]. s _ self divisors size. p _ self dividend. [p isNull] whileFalse: [ headp _ self ordering headOf: p. index _ (1 to: s) detect: [ :one | (headfi _ self ordering headOf: (fi _ self divisors at: one)) literal divides: headp literal] ifNone: []. index isNil ifTrue: [rem _ rem + headp. p _ p - headp] ifFalse: [quots at: index put: (quots at: index) + (q _ headp / headfi). p _ p - (fi * q)]]. self quotients: quots; remainder: rem; done: true! ! !MultiPolynomialDivisor methodsFor: 'printing' stamp: 'len 1/24/98 12:49'! printOn: aStream "Print a representation of the receiver on the stream aStream." aStream print: self dividend; nextPutAll: ' = '. (1 to: self divisors size) do: [ :each | aStream nextPut: $(; print: (self quotients at: each); nextPut: $); nextPut: $(; print: (self divisors at: each); nextPut: $); nextPutAll: ' + ']. aStream print: self remainder! ! !MultiPolynomialDivisor class methodsFor: 'instance creation' stamp: 'len 2/5/98 01:05'! divide: aPolynomial by: aTupleOfPolynomials "Answer a multivariate division algorithm to divide aPolynomial by aTupleOfPolynomials." | indets | indets _ aPolynomial indeterminates. aTupleOfPolynomials do: [ :each | indets addAll: each indeterminates]. ^ self divide: aPolynomial by: aTupleOfPolynomials ordering: (MonomialOrdering tlex: indets asSortedCollection)! ! !MultiPolynomialDivisor class methodsFor: 'instance creation' stamp: 'len 2/5/98 01:04'! divide: aPolynomial by: aTupleOfPolynomials ordering: aMonomialOrdering "Answer a multivariate division algorithm to divide aPolynomial by aTupleOfPolynomials using the ordering aMonomialOrdering." ^ self new ordering: aMonomialOrdering; divide: aPolynomial by: aTupleOfPolynomials! ! !Number methodsFor: 'arithmetic' stamp: 'pdm 6/20/1998 19:55'! identity ^ 1! ! !Number methodsFor: 'arithmetic' stamp: 'pdm 6/20/1998 19:55'! null ^ 0! ! !Number methodsFor: 'testing' stamp: 'pdm 6/20/1998 19:54'! isNull ^ self = 0! ! !Number methodsFor: 'testing' stamp: 'pdm 6/20/1998 20:01'! isRational ^ false! ! !Number methodsFor: 'converting' stamp: 'len 11/28/97 02:05'! , anObject "Answer the 2 dim Tuple with the receiver in the first coordinate and the argument in the second." ^ Tuple with: self with: anObject! ! !Fraction methodsFor: 'testing' stamp: 'pdm 6/20/1998 20:01'! isRational ^ true! ! !Integer methodsFor: 'testing' stamp: 'pdm 6/20/1998 20:01'! isRational ^ true! ! !Integer methodsFor: 'accessing' stamp: 'pdm 6/20/1998 20:02'! denominator ^ 1! ! !Integer methodsFor: 'accessing' stamp: 'pdm 6/20/1998 20:02'! numerator ^ self! ! !Point methodsFor: 'converting' stamp: 'len 11/28/97 02:22'! asTuple "Convert the receiver to a Tuple." ^ self x, self y! ! !Polynomial commentStamp: 'pdm 8/29/1998 19:46' prior: 0! My instances represent polynomials in one or many variables. For an examples try this: | x y | x _ Polynomial x. y _ Polynomial y. (x + y) squared - x - y. ! !Polynomial methodsFor: 'initialization' stamp: 'len 9/5/97 14:28'! initialize self monomials: OrderedCollection new! ! !Polynomial methodsFor: 'accessing-private' stamp: 'len 1/20/98 00:53'! add: aMonomial "Add aMonomial to the monomials of the receiver. Answer aMonomial." | mon coef | aMonomial isNull ifTrue: [^ aMonomial]. mon _ self privateMonomialAt: aMonomial literal. mon isNil ifTrue: [self privateAddMonomial: aMonomial] ifFalse: [mon coefficient: (coef _ mon coefficient + aMonomial coefficient). coef isNull ifTrue: [self privateRemoveMonomial: mon]]. ^ aMonomial! ! !Polynomial methodsFor: 'accessing-private' stamp: 'len 12/3/97 02:24'! addAll: aCollection "Add all the monomials in the argument to the receiver. Answer the argument." aCollection do: [ :each | self add: each]. ^ aCollection! ! !Polynomial methodsFor: 'accessing-private' stamp: 'len 1/27/98 23:33'! monomials: aCollection monomials _ aCollection! ! !Polynomial methodsFor: 'accessing-private' stamp: 'len 1/20/98 01:28'! privateAddMonomial: aMonomial self monomials add: aMonomial! ! !Polynomial methodsFor: 'accessing-private' stamp: 'len 1/20/98 01:28'! privateMonomialAt: aMonomialLiteral ^ self monomials detect: [ :each | each literal = aMonomialLiteral] ifNone: []! ! !Polynomial methodsFor: 'accessing-private' stamp: 'len 1/20/98 01:28'! privateRemoveMonomial: aMonomial self monomials remove: aMonomial! ! !Polynomial methodsFor: 'accessing' stamp: 'pdm 3/22/98 20:49'! denominator ^ self identity! ! !Polynomial methodsFor: 'accessing' stamp: 'len 1/27/98 23:33'! first "Answer the first monomial of the receiver." ^ self isNull ifTrue: [self class monomialClass constant: self nullCoefficient] ifFalse: [self sortedMonomials first]! ! !Polynomial methodsFor: 'accessing' stamp: 'len 1/13/98 00:05'! head "Answer the head monomial of the receiver (a monomial of greatest degree)." ^ self first! ! !Polynomial methodsFor: 'accessing' stamp: 'len 1/27/98 23:33'! last "Answer the last monomial of the receiver." ^ self isNull ifTrue: [self class monomialClass constant: self nullCoefficient] ifFalse: [self sortedMonomials last]! ! !Polynomial methodsFor: 'accessing' stamp: 'len 9/1/97 20:36'! monomials "Answer the collection of the receiver's monomials." ^ monomials! ! !Polynomial methodsFor: 'accessing' stamp: 'pdm 3/22/98 20:49'! numerator ^ self! ! !Polynomial methodsFor: 'accessing' stamp: 'len 1/27/98 23:33'! sortedMonomials "Answer the collection of the receiver's monomials, but sorted. Notice that the returning collection can be used even to add more monomials to the polynomials. The monomials are keeped in a collection, refered by the instance variable ""monomials"", and eventually, only when it's needed (when this method is invocated), the collection is sorted." (monomials isKindOf: SortedCollection) ifFalse: [monomials _ monomials asSortedCollection: [ :a :b | a literal >= b literal]]. ^ monomials! ! !Polynomial methodsFor: 'accessing' stamp: 'len 10/18/97 02:30'! tail "Answer the tail of the receiver." ^ self - self head! ! !Polynomial methodsFor: 'accessing indeterminates' stamp: 'len 12/3/97 02:21'! indeterminates "Answer the indeterminates of the receiver." | answer | answer _ Set new. self do: [ :each | answer addAll: each indeterminates]. ^ answer! ! !Polynomial methodsFor: 'accessing indeterminates' stamp: 'len 11/22/97 19:12'! main "Answer the main indeterminate of the receiver." ^ 1! ! !Polynomial methodsFor: 'accessing coefficients' stamp: 'len 1/27/98 05:15'! coefficientAt: anIntegerOrALiteral "Answer the coefficient of the degree (univariate case) or literal given by the argument." ^ (anIntegerOrALiteral isInteger ifTrue: [self monomials detect: [:each | each degree = anIntegerOrALiteral] ifNone: [^ self nullCoefficient]] ifFalse: [self monomials detect: [:each | each literal = anIntegerOrALiteral] ifNone: [^ self nullCoefficient]]) coefficient! ! !Polynomial methodsFor: 'accessing coefficients' stamp: 'len 12/3/97 02:25'! coefficientAt: anInteger in: anotherInteger "Answer the coefficient of degree anInteger looking at the receiver as univariate in the anotherInteger-th indeterminate." | answer | "The answer will be 0 when the argument were negative or greater than the degree of the receiver." (self degree < anInteger or: [anInteger negative]) ifTrue: [^ self nullCoefficient]. answer _ self class new. self do: [ :each | (each degreeIn: anotherInteger) = anInteger ifTrue: [answer add: (each copyWithout: anotherInteger)]]. ^ answer isConstant ifTrue: [answer leadingCoefficient] ifFalse: [answer]! ! !Polynomial methodsFor: 'accessing coefficients' stamp: 'len 11/22/97 21:51'! coefficients "Answer the Array of coefficients of the receiver." ^ self isNull ifTrue: [Array new] ifFalse: [(0 to: self degree) collect: [ :each | self coefficientAt: each]]! ! !Polynomial methodsFor: 'accessing coefficients' stamp: 'len 1/13/98 00:03'! independentCoefficient "Answer the coefficient of the constant monomial of the receiver." | monomial | ^ (monomial _ self last) isConstant ifTrue: [monomial coefficient] ifFalse: [self nullCoefficient]! ! !Polynomial methodsFor: 'accessing coefficients' stamp: 'len 11/22/97 21:50'! leadingCoefficient "Answer the leading coefficient of the receiver." ^ self isNull ifTrue: [self nullCoefficient] ifFalse: [self head coefficient]! ! !Polynomial methodsFor: 'accessing coefficients' stamp: 'len 12/3/97 02:25'! leadingCoefficientIn: anInteger "Answer the leading coefficient of the receiver as univariate polynomial in the anInteger-th indeterminate." | deg answer | deg _ self degreeIn: anInteger. answer _ self class new. self do: [ :each | (each degreeIn: anInteger) = deg ifTrue: [answer add: (each copyWithout: anInteger)]]. ^ answer! ! !Polynomial methodsFor: 'arithmetic-private' stamp: 'len 1/23/98 16:28'! divideBy: aPolynomial "Answer a division algorithm to divide the receiver by aPolynomial." ^ PolynomialDivisor divide: self by: aPolynomial! ! !Polynomial methodsFor: 'arithmetic-private' stamp: 'len 10/18/97 21:34'! privateMonomialDivision: anObject "Answer the product of the receiver and the argument, monomial by monomial." ^ self class new monomials: (self monomials collect: [ :each | each / anObject])! ! !Polynomial methodsFor: 'arithmetic-private' stamp: 'len 10/18/97 21:33'! privateMonomialProduct: anObject "Answer the product of the receiver and the argument, monomial by monomial." | newMonomials monomial | newMonomials _ OrderedCollection new. self monomials do: [ :each | (monomial _ each * anObject) isNull ifFalse: [newMonomials add: monomial]]. ^ self class new monomials: newMonomials! ! !Polynomial methodsFor: 'arithmetic-private' stamp: 'len 1/23/98 16:27'! pseudoDivideBy: aPolynomial "Answer a pseudo-division algorithm to divide the receiver by aPolynomial." ^ PolynomialPseudoDivisor divide: self by: aPolynomial! ! !Polynomial methodsFor: 'arithmetic-private' stamp: 'len 1/23/98 16:26'! pseudoDivideBy: aPolynomial in: anInteger "Answer a pseudo-division algorithm to divide the receiver by aPolynomial with respect to the anInteger-th indeterminate." ^ PolynomialPseudoDivisor divide: self by: aPolynomial in: anInteger! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 1/24/98 13:39'! * anObject "Answer the product of the receiver and the argument." | answer | anObject isPolynomial ifTrue: [ answer _ self class new. anObject do: [ :each | answer addAll: (self privateMonomialProduct: each) monomials]. ^ answer]. (anObject isMonomial or: [anObject isMonomialLiteral]) ifTrue: [^ self privateMonomialProduct: anObject]. anObject isRationalFunction ifTrue: [^ self asRationalFunction * anObject]. ^ self mapCoefficients: [ :each | each * anObject]! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 9/1/97 20:42'! ** anInteger "Answer the receiver raised to anInteger." ^ self raisedToInteger: anInteger! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 1/24/98 13:40'! + anObject "Answer the sum of the receiver and the argument." anObject isPolynomial ifTrue: [^ self copy addAll: (anObject monomials); yourself]. anObject isMonomial ifTrue: [^ self copy add: anObject; yourself]. anObject isRationalFunction ifTrue: [^ self asRationalFunction + anObject]. ^ self + (self identity * anObject)! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 10/18/97 02:33'! - anObject "Answer the difference between the receiver and the argument." ^ self + anObject negated! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 1/24/98 13:40'! / anObject "Answer the division of the receiver by the argument." (anObject isMonomial or: [anObject isMonomialLiteral]) ifTrue: [^ self privateMonomialDivision: anObject]. ^ self * anObject reciprocal! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 1/24/98 13:41'! // anObject "Answer the quotient of the division of the receiver by the argument." anObject isPolynomial ifTrue: [^ (self divideBy: anObject) quotient]. ^ self mapCoefficients: [ :each | each // anObject]! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 1/24/98 13:40'! \\ anObject "Answer the remainder of the division of the receiver by the argument." anObject isPolynomial ifTrue: [^ (self divideBy: anObject) remainder]. ^ self mapCoefficients: [ :each | each \\ anObject]! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 10/18/97 02:33'! negated "Answer the additive inverse of the receiver." ^ self mapCoefficients: [ :each | each negated]! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 1/23/98 16:29'! pseudoQuo: aPolynomial "Answer the quotient of the pseudo-division of the receiver by the argument." ^ (self pseudoDivideBy: aPolynomial) quotient! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 1/23/98 16:29'! pseudoQuo: aPolynomial in: anInteger "Answer the quotient of the pseudo-division of the receiver by the argument w.r.t to the anInteger-th indeterminate." ^ (self pseudoDivideBy: aPolynomial in: anInteger) quotient! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 1/23/98 16:29'! pseudoRem: aPolynomial "Answer the remainder of the pseudo-division of the receiver by the argument." ^ (self pseudoDivideBy: aPolynomial) remainder! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 1/23/98 16:29'! pseudoRem: aPolynomial in: anInteger "Answer the remainder of the pseudo-division of the receiver by the argument w.r.t to the anInteger-th indeterminate." ^ (self pseudoDivideBy: aPolynomial in: anInteger) remainder! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 11/12/97 20:51'! raisedToInteger: anInteger "Answer the receiver raised to the power anInteger." anInteger = 0 ifTrue: [^ self identity]. anInteger = 1 ifTrue: [^ self]. anInteger > 1 ifTrue: [^ (self * self raisedToInteger: anInteger // 2) * (self raisedToInteger: anInteger \\ 2)]. ^ (self raisedToInteger: anInteger negated) reciprocal! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 11/22/97 21:40'! reciprocal "Answer the receiprocal of the receiver." ^ self asRationalFunction reciprocal! ! !Polynomial methodsFor: 'arithmetic' stamp: 'len 9/1/97 20:44'! squared "Answer the square of the receiver." ^ self * self! ! !Polynomial methodsFor: 'mathematical functions' stamp: 'len 11/22/97 21:41'! gcd: aPolynomial "Answer the greatest common divisor of the receiver and aPolynomial." | a b r | aPolynomial isNull ifTrue: [^ self]. a _ self. b _ aPolynomial. [(r _ a \\ b) isNull] whileFalse: [a _ b. b _ r]. ^ b * b leadingCoefficient reciprocal! ! !Polynomial methodsFor: 'mathematical functions' stamp: 'len 11/22/97 21:41'! lcm: aPolynomial "Answer the least common multiple of the receiver and aPolynomial." ^ self // (self gcd: aPolynomial) * aPolynomial! ! !Polynomial methodsFor: 'mathematical functions' stamp: 'len 11/23/97 01:44'! mod: anObject "Answer the receiver modulo anObject." anObject isInteger ifFalse: [^ self notYetImplemented]. ^ self mapCoefficients: [ :each | each mod: anObject]! ! !Polynomial methodsFor: 'mathematical functions' stamp: 'len 10/21/97 01:18'! sign "Answer the sign of the receiver, i.e. the sign if its head coefficient." ^ self head coefficient sign! ! !Polynomial methodsFor: 'equations' stamp: 'len 11/22/97 19:20'! eq: anObject "Answer the equation 'self = anObject'." ^ PolynomialEquation polynomial: self - anObject! ! !Polynomial methodsFor: 'operations' stamp: 'len 11/22/97 19:20'! affinizedIn: anInteger "Answer the affinization of the receiver in the anInteger-th indeterminate." ^ self class new monomials: (self monomials collect: [ :each | each copyWithout: anInteger])! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:21'! content "Answer the content of the receiver." | answer | self isNull ifTrue: [^ self nullCoefficient]. self do: [ :each | answer _ answer isNil ifTrue: [each coefficient] ifFalse: [answer gcd: each coefficient]]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 1/23/98 03:06'! degree "Answer the total degree of the receiver." | answer | self isNull ifTrue: [^ Infinity negative]. answer _ 0. self do: [ :each | answer _ answer max: each degree]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:21'! degreeIn: anInteger "Answer the degree of the receiver in the anInteger-th indeterminate." | answer | self isNull ifTrue: [^ Infinity negative]. answer _ 0. self do: [ :each | answer _ answer max: (each degreeIn: anInteger)]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:25'! derivativeIn: anInteger "Answer the derivative of the receiver in the anInteger-th indeterminate." | answer | answer _ self class new. self do: [ :each | answer add: (each derivativeIn: anInteger)]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 11/22/97 21:56'! descendentPower: n "Answer the descendent power of the recever raised to the integer argument." | mid | n = 0 ifTrue: [^ self identity]. n = 1 ifTrue: [^ self]. n negative ifTrue: [^ (self descendentPower: n negated) reciprocal]. mid _ n bitShift: -1. ^ n even ifTrue: [(self - (self identityCoefficient * mid) descendentPower: mid) * (self descendentPower: mid)] ifFalse: [(self - (self identityCoefficient * mid) descendentPower: mid + 1) * (self descendentPower: mid)]! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:25'! evenIn: anInteger "Decompose the receiver in the form f(x^2)x + g(x^2) and answer g(x), where 'x' is the anInteger-th indeterminate." | answer monomial d | answer _ self class new. self do: [ :each | (d _ each degreeIn: anInteger) even ifTrue: [ monomial _ each copy. monomial literal at: anInteger put: d // 2. answer add: monomial]]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 11/22/97 19:20'! homogeneousComponentAt: anInteger "Answer the receiver's homogeneous component of degree anInteger." ^ self class new monomials: (self monomials select: [ :each | each degree = anInteger])! ! !Polynomial methodsFor: 'operations' stamp: 'len 11/22/97 19:20'! homogenizedIn: anInteger "Answer the homogenization of the receiver in the anInteger-th indeterminate." | degree | degree _ self degree. ^ self class new monomials: (self monomials collect: [ :each | each complete: degree with: anInteger])! ! !Polynomial methodsFor: 'operations' stamp: 'len 9/5/97 14:12'! integerContent "Answer the integer content of the receiver. NOTE: the receiver is supposed a polynomial over the rational numbers." | num den | self isNull ifTrue: [^ self]. num _ self monomials first coefficient numerator. den _ self monomials first coefficient denominator. self monomials do: [ :each | num _ num gcd: each coefficient numerator. den _ den lcm: each coefficient denominator]. ^ (num / den) abs! ! !Polynomial methodsFor: 'operations' stamp: 'len 11/22/97 21:59'! integerPrimitive "Answer the integer primitive polynomial associated to the receiver. Remove the integer content and the sign. NOTE: the receiver is supposed a polynomial over the rational numbers." self isNull ifTrue: [^ self]. ^ self / (self integerContent * self sign)! ! !Polynomial methodsFor: 'operations' stamp: 'len 1/13/98 00:03'! ldegree "Answer the lowest degree of the receiver's monomials." ^ self isNull ifTrue: [Infinity negative] ifFalse: [self last degree]! ! !Polynomial methodsFor: 'operations' stamp: 'len 8/25/97 01:23'! mapCoefficients: aBlock "Answer a new polynomial like the receiver but with changing the coefficients applying to them aBlock." | newMonomials newCoefficient | newMonomials _ OrderedCollection new. self monomials do: [ :each | newCoefficient _ aBlock value: each coefficient. newCoefficient isNull ifFalse: [ newMonomials add: (each copy coefficient: newCoefficient)]]. ^ self class new monomials: newMonomials! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:22'! norm1 "Answer the 1-norm of the receiver." | answer | answer _ self nullCoefficient. self do: [ :each | answer _ answer + each coefficient abs]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:22'! norm2 "Answer the square norm of the receiver." | answer | answer _ self nullCoefficient. self do: [ :each | answer _ answer + each coefficient squared]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:22'! normInfinite "Answer the infinite-norm of the receiver." | answer | answer _ self nullCoefficient. self do: [ :each | answer _ answer max: each coefficient abs]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:22'! normMax "Answer the maximun norm of the receiver." | answer | answer _ self nullCoefficient. self do: [ :each | answer _ answer + each coefficient abs]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:25'! oddIn: anInteger "Decompose the receiver in the form f(x^2)x + g(x^2) and answer f(x), where 'x' is the anInteger-th indeterminate." | answer monomial d | answer _ self class new. self do: [ :each | (d _ each degreeIn: anInteger) odd ifTrue: [ monomial _ each copy. monomial literal at: anInteger put: d // 2. answer add: monomial]]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 9/5/97 14:13'! primitive "Answer the primitive part of the receiver." | content | content _ self content. ^ self mapCoefficients: [ :each | each / content]! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:25'! reversedIn: anInteger "Answer the reverse of the receiver as univariate polynomial in the anInteger-th indeterminate." | answer monomial n | n _ self degreeIn: anInteger. answer _ self class new. self do: [ :each | monomial _ each copy. monomial literal at: anInteger put: n - (each degreeIn: anInteger). answer add: each]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:25'! shift: anInteger in: anotherInteger "Answer the receiver shifted anInteger places as univariate polynomial in the anotherInteger-th indeterminate." | answer monomial d | answer _ self class new. self do: [ :each | d _ (each degreeIn: anotherInteger) + anInteger. d negative ifFalse: [ monomial _ each copy. monomial literal at: anotherInteger put: d. answer add: monomial]]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'len 12/3/97 02:23'! valueAt: anObject "Answer the value of the receiver at the argument." | answer | (anObject isTuple or: [anObject class == Array]) ifFalse: [^ self valueAt: anObject in: self main]. answer _ anObject first null. self do: [ :each | answer _ answer + (each valueAt: anObject)]. ^ answer! ! !Polynomial methodsFor: 'operations' stamp: 'pdm 5/2/98 16:56'! valueAt: anObject in: anInteger "Answer the value of the receiver at anObject as univariate polynomial in the anInteger-th indeterminate." | f answer id deg | self isNull ifTrue: [^ anObject null]. f _ self univariateIn: anInteger. id _ anObject identity. answer _ anObject null. deg _ f degree + 1. f sortedMonomials do: [:each | answer _ (anObject raisedToInteger: deg - (deg _ each degree)) * answer + (id * each coefficient)]. answer _ (anObject raisedToInteger: deg) * answer. ^ answer! ! !Polynomial methodsFor: 'operations univariate' stamp: 'len 11/22/97 22:13'! derivative "Answer the derivative of the receiver." ^ self derivativeIn: self main! ! !Polynomial methodsFor: 'operations univariate' stamp: 'len 11/22/97 22:12'! even "Decompose the receiver in the form f(x^2)x + g(x^2) and answer g(x)." ^ self evenIn: self main! ! !Polynomial methodsFor: 'operations univariate' stamp: 'len 11/22/97 21:59'! multiplicityAt: anObject "Answer the multiplicity of anObject as zero of the receiver." | answer f | self isNull ifTrue: [^ Infinity positive]. answer _ 0. f _ self. [(f valueAt: anObject) isNull] whileTrue: [ answer _ answer + 1. f _ f derivative]. ^ answer! ! !Polynomial methodsFor: 'operations univariate' stamp: 'len 11/22/97 22:12'! odd "Decompose the receiver in the form f(x^2)x + g(x^2) and answer f(x)." ^ self oddIn: self main! ! !Polynomial methodsFor: 'operations univariate' stamp: 'len 11/22/97 22:15'! reversed "Answer the reverse of the receiver." ^ self reversedIn: self main! ! !Polynomial methodsFor: 'operations univariate' stamp: 'len 11/22/97 23:24'! shift: anInteger "Answer the receiver shifted anInteger places." ^ self shift: anInteger in: self main! ! !Polynomial methodsFor: 'enumerating' stamp: 'len 12/3/97 02:23'! do: aBlock "Enumerate the monomials of the receiver." self monomials do: aBlock! ! !Polynomial methodsFor: 'comparing' stamp: 'len 12/4/97 00:42'! = anObject "Answer true if the receiver equals anObject." ^ (self - anObject) isNull! ! !Polynomial methodsFor: 'comparing' stamp: 'len 1/23/98 03:12'! hash "Answer the hash value of the receiver." | answer | answer _ -918347. self monomials do: [ :each | answer _ answer + each hash]. ^ answer! ! !Polynomial methodsFor: 'testing' stamp: 'len 7/30/97 21:39'! isBinomial "Answer true if the receiver is a binomial." ^ self monomials size = 2! ! !Polynomial methodsFor: 'testing' stamp: 'len 10/18/97 03:01'! isConstant "Answer true if the receiver is constant." ^ self degree < 1! ! !Polynomial methodsFor: 'testing' stamp: 'len 12/3/97 02:21'! isHomogeneous "Answer true if the receiver is homogeneous." | n | self isNull ifTrue: [^ true]. n _ self degree. self do: [ :each | each degree = n ifFalse: [^ false]]. ^ true! ! !Polynomial methodsFor: 'testing' stamp: 'len 10/18/97 03:01'! isLinear "Answer true if the receiver is linear." ^ self degree < 2! ! !Polynomial methodsFor: 'testing' stamp: 'len 11/22/97 21:45'! isMonic "Answer true if the receiver is monic." ^ self leadingCoefficient = self identityCoefficient! ! !Polynomial methodsFor: 'testing' stamp: 'len 9/1/97 20:49'! isNull "Answer true if the receiver is null." ^ self monomials isEmpty! ! !Polynomial methodsFor: 'testing' stamp: 'len 9/13/97 03:46'! isPolynomial "Answer true if the receiver is a polynomial." ^ true! ! !Polynomial methodsFor: 'testing' stamp: 'len 11/22/97 21:45'! isSquareFree "Answer true if the receiver is square free." ^ (self gcd: self derivative) degree = 0! ! !Polynomial methodsFor: 'testing' stamp: 'len 12/3/97 02:21'! isUnivariateIn: anInteger "Answer true if the receiver is an univariate polynomial in the anInteger-th indeterminate." self do: [ :each | (each isUnivariateIn: anInteger) ifFalse: [^ false]]. ^ true! ! !Polynomial methodsFor: 'converting' stamp: 'len 8/1/97 18:30'! @ anObject ^ Point x: self y: anObject! ! !Polynomial methodsFor: 'converting' stamp: 'len 10/23/97 03:38'! adaptFraction: aFraction ^ self identity * aFraction! ! !Polynomial methodsFor: 'converting' stamp: 'len 7/12/97 23:27'! adaptInteger: anInteger ^ self identity * anInteger! ! !Polynomial methodsFor: 'converting' stamp: 'len 8/30/97 01:24'! adaptToFraction ^ self! ! !Polynomial methodsFor: 'converting' stamp: 'len 7/12/97 23:27'! adaptToInteger ^ self! ! !Polynomial methodsFor: 'converting' stamp: 'len 12/1/97 20:41'! asPolynomial ^ self! ! !Polynomial methodsFor: 'converting' stamp: 'len 11/22/97 21:43'! asRationalFunction "Answer the rational function representing the receiver." ^ RationalFunction numerator: self denominator: self identity! ! !Polynomial methodsFor: 'converting' stamp: 'pdm 5/1/98 18:37'! univariateIn: anInteger "Answer the receiver as univariate in the anInteger-th indeterminate. " | answer | (self isUnivariateIn: anInteger) ifTrue: [^ self]. answer _ self class new. self do: [:each | answer add: (each univariateIn: anInteger)]. ^ answer! ! !Polynomial methodsFor: 'copying' stamp: 'len 9/1/97 20:56'! copy "Answer a copy of the receiver." ^ self class new monomials: (self monomials collect: [ :each | each copy])! ! !Polynomial methodsFor: 'constants' stamp: 'len 10/23/97 03:40'! identity self monomials do: [ :each | ^ self class fromMonomial: each identity]. ^ self class constant: self identityCoefficient! ! !Polynomial methodsFor: 'constants' stamp: 'len 7/28/97 19:25'! identityCoefficient self isNull ifTrue: [^ self class identityCoefficient]. ^ self monomials first coefficient identity! ! !Polynomial methodsFor: 'constants' stamp: 'len 7/28/97 19:23'! null ^ self class new! ! !Polynomial methodsFor: 'constants' stamp: 'len 7/28/97 19:25'! nullCoefficient self isNull ifTrue: [^ self class nullCoefficient]. ^ self monomials first coefficient null! ! !Polynomial methodsFor: 'constants' stamp: 'len 11/22/97 21:54'! x "Answer the x polynomial." ^ self class fromMonomial: (self class monomialClass coefficient: self identityCoefficient degree: 1)! ! !Polynomial methodsFor: 'printing-private' stamp: 'len 12/26/97 17:58'! defaultNames "Answer the default names for the indeterminates." ^ self class defaultNames! ! !Polynomial methodsFor: 'printing' stamp: 'len 12/26/97 17:59'! printOn: aStream "Print a representation of the receiver on the stream aStream." self printOn: aStream withNames: self defaultNames! ! !Polynomial methodsFor: 'printing' stamp: 'len 12/21/97 20:51'! printOn: aStream withNames: aDictionary "Print a representation of the receiver on the stream aStream. Use aDictionary to name the indeterminates." self head printOn: aStream withNames: aDictionary. self tail sortedMonomials do: [ :each | each coefficient printString first = $- ifTrue: [aStream nextPutAll: ' - '. each negated printOn: aStream withNames: aDictionary] ifFalse: [aStream nextPutAll: ' + '. each printOn: aStream withNames: aDictionary]]! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 11/23/97 00:31'! coefficients: anArray "Answer a new instance of the receiver whose coefficients are the elements of the argument." | monomials | monomials _ OrderedCollection new: anArray size. 1 to: anArray size do: [ :each | (anArray at: each) isNull ifFalse: [ monomials add: (self monomialClass coefficient: (anArray at: each) degree: each - 1)]]. ^ self new monomials: monomials! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 9/9/97 00:51'! constant: anObject "Answer a new instance the receiver with the constant object anObject." ^ self fromMonomial: (self monomialClass constant: anObject)! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 12/3/97 02:25'! fromMonomial: aMonomial "Answer a new instance of the receiver with only one monomial." ^ self new add: aMonomial; yourself! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 9/9/97 00:54'! identity "Answer an instance of the receiver representing the '1' polynomial." ^ self constant: self identityCoefficient! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 7/11/97 20:51'! new ^ super new initialize! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 9/5/97 14:27'! null "Answer an instance of the receiver representing a null polynomial." ^ self new! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 11/22/97 19:30'! x "Answer the 'x' polynomial." ^ self x: 1! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 11/22/97 19:30'! x: anInteger "Answer an instance of the receiver representing the polynomial with the sole anInteger-th indeterminate with degree 1 and coefficient 1." ^ self x: anInteger to: 1 coefficient: self identityCoefficient! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 11/22/97 19:30'! x: anInteger coefficient: anObject "Answer an instance of the receiver representing the polynomial with the sole anInteger-th indeterminate with degree 1 and coefficient anObject." ^ self x: anInteger to: 1 coefficient: anObject! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 11/22/97 19:30'! x: anInteger to: anotherInteger "Answer an instance of the receiver representing the polynomial with the sole anInteger-th indeterminate with degree anotherInteger and coefficient 1." ^ self x: anInteger to: anotherInteger coefficient: self identityCoefficient! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 11/22/97 19:30'! x: anInteger to: anotherInteger coefficient: anObject "Answer an instance of the receiver representing the polynomial with the sole anInteger-th indeterminate raised to anotherInteger and with coefficient anObject." ^ self fromMonomial: (self monomialClass x: anInteger to: anotherInteger coefficient: anObject)! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 11/22/97 19:30'! y "Answer the 'y' polynomial." ^ self x: 2! ! !Polynomial class methodsFor: 'instance creation' stamp: 'len 11/22/97 19:30'! z "Answer the 'z' polynomial." ^ self x: 3! ! !Polynomial class methodsFor: 'related classes' stamp: 'len 11/22/97 19:58'! monomialClass ^ Monomial! ! !Polynomial class methodsFor: 'examples' stamp: 'len 11/22/97 19:35'! chebyshevOfOrder: n "Answer the n-th Chebyshev polynomial." | monomials c m k | n <= 0 ifTrue: [^ self identity]. monomials _ OrderedCollection new: n // 2 + 1. c _ (1 bitShift: n - 1). m _ 4. k _ n - 1. monomials add: (self monomialClass degree: n coefficient: self identityCoefficient * c). n - 1 to: 1 by: -2 do: [ :each | c _ ((c * (each + 1) * each) / (k * m)) negated. m _ m + 4. k _ k - 1. c isNull ifFalse: [ monomials add: (self monomialClass degree: each - 1 coefficient: self identityCoefficient * c)]]. ^ self new monomials: monomials! ! !Polynomial class methodsFor: 'examples' stamp: 'len 11/22/97 19:33'! continuantOfOrder: n "Answer the continuant polynomial of order n." "Polynomial continuantOfOrder: 3" n = 0 ifTrue: [^ self identity]. n = 1 ifTrue: [^ self x: 1]. ^ (self continuantOfOrder: n - 1) * (self x: n) + (self continuantOfOrder: n - 2)! ! !Polynomial class methodsFor: 'examples' stamp: 'len 11/22/97 19:35'! fibonacciOfOrder: n "Answer the n-th Fibonacci polynomial." "Polynomial fibonacciOfOrder: 3" n negative ifTrue: [^ self notYetImplemented]. n = 0 ifTrue: [^ self null]. n = 1 ifTrue: [^ self identity]. ^ (self fibonacciOfOrder: n - 1) - (self x * (self fibonacciOfOrder: n - 2))! ! !Polynomial class methodsFor: 'constants' stamp: 'len 1/23/98 16:24'! defaultNames "Answer the default names for the indeterminates." ^ MonomialLiteral defaultNames! ! !Polynomial class methodsFor: 'constants' stamp: 'len 8/30/97 01:09'! identityCoefficient ^ 1! ! !Polynomial class methodsFor: 'constants' stamp: 'len 8/30/97 01:09'! nullCoefficient ^ 0! ! !PolynomialDivisor methodsFor: 'initialization' stamp: 'len 1/23/98 15:49'! divide: aPolynomial by: anotherPolynomial self dividend: aPolynomial. self divisor: anotherPolynomial. self done: false! ! !PolynomialDivisor methodsFor: 'accessing-private' stamp: 'len 8/29/97 00:17'! done: aBoolean done _ aBoolean! ! !PolynomialDivisor methodsFor: 'accessing-private' stamp: 'len 8/29/97 00:18'! quotient: aPolynomial quotient _ aPolynomial! ! !PolynomialDivisor methodsFor: 'accessing-private' stamp: 'len 8/29/97 00:18'! remainder: aPolynomial remainder _ aPolynomial! ! !PolynomialDivisor methodsFor: 'accessing' stamp: 'len 8/29/97 00:21'! dividend "Answer the dividend of the receiver." ^ dividend! ! !PolynomialDivisor methodsFor: 'accessing' stamp: 'len 1/23/98 15:50'! dividend: aPolynomial dividend _ aPolynomial. self done: false! ! !PolynomialDivisor methodsFor: 'accessing' stamp: 'len 8/29/97 00:21'! divisor "Answer the divisor of the receiver." ^ divisor! ! !PolynomialDivisor methodsFor: 'accessing' stamp: 'len 1/23/98 15:50'! divisor: aPolynomial divisor _ aPolynomial. self done: false! ! !PolynomialDivisor methodsFor: 'accessing' stamp: 'len 8/29/97 00:22'! done "Answer true if the quotient and the remainder have been computed." ^ done! ! !PolynomialDivisor methodsFor: 'accessing' stamp: 'len 1/23/98 15:51'! quotient "Answer the quotient of the receiver." self divide. ^ quotient! ! !PolynomialDivisor methodsFor: 'accessing' stamp: 'len 1/23/98 15:51'! remainder "Answer the remainder of the receiver." self divide. ^ remainder! ! !PolynomialDivisor methodsFor: 'operations' stamp: 'len 1/24/98 13:35'! divide "Divide the dividend by the divisor, computing the quotient and the remainder polynoials." | quo rem lc monomial n m | self done ifTrue: [^ self]. self divisor isNull ifTrue: [^ self error: 'division by zero']. self divisor degree = 0 ifTrue: [^ self quotient: self dividend * self divisor leadingCoefficient reciprocal; remainder: self dividend null; done: true]. self dividend degree < self divisor degree ifTrue: [^ self quotient: self dividend null; remainder: self dividend; done: true]. m _ self divisor degree. quo _ self dividend null. rem _ self dividend. lc _ self divisor leadingCoefficient. [(n _ rem degree) >= m] whileTrue: [ monomial _ self dividend class monomialClass coefficient: rem leadingCoefficient / lc degree: n - m. rem _ rem + (self divisor * monomial negated). quo _ quo add: monomial; yourself]. self quotient: quo; remainder: rem; done: true! ! !PolynomialDivisor methodsFor: 'printing' stamp: 'len 1/24/98 12:43'! printOn: aStream "Print a representation of the receiver on the stream aStream." aStream print: self dividend; nextPutAll: ' = ('; print: self quotient; nextPutAll: ')('; print: self divisor; nextPutAll: ') + '; print: self remainder! ! !PolynomialDivisor class methodsFor: 'instance creation' stamp: 'len 1/23/98 16:03'! divide: aPolynomial by: anotherPolynomial "Answer a division algorithm to divide aPolynomial by anotherPolynomial." ^ self new divide: aPolynomial by: anotherPolynomial! ! !PolynomialEquation commentStamp: 'pdm 8/29/1998 19:46' prior: 0! My instances are polynomial equations. For an example try: | x y | x _ Polynomial x. y _ Polynomial y. PolynomialEquation polynomial: x*x + (y*y) - 1. which is equivalent to: | x y | x _ Polynomial x. y _ Polynomial y. x*x + (y*y) eq: 1. ! !PolynomialEquation methodsFor: 'accessing-private' stamp: 'len 9/5/97 14:15'! polynomial: aPolynomial aPolynomial monomials do: [ :each | each coefficient isRational ifFalse: [polynomial _ aPolynomial. ^ self]]. polynomial _ aPolynomial integerPrimitive! ! !PolynomialEquation methodsFor: 'accessing' stamp: 'len 12/18/97 20:34'! indeterminates "Answer the indeterminates of the receiver." ^ self polynomial indeterminates! ! !PolynomialEquation methodsFor: 'accessing' stamp: 'len 7/30/97 23:47'! polynomial "Answer the polynomial that defines the receiver." ^ polynomial! ! !PolynomialEquation methodsFor: 'copying' stamp: 'len 12/19/97 02:48'! copy "Answer a copy of the receiver." ^ self class polynomial: self polynomial copy! ! !PolynomialEquation methodsFor: 'testing' stamp: 'len 8/22/97 01:25'! isSolution: anObject "Answer true if the argument satisfies the receiver." ^ (self polynomial valueAt: anObject) isNull! ! !PolynomialEquation methodsFor: 'printing' stamp: 'len 7/30/97 23:51'! printOn: aStream "Print a representation of the receiver on the stream aStream." aStream print: self polynomial; nextPutAll: ' = 0'! ! !PolynomialEquation class methodsFor: 'instance creation' stamp: 'len 7/30/97 23:45'! polynomial: aPolynomial "Answer an instance of the receiver representing the equation 'aPolynomial = 0'." ^ self new polynomial: aPolynomial! ! !PolynomialPseudoDivisor methodsFor: 'initialization' stamp: 'len 1/23/98 15:38'! divide: aPolynomial by: anotherPolynomial in: anInteger self dividend: aPolynomial; divisor: anotherPolynomial; indeterminate: anInteger; done: false! ! !PolynomialPseudoDivisor methodsFor: 'accessing-private' stamp: 'len 8/29/97 00:39'! done: aBoolean done _ aBoolean! ! !PolynomialPseudoDivisor methodsFor: 'accessing-private' stamp: 'len 8/29/97 00:39'! quotient: aPolynomial quotient _ aPolynomial! ! !PolynomialPseudoDivisor methodsFor: 'accessing-private' stamp: 'len 8/29/97 00:39'! remainder: aPolynomial remainder _ aPolynomial! ! !PolynomialPseudoDivisor methodsFor: 'accessing' stamp: 'len 1/24/98 13:01'! delta "Answer an integer delta such that the dividend multiplied by its leading coeficient raised to the delta equals the product of the quotient by the divisor plus the remainder (the pseudo-division relation)." ^ self dividend degree - self divisor degree + 1 max: 0! ! !PolynomialPseudoDivisor methodsFor: 'accessing' stamp: 'len 8/29/97 00:39'! dividend "Answer the dividend of the receiver." ^ dividend! ! !PolynomialPseudoDivisor methodsFor: 'accessing' stamp: 'len 1/23/98 15:35'! dividend: aPolynomial dividend _ aPolynomial. self done: false! ! !PolynomialPseudoDivisor methodsFor: 'accessing' stamp: 'len 8/29/97 00:40'! divisor "Answer the divisor of the receiver." ^ divisor! ! !PolynomialPseudoDivisor methodsFor: 'accessing' stamp: 'len 1/23/98 15:35'! divisor: aPolynomial divisor _ aPolynomial. self done: false! ! !PolynomialPseudoDivisor methodsFor: 'accessing' stamp: 'len 8/29/97 00:40'! done "Answer true if the quotient and the remainder have been computed." ^ done! ! !PolynomialPseudoDivisor methodsFor: 'accessing' stamp: 'len 1/23/98 15:37'! indeterminate "Answer the indeterminate with respect to is the receiver dividing." ^ indeterminate! ! !PolynomialPseudoDivisor methodsFor: 'accessing' stamp: 'len 1/23/98 15:36'! indeterminate: anInteger indeterminate _ anInteger. self done: false! ! !PolynomialPseudoDivisor methodsFor: 'accessing' stamp: 'len 1/23/98 15:43'! quotient "Answer the quotient of the receiver." self divide. ^ quotient! ! !PolynomialPseudoDivisor methodsFor: 'accessing' stamp: 'len 1/23/98 15:47'! remainder "Answer the remainder of the receiver." self divide. ^ remainder! ! !PolynomialPseudoDivisor methodsFor: 'operations' stamp: 'len 1/24/98 13:35'! divide | m n am bn nextDivisor indet | self done ifTrue: [^ self]. self divisor isNull ifTrue: [self error: 'division by zero']. indet _ self indeterminate. (m _ self dividend degreeIn: indet) < (n _ self divisor degreeIn: indet) ifTrue: [^ self quotient: self dividend null; remainder: self dividend; done: true]. am _ self dividend leadingCoefficientIn: indet. bn _ self divisor leadingCoefficientIn: indet. nextDivisor _ self class divide: bn * self dividend - (am * self divisor shift: m - n in: indet) by: self divisor in: indet. self quotient: (am * (bn raisedToInteger: m - n) shift: m - n in: indet) + nextDivisor quotient; remainder: nextDivisor remainder; done: true! ! !PolynomialPseudoDivisor methodsFor: 'printing' stamp: 'len 1/24/98 12:55'! printOn: aStream "Print a representation of the receiver on the stream aStream." aStream print: (self divisor leadingCoefficient raisedToInteger: self delta); nextPut: $(; print: self dividend; nextPutAll: ') = ('; print: self quotient; nextPutAll: ')('; print: self divisor; nextPutAll: ') + '; print: self remainder! ! !PolynomialPseudoDivisor class methodsFor: 'instance creation' stamp: 'len 1/23/98 16:05'! divide: aPolynomial by: anotherPolynomial "Answer a pseudo-division algorithm to divide aPolynomial by anotherPolynomial." ^ self divide: aPolynomial by: anotherPolynomial in: aPolynomial main! ! !PolynomialPseudoDivisor class methodsFor: 'instance creation' stamp: 'len 1/23/98 16:05'! divide: aPolynomial by: anotherPolynomial in: anInteger "Answer a pseudo-division algorithm to divide aPolynomial by anotherPolynomial with respect to the anInteger-th indeterminate." ^ self new divide: aPolynomial by: anotherPolynomial in: anInteger! ! !PolynomialSystem commentStamp: 'pdm 8/29/1998 19:46' prior: 0! My instances represent systems of polynomial equations. For an examples try this: | x y | x _ Polynomial x. y _ Polynomial y. PolynomialSystem new add: (x*x eq: 1); add: (y*y - (x*x) eq: 3); yourself. ! !PolynomialSystem methodsFor: 'initialization' stamp: 'len 8/3/97 22:46'! initialize self equations: OrderedCollection new! ! !PolynomialSystem methodsFor: 'accessing-private' stamp: 'len 1/30/98 01:13'! equations ^ equations! ! !PolynomialSystem methodsFor: 'accessing-private' stamp: 'pdm 3/9/98 16:36'! equations: aCollection equations _ aCollection! ! !PolynomialSystem methodsFor: 'accessing' stamp: 'pdm 4/19/98 23:08'! , anObject "Answer a copy of the receiver concatenated with the argument." | answer | answer _ self copy. anObject class == self class ifTrue: [answer addAll: anObject] ifFalse: [answer add: anObject]. ^ answer! ! !PolynomialSystem methodsFor: 'accessing' stamp: 'pdm 3/9/98 16:36'! add: aPolynomialEquation "Add the argument to the equations of the receiver. Answer the argument. " ^ self equations add: aPolynomialEquation! ! !PolynomialSystem methodsFor: 'accessing' stamp: 'pdm 3/9/98 16:37'! addAll: aCollection "Add all the elements in argument to the equations of the receiver. Answer the argument." aCollection do: [:each | self add: each]. ^ aCollection! ! !PolynomialSystem methodsFor: 'accessing' stamp: 'pdm 3/9/98 16:37'! solutions "Answer the set of solutions of the receiver." ^ AlgebraicVariety system: self! ! !PolynomialSystem methodsFor: 'enumerating' stamp: 'pdm 3/9/98 16:37'! do: aBlock "Enumerate the equations of the receiver." self equations do: aBlock! ! !PolynomialSystem methodsFor: 'testing' stamp: 'pdm 3/9/98 16:37'! isSolution: anObject "Answer true if the argument is a solutions of the receiver." self do: [:each | (each isSolution: anObject) ifFalse: [^ false]]. ^ true! ! !PolynomialSystem methodsFor: 'copying' stamp: 'pdm 3/9/98 16:37'! copy "Answer a copy of the receiver." ^ self class new addAll: self; yourself! ! !PolynomialSystem methodsFor: 'printing' stamp: 'pdm 4/19/98 16:57'! printOn: aStream "Print a representation of the receiver on the stream aStream." | first | aStream nextPutAll: '{ '. first _ true. self do: [:each | first ifFalse: [aStream nextPutAll: ', ']. aStream print: each. first _ false]. aStream nextPutAll: ' }'! ! !PolynomialSystem class methodsFor: 'instance creation' stamp: 'len 10/22/97 01:00'! new ^ super new initialize! ! !PositionableStream methodsFor: 'accessing' stamp: 'len 11/24/97 20:44'! nextLine "Answer the next line of the receiver. (line delimiters are lf, cr or crlf)." | answer char cr lf | self atEnd ifTrue: [^ nil]. cr _ Character cr. lf _ Character linefeed. answer _ WriteStream with: ''. [self atEnd] whileFalse: [ char _ self next. (char = lf or: [char = cr]) ifTrue: [(char = cr and: [self peek = lf]) ifTrue: [self next]. ^ answer contents]. answer nextPut: char]. ^ answer contents! ! !RationalFunction methodsFor: 'initialization' stamp: 'len 7/17/97 18:45'! setNumerator: aPolynomial denominator: otherPolynomial numerator _ aPolynomial asPolynomial. denominator _ otherPolynomial asPolynomial! ! !RationalFunction methodsFor: 'accessing'! denominator "Answer the denominator." ^ denominator! ! !RationalFunction methodsFor: 'accessing' stamp: 'pdm 3/22/98 20:53'! indeterminates ^ Set new addAll: self numerator indeterminates; addAll: self denominator indeterminates; yourself! ! !RationalFunction methodsFor: 'accessing'! numerator "Answer the numerator." ^ numerator! ! !RationalFunction methodsFor: 'arithmetic' stamp: 'pdm 3/22/98 20:38'! * anObject "Answer the multiplication of the receiver and the argument." anObject isRationalFunction ifTrue: [ " g1 _ self numerator gcd: anObject denominator. g2 _ self denominator gcd: anObject numerator. newNumerator _ self numerator // g1 * (anObject numerator // g2). newDenominator _ self denominator // g2 * (anObject denominator // g1). ^ (newDenominator = 1 or: [newNumerator isNull]) ifTrue: [newNumerator] ifFalse: [self class numerator: newNumerator denominator: newDenominator]" ^ self class numerator: self numerator * anObject numerator denominator: self denominator * anObject denominator]. ^ self numerator * anObject / self denominator! ! !RationalFunction methodsFor: 'arithmetic' stamp: 'pdm 3/22/98 21:02'! + anObject "Answer the sum of the receiver and the argument." anObject isRationalFunction ifTrue: [ "denGcd _ self denominator gcd: anObject denominator. rden1 _ self denominator // denGcd. rden2 _ anObject denominator // denGcd. crossProduct _ self numerator * rden2 + (anObject numerator * rden1). crossGcd _ crossProduct gcd: denGcd. ((newDen _ denGcd // crossGcd * rden1 * rden2) = 1 or: [crossProduct isNull]) ifTrue: [^ crossProduct // crossGcd]. ^ self class numerator: crossProduct // crossGcd denominator: newDen" ^ self class numerator: self numerator * anObject denominator + (self denominator * anObject numerator) denominator: self numerator * self denominator]. ^ self numerator + (self denominator * anObject) / self denominator! ! !RationalFunction methodsFor: 'arithmetic' stamp: 'len 8/18/97 19:15'! - anObject "Answer the difference of the receiver and the argument." ^ self + anObject negated! ! !RationalFunction methodsFor: 'arithmetic' stamp: 'len 8/18/97 19:16'! / anObject "Answer the division of the receiver by the argument." ^ self * anObject reciprocal! ! !RationalFunction methodsFor: 'arithmetic'! negated "Answer the additive inverse of the receiver." ^ self class numerator: numerator negated denominator: denominator! ! !RationalFunction methodsFor: 'arithmetic' stamp: 'len 10/18/97 02:55'! reciprocal "Answer the multiplicative inverse of the receiver." | mult | mult _ self numerator leadingCoefficient reciprocal. self numerator isConstant ifTrue: [^ denominator * mult]. ^ self class numerator: denominator * mult denominator: numerator * mult! ! !RationalFunction methodsFor: 'mathematical functions' stamp: 'len 9/1/97 00:45'! raisedToInteger: anInteger "Answer the receiver raised to the power anInteger where the argument must be a kind of Integer." ^ self class numerator: (self numerator raisedToInteger: anInteger) denominator: (self denominator raisedToInteger: anInteger)! ! !RationalFunction methodsFor: 'mathematical functions' stamp: 'len 9/1/97 00:45'! squared "Answer the square of the receiver." ^ self class numerator: self numerator squared denominator: self denominator squared! ! !RationalFunction methodsFor: 'operations' stamp: 'len 9/4/97 00:24'! degree "Answer the degree of the receiver." ^ self numerator degree - self denominator degree! ! !RationalFunction methodsFor: 'operations' stamp: 'len 9/3/97 23:49'! derivative "Answer the derivative of the receiver." | num gcd | num _ self denominator * self numerator derivative - (self numerator * self denominator derivative). gcd _ self denominator gcd: num. ^ self class numerator: num // gcd denominator: (self denominator // gcd) squared * gcd! ! !RationalFunction methodsFor: 'operations' stamp: 'len 9/3/97 23:35'! derivativeOfOrder: anInteger "Answer the anInteger-th derivative of the receiver." | answer | answer _ self. anInteger timesRepeat: [answer _ answer derivative]. ^ answer! ! !RationalFunction methodsFor: 'operations' stamp: 'len 9/4/97 00:24'! valueAt: anObject "Answer the result of evaluating the receiver at the argument." ^ (self numerator valueAt: anObject) / (self denominator valueAt: anObject)! ! !RationalFunction methodsFor: 'comparing' stamp: 'pdm 3/22/98 20:35'! = anObject "Answer true if the receiver equals the argument." anObject isRationalFunction ifTrue: [ ^ self numerator * anObject denominator = (self denominator * anObject numerator)]. ^ self numerator = (anObject * self denominator)! ! !RationalFunction methodsFor: 'comparing' stamp: 'pdm 3/22/98 20:36'! hash "Answer the hash value for the receiver." ^ 0! ! !RationalFunction methodsFor: 'converting' stamp: 'len 8/30/97 01:15'! adaptFraction: aFraction "If I am involved in arithmetic with a Fraction, convert the Fraction." ^ self class numerator: (self numerator adaptFraction: aFraction) denominator: self denominator identity! ! !RationalFunction methodsFor: 'converting' stamp: 'len 8/30/97 01:15'! adaptInteger: anInteger "If I am involved in arithmetic with an Integer, convert the Integer." ^ self class numerator: (self numerator adaptInteger: anInteger) denominator: self denominator identity! ! !RationalFunction methodsFor: 'converting'! adaptToFraction "If I am involved in arithmetic with a Fraction, do not convert me." ^self! ! !RationalFunction methodsFor: 'converting'! adaptToInteger "If I am involved in arithmetic with an Integer, do not convert me." ^self! ! !RationalFunction methodsFor: 'testing' stamp: 'len 9/4/97 00:27'! isNull "Answer true if the receiver is null." ^ self numerator isNull! ! !RationalFunction methodsFor: 'testing'! isRationalFunction "Answer true if the receiver is a rational function." ^ true! ! !RationalFunction methodsFor: 'basic' stamp: 'len 7/29/97 23:41'! identity ^ self numerator identity! ! !RationalFunction methodsFor: 'basic' stamp: 'len 7/29/97 23:40'! identityCoefficient ^ self numerator identityCoefficient! ! !RationalFunction methodsFor: 'basic' stamp: 'len 7/29/97 23:41'! null ^ self numerator null! ! !RationalFunction methodsFor: 'basic' stamp: 'len 7/29/97 23:40'! nullCoefficient ^ self numerator nullCoefficient! ! !RationalFunction methodsFor: 'private'! denominator: arg denominator _ arg asPolynomial! ! !RationalFunction methodsFor: 'private'! numerator: arg numerator _ arg asPolynomial! ! !RationalFunction methodsFor: 'private' stamp: 'len 10/18/97 02:56'! reduced "Reduce the receiver dividing the numerator and the denominator by them GCD and making the denominator monic." | gcd mult num den | (num _ self numerator) isNull ifTrue: [^ num]. den _ self denominator. gcd _ num gcd: den. num _ num // gcd. den _ den // gcd. mult _ den asPolynomial leadingCoefficient reciprocal. self numerator: num * mult. self denominator: den * mult! ! !RationalFunction methodsFor: 'printing' stamp: 'len 8/23/97 02:03'! printOn: aStream "Print a representation of the reseiver on the stream aStream." | string | aStream print: self numerator; nextPutAll: ' / '. string _ self denominator printString. ((string includes: $+) or: [string includes: $-]) ifTrue: [aStream nextPut: $(; print: self denominator; nextPut: $)] ifFalse: [aStream print: self denominator]! ! !RationalFunction methodsFor: 'printing' stamp: 'len 9/1/97 00:49'! printOn: aStream withName: aString "Print a representation of the receiver on the stream aStream. Use the aString to name the indeterminate." | string | self numerator printOn: aStream withName: aString. aStream nextPutAll: ' / '. string _ self denominator printString. ((string includes: $+) or: [string includes: $-]) ifTrue: [aStream nextPut: $(. self denominator printOn: aStream withName: aString. aStream nextPut: $)] ifFalse: [self denominator printOn: aStream withName: aString]! ! !RationalFunction class methodsFor: 'instance creation' stamp: 'len 8/27/97 01:39'! numerator: aPolynomial denominator: anotherPolynomial "Answer a new instance of the receiver representing a rational function with the given numerator and denominator." ^ self new setNumerator: aPolynomial denominator: anotherPolynomial! ! !RationalParametrization methodsFor: 'initialization' stamp: 'pdm 3/22/98 19:21'! initialize self contents: OrderedCollection new! ! !RationalParametrization methodsFor: 'accessing-private' stamp: 'pdm 3/22/98 19:19'! contents ^ contents! ! !RationalParametrization methodsFor: 'accessing-private' stamp: 'pdm 3/22/98 19:19'! contents: aCollection contents _ aCollection! ! !RationalParametrization methodsFor: 'accessing' stamp: 'pdm 4/19/98 23:42'! add: aRationalFunction ^ self contents add: aRationalFunction! ! !RationalParametrization methodsFor: 'accessing' stamp: 'pdm 4/19/98 23:42'! at: anInteger ^ self contents at: anInteger! ! !RationalParametrization methodsFor: 'accessing' stamp: 'pdm 4/19/98 23:42'! at: anInteger put: aRationalFunction ^ self contents at: anInteger put: aRationalFunction! ! !RationalParametrization methodsFor: 'accessing' stamp: 'pdm 4/19/98 23:45'! implicit | normal tindets y n generators g ordering basis answer | normal _ self copy normalize. tindets _ normal parameters asSortedCollection. y _ tindets last + 1. n _ self size. generators _ OrderedCollection new. 1 to: n do: [:each | generators add: (normal at: each) denominator * (Polynomial x: each) - (normal at: each) numerator]. normal do: [:each | g _ g isNil ifTrue: [each denominator] ifFalse: [g * each denominator]]. generators add: g identity - (g * (Polynomial x: y)). ordering _ MonomialOrdering lex: (1 to: n) , tindets , (Array with: y). ordering _ ordering inverse. basis _ (GroebnerBasis from: generators ordering: ordering) minimal. answer _ PolynomialSystem new. basis do: [:each | ((each degreeIn: y) = 0 and: [(tindets detect: [:one | (each degreeIn: one) > 0] ifNone: []) isNil]) ifTrue: [answer add: (each eq: each null)]]. ^ answer! ! !RationalParametrization methodsFor: 'accessing' stamp: 'pdm 4/20/98 22:39'! parameters | answer | answer _ Set new. self do: [:each | answer addAll: (each indeterminates select: [:any | (each numerator degreeIn: any) > 0 or: [(each numerator degreeIn: any) > 0]])]. ^ answer! ! !RationalParametrization methodsFor: 'accessing' stamp: 'pdm 3/22/98 19:22'! size ^ self contents size! ! !RationalParametrization methodsFor: 'arithmetic' stamp: 'pdm 4/19/98 23:46'! * anObject | answer | answer _ self class new. 1 to: self size do: [:each | answer add: (self at: each) * anObject]. ^ answer! ! !RationalParametrization methodsFor: 'arithmetic' stamp: 'pdm 4/19/98 23:46'! + aRationalParametrization | answer | answer _ self class new. 1 to: self size do: [:each | answer add: (self at: each) + (aRationalParametrization at: each)]. ^ answer! ! !RationalParametrization methodsFor: 'arithmetic' stamp: 'pdm 4/19/98 23:46'! - aRationalParametrization ^ self + aRationalParametrization negated! ! !RationalParametrization methodsFor: 'arithmetic' stamp: 'pdm 4/19/98 23:46'! / anObject ^ self * anObject reciprocal! ! !RationalParametrization methodsFor: 'arithmetic' stamp: 'pdm 4/19/98 23:47'! negated | answer | answer _ self class new. 1 to: self size do: [:each | answer add: (self at: each) negated]. ^ answer! ! !RationalParametrization methodsFor: 'enumerating' stamp: 'pdm 4/19/98 23:47'! do: aBlock self contents do: aBlock! ! !RationalParametrization methodsFor: 'copying' stamp: 'pdm 4/19/98 23:47'! copy | answer | answer _ self class new. self do: [:each | answer add: each]. ^ answer! ! !RationalParametrization methodsFor: 'private' stamp: 'pdm 4/19/98 23:48'! normalize | max indets | indets _ Set new. self do: [:each | indets addAll: each indeterminates]. indets _ indets asSortedCollection. max _ self size max: indets last. 1 to: indets size do: [:each | self rename: (indets at: each) to: max + each]! ! !RationalParametrization methodsFor: 'private' stamp: 'pdm 4/19/98 23:48'! rename: anInteger to: anotherInteger "Rename the anInteger-th indeterminate of the receiver to anotherInteger. " | xi | xi _ Polynomial x: anotherInteger. 1 to: self size do: [:each | self at: each put: ((self at: each) numerator valueAt: xi in: anInteger) / ((self at: each) denominator valueAt: xi in: anInteger)]! ! !RationalParametrization methodsFor: 'printing' stamp: 'pdm 3/22/98 19:35'! printOn: aStream "Print a representation of the receiver on the stream aStream." | first | first _ true. aStream nextPut: $(. 1 to: self size do: [:each | first ifFalse: [aStream nextPut: $,; space]. aStream print: (self at: each). first _ false]. aStream nextPut: $)! ! !RationalParametrization class methodsFor: 'instance creation' stamp: 'pdm 3/22/98 19:21'! new ^ super new initialize! ! !Tuple commentStamp: 'pdm 8/29/1998 19:46' prior: 0! My instances are tuples of any given finite dimension. For some examples try: Tuple fromArray: #(1 -2 3). Tuple with: 1 with: -2 with: 3. All the objects understand the message #, that is used to create tuples. For instance, writing (1, -2, 3) is equivalent to the preceding examples. Tuples understand addition, multiplication by an scalar and the cannonical (real) inner product. For an example try: | a b | a _ (1, 2, -1). b _ (5, -3, 0). a + b. a - b. a * 3. a * b. Furthermore, you can create 2-dim tuples pointing with the mouse a position in the screen. Try: Tuple fromUser. ! !Tuple methodsFor: 'initialization' stamp: 'len 10/22/97 03:10'! initialize: anInteger self contents: (Array new: anInteger)! ! !Tuple methodsFor: 'accessing-private' stamp: 'len 10/5/97 21:57'! contents ^ contents ! ! !Tuple methodsFor: 'accessing-private'! contents: anArray contents _ anArray ! ! !Tuple methodsFor: 'accessing' stamp: 'len 9/1/97 23:11'! at: anInteger "Answer the element of the receiver at the index anInteger." ^ self contents at: anInteger! ! !Tuple methodsFor: 'accessing' stamp: 'len 10/22/97 03:04'! at: anInteger put: anObject "Put anObject at the index anInteger in the receiver. Answer anObject." ^ self contents at: anInteger put: anObject! ! !Tuple methodsFor: 'accessing' stamp: 'len 9/1/97 23:08'! dimension "Answer the dimension of the receiver." ^ self contents size ! ! !Tuple methodsFor: 'accessing' stamp: 'len 12/13/97 04:52'! first "Answer the first entry of the receiver." ^ self at: 1! ! !Tuple methodsFor: 'accessing' stamp: 'len 1/17/98 13:58'! last "Answer the last entry of the receiver." ^ self at: self size! ! !Tuple methodsFor: 'accessing' stamp: 'len 10/5/97 21:51'! size "Answer the size of the receiver." ^ self dimension! ! !Tuple methodsFor: 'accessing' stamp: 'len 10/16/97 20:11'! x "Answer the x coordinate." ^ self at: 1! ! !Tuple methodsFor: 'accessing' stamp: 'len 10/16/97 20:11'! y "Answer the y coordinate." ^ self at: 2! ! !Tuple methodsFor: 'accessing' stamp: 'len 10/16/97 20:11'! z "Answer the z coordinate." ^ self at: 3! ! !Tuple methodsFor: 'arithmetic' stamp: 'len 12/3/97 03:43'! * anObject "Answer the product of the receiver by the argument." anObject isTuple ifTrue: [^ self halt]. "If the argument is not a tuple, I assume it is a constant." ^ self collect: [ :each | each * anObject]! ! !Tuple methodsFor: 'arithmetic' stamp: 'len 9/1/97 23:31'! + aVector "Answer the sum of the receiver and the argument." aVector dimension = self dimension ifFalse: [^ self errorDimensionNotMatch]. ^ self class dimension: self dimension fromBlock: [ :each | (self at: each) + (aVector at: each)]! ! !Tuple methodsFor: 'arithmetic' stamp: 'len 7/18/97 01:52'! - anObject "Answer the difference of the receiver and the argument." ^ self + anObject negated! ! !Tuple methodsFor: 'arithmetic' stamp: 'len 8/13/97 02:01'! / anObject "Answer the division of the receiver by the argument." ^ self * anObject reciprocal! ! !Tuple methodsFor: 'arithmetic' stamp: 'pdm 6/20/1998 19:38'! inner: aTuple "Answer the inner product of the receiver by the argument." ^ self scalar: aTuple! ! !Tuple methodsFor: 'arithmetic' stamp: 'len 10/5/97 21:52'! negated "Answer the additive inverse of the receiver." ^ self collect: [ :each | each negated]! ! !Tuple methodsFor: 'arithmetic' stamp: 'len 2/18/98 18:54'! scalar: aTuple "Answer the scalar product of the receiver by the argument." | answer | answer _ (self at: 1) * (aTuple at: 1). 2 to: self dimension do: [ :each | answer _ (self at: each) * (aTuple at: each) + answer]. ^ answer! ! !Tuple methodsFor: 'enumerating' stamp: 'len 10/5/97 21:53'! collect: aBlock "Answer a copy of the receiver with the coefficients mapped by aBlock." ^ self class dimension: self dimension fromBlock: [ :each | aBlock value: (self at: each)]! ! !Tuple methodsFor: 'enumerating' stamp: 'len 10/22/97 03:24'! do: aBlock "Enumerate the entries of the receiver." self contents do: aBlock! ! !Tuple methodsFor: 'operations' stamp: 'len 11/28/97 02:10'! distance2To: anObject "Answer the distance squared to the argument." ^ anObject isTuple ifTrue: [(self - anObject) norm2] ifFalse: [anObject distance2To: self]! ! !Tuple methodsFor: 'operations' stamp: 'len 11/28/97 02:10'! distanceTo: anObject "Answer the distance to the argument." ^ anObject isTuple ifTrue: [(self - anObject) norm] ifFalse: [anObject distanceTo: self]! ! !Tuple methodsFor: 'operations' stamp: 'len 1/25/98 01:31'! euclid "Answer a Tuple of coefficients such that the linear combination of those coefficients with the elements of the receiver equals the greatest common divisor of the receiver." | a null id s t sPrev tPrev b q r temp answer | self dimension = 0 ifTrue: [^ self]. a _ self at: 1. null _ self nullCoefficient. id _ self identityCoefficient. answer _ self class with: id. 2 to: self dimension do: [ :each | b _ self at: each. s _ id. t _ null. sPrev _ null. tPrev _ id. [b isNull] whileFalse: [q _ a // b. r _ a \\ b. temp _ s - (q * sPrev). s _ sPrev. sPrev _ temp. temp _ t - (q * tPrev). t _ tPrev. tPrev _ temp. a _ b. b _ r]. answer _ answer * s , t]. ^ answer! ! !Tuple methodsFor: 'operations' stamp: 'len 1/25/98 01:32'! gcd "Answer the gcd of the entries of the receiver." | answer | self dimension = 0 ifTrue: [^ self identityCoefficient]. self do: [ :each | answer _ answer isNil ifTrue: [each] ifFalse: [answer gcd: each]]. ^ answer! ! !Tuple methodsFor: 'operations' stamp: 'len 10/5/97 21:53'! mapCoefficients: aBlock "Answer a copy of the receiver with the coefficients mapped by aBlock." ^ self collect: aBlock! ! !Tuple methodsFor: 'operations' stamp: 'len 7/18/97 01:59'! norm "Answer the euclidean norm of the receiver." ^ self norm2 sqrt! ! !Tuple methodsFor: 'operations' stamp: 'len 12/3/97 03:21'! norm2 "Answer the square norm of the receiver." ^ self inner: self! ! !Tuple methodsFor: 'operations' stamp: 'len 12/12/97 20:52'! shift: anInteger "Answer the receiver shifted anInteger places." | n null | null _ self nullCoefficient. n _ self dimension. ^ self class dimension: n fromBlock: [ :each | (each - anInteger between: 1 and: n) ifTrue: [self at: each - anInteger] ifFalse: [null]]! ! !Tuple methodsFor: 'operations' stamp: 'len 10/5/97 21:53'! valueAt: anObject "Answer the result of evaluating the receiver at the argument." ^ self collect: [ :each | each valueAt: anObject]! ! !Tuple methodsFor: 'comparing' stamp: 'len 10/5/97 21:57'! = anObject "Answer true if the receiver equals the argument." ^ self class == anObject class and: [self contents = anObject contents]! ! !Tuple methodsFor: 'comparing' stamp: 'len 8/13/97 21:44'! hash "Answer the hash value of the receiver." ^ self contents hash! ! !Tuple methodsFor: 'testing' stamp: 'len 10/5/97 21:54'! isNull "Answer true if the reciver is null." self do: [ :each | each isNull ifFalse: [^false]]. ^ true! ! !Tuple methodsFor: 'testing' stamp: 'len 11/28/97 02:08'! isTuple "Answer true if the receiver is a Tuple." ^ true! ! !Tuple methodsFor: 'converting' stamp: 'len 11/20/97 01:51'! , anObject "Answer a new Vector appeding anObject to the receiver." ^ anObject class == self class ifTrue: [self class fromArray: self asArray, anObject asArray] ifFalse: [self class fromArray: (self asArray copyWith: anObject)]! ! !Tuple methodsFor: 'converting' stamp: 'len 10/5/97 21:56'! asArray "Answer an Array with the contents of the receiver." ^ self contents! ! !Tuple methodsFor: 'converting' stamp: 'len 2/9/98 18:03'! asEquation "Answer a LinearEquation with the coordinates of the receiver." ^ (self copyFrom: 1 to: self size - 1) asLinearForm eq: self last! ! !Tuple methodsFor: 'converting' stamp: 'len 10/16/97 00:38'! asPoint "Answer the Point with the same coordinates than the receiver. Raise an error if the receiver is not of dimension 2." self dimension = 2 ifFalse: [^ self error: 'not dimension 2']. ^ (self at: 1) @ (self at: 2)! ! !Tuple methodsFor: 'copying' stamp: 'len 11/27/97 01:32'! copy "Answer a copy of the receiver." ^ self class new contents: self contents copy! ! !Tuple methodsFor: 'copying' stamp: 'len 10/5/97 21:55'! copyFrom: anInteger to: anotherInteger "Answer a copy of the receiver from anInteger to anotherInteger." ^ self class fromArray: (self asArray copyFrom: anInteger to: anotherInteger)! ! !Tuple methodsFor: 'constants' stamp: 'len 8/22/97 20:06'! e: anInteger "Answer the anInteger-th canonical vector with the dimencion of the receiver." ^ self e: anInteger dimension: self dimension! ! !Tuple methodsFor: 'constants' stamp: 'len 8/21/97 00:12'! e: anInteger dimension: anotherInteger "Answer the anInteger-th canonical vector of dimencion anotherInteger." | null | null _ self nullCoefficient. ^ self class dimension: anotherInteger fromBlock: [ :each | each = anInteger ifTrue: [self identityCoefficient] ifFalse: [null]]! ! !Tuple methodsFor: 'constants' stamp: 'len 10/5/97 21:57'! identityCoefficient "Answer the identity coefficient for the receiver." self do: [ :each | each notNil ifTrue: [^ each identity]]. ^ self class identityCoefficient! ! !Tuple methodsFor: 'constants' stamp: 'len 8/22/97 20:35'! null "Answer the null vector with the dimension of the receiver." ^ self null: self dimension! ! !Tuple methodsFor: 'constants' stamp: 'len 9/1/97 23:32'! null: anInteger "Answer the null vector of dimension anInteger." | null | null _ self nullCoefficient. ^ self class dimension: anInteger fromBlock: [ :each | null]! ! !Tuple methodsFor: 'constants' stamp: 'len 10/5/97 21:57'! nullCoefficient "Answer the null coefficient for the receiver." self do: [ :each | each notNil ifTrue: [^ each null]]. ^ self class nullCoefficient! ! !Tuple methodsFor: 'private' stamp: 'len 8/13/97 21:47'! errorDimensionNotMatch self error: 'dimension not match'! ! !Tuple methodsFor: 'printing' stamp: 'len 10/5/97 22:18'! printOn: aStream "Print a representation of the receiver on the stream aStream." | first | first _ true. aStream nextPut: $(. self do: [ :each | first ifFalse: [aStream nextPut: $,; space]. aStream print: each. first _ false]. aStream nextPut: $)! ! !Tuple class methodsFor: 'instance creation' stamp: 'len 10/22/97 03:09'! dimension: anInteger ^ self new initialize: anInteger! ! !Tuple class methodsFor: 'instance creation' stamp: 'len 2/19/98 01:33'! dimension: anInteger e: anotherInteger scalars: anAlgebraicAmbient "Answer the anotherInteger-th canonic tuple of dimencion anInteger and with scalars of anAlgebraicAmbient." | null | null _ anAlgebraicAmbient null. ^ self dimension: anInteger fromBlock: [ :each | each = anotherInteger ifTrue: [anAlgebraicAmbient identity] ifFalse: [null]]! ! !Tuple class methodsFor: 'instance creation' stamp: 'len 5/28/1998 19:54'! dimension: anInteger fromBlock: aBlock ^ self fromArray: ((1 to: anInteger) collect: aBlock)! ! !Tuple class methodsFor: 'instance creation' stamp: 'len 2/21/98 23:09'! fromArray: anArray ^ self new contents: anArray! ! !Tuple class methodsFor: 'instance creation' stamp: 'len 10/16/97 20:10'! fromPoint: aPoint "Answer a new instance of the receiver representing the 2-dim vector with the same coordinates that the argument has." ^ self with: aPoint x with: aPoint y! ! !Tuple class methodsFor: 'instance creation' stamp: 'len 9/1/97 23:32'! null: anInteger "Answer the null vector of dimension anInteger." | null | null _ self nullCoefficient. ^ self dimension: anInteger fromBlock: [ :each | null]! ! !Tuple class methodsFor: 'instance creation' stamp: 'len 7/18/97 01:37'! with: anElement ^ self fromArray: (Array with: anElement)! ! !Tuple class methodsFor: 'instance creation' stamp: 'len 7/18/97 01:37'! with: anElement with: otherElement ^ self fromArray: (Array with: anElement with: otherElement)! ! !Tuple class methodsFor: 'instance creation' stamp: 'len 7/18/97 01:38'! with: anElement with: otherElement with: thirthElement ^ self fromArray: (Array with: anElement with: otherElement with: thirthElement)! ! !Tuple class methodsFor: 'instance creation' stamp: 'len 11/7/97 01:38'! x: x y: y "Answer a new instance of the receiver with the given coordinates." ^ self with: x with: y! ! !Tuple class methodsFor: 'instance creation' stamp: 'len 11/7/97 01:38'! x: x y: y z: z "Answer a new instance of the receiver with the given coordinates." ^ self with: x with: y with: z! ! !Tuple class methodsFor: 'constants' stamp: 'len 8/30/97 01:05'! identityCoefficient ^ 1! ! !Tuple class methodsFor: 'constants' stamp: 'len 8/30/97 01:05'! nullCoefficient ^ 0! ! !Tuple class methodsFor: 'examples' stamp: 'len 11/28/97 02:13'! fromUser "Let the user select a 2-dim Tuple from the screen with the mouse." | dot point answer | dot _ Form dotOfSize: 4. Cursor crossHair showWhile: [Sensor waitButton. point _ Sensor waitNoButton]. dot displayOn: Display at: point clippingBox: Display boundingBox rule: Form oldPaint fillColor: Color black. answer _ self fromPoint: point. answer printString asParagraph form displayOn: Display at: point clippingBox: Display boundingBox rule: Form oldPaint fillColor: Color black. ^ answer! !