Skip to content

Commit

Permalink
Merge pull request #322 from PolyMathOrg/refactor-polynomials-tests
Browse files Browse the repository at this point in the history
Refactor Polynomials: Extract Method to Introduce RootFinder Factory Method and Tighten Encapsulation
  • Loading branch information
Ducasse authored Dec 25, 2023
2 parents d9a495e + 6de9e74 commit 761fb9a
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 16 deletions.
9 changes: 9 additions & 0 deletions src/Math-Numerical/PMNewtonZeroFinder.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ PMNewtonZeroFinder class >> function: aBlock1 derivative: aBlock2 [
^(self new) setFunction: aBlock1; setDerivative: aBlock2; yourself
]

{ #category : #information }
PMNewtonZeroFinder class >> with: precision [

| rootFinder |
rootFinder := self new.
rootFinder desiredPrecision: precision.
^ rootFinder
]

{ #category : #operation }
PMNewtonZeroFinder >> computeInitialValues [
"Private - If no derivative has been defined, take an ad-hoc definition.
Expand Down
30 changes: 15 additions & 15 deletions src/Math-Polynomials/PMPolynomial.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -233,27 +233,27 @@ PMPolynomial >> reciprocal [

{ #category : #information }
PMPolynomial >> roots [

^ self roots: Float defaultComparisonPrecision
^ (self roots: Float defaultComparisonPrecision) asSortedCollection asArray
]

{ #category : #information }
PMPolynomial >> roots: aNumber [

| pol roots x rootFinder |
rootFinder := PMNewtonZeroFinder new.
rootFinder desiredPrecision: aNumber.
pol := self class coefficients: ( coefficients reverse collect: [ :each | each asFloat]).
| pol roots root rootFinder |
rootFinder := PMNewtonZeroFinder with: aNumber.
pol := self class coefficients:
(coefficients reverse collect: [ :each | each asFloat ]).
roots := OrderedCollection new: self degree.
[ rootFinder setFunction: pol; setDerivative: pol derivative.
x := rootFinder evaluate.
rootFinder hasConverged
] whileTrue: [ roots add: x.
pol := pol deflatedAt: x.
pol degree > 0
ifFalse: [ ^roots].
].
^roots
[
rootFinder
setFunction: pol;
setDerivative: pol derivative.
root := rootFinder evaluate.
rootFinder hasConverged ] whileTrue: [
roots add: root.
pol := pol deflatedAt: root.
pol degree > 0 ifFalse: [ ^ roots ] ].
^ roots
]

{ #category : #'double dispatching' }
Expand Down
36 changes: 35 additions & 1 deletion src/Math-Tests-Polynomials/PMPolynomialTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,36 @@ PMPolynomialTest >> testPolynomialRoots [

| polynomial roots |
polynomial := PMPolynomial coefficients: #( -10 -13 -2 1 ).
roots := polynomial roots asSortedCollection asArray.
roots := polynomial roots .
self assert: roots size equals: 3.
self assert: (roots at: 1) + 2 closeTo: 0.
self assert: (roots at: 2) + 1 closeTo: 0.
self assert: (roots at: 3) - 5 closeTo: 0
]

{ #category : #'iterative algorithms' }
PMPolynomialTest >> testPolynomialRootsConstantsHaveNoRoots [

| constant |
"Here, compute the roots of the constant C = 1"
constant := PMPolynomial coefficients: #( 1 ).
self
should: [ constant roots ]
raise: Error
description: 'Function''s derivative seems to be zero everywhere'
]

{ #category : #'iterative algorithms' }
PMPolynomialTest >> testPolynomialRootsForLinear [

| linearPolynomial roots |
"Here, compute the roots of the linear (2x + 1)"
linearPolynomial := PMPolynomial coefficients: #( 1 2 ).
roots := linearPolynomial roots.
self assert: roots size equals: 1.
self assert: (roots at: 1) closeTo: -0.5
]

{ #category : #'function evaluation' }
PMPolynomialTest >> testPolynomialSubtraction [
| polynomial |
Expand All @@ -253,3 +276,14 @@ PMPolynomialTest >> testPolynomialSubtraction [
self assert: (polynomial at: 3) equals: -1.
self assert: (polynomial at: 4) equals: 0
]

{ #category : #'iterative algorithms' }
PMPolynomialTest >> testPolynomialWithRepeatedRoots [
| polynomialWithRepeatedRoots roots |
"Here, compute the roots of the quadratic (2x + 1)^2 = 4 x^2 + 4 x + 1"
polynomialWithRepeatedRoots := PMPolynomial coefficients: #(1 4 4).
roots := polynomialWithRepeatedRoots roots .
self assert: roots size equals: 2.
self assert: (roots at: 1) closeTo: -0.5 .
self assert: (roots at: 2) closeTo: -0.5 .
]

0 comments on commit 761fb9a

Please sign in to comment.