Skip to content

Commit 4cd4776

Browse files
Merge pull request #74 from PolyMathOrg/development
Release v0.102
2 parents 0af624f + f49c36c commit 4cd4776

File tree

10 files changed

+654
-26
lines changed

10 files changed

+654
-26
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Metacello new
1414
load
1515
```
1616

17-
We have **744** green tests !
17+
We have **767** green tests !
1818

1919
PolyMath is a Smalltalk project, similar to existing scientific libraries like NumPy, SciPy for Python or SciRuby for Ruby. PolyMath already provide the following basic functionalities:
2020
- complex and quaternions extensions,

src/BaselineOfPolyMath/BaselineOfPolyMath.class.st

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ BaselineOfPolyMath >> baseline: spec [
5353
package: 'Math-Matrix';
5454
package: 'Math-Number-Extensions';
5555
package: 'Math-ODE' with: [ spec requires: #('Math-DHB-Numerical' 'Math-Matrix' 'Math-Polynomials') ];
56+
package: 'Math-Permutation' with:[ spec requires: #('Math-Core' 'Math-Matrix' 'Math-Core-Process') ];
5657
package: 'Math-Physics-Constants';
5758
package: 'Math-PrincipalComponentAnalysis' with: [ spec requires: #('Math-DHB-Numerical' 'Math-Matrix' 'Math-Polynomials') ];
5859
package: 'Math-Quantile';
@@ -86,7 +87,7 @@ BaselineOfPolyMath >> baseline: spec [
8687
group: 'Accuracy' with: #('Math-Accuracy-ODE' 'Math-Accuracy-Core');
8788
group: 'Benchmarks' with: #('Math-Benchmarks-ODE' 'Math-Benchmarks-KDTree');
8889
group: 'Core' with: #('Math-Complex' 'Math-Quaternion' 'Math-DHB-Numerical' 'Math-Random' 'Math-KDTree' 'Math-ODE' 'Math-ArbitraryPrecisionFloat' 'Math-FastFourierTransform' 'ExtendedNumberParser' 'Math-Quantile' 'Math-Physics-Constants' 'Math-Polynomials' 'Math-TSNE');
89-
group: 'Extensions' with: #('Math-Clustering' 'Math-Number-Extensions' 'Math-Chromosome' 'Math-PrincipalComponentAnalysis' 'Math-FunctionFit' 'Math-AutomaticDifferenciation' 'Math-KernelSmoothing' 'Math-RandomDistributionBased' 'Math-KolmogorovSmirnov');
90+
group: 'Extensions' with: #('Math-Clustering' 'Math-Number-Extensions' 'Math-Chromosome' 'Math-PrincipalComponentAnalysis' 'Math-FunctionFit' 'Math-AutomaticDifferenciation' 'Math-KernelSmoothing' 'Math-Permutation' 'Math-RandomDistributionBased' 'Math-KolmogorovSmirnov');
9091
group: 'Tests' with: #('Math-Tests-Matrix' 'Math-Tests-Clustering' 'Math-Tests-DHB-Numerical' 'Math-Tests-Complex' 'Math-Tests-Quaternion' 'Math-Tests-Random' 'Math-Tests-ODE' 'Math-Tests-KDTree' 'Math-Tests-DHB-wk' 'Math-Tests-FunctionFit' 'Math-Tests-AutomaticDifferenciation' 'Math-Tests-FastFourierTransform' 'Math-Tests-Accuracy' 'Math-Tests-ArbitraryPrecisionFloat' 'Math-Tests-KolmogorovSmirnov' 'Math-Tests-Quantile' 'Math-Tests-Polynomials');
9192
group: 'default' with: #('Core' 'Extensions' 'Tests' 'Benchmarks' 'Accuracy') ]
9293
]

src/Math-Complex/PMComplex.class.st

+5
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,11 @@ PMComplex >> sign [
650650
^ real sign
651651
]
652652

653+
{ #category : #testing }
654+
PMComplex >> signBit [
655+
^self real signBit
656+
]
657+
653658
{ #category : #'mathematical functions' }
654659
PMComplex >> sin [
655660
"Answer receiver's sine."

src/Math-Complex/PMComplex.extension.st

+7-7
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ PMComplex >> productWithVector: aVector [
1717
^ aVector collect: [ :each | each * self ]
1818
]
1919

20+
{ #category : #'*Math-Complex' }
21+
PMComplex class >> random [
22+
"Answers a random number with abs between 0 and 1."
23+
24+
^ self abs: 1.0 random arg: 2 * Float pi random
25+
]
26+
2027
{ #category : #'*Math-Complex' }
2128
PMComplex >> random [
2229
"analog to Number>>random. However, the only bound is that the abs of the produced complex is less than the length of the receive. The receiver effectively defines a disc within which the random element can be produced."
2330
^ self class random * self
2431

2532
]
2633

27-
{ #category : #'*Math-Complex' }
28-
PMComplex classSide >> random [
29-
"Answers a random number with abs between 0 and 1."
30-
31-
^ self abs: 1.0 random arg: 2 * Float pi random
32-
]
33-
3434
{ #category : #'*Math-Complex' }
3535
PMComplex >> subtractToPolynomial: aPolynomial [
3636
^ aPolynomial addNumber: self negated
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"
2+
I store metadata for this package. These meta data are used by other tools such as the SmalllintManifestChecker and the critics Browser
3+
"
4+
Class {
5+
#name : #ManifestMathPermutation,
6+
#superclass : #PackageManifest,
7+
#category : #'Math-Permutation'
8+
}
9+
10+
{ #category : #'code-critics' }
11+
ManifestMathPermutation class >> ruleRBCollectionProtocolRuleV1FalsePositive [
12+
^ #(#(#(#RGMethodDefinition #(#'Permutation class' #generator: #true)) #'2018-07-07T11:52:50.239421+02:00') )
13+
]
14+
15+
{ #category : #'code-critics' }
16+
ManifestMathPermutation class >> ruleRBModifiesCollectionRuleV1FalsePositive [
17+
^ #(#(#(#RGMethodDefinition #(#'Permutation class' #generator: #true)) #'2018-07-07T11:52:46.085547+02:00') )
18+
]
19+
20+
{ #category : #'code-critics' }
21+
ManifestMathPermutation class >> ruleRBSendsDifferentSuperRuleV1FalsePositive [
22+
^ #(#(#(#RGMetaclassDefinition #(#'Permutation class' #PMPermutation)) #'2018-07-07T11:53:26.042043+02:00') )
23+
]
24+
25+
{ #category : #'code-critics' }
26+
ManifestMathPermutation class >> ruleRBSuperSendsRuleV1FalsePositive [
27+
^ #(#(#(#RGMetaclassDefinition #(#'Permutation class' #PMPermutation)) #'2018-07-07T11:53:19.542428+02:00') )
28+
]
29+
30+
{ #category : #'code-critics' }
31+
ManifestMathPermutation class >> ruleRBTempsReadBeforeWrittenRuleV1FalsePositive [
32+
^ #(#(#(#RGMethodDefinition #(#'Permutation class' #stirling1:over: #true)) #'2018-07-07T11:54:16.87423+02:00') )
33+
]
34+
35+
{ #category : #'code-critics' }
36+
ManifestMathPermutation class >> ruleRBToDoRuleV1FalsePositive [
37+
^ #(#(#(#RGMetaclassDefinition #(#'Permutation class' #PMPermutation)) #'2018-07-07T11:54:04.307575+02:00') )
38+
]
+256
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
"
2+
Permutation is an Array, that - if it's reduced - consists of the numbers from (1 to: self size) in the original order.
3+
example:
4+
Permutation ordering: #(5 4 1). -> a Permutation(3 2 1)
5+
6+
you can think of a permutation as a positioning specification for a SequentialCollection.
7+
another example:
8+
a:=Permutation randomPermutation: 4. -> a Permutation(1 4 2 3)
9+
a permute: #(a b cd e). -> #(#a #e #b #cd)
10+
yet another one:
11+
Permutation ordering: #(a e b cd). ""a Permutation(1 4 2 3)""
12+
13+
14+
"
15+
Class {
16+
#name : #PMPermutation,
17+
#superclass : #Array,
18+
#type : #variable,
19+
#classVars : [
20+
'RandomGenerator'
21+
],
22+
#category : #'Math-Permutation'
23+
}
24+
25+
{ #category : #accessing }
26+
PMPermutation class >> allOfSize: anInteger [
27+
"generates all permutations of the given size, in other words it produces the symmetric group of degree anInteger.
28+
Heap's algorithm, used here, seems to be just a tiny bit faster than using #permutationsDo:"
29+
| result perm c i ci|
30+
anInteger = 0 ifTrue:[^#()].
31+
perm := self identity: anInteger.
32+
(result := WriteStream on:(Array new: anInteger factorial)) nextPut: perm copy.
33+
c := Array new: anInteger withAll: 1.
34+
i := 1.
35+
[ i <= anInteger ]
36+
whileTrue: [
37+
(ci :=(c at: i)) < i
38+
ifTrue: [
39+
i odd
40+
ifTrue: [ perm swap: 1 with: i ]
41+
ifFalse: [ perm swap: ci with: i ].
42+
result nextPut: perm copy.
43+
c at: i put: ci + 1.
44+
i := 1 ]
45+
ifFalse: [ c at: i put: 1. i := i + 1 ] ].
46+
^ result contents
47+
]
48+
49+
{ #category : #'instance creation' }
50+
PMPermutation class >> fromCycles: aCollectionofCollections [
51+
| length |
52+
length := aCollectionofCollections flattened.
53+
length := length isEmpty
54+
ifTrue: [ 0 ]
55+
ifFalse: [ length max ].
56+
^ self size: length fromCycles: aCollectionofCollections
57+
]
58+
59+
{ #category : #accessing }
60+
PMPermutation class >> generator:arrayOfPermutations [
61+
|f max generators|
62+
max:=(arrayOfPermutations collect:[:g|g size])max.
63+
generators:=arrayOfPermutations collect:[:g| g extendTo: max].
64+
f:=PMFixpoint
65+
block: [ :s| |aSet|
66+
aSet:=Set newFrom: s.
67+
s do:[:p|s do:[:q|
68+
aSet add:(p permute:q)]].
69+
aSet]
70+
value: generators.
71+
f verbose:false.
72+
^f evaluate asArray.
73+
74+
]
75+
76+
{ #category : #'instance creation' }
77+
PMPermutation class >> identity: size [
78+
^ super withAll: (1 to: size)
79+
]
80+
81+
{ #category : #'instance creation' }
82+
PMPermutation class >> newFrom: aCollection [
83+
"returns the unreduced form, for a reduced form use #ordering:.
84+
uses super withAll: since this way a primitive can be used, which is generally much faster than super newFrom:"
85+
^( super withAll: aCollection )
86+
]
87+
88+
{ #category : #'instance creation' }
89+
PMPermutation class >> ordering: aCollection [
90+
"use #newFrom: for an unreduced Permutation! but then most things won't work before you call #reduce.
91+
aCollection must consist of elements that can be sorted via #<="
92+
^( super withAll: aCollection ) reduce
93+
]
94+
95+
{ #category : #accessing }
96+
PMPermutation class >> randomGenerator [
97+
^RandomGenerator ifNil: [ RandomGenerator := Random new ]
98+
]
99+
100+
{ #category : #'instance creation' }
101+
PMPermutation class >> randomPermutation: size [
102+
^self ordering: (self randomGenerator next:size)
103+
]
104+
105+
{ #category : #'instance creation' }
106+
PMPermutation class >> size: anInteger fromCycles: aCollectionofCollections [
107+
| result |
108+
result := self identity: anInteger.
109+
aCollectionofCollections do: [ :cycle |
110+
1 to: cycle size do: [ :i |
111+
result at: (cycle at: i) put: (cycle atWrap: i + 1) ] ].
112+
^ result
113+
]
114+
115+
{ #category : #'instance creation' }
116+
PMPermutation class >> size: size shift: aNumber [
117+
"number positive -> leftshift, negative -> rightshift"
118+
^ (super withAll: (1 to: size) )shift: aNumber
119+
]
120+
121+
{ #category : #accessing }
122+
PMPermutation class >> stirling1:anInteger over:anotherInteger [
123+
"unsigned Stirling number of the first kind: the number of permutations of size anInteger with anotherInteger number of cycles"
124+
|block|
125+
block:=[:nandk||n k|
126+
n:=nandk first.
127+
k:=nandk second.
128+
(n=k and:[n isZero])
129+
ifTrue:[1]
130+
ifFalse:[ (n * k) isZero
131+
ifTrue:[0]
132+
ifFalse:[ (block value:{n-1.k-1})+((n-1)*(block value:{n-1.k}))]]]memoized .
133+
^block value:{anInteger . anotherInteger }
134+
]
135+
136+
{ #category : #converting }
137+
PMPermutation >> asCycles [
138+
| unused start next result cycle |
139+
unused := (1 to: self size) asOrderedCollection.
140+
result := OrderedCollection new.
141+
[ unused isEmpty ]
142+
whileFalse: [
143+
next := start := unused first.
144+
cycle := OrderedCollection new.
145+
[ cycle add: (unused remove: next).
146+
next := self at: next ] doWhileFalse: [ next = start ].
147+
result add: cycle asArray ].
148+
^ result asArray
149+
]
150+
151+
{ #category : #converting }
152+
PMPermutation >> asMatrix [
153+
^ PMMatrix
154+
rows:
155+
(self asPMVector
156+
collect: [ :n |
157+
(PMVector new: self size)
158+
atAllPut: 0;
159+
at: n put: 1;
160+
yourself ])
161+
]
162+
163+
{ #category : #applying }
164+
PMPermutation >> discriminant [
165+
^self size - self asCycles size
166+
]
167+
168+
{ #category : #testing }
169+
PMPermutation >> even [
170+
^self odd not
171+
]
172+
173+
{ #category : #applying }
174+
PMPermutation >> extendTo: size [
175+
| c |
176+
size=self size ifTrue: [ ^self copy ].
177+
c := self class identity: size.
178+
c
179+
replaceFrom: 1
180+
to: self size
181+
with: self
182+
startingAt: 1.
183+
^ c
184+
]
185+
186+
{ #category : #applying }
187+
PMPermutation >> inverse [
188+
|c|
189+
c:=self class new:self size.
190+
1 to: self size do: [:i | c at: i put: (self indexOf: i)].
191+
^c
192+
]
193+
194+
{ #category : #testing }
195+
PMPermutation >> isCollection [
196+
"pffh, i found this useful, but i dont remember anymore why."
197+
^ false
198+
]
199+
200+
{ #category : #testing }
201+
PMPermutation >> odd [
202+
"using the number of transpositions is faster than using the number of inversions"
203+
^self discriminant odd.
204+
]
205+
206+
{ #category : #applying }
207+
PMPermutation >> permute: aSequentialCollection [
208+
| s c |
209+
(s := aSequentialCollection size) < self size
210+
ifTrue: [ aSequentialCollection class==self class
211+
ifTrue: [ ^ self permute: (aSequentialCollection extendTo: self size) ]
212+
ifFalse: [ ^ SizeMismatch signal ] ].
213+
c := aSequentialCollection copy.
214+
1 to: self size do: [ :i | c at: i put: (aSequentialCollection at: (self at: i)) ].
215+
^ c
216+
]
217+
218+
{ #category : #private }
219+
PMPermutation >> reduce [
220+
"automatically used only in #withAll: so far"
221+
| sorted range |
222+
(sorted := self sorted) = (range := 1 to: self size)
223+
ifTrue: [ ^ self ].
224+
self size = self asSet size
225+
ifFalse: [ ^ self error: 'Permutation has doubles' ].
226+
range do: [ :n | self at: n put: (sorted indexOf: (self at: n)) ]
227+
]
228+
229+
{ #category : #converting }
230+
PMPermutation >> reversed [
231+
"copy of SequenceableCollection>>reversed, but uses class instead of species."
232+
| n result src |
233+
n := self size.
234+
result := self class new: n.
235+
src := n + 1.
236+
1 to: n do: [:i | result at: i put: (self at: (src := src - 1))].
237+
^ result
238+
]
239+
240+
{ #category : #converting }
241+
PMPermutation >> shift: anInteger [
242+
"number positive -> leftshift, negative -> rightshift.
243+
does _not_ return a new Permutation!"
244+
| n c |
245+
self ifEmpty: [ ^ self ].
246+
n := anInteger \\ self size.
247+
c := self copy.
248+
self
249+
replaceFrom: 1 to: self size - n with: c startingAt: n + 1;
250+
replaceFrom: self size - n + 1 to: self size with: c startingAt: 1
251+
]
252+
253+
{ #category : #private }
254+
PMPermutation >> species [
255+
^ Array
256+
]

0 commit comments

Comments
 (0)