 ## [squeak-dev] Exact #sqrt

Juan Vuletich juan at jvuletich.org
Fri Oct 14 11:07:13 UTC 2011

```Nicolas Cellier wrote:
> You might also want another way to quickly discriminate non square
> large integers
>
> http://en.wikipedia.org/wiki/Square_number
>
> if (n & 7 == 1) or (n & 31 == 4) or (n & 127 == 16) or (n & 191 == 0) then
>     return n is probably square
> else
>     return n is definitely not square
>
> LargePositiveInteger>>canBeASquare
>     | lsb |
>     lsb := self digitAt: 1.
>     ^((lsb bitAnd: 7) = 1
>         or: [(lsb bitAnd: 31) = 4
>         or: [(lsb bitAnd: 127) = 16
>         or: [(lsb bitAnd: 191) = 0]]])
>
> Nicolas
>
> 2011/10/13 Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com>:
>
>> This can cause an overflow...
>>
>> ((1 << 1024 + 1) / (1 << 1024 + 3)) sqrt
>>
>> I'd expect 1.0 (inexact, but not that much).
>>

Thanks, Nicolas. This new version addresses all the issues you raised.

Cheers,
Juan Vuletich
-------------- next part --------------
'From Cuis 3.3 of 2 June 2011 [latest update: #1024] on 14 October 2011 at 7:57:15 am'!

!FloatTest methodsFor: 'testing' stamp: 'jmv 10/11/2011 08:55'!
testMaxExactInteger
"
FloatTest new testMaxExactInteger
"

self assert: Float maxExactInteger asFloat truncated = Float maxExactInteger.
0 to: 10000 do: [ :j |
self assert: (Float maxExactInteger-j) asFloat truncated = (Float maxExactInteger-j) ].
self deny: (Float maxExactInteger+1) asFloat truncated = (Float maxExactInteger+1)
! !

!FloatTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/13/2011 09:06'!
testNthRoot
"
FloatTest new testNthRoot
"
self should: [ -1.23 nthRoot: 4 ] raise: ArithmeticError! !

!FloatTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/13/2011 09:06'!
testRaisedTo
"
FloatTest new testRaisedTo
"
self should: [ -1.23 raisedTo: 1/4 ] raise: ArithmeticError! !

!FractionTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/11/2011 22:27'!
testExactRaisedTo
"
FractionTest new testExactRaisedTo
"
| f |
self assert: (4/9 raisedTo: 1/2) classAndValueEquals: 2/3.
self assert: (9/4 raisedTo: 1/2) classAndValueEquals: 3/2.
#( 1 5 29 135 1234 567890 123123123 456456456456 98765432109876543210987654321 987123987123987123987123987123987123987123987123) pairsDo: [ :a :b |
f _ a / b.
self assert: (f squared raisedTo: 1/2) classAndValueEquals: f.
self assert: (f negated squared raisedTo: 1/2) classAndValueEquals: f.
f _ b / a.
self assert: (f squared raisedTo: 1/2) classAndValueEquals: f.
self assert: (f negated squared raisedTo: 1/2) classAndValueEquals: f ].

self assert: (8/27 raisedTo: 1/3) classAndValueEquals: 2/3.
self assert: (27/8 raisedTo: 1/3) classAndValueEquals: 3/2.
#( 1 5 29 135 1234 567890 123123123 456456456456 98765432109876543210987654321 987123987123987123987123987123987123987123987123) pairsDo: [ :a :b |
f _ a / b.
self assert: ((f raisedTo: 3) raisedTo: 1/3) classAndValueEquals: f.
self assert: ((f negated raisedTo: 3) raisedTo: 1/3) classAndValueEquals: f negated.
f _ b / a.
self assert: ((f raisedTo: 3) raisedTo: 1/3) classAndValueEquals: f.
self assert: ((f negated raisedTo: 3) raisedTo: 1/3) classAndValueEquals: f negated ].

self assert: (4/9 raisedTo: 3/2) classAndValueEquals: 8/27.
self assert: (8/27 raisedTo: 2/3) classAndValueEquals: 4/9.
#( 1 5 29 135 1234 567890 123123123 456456456456 98765432109876543210987654321 987123987123987123987123987123987123987123987123) pairsDo: [ :a :b |
f _ a / b.
self assert: ((f raisedTo: 3) raisedTo: 2/3) classAndValueEquals: f*f.
self assert: ((f raisedTo: 2) raisedTo: 3/2) classAndValueEquals: f*f*f.
self assert: ((f negated raisedTo: 3) raisedTo: 2/3) classAndValueEquals: f*f.
self assert: ((f negated raisedTo: 2) raisedTo: 3/2) classAndValueEquals: f*f*f.
f _ b / a.
self assert: ((f raisedTo: 3) raisedTo: 2/3) classAndValueEquals: f*f.
self assert: ((f raisedTo: 2) raisedTo: 3/2) classAndValueEquals: f*f*f.
self assert: ((f negated raisedTo: 3) raisedTo: 2/3) classAndValueEquals: f*f.
self assert: ((f negated raisedTo: 2) raisedTo: 3/2) classAndValueEquals: f*f*f ].

self assert: (32/243 raisedTo: 3/5) classAndValueEquals: 8/27.
self assert: (8/27 raisedTo: 5/3) classAndValueEquals: 32/243.
#( 1 5 29 135 1234 567890 123123123 456456456456 98765432109876543210987654321 987123987123987123987123987123987123987123987123) pairsDo: [ :a :b |
f _ a / b.
self assert: ((f raisedTo: 5) raisedTo: 3/5) classAndValueEquals: f*f*f.
self assert: ((f raisedTo: 3) raisedTo: 5/3) classAndValueEquals: f*f*f*f*f.
self assert: ((f negated raisedTo: 5) raisedTo: 3/5) classAndValueEquals: (f*f*f) negated.
self assert: ((f negated raisedTo: 3) raisedTo: 5/3) classAndValueEquals: (f*f*f*f*f) negated.

self assert: ((f raisedTo: -5) raisedTo: 3/5) classAndValueEquals: 1/(f*f*f).
self assert: ((f raisedTo: -3) raisedTo: 5/3) classAndValueEquals: 1/(f*f*f*f*f).
self assert: ((f negated raisedTo: -5) raisedTo: 3/5) classAndValueEquals: -1/(f*f*f).
self assert: ((f negated raisedTo: -3) raisedTo: 5/3) classAndValueEquals: -1/(f*f*f*f*f).
self assert: ((f raisedTo: 5) raisedTo: -3/5) classAndValueEquals: 1/(f*f*f).
self assert: ((f raisedTo: 3) raisedTo: -5/3) classAndValueEquals: 1/(f*f*f*f*f).
self assert: ((f negated raisedTo: 5) raisedTo: -3/5) classAndValueEquals: -1/(f*f*f).
self assert: ((f negated raisedTo: 3) raisedTo: -5/3) classAndValueEquals: -1/(f*f*f*f*f).

"No exact result => Float result"
self assert: ((f raisedTo: 3) +1 raisedTo: 5/3) isFloat.
self assert: ((f negated raisedTo: 3) -1 raisedTo: 5/3) isFloat.

f _ b / a.
self assert: ((f raisedTo: 5) raisedTo: 3/5) classAndValueEquals: f*f*f.
self assert: ((f raisedTo: 3) raisedTo: 5/3) classAndValueEquals: f*f*f*f*f.
self assert: ((f negated raisedTo: 5) raisedTo: 3/5) classAndValueEquals: (f*f*f) negated.
self assert: ((f negated raisedTo: 3) raisedTo: 5/3) classAndValueEquals: (f*f*f*f*f) negated.

"No exact result => Float result"
self assert: ((f raisedTo: 3) +1 raisedTo: 5/3) isFloat.
self assert: ((f negated raisedTo: 3) -1 raisedTo: 5/3) isFloat ].! !

!FractionTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/11/2011 22:12'!
testExactSqrt
"
FractionTest new testExactSqrt
"
| f |
self assert: (4/9) sqrt classAndValueEquals: 2/3.
#( 1 5 29 135 1234 567890 123123123 456456456456 98765432109876543210987654321 987123987123987123987123987123987123987123987123) pairsDo: [ :i :j |
f _ i / j.
self assert: f squared sqrt classAndValueEquals: f.
f _ j / i.
self assert: f squared sqrt classAndValueEquals: f ]! !

!FractionTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/13/2011 21:38'!
testInexactRaisedTo
"
FractionTest new testInexactRaisedTo
"
self assert: (((1 << 1024 + 1) / (1 << 1024 + 3)) raisedTo: 1/3) = 1.0.
self assert: (((1 << 1024 + 1) / (1 << 1024 + 3)) negated raisedTo: 1/3) = -1.0! !

!FractionTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/13/2011 21:27'!
testInexactSqrt
"
FractionTest new testInexactSqrt
"
self assert: ((1 << 1024 + 1) / (1 << 1024 + 3)) sqrt = 1.0! !

!FractionTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/13/2011 21:49'!
testRaisedToErrorConditions
"
FractionTest new testRaisedToErrorConditions
"
self should: [ (-1/16) raisedTo: 1/4 ] raise: ArithmeticError.
self should: [ ((1 << 1024 + 1) / (1 << 1024 + 3)) negated raisedTo: 1/4 ] raise: ArithmeticError! !

!FractionTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/13/2011 21:48'!
testSqrtErrorConditions
"
FractionTest new testSqrtErrorConditions
"
self should: [ (-1/4) sqrt ] raise: DomainError.
self should: [ ((1 << 1024 + 1) / (1 << 1024 + 3)) negated sqrt ] raise: DomainError! !

!FractionTest methodsFor: 'private' stamp: 'jmv 10/11/2011 22:12'!
assert: a classAndValueEquals: b
self assert: a class = b class.
self assert: a = b! !

!IntegerTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/13/2011 21:46'!
testExactRaisedTo
"
IntegerTest new testExactRaisedTo
"
self assert: (4 raisedTo: 1/2) classAndValueEquals: 2.
self assert: (9 raisedTo: 1/2) classAndValueEquals: 3.
self assert: (9 raisedTo: -1/2) classAndValueEquals: 1/3.
self assert: (-1 raisedTo: 1/3) classAndValueEquals: -1.
#( 1 5 29 135 1234 567890 123123123 456456456456 98765432109876543210987654321 987123987123987123987123987123987123987123987123) do: [ :i |
self assert: (i squared raisedTo: 1/2) classAndValueEquals: i.
self assert: (i negated squared raisedTo: 1/2) classAndValueEquals: i ].

self assert: (8 raisedTo: 1/3) classAndValueEquals: 2.
self assert: (27 raisedTo: 1/3) classAndValueEquals: 3.
#( 1 5 29 135 1234 567890 123123123 456456456456 98765432109876543210987654321 987123987123987123987123987123987123987123987123) do: [ :i |
self assert: ((i raisedTo: 3) raisedTo: 1/3) classAndValueEquals: i.
self assert: ((i negated raisedTo: 3) raisedTo: 1/3) classAndValueEquals: i negated ].

self assert: (4 raisedTo: 3/2) classAndValueEquals: 8.
self assert: (8 raisedTo: 2/3) classAndValueEquals: 4.
self assert: (8 raisedTo: -2/3) classAndValueEquals: 1/4.
#( 1 5 29 135 1234 567890 123123123 456456456456 98765432109876543210987654321 987123987123987123987123987123987123987123987123) do: [ :i |
self assert: ((i raisedTo: 3) raisedTo: 2/3) classAndValueEquals: i*i.
self assert: ((i raisedTo: 2) raisedTo: 3/2) classAndValueEquals: i*i*i.
self assert: ((i negated raisedTo: 3) raisedTo: 2/3) classAndValueEquals: i*i.
self assert: ((i negated raisedTo: 2) raisedTo: 3/2) classAndValueEquals: i*i*i ].

self assert: (32 raisedTo: 3/5) classAndValueEquals: 8.
self assert: (8 raisedTo: 5/3) classAndValueEquals: 32.
#( 1 5 29 135 1234 567890 123123123 456456456456 98765432109876543210987654321 987123987123987123987123987123987123987123987123) do: [ :i |
self assert: ((i raisedTo: 5) raisedTo: 3/5) classAndValueEquals: i*i*i.
self assert: ((i raisedTo: 3) raisedTo: 5/3) classAndValueEquals: i*i*i*i*i.
self assert: ((i negated raisedTo: 5) raisedTo: 3/5) classAndValueEquals: (i*i*i) negated.
self assert: ((i negated raisedTo: 3) raisedTo: 5/3) classAndValueEquals: (i*i*i*i*i) negated.

self assert: ((i raisedTo: -5) raisedTo: 3/5) classAndValueEquals: 1/(i*i*i).
self assert: ((i raisedTo: -3) raisedTo: 5/3) classAndValueEquals: 1/(i*i*i*i*i).
self assert: ((i negated raisedTo: -5) raisedTo: 3/5) classAndValueEquals: -1/(i*i*i).
self assert: ((i negated raisedTo: -3) raisedTo: 5/3) classAndValueEquals: -1/(i*i*i*i*i).

self assert: ((i raisedTo: 5) raisedTo: -3/5) classAndValueEquals: 1/(i*i*i).
self assert: ((i raisedTo: 3) raisedTo: -5/3) classAndValueEquals: 1/(i*i*i*i*i).
self assert: ((i negated raisedTo: 5) raisedTo: -3/5) classAndValueEquals: -1/(i*i*i).
self assert: ((i negated raisedTo: 3) raisedTo: -5/3) classAndValueEquals: -1/(i*i*i*i*i).

"No exact result => Float result"
self assert: ((i raisedTo: 3) +1 raisedTo: 5/3) isFloat.
self assert: ((i negated raisedTo: 3) -1 raisedTo: 5/3) isFloat ].! !

!IntegerTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/11/2011 22:09'!
testExactSqrt
"
IntegerTest new testExactSqrt
"
self assert: 4 sqrt classAndValueEquals: 2.
self assert: 9 sqrt classAndValueEquals: 3.
self assert: Float maxExactInteger squared sqrt classAndValueEquals: Float maxExactInteger.
self assert: (Float maxExactInteger+1) squared sqrt classAndValueEquals: Float maxExactInteger+1.
#( 1 5 29 135 1234 567890 123123123 456456456456 98765432109876543210987654321 987123987123987123987123987123987123987123987123) do: [ :i |
self assert: i squared sqrt classAndValueEquals: i ]! !

!IntegerTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/13/2011 09:09'!
testNthRootErrorConditions
"
IntegerTest new testExactRaisedToErrorConditions
"

self should: [ -2 nthRoot: 1/4 ] raise: ArithmeticError.
self should: [ -2 nthRoot: 1.24 ] raise: ArithmeticError.! !

!IntegerTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/13/2011 21:45'!
testRaisedToErrorConditions
"
IntegerTest new testRaisedToErrorConditions
"

self should: [ -2 raisedTo: 1/4 ] raise: ArithmeticError.
self should: [ -2 raisedTo: 1.24 ] raise: ArithmeticError.! !

!IntegerTest methodsFor: 'tests - mathematical functions' stamp: 'jmv 10/13/2011 21:46'!
testSqrtErrorConditions
"
IntegerTest new testSqrtErrorConditions
"

self should: [ -1 sqrt ] raise: ArithmeticError! !

!IntegerTest methodsFor: 'private' stamp: 'jmv 10/11/2011 08:14'!
assert: a classAndValueEquals: b
self assert: a class = b class.
self assert: a = b! !

!Number methodsFor: 'mathematical functions' stamp: 'jmv 10/13/2011 08:36'!
nthRoot: aPositiveInteger

self subclassResponsibility! !

!Number methodsFor: 'mathematical functions' stamp: 'jmv 10/13/2011 08:50'!
raisedTo: aNumber

aNumber isInteger ifTrue: [
"Do the special case of integer power"
^ self raisedToInteger: aNumber].
aNumber isFraction ifTrue: [
"Special case for fraction power"
^ (self nthRoot: aNumber denominator) raisedToInteger: aNumber numerator ].
self < 0 ifTrue: [
^ ArithmeticError signal: 'Negative numbers can''t be raised to float powers.' ].
0 = aNumber ifTrue: [^ self class one].	"Special case of exponent=0"
1 = aNumber ifTrue: [^ self].	"Special case of exponent=1"
0 = self ifTrue: [				"Special case of self = 0"
aNumber < 0
ifTrue: [^ (ZeroDivide dividend: self) signal]
ifFalse: [^ self]].
^ (aNumber * self ln) exp		"Otherwise use logarithms"! !

!Number methodsFor: 'mathematical functions' stamp: 'jmv 10/11/2011 08:34'!
sqrt

self subclassResponsibility! !

!Float methodsFor: 'mathematical functions' stamp: 'jmv 10/13/2011 09:03'!
nthRoot: aPositiveInteger
aPositiveInteger = 2 ifTrue: [
^self sqrt ].

(aPositiveInteger isInteger not or: [ aPositiveInteger negative ])
ifTrue: [^ ArithmeticError signal: 'nth root only defined for positive Integer n.'].

^self negative
ifTrue: [
aPositiveInteger odd
ifTrue: [ (self negated raisedTo: 1.0 / aPositiveInteger) negated ]
ifFalse: [ ArithmeticError signal: 'Negative numbers don''t have even roots.' ]]
ifFalse: [ self raisedTo: 1.0 / aPositiveInteger ]! !

!Float class methodsFor: 'constants' stamp: 'jmv 10/13/2011 19:57'!
maxExactInteger
"Answer the biggest integer such that it is exactly represented in a float, and all smaller integers also are"
^1 bitShift: self precision! !

!Fraction methodsFor: 'mathematical functions' stamp: 'jmv 10/13/2011 21:38'!
nthRoot: aPositiveInteger

| d n |
n _numerator nthRoot: aPositiveInteger.
d _ denominator nthRoot: aPositiveInteger.
"The #sqrt method in integer will only answer a Float if there's no exact square root.
So, we need a float anyway."
(n isInfinite or: [ d isInfinite ]) ifTrue: [
^self asFloat nthRoot: aPositiveInteger ].
^n / d! !

!Fraction methodsFor: 'mathematical functions' stamp: 'jmv 10/13/2011 20:16'!
sqrt
| d n |
n _numerator sqrt.
d _ denominator sqrt.
"The #sqrt method in integer will only answer a Float if there's no exact square root.
So, we need a float anyway."
(n isInfinite or: [ d isInfinite ]) ifTrue: [
^self asFloat sqrt ].
^n / d! !

!Integer methodsFor: 'mathematical functions' stamp: 'jmv 10/13/2011 20:19'!
nthRoot: aPositiveInteger

| selfAsFloat floatResult guess raised higher lower delta |
selfAsFloat _ self asFloat.
floatResult _ selfAsFloat nthRoot: aPositiveInteger.

"If we can't do Float arithmetic, currently we can't look for an exact answer"
floatResult isInfinite ifTrue: [
^floatResult ].

guess _ floatResult rounded.

raised _ guess raisedToInteger: aPositiveInteger.
raised = self
ifTrue: [ ^ guess ].

"In this case, maybe it failed because we are such a big integer that the Float
method gets inexact, even if we are a whole square number.
Note (jmv): The algorithms I found for computing the nthRoot would havily use
very large fractions. I wrote this one, that doesn't create fractions."
selfAsFloat abs >= (Float maxExactInteger asFloat raisedToInteger: aPositiveInteger)
ifTrue: [
raised > self
ifTrue: [
higher _ guess.
delta _  floatResult predecessor - floatResult.
[
floatResult _ floatResult + delta.
lower _ floatResult rounded.
(lower raisedToInteger: aPositiveInteger) > self ] whileTrue: [
delta _ delta * 2.
higher _ lower ] ]
ifFalse: [
lower _ guess.
delta _  floatResult successor - floatResult.
[
floatResult _ floatResult + delta.
higher _ floatResult rounded.
(higher raisedToInteger: aPositiveInteger) < self ] whileTrue: [
delta _ delta * 2.
lower _ higher ]].
[ higher - lower > 1 ] whileTrue: [
guess _ lower + higher // 2.
raised _ guess raisedToInteger: aPositiveInteger.
raised = self
ifTrue: [
^ guess ].
raised > self
ifTrue: [ higher _ guess ]
ifFalse: [ lower _ guess ]]].

"We need an approximate result"
^floatResult! !

!Integer methodsFor: 'mathematical functions' stamp: 'jmv 10/13/2011 20:17'!
sqrt

| selfAsFloat floatResult guess |
selfAsFloat _ self asFloat.
floatResult _ selfAsFloat sqrt.

floatResult isInfinite ifFalse: [
guess _ floatResult truncated.

guess squared = self
ifTrue: [ ^ guess ]].

"In this case, maybe it failed because we are such a big integer that the Float method becomes
inexact, even if we are a whole square number. So, try the slower but more general method"
selfAsFloat >= Float maxExactInteger asFloat squared
ifTrue: [
guess _ self sqrtFloor.
guess * guess = self ifTrue: [
^guess ]].

"We need an approximate result"
^floatResult! !

!LargePositiveInteger methodsFor: 'mathematical functions' stamp: 'jmv 10/14/2011 07:56'!
mightBeASquare
"In base 16, a square number can end only with 0,1,4 or 9 and
- in case 0, only 0,1,4,9 can precede it,
- in case 4, only even numbers can precede it.
See http://en.wikipedia.org/wiki/Square_number
So, in hex, the last byte must be one of:
00
10
40
90
x1
e4
x9
where x is any hex digit and e is any even digit
"
| lsb |
lsb := self digitAt: 1.
^((lsb bitAnd: 7) = 1					"any|1 or any|9"
or: [(lsb bitAnd: 31) = 4			"even|4"
or: [(lsb bitAnd: 127) = 16			"10 or 90"
or: [(lsb bitAnd: 191) = 0]]])		"00 or 40"! !

!LargePositiveInteger methodsFor: 'mathematical functions' stamp: 'jmv 10/13/2011 22:11'!
sqrt
"If we know for sure no exact solution exists, then just answer the cheap float approximation without wasting time."
self mightBeASquare ifFalse: [
^self asFloat sqrt ].

"If some exact solution might exist,  call potentially expensive super"
^super sqrt! !

!LargeNegativeInteger methodsFor: 'mathematical functions' stamp: 'jmv 10/13/2011 21:40'!
sqrt
^ DomainError signal: 'sqrt undefined for number less than zero.'! !

!SmallInteger methodsFor: 'mathematical functions' stamp: 'jmv 10/13/2011 21:41'!
sqrt
self negative ifTrue: [
^ DomainError signal: 'sqrt undefined for number less than zero.' ].
^super sqrt! !

!SmallInteger reorganize!
('arithmetic' * + - / // \\ gcd: quo:)
('bit manipulation' bitAnd: bitOr: bitShift: bitXor: byteReversed hashMultiply highBit highBitOfMagnitude lowBit)
('testing' even isLarge odd)
('comparing' < <= = > >= hash identityHash ~=)
('copying' clone shallowCopy)
('converting' as31BitSmallInt asFloat)
('printing' decimalDigitLength destinationBuffer: numberOfDigitsInBase: printOn:base: printOn:base:length:padded: printOn:base:nDigits: printString printStringBase: printStringBase:nDigits: threeDigitName)
('system primitives' digitAt: digitAt:put: digitLength instVarAt: nextInstance nextObject)
('mathematical functions' sqrt)
!

!LargeNegativeInteger reorganize!
('arithmetic' abs negated)
('bit manipulation' bitAt: highBit)
('converting' asFloat normalize)
('testing' negative positive sign strictlyPositive)
('printing' printOn:base:)
('mathematical functions' sqrt)
!

!LargePositiveInteger reorganize!
('arithmetic' * + - / // \\ \\\ abs negated quo:)
('bit manipulation' bitAt: bitReverse: hashMultiply highBit highBitOfMagnitude)
('testing' isLarge isPrime negative positive sign strictlyPositive)
('comparing' < <= > >= hash)
('converting' as31BitSmallInt asFloat normalize withAtLeastNDigits:)
('system primitives' digitAt: digitAt:put: digitLength replaceFrom:to:with:startingAt:)
('printing' printOn:base: printOn:base:nDigits: printStringBase:)
('mathematical functions' mightBeASquare sqrt)
!

IntegerTest removeSelector: #testExactRaisedToErrorConditions!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 1105-sqrtAndnThRoot-jmv.13.cs.zip
Type: application/zip
Size: 4364 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20111014/c37f86f4/1105-sqrtAndnThRoot-jmv.13.cs.zip
```