LargeInt.st
author claus
Fri, 16 Jul 1993 11:39:45 +0200
changeset 1 a27a279701f8
child 2 6526dde5f3ac
permissions -rw-r--r--
Initial revision
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
     1
"
a27a279701f8 Initial revision
claus
parents:
diff changeset
     2
 COPYRIGHT (c) 1988-93 by Claus Gittinger
a27a279701f8 Initial revision
claus
parents:
diff changeset
     3
              All Rights Reserved
a27a279701f8 Initial revision
claus
parents:
diff changeset
     4
a27a279701f8 Initial revision
claus
parents:
diff changeset
     5
 This software is furnished under a license and may be used
a27a279701f8 Initial revision
claus
parents:
diff changeset
     6
 only in accordance with the terms of that license and with the
a27a279701f8 Initial revision
claus
parents:
diff changeset
     7
 inclusion of the above copyright notice.   This software may not
a27a279701f8 Initial revision
claus
parents:
diff changeset
     8
 be provided or otherwise made available to, or used by, any
a27a279701f8 Initial revision
claus
parents:
diff changeset
     9
 other person.  No title to or ownership of the software is
a27a279701f8 Initial revision
claus
parents:
diff changeset
    10
 hereby transferred.
a27a279701f8 Initial revision
claus
parents:
diff changeset
    11
"
a27a279701f8 Initial revision
claus
parents:
diff changeset
    12
a27a279701f8 Initial revision
claus
parents:
diff changeset
    13
Integer subclass:#LargeInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
    14
       instanceVariableNames:'sign digitArray'
a27a279701f8 Initial revision
claus
parents:
diff changeset
    15
       classVariableNames:''
a27a279701f8 Initial revision
claus
parents:
diff changeset
    16
       poolDictionaries:''
a27a279701f8 Initial revision
claus
parents:
diff changeset
    17
       category:'Magnitude-Numbers'
a27a279701f8 Initial revision
claus
parents:
diff changeset
    18
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    19
a27a279701f8 Initial revision
claus
parents:
diff changeset
    20
LargeInteger comment:'
a27a279701f8 Initial revision
claus
parents:
diff changeset
    21
a27a279701f8 Initial revision
claus
parents:
diff changeset
    22
COPYRIGHT (c) 1988-93 by Claus Gittinger
a27a279701f8 Initial revision
claus
parents:
diff changeset
    23
              All Rights Reserved
a27a279701f8 Initial revision
claus
parents:
diff changeset
    24
a27a279701f8 Initial revision
claus
parents:
diff changeset
    25
This class provides arbitrary precision integers. These are represented as:
a27a279701f8 Initial revision
claus
parents:
diff changeset
    26
  sign (-1/0/+1) and, if sign ~~ 0
a27a279701f8 Initial revision
claus
parents:
diff changeset
    27
  an Array of digits with 4 digits per element; 
a27a279701f8 Initial revision
claus
parents:
diff changeset
    28
  least significant 4 digits at index 1 ...
a27a279701f8 Initial revision
claus
parents:
diff changeset
    29
a27a279701f8 Initial revision
claus
parents:
diff changeset
    30
This is definitely not a good (fast) implementation -
a27a279701f8 Initial revision
claus
parents:
diff changeset
    31
but ok for now, since LargeIntegers are not used very often.
a27a279701f8 Initial revision
claus
parents:
diff changeset
    32
It will be reimplemented when everything else runs fine and a need arises
a27a279701f8 Initial revision
claus
parents:
diff changeset
    33
(or someone rewrites it and sends me the code :-).
a27a279701f8 Initial revision
claus
parents:
diff changeset
    34
a27a279701f8 Initial revision
claus
parents:
diff changeset
    35
%W% %E%
a27a279701f8 Initial revision
claus
parents:
diff changeset
    36
'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    37
a27a279701f8 Initial revision
claus
parents:
diff changeset
    38
!LargeInteger class methodsFor:'instance creation'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    39
a27a279701f8 Initial revision
claus
parents:
diff changeset
    40
new:numberOfDigits
a27a279701f8 Initial revision
claus
parents:
diff changeset
    41
    "catch creation message"
a27a279701f8 Initial revision
claus
parents:
diff changeset
    42
a27a279701f8 Initial revision
claus
parents:
diff changeset
    43
    self error:'LargeIntegers cannot be created with new'
a27a279701f8 Initial revision
claus
parents:
diff changeset
    44
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    45
a27a279701f8 Initial revision
claus
parents:
diff changeset
    46
new
a27a279701f8 Initial revision
claus
parents:
diff changeset
    47
    "catch creation message"
a27a279701f8 Initial revision
claus
parents:
diff changeset
    48
a27a279701f8 Initial revision
claus
parents:
diff changeset
    49
    self error:'LargeIntegers cannot be created with new'
a27a279701f8 Initial revision
claus
parents:
diff changeset
    50
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    51
a27a279701f8 Initial revision
claus
parents:
diff changeset
    52
value:aSmallInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
    53
    "create and return a new LargeInteger with value taken from
a27a279701f8 Initial revision
claus
parents:
diff changeset
    54
     the argument, aSmallInteger"
a27a279701f8 Initial revision
claus
parents:
diff changeset
    55
a27a279701f8 Initial revision
claus
parents:
diff changeset
    56
    ^ self basicNew value:aSmallInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
    57
a27a279701f8 Initial revision
claus
parents:
diff changeset
    58
    "LargeInteger value:3689"
a27a279701f8 Initial revision
claus
parents:
diff changeset
    59
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    60
a27a279701f8 Initial revision
claus
parents:
diff changeset
    61
valueLow:lowBits hi:hiBits
a27a279701f8 Initial revision
claus
parents:
diff changeset
    62
    "create and return a new LargeInteger with value taken from
a27a279701f8 Initial revision
claus
parents:
diff changeset
    63
     the two 16-bit args"
a27a279701f8 Initial revision
claus
parents:
diff changeset
    64
a27a279701f8 Initial revision
claus
parents:
diff changeset
    65
    hiBits < 0 ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
    66
        ^ ((self value:hiBits negated) * 16r10000 + lowBits) negated
a27a279701f8 Initial revision
claus
parents:
diff changeset
    67
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
    68
    ^ (self value:hiBits) * 16r10000 + lowBits
a27a279701f8 Initial revision
claus
parents:
diff changeset
    69
! !
a27a279701f8 Initial revision
claus
parents:
diff changeset
    70
a27a279701f8 Initial revision
claus
parents:
diff changeset
    71
a27a279701f8 Initial revision
claus
parents:
diff changeset
    72
!LargeInteger methodsFor:'coercing & converting'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    73
a27a279701f8 Initial revision
claus
parents:
diff changeset
    74
coerce:aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
    75
    "return the argument as a LargeInteger"
a27a279701f8 Initial revision
claus
parents:
diff changeset
    76
a27a279701f8 Initial revision
claus
parents:
diff changeset
    77
    ^ aNumber asLargeInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
    78
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    79
a27a279701f8 Initial revision
claus
parents:
diff changeset
    80
asLargeInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
    81
    "return a LargeInteger with same value as myself - thats me"
a27a279701f8 Initial revision
claus
parents:
diff changeset
    82
a27a279701f8 Initial revision
claus
parents:
diff changeset
    83
    ^ self
a27a279701f8 Initial revision
claus
parents:
diff changeset
    84
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    85
a27a279701f8 Initial revision
claus
parents:
diff changeset
    86
asSmallInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
    87
    "return a SmallInteger with same value as myself - the result
a27a279701f8 Initial revision
claus
parents:
diff changeset
    88
     is invalid if the receivers value cannot be represented
a27a279701f8 Initial revision
claus
parents:
diff changeset
    89
     as a SmallInteger"
a27a279701f8 Initial revision
claus
parents:
diff changeset
    90
a27a279701f8 Initial revision
claus
parents:
diff changeset
    91
    |value|
a27a279701f8 Initial revision
claus
parents:
diff changeset
    92
a27a279701f8 Initial revision
claus
parents:
diff changeset
    93
    value := 0.
a27a279701f8 Initial revision
claus
parents:
diff changeset
    94
    (sign == 0) ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
    95
        digitArray reverseDo:[:aDigit |
a27a279701f8 Initial revision
claus
parents:
diff changeset
    96
            value := (value times:10000) + aDigit 
a27a279701f8 Initial revision
claus
parents:
diff changeset
    97
        ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
    98
        (sign < 0) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
    99
            value := value negated
a27a279701f8 Initial revision
claus
parents:
diff changeset
   100
        ]
a27a279701f8 Initial revision
claus
parents:
diff changeset
   101
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   102
    ^ value
a27a279701f8 Initial revision
claus
parents:
diff changeset
   103
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   104
a27a279701f8 Initial revision
claus
parents:
diff changeset
   105
asFloat
a27a279701f8 Initial revision
claus
parents:
diff changeset
   106
    "return a Float with same value as myself"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   107
a27a279701f8 Initial revision
claus
parents:
diff changeset
   108
    |newFloat|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   109
a27a279701f8 Initial revision
claus
parents:
diff changeset
   110
    newFloat := 0.0.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   111
    (sign == 0) ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   112
        digitArray reverseDo:[:aDigit |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   113
            newFloat := (newFloat * 10000.0) + aDigit asFloat
a27a279701f8 Initial revision
claus
parents:
diff changeset
   114
        ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   115
        (sign < 0) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   116
            newFloat := newFloat negated
a27a279701f8 Initial revision
claus
parents:
diff changeset
   117
        ]
a27a279701f8 Initial revision
claus
parents:
diff changeset
   118
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   119
    ^ newFloat
a27a279701f8 Initial revision
claus
parents:
diff changeset
   120
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   121
a27a279701f8 Initial revision
claus
parents:
diff changeset
   122
value:aSmallInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
   123
    "return a new LargeInteger with value taken from a SmallInteger"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   124
a27a279701f8 Initial revision
claus
parents:
diff changeset
   125
    |absValue 
a27a279701f8 Initial revision
claus
parents:
diff changeset
   126
     index "{ Class: SmallInteger }"|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   127
a27a279701f8 Initial revision
claus
parents:
diff changeset
   128
    (aSmallInteger == 0) ifTrue: [
a27a279701f8 Initial revision
claus
parents:
diff changeset
   129
        digitArray := nil.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   130
        sign := 0.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   131
        ^ self
a27a279701f8 Initial revision
claus
parents:
diff changeset
   132
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   133
    (aSmallInteger < 0) ifTrue: [
a27a279701f8 Initial revision
claus
parents:
diff changeset
   134
        sign := -1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   135
        absValue := aSmallInteger negated
a27a279701f8 Initial revision
claus
parents:
diff changeset
   136
    ] ifFalse: [
a27a279701f8 Initial revision
claus
parents:
diff changeset
   137
        sign := 1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   138
        absValue := aSmallInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
   139
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   140
    digitArray := Array new:3.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   141
    index := 1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   142
    [absValue == 0] whileFalse: [
a27a279701f8 Initial revision
claus
parents:
diff changeset
   143
        digitArray at:index put:(absValue \\ 10000).
a27a279701f8 Initial revision
claus
parents:
diff changeset
   144
        absValue := absValue // 10000.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   145
        index := index + 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   146
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   147
    [index <= 3] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   148
        digitArray at:index put:0.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   149
        index := index + 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   150
    ]
a27a279701f8 Initial revision
claus
parents:
diff changeset
   151
! !
a27a279701f8 Initial revision
claus
parents:
diff changeset
   152
    
a27a279701f8 Initial revision
claus
parents:
diff changeset
   153
!LargeInteger methodsFor:'comparing'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   154
a27a279701f8 Initial revision
claus
parents:
diff changeset
   155
= aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   156
    "return true, if the argument, aNumber has the same value as
a27a279701f8 Initial revision
claus
parents:
diff changeset
   157
     the receiver"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   158
a27a279701f8 Initial revision
claus
parents:
diff changeset
   159
    (aNumber class == LargeInteger) ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   160
        aNumber respondsToArithmetic ifFalse:[ ^ false ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   161
        ^ self retry:#= coercing:aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   162
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   163
    (aNumber sign == sign) ifFalse:[^ false].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   164
    ^ self absEq:aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   165
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   166
a27a279701f8 Initial revision
claus
parents:
diff changeset
   167
< aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   168
    "return true, if the argument, aNumber is greater than the receiver"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   169
a27a279701f8 Initial revision
claus
parents:
diff changeset
   170
    |otherSign|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   171
a27a279701f8 Initial revision
claus
parents:
diff changeset
   172
    (aNumber class == LargeInteger) ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   173
        ^ self retry:#< coercing:aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   174
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   175
    otherSign := aNumber sign.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   176
a27a279701f8 Initial revision
claus
parents:
diff changeset
   177
    (sign > 0) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   178
        "I am positive"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   179
        (otherSign > 0) ifTrue:[^ self absLess:aNumber].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   180
        ^ false "aNumber is <= 0"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   181
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   182
    (sign == 0) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   183
        (otherSign > 0) ifTrue:[^ true].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   184
        ^ false
a27a279701f8 Initial revision
claus
parents:
diff changeset
   185
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   186
    "I am negative"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   187
    (otherSign > 0) ifTrue:[^ true].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   188
    (otherSign == 0) ifTrue:[^ true].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   189
    ^ (self absLess:aNumber) not
a27a279701f8 Initial revision
claus
parents:
diff changeset
   190
! !
a27a279701f8 Initial revision
claus
parents:
diff changeset
   191
a27a279701f8 Initial revision
claus
parents:
diff changeset
   192
!LargeInteger methodsFor:'arithmetic'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   193
a27a279701f8 Initial revision
claus
parents:
diff changeset
   194
+ aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   195
    "return the sum of the receiver and the argument, aNumber"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   196
a27a279701f8 Initial revision
claus
parents:
diff changeset
   197
    |otherSign|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   198
a27a279701f8 Initial revision
claus
parents:
diff changeset
   199
    (aNumber class == LargeInteger) ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   200
        ^ self retry:#+ coercing:aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   201
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   202
    otherSign := aNumber sign.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   203
a27a279701f8 Initial revision
claus
parents:
diff changeset
   204
    (sign > 0) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   205
        "I am positive"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   206
        (otherSign > 0) ifTrue:[^ self absPlus:aNumber].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   207
        (otherSign < 0) ifTrue:[^ self absMinus:aNumber].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   208
        ^ self
a27a279701f8 Initial revision
claus
parents:
diff changeset
   209
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   210
    (sign == 0) ifTrue:[^ aNumber].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   211
    "I am negative"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   212
    (otherSign > 0) ifTrue:[^ aNumber absMinus:self].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   213
    (otherSign < 0) ifTrue:[^ (self absPlus:aNumber) negated].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   214
    ^ self
a27a279701f8 Initial revision
claus
parents:
diff changeset
   215
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   216
a27a279701f8 Initial revision
claus
parents:
diff changeset
   217
- aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   218
    "return the difference of the receiver and the argument, aNumber"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   219
a27a279701f8 Initial revision
claus
parents:
diff changeset
   220
    |otherSign|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   221
a27a279701f8 Initial revision
claus
parents:
diff changeset
   222
    (aNumber class == LargeInteger) ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   223
        ^ self retry:#- coercing:aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   224
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   225
    otherSign := aNumber sign.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   226
    (sign > 0) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   227
        "I am positive"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   228
        (otherSign > 0) ifTrue:[^ self absMinus:aNumber].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   229
        (otherSign < 0) ifTrue:[^ self absPlus:aNumber].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   230
        ^ self
a27a279701f8 Initial revision
claus
parents:
diff changeset
   231
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   232
    (sign == 0) ifTrue:[^ aNumber negated].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   233
    "I am negative"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   234
    (otherSign > 0) ifTrue:[^ (self absPlus:aNumber) negated].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   235
    (otherSign < 0) ifTrue:[^ (self absMinus:aNumber) negated].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   236
    ^ self
a27a279701f8 Initial revision
claus
parents:
diff changeset
   237
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   238
a27a279701f8 Initial revision
claus
parents:
diff changeset
   239
* aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   240
    "return the product of the receiver and the argument, aNumber"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   241
a27a279701f8 Initial revision
claus
parents:
diff changeset
   242
    |otherSign|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   243
a27a279701f8 Initial revision
claus
parents:
diff changeset
   244
    (aNumber = 10) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   245
        ^ self deepCopy mul10
a27a279701f8 Initial revision
claus
parents:
diff changeset
   246
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   247
    (aNumber class == LargeInteger) ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   248
        ^ self retry:#* coercing:aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   249
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   250
    otherSign := aNumber sign.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   251
   
a27a279701f8 Initial revision
claus
parents:
diff changeset
   252
    (sign == 0) ifTrue:[^ 0].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   253
    (sign == otherSign) ifTrue:[^ self absMul:aNumber].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   254
    (otherSign == 0) ifTrue:[^ 0].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   255
    ^ (self absMul:aNumber) negated
a27a279701f8 Initial revision
claus
parents:
diff changeset
   256
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   257
a27a279701f8 Initial revision
claus
parents:
diff changeset
   258
/ aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   259
    "this is a q&d hack - we loose lots of precision here ..."
a27a279701f8 Initial revision
claus
parents:
diff changeset
   260
a27a279701f8 Initial revision
claus
parents:
diff changeset
   261
    ^ (self asFloat / aNumber asFloat)
a27a279701f8 Initial revision
claus
parents:
diff changeset
   262
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   263
    
a27a279701f8 Initial revision
claus
parents:
diff changeset
   264
// aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   265
    "return the quotient of the receiver and the argument, aNumber"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   266
a27a279701f8 Initial revision
claus
parents:
diff changeset
   267
    |otherSign|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   268
a27a279701f8 Initial revision
claus
parents:
diff changeset
   269
    (aNumber = 10) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   270
        ^ self deepCopy div10
a27a279701f8 Initial revision
claus
parents:
diff changeset
   271
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   272
    (aNumber class == LargeInteger) ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   273
        ^ self retry:#// coercing:aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   274
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   275
    otherSign := aNumber sign.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   276
a27a279701f8 Initial revision
claus
parents:
diff changeset
   277
    sign < 0 ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   278
        (sign == otherSign) ifTrue:[^ (self negated absDiv:aNumber negated) at:1].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   279
        ^ ((self negated absDiv:aNumber) at:1) negated
a27a279701f8 Initial revision
claus
parents:
diff changeset
   280
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   281
    (sign == otherSign) ifTrue:[^ (self absDiv:aNumber) at:1].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   282
    ^ ((self absDiv:aNumber negated) at:1) negated
a27a279701f8 Initial revision
claus
parents:
diff changeset
   283
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   284
    
a27a279701f8 Initial revision
claus
parents:
diff changeset
   285
\\ aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   286
    "return the remainder of division of the receiver by the argument, aNumber"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   287
a27a279701f8 Initial revision
claus
parents:
diff changeset
   288
    |otherSign|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   289
a27a279701f8 Initial revision
claus
parents:
diff changeset
   290
    (aNumber class == LargeInteger) ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   291
        ^ self retry:#\\ coercing:aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   292
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   293
a27a279701f8 Initial revision
claus
parents:
diff changeset
   294
    otherSign := aNumber sign.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   295
    sign < 0 ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   296
        (sign == otherSign) ifTrue:[^ (self negated absDiv:aNumber negated) at:2].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   297
        ^ ((self negated absDiv:aNumber) at:2) negated
a27a279701f8 Initial revision
claus
parents:
diff changeset
   298
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   299
    (sign == otherSign) ifTrue:[^ (self absDiv:aNumber) at:2].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   300
    ^ ((self absDiv:aNumber negated) at:2) negated
a27a279701f8 Initial revision
claus
parents:
diff changeset
   301
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   302
a27a279701f8 Initial revision
claus
parents:
diff changeset
   303
negated
a27a279701f8 Initial revision
claus
parents:
diff changeset
   304
    "return a LargeInteger with value negated from receivers value"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   305
a27a279701f8 Initial revision
claus
parents:
diff changeset
   306
    |newNumber|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   307
a27a279701f8 Initial revision
claus
parents:
diff changeset
   308
    (sign == 0) ifTrue:[^ 0].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   309
    newNumber := self shallowCopy.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   310
    newNumber sign:(sign negated).
a27a279701f8 Initial revision
claus
parents:
diff changeset
   311
    ^ newNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   312
! !
a27a279701f8 Initial revision
claus
parents:
diff changeset
   313
a27a279701f8 Initial revision
claus
parents:
diff changeset
   314
!LargeInteger methodsFor:'bit operations'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   315
a27a279701f8 Initial revision
claus
parents:
diff changeset
   316
bitAnd:anInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
   317
    "q & d hack to make Random work;
a27a279701f8 Initial revision
claus
parents:
diff changeset
   318
     this works only correctly, if my value can be represented
a27a279701f8 Initial revision
claus
parents:
diff changeset
   319
     as a SmallInteger"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   320
a27a279701f8 Initial revision
claus
parents:
diff changeset
   321
    ^ self asSmallInteger bitAnd:anInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
   322
! !
a27a279701f8 Initial revision
claus
parents:
diff changeset
   323
a27a279701f8 Initial revision
claus
parents:
diff changeset
   324
!LargeInteger methodsFor:'testing'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   325
a27a279701f8 Initial revision
claus
parents:
diff changeset
   326
sign
a27a279701f8 Initial revision
claus
parents:
diff changeset
   327
    "return the sign of the receiver"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   328
a27a279701f8 Initial revision
claus
parents:
diff changeset
   329
    ^ sign
a27a279701f8 Initial revision
claus
parents:
diff changeset
   330
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   331
a27a279701f8 Initial revision
claus
parents:
diff changeset
   332
odd
a27a279701f8 Initial revision
claus
parents:
diff changeset
   333
    "return true if the receiver is odd"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   334
a27a279701f8 Initial revision
claus
parents:
diff changeset
   335
    ^ (digitArray at:1) even
a27a279701f8 Initial revision
claus
parents:
diff changeset
   336
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   337
a27a279701f8 Initial revision
claus
parents:
diff changeset
   338
even
a27a279701f8 Initial revision
claus
parents:
diff changeset
   339
    "return true if the receiver is even"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   340
a27a279701f8 Initial revision
claus
parents:
diff changeset
   341
    ^ (digitArray at:1) even
a27a279701f8 Initial revision
claus
parents:
diff changeset
   342
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   343
a27a279701f8 Initial revision
claus
parents:
diff changeset
   344
negative
a27a279701f8 Initial revision
claus
parents:
diff changeset
   345
    "return true, if the receiver is < 0"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   346
a27a279701f8 Initial revision
claus
parents:
diff changeset
   347
    ^ (sign < 0)
a27a279701f8 Initial revision
claus
parents:
diff changeset
   348
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   349
a27a279701f8 Initial revision
claus
parents:
diff changeset
   350
positive
a27a279701f8 Initial revision
claus
parents:
diff changeset
   351
    "return true, if the receiver is >= 0"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   352
a27a279701f8 Initial revision
claus
parents:
diff changeset
   353
    ^ (sign >= 0)
a27a279701f8 Initial revision
claus
parents:
diff changeset
   354
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   355
a27a279701f8 Initial revision
claus
parents:
diff changeset
   356
strictlyPositive
a27a279701f8 Initial revision
claus
parents:
diff changeset
   357
    "return true, if the receiver is > 0"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   358
a27a279701f8 Initial revision
claus
parents:
diff changeset
   359
    ^ (sign > 0)
a27a279701f8 Initial revision
claus
parents:
diff changeset
   360
! !
a27a279701f8 Initial revision
claus
parents:
diff changeset
   361
a27a279701f8 Initial revision
claus
parents:
diff changeset
   362
!LargeInteger methodsFor:'private'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   363
a27a279701f8 Initial revision
claus
parents:
diff changeset
   364
absEq:aLargeInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
   365
    "return true, if abs(self) = abs(theArgument)"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   366
a27a279701f8 Initial revision
claus
parents:
diff changeset
   367
    |len1 "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   368
     len2 "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   369
     d1   "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   370
     d2   "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   371
     otherDigits |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   372
a27a279701f8 Initial revision
claus
parents:
diff changeset
   373
    len1 := digitArray size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   374
    otherDigits := aLargeInteger digits.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   375
    len2 := otherDigits size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   376
a27a279701f8 Initial revision
claus
parents:
diff changeset
   377
    [(digitArray basicAt:len1) == 0] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   378
        len1 := len1 - 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   379
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   380
    [(otherDigits basicAt:len2) == 0] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   381
        len2 := len2 - 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   382
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   383
    (len1 ~~ len2) ifTrue:[^ false].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   384
    [len1 > 0] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   385
        d1 := digitArray basicAt:len1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   386
        d2 := otherDigits basicAt:len1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   387
        (d1 ~~ d2) ifTrue:[^ false].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   388
        len1 := len1 - 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   389
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   390
    ^ true
a27a279701f8 Initial revision
claus
parents:
diff changeset
   391
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   392
a27a279701f8 Initial revision
claus
parents:
diff changeset
   393
absLess:aLargeInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
   394
    "return true, if abs(self) < abs(theArgument)"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   395
a27a279701f8 Initial revision
claus
parents:
diff changeset
   396
    |len1 "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   397
     len2 "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   398
     d1   "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   399
     d2   "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   400
     otherDigits |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   401
a27a279701f8 Initial revision
claus
parents:
diff changeset
   402
    len1 := digitArray size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   403
    otherDigits := aLargeInteger digits.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   404
    len2 := otherDigits size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   405
a27a279701f8 Initial revision
claus
parents:
diff changeset
   406
    [(digitArray basicAt:len1) == 0] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   407
        len1 := len1 - 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   408
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   409
    [(otherDigits basicAt:len2) == 0] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   410
        len2 := len2 - 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   411
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   412
    (len1 < len2) ifTrue:[^ true].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   413
    (len1 > len2) ifTrue:[^ false].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   414
a27a279701f8 Initial revision
claus
parents:
diff changeset
   415
    [len1 > 0] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   416
        d1 := digitArray basicAt:len1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   417
        d2 := otherDigits basicAt:len1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   418
        (d1 < d2) ifTrue:[^ true].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   419
        (d1 > d2) ifTrue:[^ false].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   420
        len1 := len1 - 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   421
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   422
    ^ false
a27a279701f8 Initial revision
claus
parents:
diff changeset
   423
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   424
a27a279701f8 Initial revision
claus
parents:
diff changeset
   425
absPlus:aLargeInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
   426
    "return a LargeInteger representing abs(self) + abs(theArgument)"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   427
a27a279701f8 Initial revision
claus
parents:
diff changeset
   428
    |result done otherDigits resultDigits
a27a279701f8 Initial revision
claus
parents:
diff changeset
   429
     len1  "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   430
     len2  "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   431
     index "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   432
     carry "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   433
     sum   "{ Class: SmallInteger }" |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   434
a27a279701f8 Initial revision
claus
parents:
diff changeset
   435
    len1 := digitArray size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   436
    otherDigits := aLargeInteger digits.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   437
    len2 := otherDigits size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   438
a27a279701f8 Initial revision
claus
parents:
diff changeset
   439
    result := LargeInteger basicNew 
a27a279701f8 Initial revision
claus
parents:
diff changeset
   440
                           numberOfDigits:((len1 max: len2) + 1).
a27a279701f8 Initial revision
claus
parents:
diff changeset
   441
    result sign:1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   442
    resultDigits := result digits.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   443
a27a279701f8 Initial revision
claus
parents:
diff changeset
   444
    index := 1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   445
    carry := 0.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   446
a27a279701f8 Initial revision
claus
parents:
diff changeset
   447
    done := false.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   448
    [done] whileFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   449
        sum := carry.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   450
        (index <= len1) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   451
            sum := sum + (digitArray basicAt:index).
a27a279701f8 Initial revision
claus
parents:
diff changeset
   452
            (index <= len2) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   453
                sum := sum + (otherDigits basicAt:index)
a27a279701f8 Initial revision
claus
parents:
diff changeset
   454
            ]
a27a279701f8 Initial revision
claus
parents:
diff changeset
   455
        ] ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   456
            (index <= len2) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   457
                sum := sum + (otherDigits basicAt:index)
a27a279701f8 Initial revision
claus
parents:
diff changeset
   458
            ] ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   459
                "end reached"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   460
                done := true
a27a279701f8 Initial revision
claus
parents:
diff changeset
   461
            ]
a27a279701f8 Initial revision
claus
parents:
diff changeset
   462
        ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   463
        (sum > 9999) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   464
            carry := 1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   465
            sum := sum - 10000
a27a279701f8 Initial revision
claus
parents:
diff changeset
   466
        ] ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   467
            carry := 0
a27a279701f8 Initial revision
claus
parents:
diff changeset
   468
        ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   469
        resultDigits basicAt:index put:sum.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   470
        index := index + 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   471
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   472
    ^ result normalize
a27a279701f8 Initial revision
claus
parents:
diff changeset
   473
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   474
a27a279701f8 Initial revision
claus
parents:
diff changeset
   475
absMinus:aLargeInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
   476
    "return a LargeInteger representing abs(self) - abs(theArgument)"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   477
a27a279701f8 Initial revision
claus
parents:
diff changeset
   478
    |result done
a27a279701f8 Initial revision
claus
parents:
diff changeset
   479
     otherDigits resultDigits
a27a279701f8 Initial revision
claus
parents:
diff changeset
   480
     len1   "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   481
     len2   "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   482
     index  "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   483
     borrow "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   484
     diff   "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   485
     sum    "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   486
     carry  "{ Class: SmallInteger }" |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   487
a27a279701f8 Initial revision
claus
parents:
diff changeset
   488
    len1 := digitArray size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   489
    otherDigits := aLargeInteger digits.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   490
    len2 := otherDigits size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   491
a27a279701f8 Initial revision
claus
parents:
diff changeset
   492
    result := LargeInteger basicNew 
a27a279701f8 Initial revision
claus
parents:
diff changeset
   493
                           numberOfDigits:((len1 max: len2) + 1).
a27a279701f8 Initial revision
claus
parents:
diff changeset
   494
    result sign:1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   495
    resultDigits := result digits.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   496
a27a279701f8 Initial revision
claus
parents:
diff changeset
   497
    index := 1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   498
    borrow := 0.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   499
a27a279701f8 Initial revision
claus
parents:
diff changeset
   500
    done := false.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   501
    [done] whileFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   502
        diff := borrow.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   503
        (index <= len1) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   504
            diff := diff + (digitArray basicAt:index).
a27a279701f8 Initial revision
claus
parents:
diff changeset
   505
            (index <= len2) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   506
                diff := diff - (otherDigits basicAt:index)
a27a279701f8 Initial revision
claus
parents:
diff changeset
   507
            ]
a27a279701f8 Initial revision
claus
parents:
diff changeset
   508
        ] ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   509
            (index <= len2) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   510
                diff := diff - (otherDigits basicAt:index)
a27a279701f8 Initial revision
claus
parents:
diff changeset
   511
            ] ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   512
                "end reached"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   513
                done := true
a27a279701f8 Initial revision
claus
parents:
diff changeset
   514
            ]
a27a279701f8 Initial revision
claus
parents:
diff changeset
   515
        ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   516
        (diff < 0) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   517
            borrow := -1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   518
            diff := diff + 10000
a27a279701f8 Initial revision
claus
parents:
diff changeset
   519
        ] ifFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   520
            borrow := 0
a27a279701f8 Initial revision
claus
parents:
diff changeset
   521
        ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   522
        resultDigits basicAt:index put:diff.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   523
        index := index + 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   524
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   525
    (borrow ~~ 0) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   526
        result sign: -1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   527
        carry := 0.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   528
        1 to:(index - 1) do:[:i |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   529
            sum := ((resultDigits at:i) + carry - 10000) negated.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   530
            resultDigits at:i put:sum.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   531
            carry := 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   532
        ]
a27a279701f8 Initial revision
claus
parents:
diff changeset
   533
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   534
    ^ result normalize
a27a279701f8 Initial revision
claus
parents:
diff changeset
   535
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   536
a27a279701f8 Initial revision
claus
parents:
diff changeset
   537
absMul:aLargeInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
   538
    "return a LargeInteger representing abs(self) * abs(theArgument)"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   539
a27a279701f8 Initial revision
claus
parents:
diff changeset
   540
    |result otherDigits resultDigits
a27a279701f8 Initial revision
claus
parents:
diff changeset
   541
     len1     "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   542
     len2     "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   543
     dstIndex "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   544
     carry    "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   545
     prod     "{ Class: SmallInteger }" |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   546
a27a279701f8 Initial revision
claus
parents:
diff changeset
   547
    len1 := digitArray size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   548
    otherDigits := aLargeInteger digits.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   549
    len2 := otherDigits size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   550
a27a279701f8 Initial revision
claus
parents:
diff changeset
   551
    result := LargeInteger basicNew numberOfDigits:(len1 + len2 + 1).
a27a279701f8 Initial revision
claus
parents:
diff changeset
   552
    result sign:1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   553
    resultDigits := result digits.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   554
a27a279701f8 Initial revision
claus
parents:
diff changeset
   555
    "clear result"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   556
    resultDigits atAllPut:0.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   557
a27a279701f8 Initial revision
claus
parents:
diff changeset
   558
    1 to:len1 do:[:index1 |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   559
        1 to:len2 do:[:index2 |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   560
            dstIndex := index1 + index2 - 1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   561
            prod := (digitArray basicAt:index1) * (otherDigits basicAt:index2).
a27a279701f8 Initial revision
claus
parents:
diff changeset
   562
            prod := prod + (resultDigits basicAt:dstIndex).
a27a279701f8 Initial revision
claus
parents:
diff changeset
   563
            resultDigits basicAt:dstIndex put:(prod \\ 10000).
a27a279701f8 Initial revision
claus
parents:
diff changeset
   564
            carry := prod // 10000.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   565
            (carry ~~ 0) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   566
                resultDigits basicAt:(dstIndex + 1)
a27a279701f8 Initial revision
claus
parents:
diff changeset
   567
                                 put:(resultDigits basicAt:(dstIndex + 1)) + carry
a27a279701f8 Initial revision
claus
parents:
diff changeset
   568
            ]
a27a279701f8 Initial revision
claus
parents:
diff changeset
   569
        ]
a27a279701f8 Initial revision
claus
parents:
diff changeset
   570
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   571
    ^ result normalize
a27a279701f8 Initial revision
claus
parents:
diff changeset
   572
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   573
a27a279701f8 Initial revision
claus
parents:
diff changeset
   574
absDiv:anInteger
a27a279701f8 Initial revision
claus
parents:
diff changeset
   575
    "return an array with two LargeIntegers representing
a27a279701f8 Initial revision
claus
parents:
diff changeset
   576
     abs(self) // abs(theArgument) and abs(self) \\ abs(theArgument)"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   577
a27a279701f8 Initial revision
claus
parents:
diff changeset
   578
    |tmp1 tmp2 
a27a279701f8 Initial revision
claus
parents:
diff changeset
   579
     rem 
a27a279701f8 Initial revision
claus
parents:
diff changeset
   580
     count "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   581
     digit "{ Class: SmallInteger }" |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   582
a27a279701f8 Initial revision
claus
parents:
diff changeset
   583
    self == 0 ifTrue:[^ 0].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   584
    anInteger == 0 ifTrue:[^ self divideByZeroError].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   585
a27a279701f8 Initial revision
claus
parents:
diff changeset
   586
    self < anInteger ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   587
        ^ Array with:0 with:self
a27a279701f8 Initial revision
claus
parents:
diff changeset
   588
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   589
a27a279701f8 Initial revision
claus
parents:
diff changeset
   590
    tmp1 := self deepCopy.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   591
    tmp2 := anInteger deepCopy.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   592
    count := 0.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   593
    [tmp2 < tmp1] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   594
        tmp2 mul10.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   595
        count := count + 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   596
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   597
a27a279701f8 Initial revision
claus
parents:
diff changeset
   598
    tmp2 div10.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   599
a27a279701f8 Initial revision
claus
parents:
diff changeset
   600
    rem := 0 asLargeInteger. 
a27a279701f8 Initial revision
claus
parents:
diff changeset
   601
    [count == 0] whileFalse:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   602
        digit := 0.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   603
        [tmp1 >= tmp2] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   604
            digit := digit + 1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   605
            tmp1 := tmp1 - tmp2
a27a279701f8 Initial revision
claus
parents:
diff changeset
   606
        ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   607
        rem := rem * 10 + digit.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   608
        tmp2 div10.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   609
        count := count - 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   610
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   611
    ^ Array with:rem with:tmp1 
a27a279701f8 Initial revision
claus
parents:
diff changeset
   612
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   613
a27a279701f8 Initial revision
claus
parents:
diff changeset
   614
mul10
a27a279701f8 Initial revision
claus
parents:
diff changeset
   615
    "destructively multiply the receiver by 10.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   616
     private - used for division only"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   617
a27a279701f8 Initial revision
claus
parents:
diff changeset
   618
    |carry "{ Class: SmallInteger }"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   619
     prod  "{ Class: SmallInteger }"|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   620
a27a279701f8 Initial revision
claus
parents:
diff changeset
   621
    carry := 0.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   622
    1 to:(digitArray size) do:[:index |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   623
        prod := (digitArray at:index) * 10 + carry.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   624
        digitArray at:index put:prod \\ 10000.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   625
        carry := prod // 10000
a27a279701f8 Initial revision
claus
parents:
diff changeset
   626
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   627
    carry ~~ 0 ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   628
        digitArray := digitArray copyWith:carry
a27a279701f8 Initial revision
claus
parents:
diff changeset
   629
    ]
a27a279701f8 Initial revision
claus
parents:
diff changeset
   630
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   631
a27a279701f8 Initial revision
claus
parents:
diff changeset
   632
div10
a27a279701f8 Initial revision
claus
parents:
diff changeset
   633
    "destructively divide the receiver by 10.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   634
     private - used for division only"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   635
a27a279701f8 Initial revision
claus
parents:
diff changeset
   636
    |nDigits|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   637
a27a279701f8 Initial revision
claus
parents:
diff changeset
   638
    nDigits := digitArray size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   639
    1 to:(nDigits - 1) do:[:index |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   640
        digitArray at:index put:((digitArray at:index) // 10
a27a279701f8 Initial revision
claus
parents:
diff changeset
   641
                                + ((digitArray at:index + 1) \\ 10 * 1000))
a27a279701f8 Initial revision
claus
parents:
diff changeset
   642
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   643
    digitArray at:nDigits put:(digitArray at:nDigits) // 10
a27a279701f8 Initial revision
claus
parents:
diff changeset
   644
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   645
a27a279701f8 Initial revision
claus
parents:
diff changeset
   646
normalize
a27a279701f8 Initial revision
claus
parents:
diff changeset
   647
    "if the receiver can be represented as a SmallInteger, return
a27a279701f8 Initial revision
claus
parents:
diff changeset
   648
     a SmallInteger with my value; otherwise return self with leading
a27a279701f8 Initial revision
claus
parents:
diff changeset
   649
     zeros removed"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   650
a27a279701f8 Initial revision
claus
parents:
diff changeset
   651
    |index "{ Class: SmallInteger }" |
a27a279701f8 Initial revision
claus
parents:
diff changeset
   652
a27a279701f8 Initial revision
claus
parents:
diff changeset
   653
    index := digitArray size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   654
    [(index > 0) and:[(digitArray at:index) == 0]] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   655
        index := index - 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   656
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   657
    (index == 1) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   658
        ^ (digitArray at:1) * sign
a27a279701f8 Initial revision
claus
parents:
diff changeset
   659
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   660
    (index == 2) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   661
        ^ ((digitArray at:2) * 10000 + (digitArray at:1)) * sign
a27a279701f8 Initial revision
claus
parents:
diff changeset
   662
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   663
    (index == 0) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   664
        ^ 0
a27a279701f8 Initial revision
claus
parents:
diff changeset
   665
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   666
    (index ~~ digitArray size) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   667
        digitArray := digitArray copyFrom:1 to:index
a27a279701f8 Initial revision
claus
parents:
diff changeset
   668
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   669
    ^ self
a27a279701f8 Initial revision
claus
parents:
diff changeset
   670
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   671
a27a279701f8 Initial revision
claus
parents:
diff changeset
   672
digits
a27a279701f8 Initial revision
claus
parents:
diff changeset
   673
    ^ digitArray
a27a279701f8 Initial revision
claus
parents:
diff changeset
   674
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   675
a27a279701f8 Initial revision
claus
parents:
diff changeset
   676
numberOfDigits
a27a279701f8 Initial revision
claus
parents:
diff changeset
   677
    ^ digitArray size
a27a279701f8 Initial revision
claus
parents:
diff changeset
   678
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   679
a27a279701f8 Initial revision
claus
parents:
diff changeset
   680
numberOfDigits:nDigits
a27a279701f8 Initial revision
claus
parents:
diff changeset
   681
    digitArray := Array new:nDigits
a27a279701f8 Initial revision
claus
parents:
diff changeset
   682
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   683
a27a279701f8 Initial revision
claus
parents:
diff changeset
   684
sign:aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   685
    sign := aNumber
a27a279701f8 Initial revision
claus
parents:
diff changeset
   686
! !
a27a279701f8 Initial revision
claus
parents:
diff changeset
   687
a27a279701f8 Initial revision
claus
parents:
diff changeset
   688
!LargeInteger methodsFor:'printing & storing'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   689
a27a279701f8 Initial revision
claus
parents:
diff changeset
   690
storeString
a27a279701f8 Initial revision
claus
parents:
diff changeset
   691
    "return a string representation of the receiver, which can be
a27a279701f8 Initial revision
claus
parents:
diff changeset
   692
     used to reconstruct the receiver"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   693
a27a279701f8 Initial revision
claus
parents:
diff changeset
   694
    ^ self printString , ' asLargeInteger'
a27a279701f8 Initial revision
claus
parents:
diff changeset
   695
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   696
a27a279701f8 Initial revision
claus
parents:
diff changeset
   697
printString
a27a279701f8 Initial revision
claus
parents:
diff changeset
   698
    |aString index fourDigits n|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   699
a27a279701f8 Initial revision
claus
parents:
diff changeset
   700
    index := digitArray size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   701
    [(index > 1) and:[(digitArray at:index) == 0]] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   702
        index := index - 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   703
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   704
    (sign == 0) ifTrue: [^ '0'].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   705
    (sign == -1) ifTrue: [
a27a279701f8 Initial revision
claus
parents:
diff changeset
   706
        aString := '-'
a27a279701f8 Initial revision
claus
parents:
diff changeset
   707
    ] ifFalse: [
a27a279701f8 Initial revision
claus
parents:
diff changeset
   708
        aString := ''
a27a279701f8 Initial revision
claus
parents:
diff changeset
   709
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   710
a27a279701f8 Initial revision
claus
parents:
diff changeset
   711
    aString := aString , (digitArray basicAt:index) printString.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   712
    index := index - 1.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   713
    [index > 0] whileTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   714
        fourDigits := (digitArray basicAt:index) printString.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   715
        n := fourDigits size.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   716
        (n < 4) ifTrue:[
a27a279701f8 Initial revision
claus
parents:
diff changeset
   717
            aString := aString , ('000' copyFrom:n to:3)
a27a279701f8 Initial revision
claus
parents:
diff changeset
   718
        ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   719
        aString := aString , fourDigits.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   720
        index := index - 1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   721
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   722
    ^ aString
a27a279701f8 Initial revision
claus
parents:
diff changeset
   723
! !