Skip to content

Commit bcd2bd8

Browse files
author
Hernán Morales Durand
committed
Modified with changes proposed in #184 (comment) (inverseBinomialCoefficient)
1 parent 2e5da94 commit bcd2bd8

File tree

2 files changed

+40
-83
lines changed

2 files changed

+40
-83
lines changed

src/Math-Numerical/Integer.extension.st

Lines changed: 30 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,41 @@
11
Extension { #name : #Integer }
22

33
{ #category : #'*Math-Numerical' }
4-
Integer >> findNK [
5-
" Reverse binomial coefficient. Answer a <Collection> with all n and k such that n take: k = self. Elements in the answered Collection should be read as paired. Each pair represents (n,k) in the binomial coefficient formula.
6-
See https://math.stackexchange.com/a/103385/205 for details. "
7-
8-
| k |
9-
[ self > 1 ] assert.
10-
k := 0.
11-
^ Array streamContents: [ : stream |
12-
[ true ] whileTrue: [
13-
| nmin nmax choose |
14-
k := k + 1.
15-
((2 * k + 1) * self) <= (4 ** k)
16-
ifTrue: [ ^ stream contents ].
17-
nmin := k firstOver: (k factorial * self).
18-
nmax := nmin + k + 1.
19-
nmin := nmin max: (2 * k).
20-
choose := nmin asInteger take: k.
21-
nmin to: nmax do: [ : n |
22-
choose = self
23-
ifTrue: [
24-
stream nextPutAll: { n asInteger . k asInteger }.
25-
k < (n - k)
26-
ifTrue: [ stream nextPutAll: { n asInteger . (n - k) asInteger } ] ].
27-
choose := choose * (n + 1).
28-
choose := (choose / (n + 1 - k)) ceiling ] ] ]
29-
4+
Integer >> gamma [
5+
self > 0
6+
ifFalse: [^ self error: 'Attempt to compute the Gamma function of a non-positive integer'].
7+
^ (self - 1) factorial.
308
]
319

3210
{ #category : #'*Math-Numerical' }
33-
Integer >> firstOver: c [
34-
" Binary search to find smallest value of n for which n ** self >= c "
35-
| n lo hi mid |
36-
37-
n := 1.
38-
[ (n ** self) < c ] whileTrue: [ n := n * 2 ].
39-
lo := 1.
40-
hi := n.
41-
[ (hi - lo) > 1 ] whileTrue: [
42-
mid := lo + ((hi - lo) / 2) ceiling.
43-
(mid ** self) < c
44-
ifTrue: [ lo := mid ]
45-
ifFalse: [ hi := mid ] ].
46-
[ (hi ** self) >= c ] assert.
47-
[ ((hi - 1) ** self) < c ] assert.
48-
^ hi
11+
Integer >> inverseBinomialCoefficient [
4912

50-
]
13+
" Reverse binomial coefficient. Answer a <Collection> with all n and k such that n take: k = self. Elements in the answered Collection should be read as paired. Each pair represents (n,k) in the binomial coefficient formula.
14+
See https://math.stackexchange.com/a/103385/205 for details. "
5115

52-
{ #category : #'*Math-Numerical' }
53-
Integer >> gamma [
54-
self > 0
55-
ifFalse: [^ self error: 'Attempt to compute the Gamma function of a non-positive integer'].
56-
^ (self - 1) factorial.
16+
| k |
17+
[ self > 1 ] assert.
18+
k := 0.
19+
^ Array streamContents: [ :stream |
20+
[ true ] whileTrue: [
21+
| nmin nmax choose |
22+
k := k + 1.
23+
2 * k + 1 * self <= (4 ** k) ifTrue: [ ^ stream contents ].
24+
nmin := ((k factorial * self) nthRoot: k) ceiling.
25+
nmax := nmin + k + 1.
26+
nmin := nmin max: 2 * k.
27+
choose := nmin asInteger numberOfCombinationsTaken: k.
28+
nmin to: nmax do: [ :n |
29+
choose = self ifTrue: [
30+
stream nextPutAll: {
31+
n asInteger.
32+
k asInteger }.
33+
k < (n - k) ifTrue: [
34+
stream nextPutAll: {
35+
n asInteger.
36+
(n - k) asInteger } ] ].
37+
choose := choose * (n + 1).
38+
choose := (choose / (n + 1 - k)) ceiling ] ] ]
5739
]
5840

5941
{ #category : #'*Math-Numerical' }

src/Math-Tests-Numerical/IntegerTest.extension.st

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,15 @@ Extension { #name : #IntegerTest }
33
{ #category : #'*Math-Tests-Numerical' }
44
IntegerTest >> testFindNK [
55

6-
self assert: 6 findNK equals: #(6 1 6 5 4 2).
7-
self assert: 10 findNK equals: #(10 1 10 9 5 2 5 3).
8-
self assert: 20 findNK equals: #(20 1 20 19 6 3).
9-
self assert: 21 findNK equals: #(21 1 21 20 7 2 7 5).
10-
self assert: 55 findNK equals: #(55 1 55 54 11 2 11 9).
11-
self assert: 120 findNK equals: #(120 1 120 119 16 2 16 14 10 3 10 7).
12-
self assert: 3003 findNK equals: #(3003 1 3003 3002 78 2 78 76 15 5 15 10 14 6 14 8).
13-
self assert: 8966473191018617158916954970192684 findNK equals: #(8966473191018617158916954970192684 1 8966473191018617158916954970192684 8966473191018617158916954970192683 123 45 123 78).
14-
self assert: 116682544286207712305570174244760883486876241791210077037133735047856714594324355733933738740204795317223528882568337264611289789138133946725471443924278812277695432803500115699090641248357468388106131543801393801287657125117557432072695477147403395443757359171876874010770591355653882772562301453205472707597435095925666815012707478996454360460481159339802667334477440 findNK equals: #(116682544286207712305570174244760883486876241791210077037133735047856714594324355733933738740204795317223528882568337264611289789138133946725471443924278812277695432803500115699090641248357468388106131543801393801287657125117557432072695477147403395443757359171876874010770591355653882772562301453205472707597435095925666815012707478996454360460481159339802667334477440 1 116682544286207712305570174244760883486876241791210077037133735047856714594324355733933738740204795317223528882568337264611289789138133946725471443924278812277695432803500115699090641248357468388106131543801393801287657125117557432072695477147403395443757359171876874010770591355653882772562301453205472707597435095925666815012707478996454360460481159339802667334477440 116682544286207712305570174244760883486876241791210077037133735047856714594324355733933738740204795317223528882568337264611289789138133946725471443924278812277695432803500115699090641248357468388106131543801393801287657125117557432072695477147403395443757359171876874010770591355653882772562301453205472707597435095925666815012707478996454360460481159339802667334477439 1234 567 1234 667).
15-
self should: [ 1 findNK ] raise: Error.
16-
self should: [ 0 findNK ] raise: Error.
17-
]
18-
19-
{ #category : #'*Math-Tests-Numerical' }
20-
IntegerTest >> testFirstOver [
21-
22-
self assert: (2 firstOver: 3) equals: 2.
23-
self assert: (2 firstOver: 4) equals: 2.
24-
self assert: (2 firstOver: 5) equals: 3.
25-
self assert: (2 firstOver: 6) equals: 3.
26-
27-
self assert: (3 firstOver: 3) equals: 2.
28-
self assert: (3 firstOver: 4) equals: 2.
29-
self assert: (3 firstOver: 5) equals: 2.
30-
self assert: (3 firstOver: 6) equals: 2.
31-
32-
self assert: (4 firstOver: 2) equals: 2.
33-
self assert: (4 firstOver: 3) equals: 2.
34-
self assert: (4 firstOver: 4) equals: 2.
35-
self assert: (4 firstOver: 5) equals: 2.
36-
37-
self assert: (4 firstOver: "SmallInteger maxVal"1152921504606846975) equals: 32768.
38-
self assert: (3 firstOver: 1152921504606846975) equals: 1048576.
39-
self assert: (2 firstOver: 1152921504606846975) equals: 1073741824.
40-
self assert: (1 firstOver: 1152921504606846975) equals: 1152921504606846975.
6+
self assert: 6 inverseBinomialCoefficient equals: #(6 1 6 5 4 2).
7+
self assert: 10 inverseBinomialCoefficient equals: #(10 1 10 9 5 2 5 3).
8+
self assert: 20 inverseBinomialCoefficient equals: #(20 1 20 19 6 3).
9+
self assert: 21 inverseBinomialCoefficient equals: #(21 1 21 20 7 2 7 5).
10+
self assert: 55 inverseBinomialCoefficient equals: #(55 1 55 54 11 2 11 9).
11+
self assert: 120 inverseBinomialCoefficient equals: #(120 1 120 119 16 2 16 14 10 3 10 7).
12+
self assert: 3003 inverseBinomialCoefficient equals: #(3003 1 3003 3002 78 2 78 76 15 5 15 10 14 6 14 8).
13+
self assert: 8966473191018617158916954970192684 inverseBinomialCoefficient equals: #(8966473191018617158916954970192684 1 8966473191018617158916954970192684 8966473191018617158916954970192683 123 45 123 78).
4114

15+
self should: [ 1 inverseBinomialCoefficient ] raise: Error.
16+
self should: [ 0 inverseBinomialCoefficient ] raise: Error.
4217
]

0 commit comments

Comments
 (0)