94 %} |
118 %} |
95 |
119 |
96 "SmallInteger maxBytes" |
120 "SmallInteger maxBytes" |
97 ! |
121 ! |
98 |
122 |
|
123 maxVal |
|
124 "return the largest Integer representable as SmallInteger. |
|
125 For very special uses only - not constant across implementations" |
|
126 |
|
127 %{ /* NOCONTEXT */ |
|
128 RETURN ( _MKSMALLINT(_MAX_INT) ); |
|
129 %} |
|
130 |
|
131 "SmallInteger maxVal" |
|
132 ! |
|
133 |
99 minVal |
134 minVal |
100 "return the smallest Integer representable as SmallInteger. |
135 "return the smallest Integer representable as SmallInteger. |
101 For very special uses only - not constant across implementations" |
136 For very special uses only - not constant across implementations" |
102 |
137 |
103 %{ /* NOCONTEXT */ |
138 %{ /* NOCONTEXT */ |
104 RETURN ( _MKSMALLINT(_MIN_INT) ); |
139 RETURN ( _MKSMALLINT(_MIN_INT) ); |
105 %} |
140 %} |
106 |
141 |
107 "SmallInteger minVal" |
142 "SmallInteger minVal" |
108 ! |
|
109 |
|
110 maxVal |
|
111 "return the largest Integer representable as SmallInteger. |
|
112 For very special uses only - not constant across implementations" |
|
113 |
|
114 %{ /* NOCONTEXT */ |
|
115 RETURN ( _MKSMALLINT(_MAX_INT) ); |
|
116 %} |
|
117 |
|
118 "SmallInteger maxVal" |
|
119 ! ! |
143 ! ! |
120 |
144 |
121 !SmallInteger class methodsFor:'queries'! |
145 !SmallInteger class methodsFor:'queries'! |
122 |
|
123 isBuiltInClass |
|
124 "this class is known by the run-time-system" |
|
125 |
|
126 ^ true |
|
127 ! |
|
128 |
146 |
129 canBeSubclassed |
147 canBeSubclassed |
130 "return true, if its allowed to create subclasses of the receiver. |
148 "return true, if its allowed to create subclasses of the receiver. |
131 Return nil here - since it is NOT possible for SmallInteger" |
149 Return nil here - since it is NOT possible for SmallInteger" |
132 |
150 |
133 ^ false |
151 ^ false |
|
152 ! |
|
153 |
|
154 isBuiltInClass |
|
155 "this class is known by the run-time-system" |
|
156 |
|
157 ^ true |
134 ! ! |
158 ! ! |
135 |
159 |
136 !SmallInteger methodsFor:'catching messages'! |
|
137 |
|
138 basicAt:index |
|
139 "catch indexed access - report an error |
|
140 defined here since basicAt: in Object ommits the SmallInteger check." |
|
141 |
|
142 self notIndexed |
|
143 ! |
|
144 |
|
145 basicAt:index put:anObject |
|
146 "catch indexed access - report an error |
|
147 defined here since basicAt:put: in Object ommits the SmallInteger check." |
|
148 |
|
149 self notIndexed |
|
150 ! |
|
151 |
|
152 size |
|
153 "return the number of indexed instvars - SmallIntegers have none." |
|
154 |
|
155 ^ 0 |
|
156 ! |
|
157 |
|
158 basicSize |
|
159 "return the number of indexed instvars - SmallIntegers have none. |
|
160 Defined here since basicSize in Object ommits the SmallInteger check." |
|
161 |
|
162 ^ 0 |
|
163 ! ! |
|
164 |
|
165 !SmallInteger methodsFor:'copying'! |
|
166 |
|
167 shallowCopy |
|
168 "return a shallow copy of myself |
|
169 - reimplemented here since smallintegers are unique" |
|
170 |
|
171 ^ self |
|
172 ! |
|
173 |
|
174 simpleDeepCopy |
|
175 "return a deep copy of myself |
|
176 - reimplemented here since smallintegers are unique" |
|
177 |
|
178 ^ self |
|
179 ! |
|
180 |
|
181 deepCopyUsing:aDictionary |
|
182 "return a deep copy of myself |
|
183 - reimplemented here since smallintegers are unique" |
|
184 |
|
185 ^ self |
|
186 ! |
|
187 |
|
188 deepCopy |
|
189 "return a deep copy of myself |
|
190 - reimplemented here since smallintegers are unique" |
|
191 |
|
192 ^ self |
|
193 ! ! |
|
194 |
|
195 !SmallInteger methodsFor:'comparing'! |
|
196 |
|
197 = aNumber |
|
198 "return true, if the arguments value is equal to mine" |
|
199 |
|
200 %{ /* NOCONTEXT */ |
|
201 |
|
202 if (aNumber == self) { |
|
203 RETURN ( true ); |
|
204 } |
|
205 if (! __isNonNilObject(aNumber)) { |
|
206 /* a smallint or nil */ |
|
207 RETURN ( false ); |
|
208 } |
|
209 |
|
210 if (__isFloatLike(aNumber)) { |
|
211 RETURN ( ((double)_intVal(self) == _floatVal(aNumber)) ? true : false ); |
|
212 } |
|
213 %} |
|
214 . |
|
215 aNumber respondsToArithmetic ifFalse:[^ false]. |
|
216 ^ self retry:#= coercing:aNumber |
|
217 ! |
|
218 |
|
219 ~= aNumber |
|
220 "return true, if the arguments value is not equal to mine" |
|
221 |
|
222 %{ /* NOCONTEXT */ |
|
223 |
|
224 if (aNumber == self) { |
|
225 RETURN ( false ); |
|
226 } |
|
227 if (! __isNonNilObject(aNumber)) { |
|
228 /* a smallint or nil */ |
|
229 RETURN ( true ); |
|
230 } |
|
231 |
|
232 if (__isFloatLike(aNumber)) { |
|
233 RETURN ( ((double)_intVal(self) == _floatVal(aNumber)) ? false : true ); |
|
234 } |
|
235 %} |
|
236 . |
|
237 aNumber respondsToArithmetic ifFalse:[^ true]. |
|
238 ^ self retry:#~= coercing:aNumber |
|
239 ! |
|
240 |
|
241 < aNumber |
|
242 "return true, if the argument is greater than the receiver" |
|
243 |
|
244 %{ /* NOCONTEXT */ |
|
245 |
|
246 if (__isSmallInteger(aNumber)) { |
|
247 #ifdef POSITIVE_ADDRESSES |
|
248 RETURN ( (_intVal(self) < _intVal(aNumber)) ? true : false ); |
|
249 #else |
|
250 /* tag bit does not change ordering */ |
|
251 RETURN ( ((INT)self < (INT)aNumber) ? true : false ); |
|
252 #endif |
|
253 } |
|
254 if (__isFloatLike(aNumber)) { |
|
255 RETURN ( ((double)_intVal(self) < _floatVal(aNumber)) ? true : false ); |
|
256 } |
|
257 %} |
|
258 . |
|
259 ^ aNumber lessFromInteger:self |
|
260 "^ self retry:#< coercing:aNumber" |
|
261 ! |
|
262 |
|
263 > aNumber |
|
264 "return true, if the argument is less than the receiver" |
|
265 |
|
266 %{ /* NOCONTEXT */ |
|
267 |
|
268 if (__isSmallInteger(aNumber)) { |
|
269 #ifdef POSITIVE_ADDRESSES |
|
270 RETURN ( (_intVal(self) > _intVal(aNumber)) ? true : false ); |
|
271 #else |
|
272 /* tag bit does not change ordering */ |
|
273 RETURN ( ((INT)self > (INT)aNumber) ? true : false ); |
|
274 #endif |
|
275 } |
|
276 if (__isFloatLike(aNumber)) { |
|
277 RETURN ( ((double)_intVal(self) > _floatVal(aNumber)) ? true : false ); |
|
278 } |
|
279 %} |
|
280 . |
|
281 ^ self retry:#> coercing:aNumber |
|
282 ! |
|
283 |
|
284 >= aNumber |
|
285 "return true, if the argument is less or equal" |
|
286 |
|
287 %{ /* NOCONTEXT */ |
|
288 |
|
289 if (__isSmallInteger(aNumber)) { |
|
290 #ifdef POSITIVE_ADDRESSES |
|
291 RETURN ( (_intVal(self) >= _intVal(aNumber)) ? true : false ); |
|
292 #else |
|
293 /* tag bit does not change ordering */ |
|
294 RETURN ( ((INT)self >= (INT)aNumber) ? true : false ); |
|
295 #endif |
|
296 } |
|
297 if (__isFloatLike(aNumber)) { |
|
298 RETURN ( ((double)_intVal(self) >= _floatVal(aNumber)) ? true : false ); |
|
299 } |
|
300 %} |
|
301 . |
|
302 ^ self retry:#>= coercing:aNumber |
|
303 ! |
|
304 |
|
305 <= aNumber |
|
306 "return true, if the argument is greater or equal" |
|
307 |
|
308 %{ /* NOCONTEXT */ |
|
309 |
|
310 if (__isSmallInteger(aNumber)) { |
|
311 #ifdef POSITIVE_ADDRESSES |
|
312 RETURN ( (_intVal(self) <= _intVal(aNumber)) ? true : false ); |
|
313 #else |
|
314 /* tag bit does not change ordering */ |
|
315 RETURN ( ((INT)self <= (INT)aNumber) ? true : false ); |
|
316 #endif |
|
317 } |
|
318 if (__isFloatLike(aNumber)) { |
|
319 RETURN ( ((double)_intVal(self) <= _floatVal(aNumber)) ? true : false ); |
|
320 } |
|
321 %} |
|
322 . |
|
323 ^ self retry:#<= coercing:aNumber |
|
324 ! |
|
325 |
|
326 hash |
|
327 "return an integer useful for hashing on value" |
|
328 |
|
329 self >= 0 ifTrue:[^ self]. |
|
330 ^ self negated |
|
331 ! |
|
332 |
|
333 identityHash |
|
334 "return an integer useful for hashing on identity" |
|
335 |
|
336 self >= 0 ifTrue:[^ self]. |
|
337 ^ self negated |
|
338 ! |
|
339 |
|
340 min:aNumber |
|
341 "return the receiver or the argument, whichever is smaller" |
|
342 |
|
343 %{ /* NOCONTEXT */ |
|
344 |
|
345 if (__isSmallInteger(aNumber)) { |
|
346 #ifdef POSITIVE_ADDRESSES |
|
347 if (_intVal(self) < _intVal(aNumber)) { |
|
348 #else |
|
349 /* tag bit does not change ordering */ |
|
350 if ((INT)(self) < (INT)(aNumber)) { |
|
351 #endif |
|
352 RETURN ( self ); |
|
353 } |
|
354 RETURN ( aNumber ); |
|
355 } |
|
356 if (__isFloatLike(aNumber)) { |
|
357 if ( (double)_intVal(self) < _floatVal(aNumber) ) { |
|
358 RETURN ( self ); |
|
359 } |
|
360 RETURN ( aNumber ); |
|
361 } |
|
362 %} |
|
363 . |
|
364 (self < aNumber) ifTrue:[^ self]. |
|
365 ^ aNumber |
|
366 ! |
|
367 |
|
368 max:aNumber |
|
369 "return the receiver or the argument, whichever is greater" |
|
370 |
|
371 %{ /* NOCONTEXT */ |
|
372 |
|
373 if (__isSmallInteger(aNumber)) { |
|
374 #ifdef POSITIVE_ADDRESSES |
|
375 if (_intVal(self) > _intVal(aNumber)) { |
|
376 #else |
|
377 /* tag bit does not change ordering */ |
|
378 if ((INT)(self) > (INT)(aNumber)) { |
|
379 #endif |
|
380 RETURN ( self ); |
|
381 } |
|
382 RETURN ( aNumber ); |
|
383 } |
|
384 if (__isFloatLike(aNumber)) { |
|
385 if ( (double)_intVal(self) > _floatVal(aNumber) ) { |
|
386 RETURN ( self ); |
|
387 } |
|
388 RETURN ( aNumber ); |
|
389 } |
|
390 %} |
|
391 . |
|
392 (self > aNumber) ifTrue:[^ self]. |
|
393 ^ aNumber |
|
394 ! ! |
|
395 |
|
396 !SmallInteger methodsFor:'testing'! |
|
397 |
|
398 negative |
|
399 "return true, if the receiver is less than zero |
|
400 reimplemented here for speed" |
|
401 |
|
402 %{ /* NOCONTEXT */ |
|
403 |
|
404 #ifdef POSITIVE_ADDRESSES |
|
405 RETURN ( (_intVal(self) < 0) ? true : false ); |
|
406 #else |
|
407 /* tag bit does not change sign */ |
|
408 RETURN ( ((INT)(self) < 0) ? true : false ); |
|
409 #endif |
|
410 %} |
|
411 ! |
|
412 |
|
413 positive |
|
414 "return true, if the receiver is not negative |
|
415 reimplemented here for speed" |
|
416 |
|
417 %{ /* NOCONTEXT */ |
|
418 |
|
419 #ifdef POSITIVE_ADDRESSES |
|
420 RETURN ( (_intVal(self) >= 0) ? true : false ); |
|
421 #else |
|
422 /* tag bit does not change sign */ |
|
423 RETURN ( ((INT)(self) >= 0) ? true : false ); |
|
424 #endif |
|
425 %} |
|
426 ! |
|
427 |
|
428 strictlyPositive |
|
429 "return true, if the receiver is greater than zero |
|
430 reimplemented here for speed" |
|
431 |
|
432 %{ /* NOCONTEXT */ |
|
433 |
|
434 #ifdef POSITIVE_ADDRESSES |
|
435 RETURN ( (_intVal(self) > 0) ? true : false ); |
|
436 #else |
|
437 /* tag bit does not change sign */ |
|
438 RETURN ( ((INT)(self) > 0) ? true : false ); |
|
439 #endif |
|
440 %} |
|
441 ! |
|
442 |
|
443 sign |
|
444 "return the sign of the receiver |
|
445 reimplemented here for speed" |
|
446 |
|
447 %{ /* NOCONTEXT */ |
|
448 |
|
449 INT val = _intVal(self); |
|
450 |
|
451 if (val < 0) { |
|
452 RETURN ( _MKSMALLINT(-1) ); |
|
453 } |
|
454 if (val > 0) { |
|
455 RETURN ( _MKSMALLINT(1) ); |
|
456 } |
|
457 RETURN ( _MKSMALLINT(0) ); |
|
458 %} |
|
459 ! |
|
460 |
|
461 between:min and:max |
|
462 "return true if the receiver is less than or equal to the argument max |
|
463 and greater than or equal to the argument min. |
|
464 - reimplemented here for speed" |
|
465 |
|
466 %{ /* NOCONTEXT */ |
|
467 |
|
468 if (__bothSmallInteger(min, max)) { |
|
469 REGISTER INT selfVal; |
|
470 |
|
471 selfVal = _intVal(self); |
|
472 if (selfVal < _intVal(min)) { |
|
473 RETURN ( false ); |
|
474 } |
|
475 if (selfVal > _intVal(max)) { |
|
476 RETURN ( false ); |
|
477 } |
|
478 RETURN ( true ); |
|
479 } |
|
480 %} |
|
481 . |
|
482 (self < min) ifTrue:[^ false]. |
|
483 (self > max) ifTrue:[^ false]. |
|
484 ^ true |
|
485 ! |
|
486 |
|
487 even |
|
488 "return true, if the receiver is even" |
|
489 |
|
490 %{ /* NOCONTEXT */ |
|
491 |
|
492 #ifdef POSITIVE_ADDRESSES |
|
493 RETURN ( ((INT)self & 1) ? false : true ); |
|
494 #else |
|
495 RETURN ( ((INT)self & ((INT)_MKSMALLINT(1) & ~TAG_INT)) ? false : true ); |
|
496 #endif |
|
497 %} |
|
498 ! |
|
499 |
|
500 odd |
|
501 "return true, if the receiver is odd" |
|
502 |
|
503 %{ /* NOCONTEXT */ |
|
504 |
|
505 #ifdef POSITIVE_ADDRESSES |
|
506 RETURN ( ((INT)self & 1) ? true : false ); |
|
507 #else |
|
508 RETURN ( ((INT)self & ((INT)_MKSMALLINT(1) & ~TAG_INT)) ? true : false ); |
|
509 #endif |
|
510 %} |
|
511 ! ! |
|
512 |
|
513 !SmallInteger methodsFor:'arithmetic'! |
160 !SmallInteger methodsFor:'arithmetic'! |
514 |
|
515 + aNumber |
|
516 "return the sum of the receivers value and the arguments value" |
|
517 |
|
518 %{ /* NOCONTEXT */ |
|
519 |
|
520 if (__isSmallInteger(aNumber)) { |
|
521 #ifdef _ADD_IO_IO |
|
522 RETURN ( _ADD_IO_IO(self, aNumber) ); |
|
523 #else |
|
524 REGISTER INT sum; |
|
525 extern OBJ _MKLARGEINT(); |
|
526 |
|
527 sum = _intVal(self) + _intVal(aNumber); |
|
528 if ((sum >= _MIN_INT) && (sum <= _MAX_INT)) { |
|
529 RETURN ( _MKSMALLINT(sum) ); |
|
530 } |
|
531 RETURN ( _MKLARGEINT(sum) ); |
|
532 #endif |
|
533 } |
|
534 if (__isFloatLike(aNumber)) { |
|
535 OBJ newFloat; |
|
536 double val = (double)_intVal(self) + _floatVal(aNumber); |
|
537 |
|
538 _qMKFLOAT(newFloat, val, SENDER); |
|
539 RETURN ( newFloat ); |
|
540 } |
|
541 %} |
|
542 . |
|
543 ^ aNumber sumFromInteger:self |
|
544 ! |
|
545 |
|
546 - aNumber |
|
547 "return the difference of the receivers value and the arguments value" |
|
548 |
|
549 %{ /* NOCONTEXT */ |
|
550 |
|
551 if (__isSmallInteger(aNumber)) { |
|
552 #ifdef _SUB_IO_IO |
|
553 RETURN ( _SUB_IO_IO(self, aNumber) ); |
|
554 #else |
|
555 REGISTER INT diff; |
|
556 extern OBJ _MKLARGEINT(); |
|
557 |
|
558 diff = _intVal(self) - _intVal(aNumber); |
|
559 if ((diff >= _MIN_INT) && (diff <= _MAX_INT)) { |
|
560 RETURN ( _MKSMALLINT(diff) ); |
|
561 } |
|
562 RETURN ( _MKLARGEINT(diff) ); |
|
563 #endif |
|
564 } |
|
565 if (__isFloatLike(aNumber)) { |
|
566 OBJ newFloat; |
|
567 double val = (double)_intVal(self) - _floatVal(aNumber); |
|
568 |
|
569 _qMKFLOAT(newFloat, val, SENDER); |
|
570 RETURN ( newFloat ); |
|
571 } |
|
572 %} |
|
573 . |
|
574 ^ aNumber differenceFromInteger:self |
|
575 ! |
|
576 |
161 |
577 * aNumber |
162 * aNumber |
578 "return the product of the receivers value and the arguments value" |
163 "return the product of the receivers value and the arguments value" |
579 |
164 |
580 %{ /* NOCONTEXT */ |
165 %{ /* NOCONTEXT */ |
881 %}. |
528 %}. |
882 "only reached for minVal" |
529 "only reached for minVal" |
883 ^ (LargeInteger value:(SmallInteger maxVal)) + 1 |
530 ^ (LargeInteger value:(SmallInteger maxVal)) + 1 |
884 ! ! |
531 ! ! |
885 |
532 |
886 !SmallInteger methodsFor:'modulu arithmetic'! |
533 !SmallInteger methodsFor:'binary storage'! |
887 |
534 |
888 times:aNumber |
535 hasSpecialBinaryRepresentation |
889 "return the product of the receiver and the argument, as SmallInteger. |
536 "return true, if the receiver has a special binary representation" |
890 The argument must be another SmallInteger. |
537 |
891 If the result overflows the smallInteger range, the value modulu the |
538 ^ true |
892 smallInteger range is returned (i.e. the low bits of the product). |
539 ! |
893 This is of course not always correct, but some code does a modulu anyway |
540 |
894 and can therefore speed things up by not going through LargeIntegers." |
541 storeBinaryOn: stream manager: manager |
895 |
542 "append a binary representation onto stream. |
896 %{ /* NOCONTEXT */ |
543 Redefined since SmallIntegers are stored as their value with the 32nd bit |
897 |
544 set as a tag. |
898 if (__isSmallInteger(aNumber)) { |
545 To make the binary file a bit more compact, zeros and single byte ints |
899 RETURN ( _MKSMALLINT((_intVal(self) * _intVal(aNumber)) & 0x7FFFFFFF) ); |
546 are stored with a more compact representation (using special type-codes)." |
900 } |
547 |
901 %} |
548 self == 0 ifTrue:[ |
902 . |
549 stream nextPut: manager codeForZero. |
903 self primitiveFailed |
550 ^ self |
904 ! |
551 ]. |
905 |
552 (self between:0 and:255) ifTrue:[ |
906 plus:aNumber |
553 stream nextPut: manager codeForByteInteger. |
907 "return the sum of the receiver and the argument, as SmallInteger. |
554 stream nextPut: self. |
908 The argument must be another SmallInteger. |
555 ^ self |
909 If the result overflows the smallInteger range, the value modulu the |
556 ]. |
910 smallInteger range is returned (i.e. the low bits of the sum). |
557 stream nextPut: (((self bitShift: -24) bitAnd: 16rFF) bitOr: 16r80). |
911 This is of course not always correct, but some code does a modulu anyway |
558 stream nextPut: ((self bitShift: -16) bitAnd: 16rFF). |
912 and can therefore speed things up by not going through LargeIntegers." |
559 stream nextPut: ((self bitShift: -8) bitAnd: 16rFF). |
913 |
560 stream nextPut: (self bitAnd: 16rFF) |
914 %{ /* NOCONTEXT */ |
|
915 |
|
916 if (__isSmallInteger(aNumber)) { |
|
917 RETURN ( _MKSMALLINT((_intVal(self) + _intVal(aNumber)) & 0x7FFFFFFF) ); |
|
918 } |
|
919 %} |
|
920 . |
|
921 self primitiveFailed |
|
922 ! |
|
923 |
|
924 subtract:aNumber |
|
925 "return the difference of the receiver and the argument, as SmallInteger. |
|
926 The argument must be another SmallInteger. |
|
927 If the result overflows the smallInteger range, the value modulu the |
|
928 smallInteger range is returned (i.e. the low bits of the sum). |
|
929 This is of course not always correct, but some code does a modulu anyway |
|
930 and can therefore speed things up by not going through LargeIntegers." |
|
931 |
|
932 %{ /* NOCONTEXT */ |
|
933 |
|
934 if (__isSmallInteger(aNumber)) { |
|
935 RETURN ( _MKSMALLINT((_intVal(self) - _intVal(aNumber)) & 0x7FFFFFFF) ); |
|
936 } |
|
937 %} |
|
938 . |
|
939 self primitiveFailed |
|
940 ! ! |
561 ! ! |
941 |
562 |
942 !SmallInteger class methodsFor:'bit mask constants'! |
|
943 |
|
944 bitMaskFor:index |
|
945 "return a bitmask for the index's bit (index starts at 1)" |
|
946 |
|
947 (index between:1 and:SmallInteger maxBits) ifFalse:[ |
|
948 ^ self error:'index out of bounds' |
|
949 ]. |
|
950 ^ 1 bitShift:(index - 1) |
|
951 ! ! |
|
952 |
|
953 !SmallInteger methodsFor:'bit operators'! |
563 !SmallInteger methodsFor:'bit operators'! |
|
564 |
|
565 allMask:anInteger |
|
566 "return true if all 1-bits in anInteger are also 1 in the receiver" |
|
567 |
|
568 ^ (self bitAnd:anInteger) == anInteger |
|
569 |
|
570 "2r00001111 allMask:2r00000001" |
|
571 "2r00001111 allMask:2r00011110" |
|
572 "2r00001111 allMask:2r00000000" |
|
573 ! |
|
574 |
|
575 anyMask:anInteger |
|
576 "return true if any 1-bits in anInteger is also 1 in the receiver. |
|
577 (somewhat incorrect, if the mask is zero)" |
|
578 |
|
579 ^ (self bitAnd:anInteger) ~~ 0 |
|
580 |
|
581 "2r00001111 anyMask:2r00000001" |
|
582 "2r00001111 anyMask:2r11110000" |
|
583 ! |
|
584 |
|
585 bitAnd:anInteger |
|
586 "return the bitwise-and of the receiver and the argument, anInteger" |
|
587 |
|
588 %{ /* NOCONTEXT */ |
|
589 |
|
590 /* anding the tags doesn't change it */ |
|
591 if (__isSmallInteger(anInteger)) { |
|
592 RETURN ( ((OBJ) ((INT)self & (INT)anInteger)) ); |
|
593 } |
|
594 %} |
|
595 . |
|
596 ^ self retry:#bitAnd coercing:anInteger |
|
597 |
|
598 "(2r001010100 bitAnd:2r00001111) radixPrintStringRadix:2" |
|
599 ! |
954 |
600 |
955 bitAt:index |
601 bitAt:index |
956 "return the value of the index's bit (index starts at 1). |
602 "return the value of the index's bit (index starts at 1). |
957 Notice: the result of bitAt: on negative receivers is not |
603 Notice: the result of bitAt: on negative receivers is not |
958 defined in the language standard (since the implementation |
604 defined in the language standard (since the implementation |
966 mask := 1 bitShift:(index - 1). |
612 mask := 1 bitShift:(index - 1). |
967 ((self bitAnd:mask) == 0) ifTrue:[^ 0]. |
613 ((self bitAnd:mask) == 0) ifTrue:[^ 0]. |
968 ^ 1 |
614 ^ 1 |
969 ! |
615 ! |
970 |
616 |
971 allMask:anInteger |
617 bitInvert |
972 "return true if all 1-bits in anInteger are also 1 in the receiver" |
618 "return the value of the receiver with all bits inverted" |
973 |
619 |
974 ^ (self bitAnd:anInteger) == anInteger |
620 %{ /* NOCONTEXT */ |
975 |
621 |
976 "2r00001111 allMask:2r00000001" |
622 /* invert anything except tag bits */ |
977 "2r00001111 allMask:2r00011110" |
623 RETURN ( ((OBJ) ((INT)self ^ ~TAG_MASK)) ); |
978 "2r00001111 allMask:2r00000000" |
624 %} |
979 ! |
625 ! |
980 |
626 |
981 anyMask:anInteger |
627 bitOr:anInteger |
982 "return true if any 1-bits in anInteger is also 1 in the receiver. |
628 "return the bitwise-or of the receiver and the argument, anInteger" |
983 (somewhat incorrect, if the mask is zero)" |
629 |
984 |
630 %{ /* NOCONTEXT */ |
985 ^ (self bitAnd:anInteger) ~~ 0 |
631 |
986 |
632 /* oring the tags doesn't change it */ |
987 "2r00001111 anyMask:2r00000001" |
633 if (__isSmallInteger(anInteger)) { |
988 "2r00001111 anyMask:2r11110000" |
634 RETURN ( ((OBJ) ((INT)self | (INT)anInteger)) ); |
989 ! |
635 } |
990 |
636 %} |
991 noMask:anInteger |
637 . |
992 "return true if no 1-bit in anInteger is 1 in the receiver" |
638 ^ self retry:#bitOr coercing:anInteger |
993 |
639 |
994 ^ (self bitAnd:anInteger) == 0 |
640 "(2r000000100 bitOr:2r00000011) radixPrintStringRadix:2" |
995 |
|
996 "2r00001111 noMask:2r00000001" |
|
997 "2r00001111 noMask:2r11110000" |
|
998 ! |
|
999 |
|
1000 highBit |
|
1001 "return the bitIndex of the highest bit set. The returned bitIndex |
|
1002 starts at 1 for the least significant bit. Returns -1 if no bit is set." |
|
1003 |
|
1004 %{ /* NOCONTEXT */ |
|
1005 |
|
1006 INT mask, index, bits; |
|
1007 |
|
1008 bits = _intVal(self); |
|
1009 if (bits == 0) { |
|
1010 RETURN ( _MKSMALLINT(-1) ); |
|
1011 } |
|
1012 #ifdef alpha |
|
1013 mask = 0x2000000000000000; |
|
1014 index = 62; |
|
1015 #else |
|
1016 mask = 0x20000000; |
|
1017 index = 30; |
|
1018 #endif |
|
1019 while (index) { |
|
1020 if (bits & mask) break; |
|
1021 mask = mask >> 1; |
|
1022 index--; |
|
1023 } |
|
1024 RETURN ( _MKSMALLINT(index) ); |
|
1025 %} |
|
1026 "2r000100 highBit" |
|
1027 "2r010100 highBit" |
|
1028 "2r000001 highBit" |
|
1029 "0 highBit" |
|
1030 "SmallInteger maxVal highBit" |
|
1031 ! |
|
1032 |
|
1033 lowBit |
|
1034 "return the bitIndex of the lowest bit set. The returned bitIndex |
|
1035 starts at 1 for the least significant bit. Returns -1 if no bit is set." |
|
1036 |
|
1037 %{ /* NOCONTEXT */ |
|
1038 |
|
1039 INT mask, index, bits; |
|
1040 |
|
1041 bits = _intVal(self); |
|
1042 if (bits == 0) { |
|
1043 RETURN ( _MKSMALLINT(-1) ); |
|
1044 } |
|
1045 mask = 1; |
|
1046 index = 1; |
|
1047 #ifdef alpha |
|
1048 while (index != 63) { |
|
1049 #else |
|
1050 while (index != 31) { |
|
1051 #endif |
|
1052 if (bits & mask) { |
|
1053 RETURN ( _MKSMALLINT(index) ); |
|
1054 } |
|
1055 mask = mask << 1; |
|
1056 index++; |
|
1057 } |
|
1058 RETURN ( _MKSMALLINT(-1) ); |
|
1059 %} |
|
1060 "2r000100 lowBit" |
|
1061 "2r010010 lowBit" |
|
1062 "2r100001 lowBit" |
|
1063 "0 lowBit" |
|
1064 ! |
641 ! |
1065 |
642 |
1066 bitShift:shiftCount |
643 bitShift:shiftCount |
1067 "return the value of the receiver shifted by shiftCount bits; |
644 "return the value of the receiver shifted by shiftCount bits; |
1068 leftShift if shiftCount > 0; rightShift otherwise. |
645 leftShift if shiftCount > 0; rightShift otherwise. |
1280 (16r12345678 digitAt:3) printStringRadix:16 |
884 (16r12345678 digitAt:3) printStringRadix:16 |
1281 (16r12345678 digitAt:15) printStringRadix:16 |
885 (16r12345678 digitAt:15) printStringRadix:16 |
1282 (16r12345678 digitAt:0) printStringRadix:16 |
886 (16r12345678 digitAt:0) printStringRadix:16 |
1283 (16r12345678 digitAt:-10) printStringRadix:16 |
887 (16r12345678 digitAt:-10) printStringRadix:16 |
1284 " |
888 " |
|
889 ! |
|
890 |
|
891 digitLength |
|
892 "return the number bytes used by this Integer" |
|
893 |
|
894 ^ self abs highBit - 1 // 8 + 1 |
1285 ! ! |
895 ! ! |
1286 |
896 |
1287 !SmallInteger methodsFor:'misc math'! |
897 !SmallInteger methodsFor:'catching messages'! |
1288 |
898 |
1289 gcd:anInteger |
899 basicAt:index |
1290 "return the greatest common divisor (Euclid's algorithm). |
900 "catch indexed access - report an error |
1291 This has been redefined here for more speed since due to the |
901 defined here since basicAt: in Object ommits the SmallInteger check." |
1292 use of gcd in Fraction code, it has become time-critical for |
902 |
1293 some code. (thanx to MessageTally)" |
903 self notIndexed |
1294 |
904 ! |
1295 %{ /* NOCONTEXT */ |
905 |
1296 |
906 basicAt:index put:anObject |
1297 if (__isSmallInteger(anInteger)) { |
907 "catch indexed access - report an error |
1298 INT orgArg, ttt, selfInt, temp; |
908 defined here since basicAt:put: in Object ommits the SmallInteger check." |
1299 |
909 |
1300 ttt = orgArg = _intVal(anInteger); |
910 self notIndexed |
1301 if (ttt) { |
911 ! |
1302 selfInt = _intVal(self); |
912 |
1303 while (ttt != 0) { |
913 basicSize |
1304 temp = selfInt % ttt; |
914 "return the number of indexed instvars - SmallIntegers have none. |
1305 selfInt = ttt; |
915 Defined here since basicSize in Object ommits the SmallInteger check." |
1306 ttt = temp; |
916 |
1307 } |
917 ^ 0 |
1308 /* |
918 ! |
1309 * since its not defined in what the sign of |
919 |
1310 * a modulu result is when the arg is negative, |
920 size |
1311 * change it explicitely here ... |
921 "return the number of indexed instvars - SmallIntegers have none." |
1312 */ |
922 |
1313 if (orgArg < 0) { |
923 ^ 0 |
1314 /* result should be negative */ |
|
1315 if (selfInt > 0) selfInt = -selfInt; |
|
1316 } else { |
|
1317 /* result should be positive */ |
|
1318 if (selfInt < 0) selfInt = -selfInt; |
|
1319 } |
|
1320 RETURN ( _MKSMALLINT(selfInt) ); |
|
1321 } |
|
1322 } |
|
1323 %} |
|
1324 . |
|
1325 ^ super gcd:anInteger |
|
1326 ! |
|
1327 |
|
1328 intlog10 |
|
1329 "return the truncation of log10 of the receiver - |
|
1330 stupid implementation; used to find out the number of digits needed |
|
1331 to print a number/and for conversion to a LargeInteger. |
|
1332 Implemented that way, to allow for tiny systems without a Float class |
|
1333 (i.e. without log)." |
|
1334 |
|
1335 self <= 0 ifTrue:[ |
|
1336 self error:'logarithm of negative integer' |
|
1337 ]. |
|
1338 self < 10 ifTrue:[^ 1]. |
|
1339 self < 100 ifTrue:[^ 2]. |
|
1340 self < 1000 ifTrue:[^ 3]. |
|
1341 self < 10000 ifTrue:[^ 4]. |
|
1342 self < 100000 ifTrue:[^ 5]. |
|
1343 self < 1000000 ifTrue:[^ 6]. |
|
1344 self < 10000000 ifTrue:[^ 7]. |
|
1345 self < 100000000 ifTrue:[^ 8]. |
|
1346 self < 1000000000 ifTrue:[^ 9]. |
|
1347 ^ 10 |
|
1348 ! ! |
924 ! ! |
1349 |
925 |
1350 !SmallInteger methodsFor:'coercing and converting'! |
926 !SmallInteger methodsFor:'coercing and converting'! |
|
927 |
|
928 asCharacter |
|
929 "Return a character with the receiver as ascii value" |
|
930 |
|
931 ^ Character value:self |
|
932 ! |
|
933 |
|
934 asFloat |
|
935 "return a Float with same value as receiver" |
|
936 |
|
937 %{ /* NOCONTEXT */ |
|
938 |
|
939 OBJ newFloat; |
|
940 double dVal = (double)_intVal(self); |
|
941 |
|
942 _qMKFLOAT(newFloat, dVal, SENDER); |
|
943 RETURN ( newFloat ); |
|
944 %} |
|
945 ! |
|
946 |
|
947 asLargeInteger |
|
948 "return a LargeInteger with same value as receiver" |
|
949 |
|
950 ^ LargeInteger value:self |
|
951 ! |
1351 |
952 |
1352 coerce:aNumber |
953 coerce:aNumber |
1353 "return aNumber converted into receivers type" |
954 "return aNumber converted into receivers type" |
1354 |
955 |
1355 ^ aNumber asInteger |
956 ^ aNumber asInteger |
1357 |
958 |
1358 generality |
959 generality |
1359 "return the generality value - see ArithmeticValue>>retry:coercing:" |
960 "return the generality value - see ArithmeticValue>>retry:coercing:" |
1360 |
961 |
1361 ^ 20 |
962 ^ 20 |
1362 ! |
963 ! ! |
1363 |
964 |
1364 asFloat |
965 !SmallInteger methodsFor:'comparing'! |
1365 "return a Float with same value as receiver" |
966 |
1366 |
967 < aNumber |
1367 %{ /* NOCONTEXT */ |
968 "return true, if the argument is greater than the receiver" |
1368 |
969 |
1369 OBJ newFloat; |
970 %{ /* NOCONTEXT */ |
1370 double dVal = (double)_intVal(self); |
971 |
1371 |
972 if (__isSmallInteger(aNumber)) { |
1372 _qMKFLOAT(newFloat, dVal, SENDER); |
973 #ifdef POSITIVE_ADDRESSES |
1373 RETURN ( newFloat ); |
974 RETURN ( (_intVal(self) < _intVal(aNumber)) ? true : false ); |
1374 %} |
975 #else |
1375 ! |
976 /* tag bit does not change ordering */ |
1376 |
977 RETURN ( ((INT)self < (INT)aNumber) ? true : false ); |
1377 asLargeInteger |
978 #endif |
1378 "return a LargeInteger with same value as receiver" |
979 } |
1379 |
980 if (__isFloatLike(aNumber)) { |
1380 ^ LargeInteger value:self |
981 RETURN ( ((double)_intVal(self) < _floatVal(aNumber)) ? true : false ); |
1381 ! |
982 } |
1382 |
983 %} |
1383 asCharacter |
984 . |
1384 "Return a character with the receiver as ascii value" |
985 ^ aNumber lessFromInteger:self |
1385 |
986 "^ self retry:#< coercing:aNumber" |
1386 ^ Character value:self |
987 ! |
|
988 |
|
989 <= aNumber |
|
990 "return true, if the argument is greater or equal" |
|
991 |
|
992 %{ /* NOCONTEXT */ |
|
993 |
|
994 if (__isSmallInteger(aNumber)) { |
|
995 #ifdef POSITIVE_ADDRESSES |
|
996 RETURN ( (_intVal(self) <= _intVal(aNumber)) ? true : false ); |
|
997 #else |
|
998 /* tag bit does not change ordering */ |
|
999 RETURN ( ((INT)self <= (INT)aNumber) ? true : false ); |
|
1000 #endif |
|
1001 } |
|
1002 if (__isFloatLike(aNumber)) { |
|
1003 RETURN ( ((double)_intVal(self) <= _floatVal(aNumber)) ? true : false ); |
|
1004 } |
|
1005 %} |
|
1006 . |
|
1007 ^ self retry:#<= coercing:aNumber |
|
1008 ! |
|
1009 |
|
1010 = aNumber |
|
1011 "return true, if the arguments value is equal to mine" |
|
1012 |
|
1013 %{ /* NOCONTEXT */ |
|
1014 |
|
1015 if (aNumber == self) { |
|
1016 RETURN ( true ); |
|
1017 } |
|
1018 if (! __isNonNilObject(aNumber)) { |
|
1019 /* a smallint or nil */ |
|
1020 RETURN ( false ); |
|
1021 } |
|
1022 |
|
1023 if (__isFloatLike(aNumber)) { |
|
1024 RETURN ( ((double)_intVal(self) == _floatVal(aNumber)) ? true : false ); |
|
1025 } |
|
1026 %} |
|
1027 . |
|
1028 aNumber respondsToArithmetic ifFalse:[^ false]. |
|
1029 ^ self retry:#= coercing:aNumber |
|
1030 ! |
|
1031 |
|
1032 > aNumber |
|
1033 "return true, if the argument is less than the receiver" |
|
1034 |
|
1035 %{ /* NOCONTEXT */ |
|
1036 |
|
1037 if (__isSmallInteger(aNumber)) { |
|
1038 #ifdef POSITIVE_ADDRESSES |
|
1039 RETURN ( (_intVal(self) > _intVal(aNumber)) ? true : false ); |
|
1040 #else |
|
1041 /* tag bit does not change ordering */ |
|
1042 RETURN ( ((INT)self > (INT)aNumber) ? true : false ); |
|
1043 #endif |
|
1044 } |
|
1045 if (__isFloatLike(aNumber)) { |
|
1046 RETURN ( ((double)_intVal(self) > _floatVal(aNumber)) ? true : false ); |
|
1047 } |
|
1048 %} |
|
1049 . |
|
1050 ^ self retry:#> coercing:aNumber |
|
1051 ! |
|
1052 |
|
1053 >= aNumber |
|
1054 "return true, if the argument is less or equal" |
|
1055 |
|
1056 %{ /* NOCONTEXT */ |
|
1057 |
|
1058 if (__isSmallInteger(aNumber)) { |
|
1059 #ifdef POSITIVE_ADDRESSES |
|
1060 RETURN ( (_intVal(self) >= _intVal(aNumber)) ? true : false ); |
|
1061 #else |
|
1062 /* tag bit does not change ordering */ |
|
1063 RETURN ( ((INT)self >= (INT)aNumber) ? true : false ); |
|
1064 #endif |
|
1065 } |
|
1066 if (__isFloatLike(aNumber)) { |
|
1067 RETURN ( ((double)_intVal(self) >= _floatVal(aNumber)) ? true : false ); |
|
1068 } |
|
1069 %} |
|
1070 . |
|
1071 ^ self retry:#>= coercing:aNumber |
|
1072 ! |
|
1073 |
|
1074 hash |
|
1075 "return an integer useful for hashing on value" |
|
1076 |
|
1077 self >= 0 ifTrue:[^ self]. |
|
1078 ^ self negated |
|
1079 ! |
|
1080 |
|
1081 identityHash |
|
1082 "return an integer useful for hashing on identity" |
|
1083 |
|
1084 self >= 0 ifTrue:[^ self]. |
|
1085 ^ self negated |
|
1086 ! |
|
1087 |
|
1088 max:aNumber |
|
1089 "return the receiver or the argument, whichever is greater" |
|
1090 |
|
1091 %{ /* NOCONTEXT */ |
|
1092 |
|
1093 if (__isSmallInteger(aNumber)) { |
|
1094 #ifdef POSITIVE_ADDRESSES |
|
1095 if (_intVal(self) > _intVal(aNumber)) { |
|
1096 #else |
|
1097 /* tag bit does not change ordering */ |
|
1098 if ((INT)(self) > (INT)(aNumber)) { |
|
1099 #endif |
|
1100 RETURN ( self ); |
|
1101 } |
|
1102 RETURN ( aNumber ); |
|
1103 } |
|
1104 if (__isFloatLike(aNumber)) { |
|
1105 if ( (double)_intVal(self) > _floatVal(aNumber) ) { |
|
1106 RETURN ( self ); |
|
1107 } |
|
1108 RETURN ( aNumber ); |
|
1109 } |
|
1110 %} |
|
1111 . |
|
1112 (self > aNumber) ifTrue:[^ self]. |
|
1113 ^ aNumber |
|
1114 ! |
|
1115 |
|
1116 min:aNumber |
|
1117 "return the receiver or the argument, whichever is smaller" |
|
1118 |
|
1119 %{ /* NOCONTEXT */ |
|
1120 |
|
1121 if (__isSmallInteger(aNumber)) { |
|
1122 #ifdef POSITIVE_ADDRESSES |
|
1123 if (_intVal(self) < _intVal(aNumber)) { |
|
1124 #else |
|
1125 /* tag bit does not change ordering */ |
|
1126 if ((INT)(self) < (INT)(aNumber)) { |
|
1127 #endif |
|
1128 RETURN ( self ); |
|
1129 } |
|
1130 RETURN ( aNumber ); |
|
1131 } |
|
1132 if (__isFloatLike(aNumber)) { |
|
1133 if ( (double)_intVal(self) < _floatVal(aNumber) ) { |
|
1134 RETURN ( self ); |
|
1135 } |
|
1136 RETURN ( aNumber ); |
|
1137 } |
|
1138 %} |
|
1139 . |
|
1140 (self < aNumber) ifTrue:[^ self]. |
|
1141 ^ aNumber |
|
1142 ! |
|
1143 |
|
1144 ~= aNumber |
|
1145 "return true, if the arguments value is not equal to mine" |
|
1146 |
|
1147 %{ /* NOCONTEXT */ |
|
1148 |
|
1149 if (aNumber == self) { |
|
1150 RETURN ( false ); |
|
1151 } |
|
1152 if (! __isNonNilObject(aNumber)) { |
|
1153 /* a smallint or nil */ |
|
1154 RETURN ( true ); |
|
1155 } |
|
1156 |
|
1157 if (__isFloatLike(aNumber)) { |
|
1158 RETURN ( ((double)_intVal(self) == _floatVal(aNumber)) ? false : true ); |
|
1159 } |
|
1160 %} |
|
1161 . |
|
1162 aNumber respondsToArithmetic ifFalse:[^ true]. |
|
1163 ^ self retry:#~= coercing:aNumber |
|
1164 ! ! |
|
1165 |
|
1166 !SmallInteger methodsFor:'copying'! |
|
1167 |
|
1168 deepCopy |
|
1169 "return a deep copy of myself |
|
1170 - reimplemented here since smallintegers are unique" |
|
1171 |
|
1172 ^ self |
|
1173 ! |
|
1174 |
|
1175 deepCopyUsing:aDictionary |
|
1176 "return a deep copy of myself |
|
1177 - reimplemented here since smallintegers are unique" |
|
1178 |
|
1179 ^ self |
|
1180 ! |
|
1181 |
|
1182 shallowCopy |
|
1183 "return a shallow copy of myself |
|
1184 - reimplemented here since smallintegers are unique" |
|
1185 |
|
1186 ^ self |
|
1187 ! |
|
1188 |
|
1189 simpleDeepCopy |
|
1190 "return a deep copy of myself |
|
1191 - reimplemented here since smallintegers are unique" |
|
1192 |
|
1193 ^ self |
1387 ! ! |
1194 ! ! |
1388 |
1195 |
1389 !SmallInteger methodsFor:'iteration'! |
1196 !SmallInteger methodsFor:'iteration'! |
1390 |
1197 |
1391 timesRepeat:aBlock |
1198 timesRepeat:aBlock |
1523 "/ aBlock value. |
1330 "/ aBlock value. |
1524 "/ count := count - 1 |
1331 "/ count := count - 1 |
1525 "/ ] |
1332 "/ ] |
1526 ! |
1333 ! |
1527 |
1334 |
1528 to:stop do:aBlock |
|
1529 "evaluate aBlock for every integer between (and including) the receiver |
|
1530 and the argument, stop. |
|
1531 Reimplemented as primitive for speed" |
|
1532 |
|
1533 |home| |
|
1534 %{ |
|
1535 REGISTER INT tmp; |
|
1536 INT final; |
|
1537 REGISTER OBJFUNC code; |
|
1538 extern OBJ Block; |
|
1539 static struct inlineCache blockVal = __ILC1(0); |
|
1540 REGISTER OBJ rHome; |
|
1541 |
|
1542 if (__isSmallInteger(stop)) { |
|
1543 tmp = _intVal(self); |
|
1544 final = _intVal(stop); |
|
1545 if (__isBlockLike(aBlock) |
|
1546 && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) { |
|
1547 if ((code = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
|
1548 #ifdef NEW_BLOCK_CALL |
|
1549 while (tmp <= final) { |
|
1550 if (InterruptPending != nil) interrupt(CONARG); |
|
1551 (*code)(aBlock, CON_COMMA _MKSMALLINT(tmp)); |
|
1552 tmp++; |
|
1553 } |
|
1554 #else /* old BLOCK_CALL */ |
|
1555 /* |
|
1556 * arg is a compiled block - |
|
1557 * directly call it without going through "Block-value" |
|
1558 */ |
|
1559 rHome = _BlockInstPtr(aBlock)->b_home; |
|
1560 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
1561 /* |
|
1562 * home will not move - keep in in a register |
|
1563 * since this is also the most common case, |
|
1564 * its worth trading a bit memory for speed here ... |
|
1565 */ |
|
1566 # if defined(UNROLL_LOOPS) |
|
1567 { |
|
1568 int t4; |
|
1569 |
|
1570 while ((t4 = tmp+4) < final) { |
|
1571 OBJ idx = _MKSMALLINT(tmp); |
|
1572 if (InterruptPending != nil) interrupt(CONARG); |
|
1573 (*code)(rHome, CON_COMMA idx); |
|
1574 if (InterruptPending != nil) interrupt(CONARG); |
|
1575 (*code)(rHome, CON_COMMA _ADD_INT(idx, 1)); |
|
1576 if (InterruptPending != nil) interrupt(CONARG); |
|
1577 (*code)(rHome, CON_COMMA _ADD_INT(idx,2)); |
|
1578 if (InterruptPending != nil) interrupt(CONARG); |
|
1579 (*code)(rHome, CON_COMMA _ADD_INT(idx,3)); |
|
1580 tmp = t4; |
|
1581 } |
|
1582 } |
|
1583 # endif |
|
1584 while (tmp <= final) { |
|
1585 if (InterruptPending != nil) interrupt(CONARG); |
|
1586 (*code)(rHome, CON_COMMA _MKSMALLINT(tmp)); |
|
1587 tmp++; |
|
1588 } |
|
1589 } else { |
|
1590 home = rHome; |
|
1591 while (tmp <= final) { |
|
1592 if (InterruptPending != nil) interrupt(CONARG); |
|
1593 (*code)(home, CON_COMMA _MKSMALLINT(tmp)); |
|
1594 tmp++; |
|
1595 } |
|
1596 } |
|
1597 RETURN (self); |
|
1598 #endif /* NEW_BLOCK_CALL */ |
|
1599 } |
|
1600 if (_BlockInstPtr(aBlock)->b_bytecodes != nil) { |
|
1601 /* |
|
1602 * an interpreted block |
|
1603 */ |
|
1604 #ifdef PASS_ARG_POINTER |
|
1605 extern OBJ __interpret(); |
|
1606 #else |
|
1607 extern OBJ interpret(); |
|
1608 #endif |
|
1609 home = _BlockInstPtr(aBlock)->b_home; |
|
1610 #ifdef PASS_ARG_POINTER |
|
1611 # ifdef INDIRECT_CALL_IS_FASTER |
|
1612 code = __interpret; |
|
1613 # define INTERPRET (*code) |
|
1614 # else |
|
1615 # define INTERPRET __interpret |
|
1616 # endif |
|
1617 #else |
|
1618 # ifdef INDIRECT_CALL_IS_FASTER |
|
1619 code = interpret; |
|
1620 # define INTERPRET (*code) |
|
1621 # else |
|
1622 # define INTERPRET interpret |
|
1623 # endif |
|
1624 #endif |
|
1625 #ifdef NEW_BLOCK_CALL |
|
1626 # define HOME nil |
|
1627 #else |
|
1628 # define HOME home |
|
1629 #endif |
|
1630 while (tmp <= final) { |
|
1631 |
|
1632 if (InterruptPending != nil) interrupt(CONARG); |
|
1633 #ifdef PASS_ARG_POINTER |
|
1634 { |
|
1635 OBJ idx; |
|
1636 idx = __MKSMALLINT(tmp); |
|
1637 INTERPRET(aBlock, 1, nil, HOME COMMA_SND, nil, &idx); |
|
1638 } |
|
1639 #else |
|
1640 INTERPRET(aBlock, 1, nil, HOME COMMA_SND, nil, __MKSMALLINT(tmp)); |
|
1641 #endif |
|
1642 tmp++; |
|
1643 } |
|
1644 RETURN (self); |
|
1645 } |
|
1646 } |
|
1647 /* |
|
1648 * arg is something else - call it with value" |
|
1649 */ |
|
1650 while (tmp <= final) { |
|
1651 if (InterruptPending != nil) interrupt(CONARG); |
|
1652 |
|
1653 (*blockVal.ilc_func)(aBlock, |
|
1654 @symbol(value:), |
|
1655 CON_COMMA nil, &blockVal, |
|
1656 _MKSMALLINT(tmp)); |
|
1657 tmp++; |
|
1658 } |
|
1659 RETURN ( self ); |
|
1660 } |
|
1661 %}. |
|
1662 "/ |
|
1663 "/ arrive here if stop is not a smallInteger |
|
1664 "/ |
|
1665 |
|
1666 ^ super to:stop do:aBlock |
|
1667 |
|
1668 " |
|
1669 1 to:10 do:[:i | i printNewline] |
|
1670 " |
|
1671 ! |
|
1672 |
|
1673 to:stop by:incr do:aBlock |
1335 to:stop by:incr do:aBlock |
1674 "reimplemented as primitive for speed" |
1336 "reimplemented as primitive for speed" |
1675 |
1337 |
1676 |home| |
1338 |home| |
1677 %{ |
1339 %{ |
1779 ^ super to:stop by:incr do:aBlock |
1441 ^ super to:stop by:incr do:aBlock |
1780 |
1442 |
1781 " |
1443 " |
1782 1 to:10 by:3 do:[:i | i printNewline] |
1444 1 to:10 by:3 do:[:i | i printNewline] |
1783 " |
1445 " |
|
1446 ! |
|
1447 |
|
1448 to:stop do:aBlock |
|
1449 "evaluate aBlock for every integer between (and including) the receiver |
|
1450 and the argument, stop. |
|
1451 Reimplemented as primitive for speed" |
|
1452 |
|
1453 |home| |
|
1454 %{ |
|
1455 REGISTER INT tmp; |
|
1456 INT final; |
|
1457 REGISTER OBJFUNC code; |
|
1458 extern OBJ Block; |
|
1459 static struct inlineCache blockVal = __ILC1(0); |
|
1460 REGISTER OBJ rHome; |
|
1461 |
|
1462 if (__isSmallInteger(stop)) { |
|
1463 tmp = _intVal(self); |
|
1464 final = _intVal(stop); |
|
1465 if (__isBlockLike(aBlock) |
|
1466 && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) { |
|
1467 if ((code = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
|
1468 #ifdef NEW_BLOCK_CALL |
|
1469 while (tmp <= final) { |
|
1470 if (InterruptPending != nil) interrupt(CONARG); |
|
1471 (*code)(aBlock, CON_COMMA _MKSMALLINT(tmp)); |
|
1472 tmp++; |
|
1473 } |
|
1474 #else /* old BLOCK_CALL */ |
|
1475 /* |
|
1476 * arg is a compiled block - |
|
1477 * directly call it without going through "Block-value" |
|
1478 */ |
|
1479 rHome = _BlockInstPtr(aBlock)->b_home; |
|
1480 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
1481 /* |
|
1482 * home will not move - keep in in a register |
|
1483 * since this is also the most common case, |
|
1484 * its worth trading a bit memory for speed here ... |
|
1485 */ |
|
1486 # if defined(UNROLL_LOOPS) |
|
1487 { |
|
1488 int t4; |
|
1489 |
|
1490 while ((t4 = tmp+4) < final) { |
|
1491 OBJ idx = _MKSMALLINT(tmp); |
|
1492 if (InterruptPending != nil) interrupt(CONARG); |
|
1493 (*code)(rHome, CON_COMMA idx); |
|
1494 if (InterruptPending != nil) interrupt(CONARG); |
|
1495 (*code)(rHome, CON_COMMA _ADD_INT(idx, 1)); |
|
1496 if (InterruptPending != nil) interrupt(CONARG); |
|
1497 (*code)(rHome, CON_COMMA _ADD_INT(idx,2)); |
|
1498 if (InterruptPending != nil) interrupt(CONARG); |
|
1499 (*code)(rHome, CON_COMMA _ADD_INT(idx,3)); |
|
1500 tmp = t4; |
|
1501 } |
|
1502 } |
|
1503 # endif |
|
1504 while (tmp <= final) { |
|
1505 if (InterruptPending != nil) interrupt(CONARG); |
|
1506 (*code)(rHome, CON_COMMA _MKSMALLINT(tmp)); |
|
1507 tmp++; |
|
1508 } |
|
1509 } else { |
|
1510 home = rHome; |
|
1511 while (tmp <= final) { |
|
1512 if (InterruptPending != nil) interrupt(CONARG); |
|
1513 (*code)(home, CON_COMMA _MKSMALLINT(tmp)); |
|
1514 tmp++; |
|
1515 } |
|
1516 } |
|
1517 RETURN (self); |
|
1518 #endif /* NEW_BLOCK_CALL */ |
|
1519 } |
|
1520 if (_BlockInstPtr(aBlock)->b_bytecodes != nil) { |
|
1521 /* |
|
1522 * an interpreted block |
|
1523 */ |
|
1524 #ifdef PASS_ARG_POINTER |
|
1525 extern OBJ __interpret(); |
|
1526 #else |
|
1527 extern OBJ interpret(); |
|
1528 #endif |
|
1529 home = _BlockInstPtr(aBlock)->b_home; |
|
1530 #ifdef PASS_ARG_POINTER |
|
1531 # ifdef INDIRECT_CALL_IS_FASTER |
|
1532 code = __interpret; |
|
1533 # define INTERPRET (*code) |
|
1534 # else |
|
1535 # define INTERPRET __interpret |
|
1536 # endif |
|
1537 #else |
|
1538 # ifdef INDIRECT_CALL_IS_FASTER |
|
1539 code = interpret; |
|
1540 # define INTERPRET (*code) |
|
1541 # else |
|
1542 # define INTERPRET interpret |
|
1543 # endif |
|
1544 #endif |
|
1545 #ifdef NEW_BLOCK_CALL |
|
1546 # define HOME nil |
|
1547 #else |
|
1548 # define HOME home |
|
1549 #endif |
|
1550 while (tmp <= final) { |
|
1551 |
|
1552 if (InterruptPending != nil) interrupt(CONARG); |
|
1553 #ifdef PASS_ARG_POINTER |
|
1554 { |
|
1555 OBJ idx; |
|
1556 idx = __MKSMALLINT(tmp); |
|
1557 INTERPRET(aBlock, 1, nil, HOME COMMA_SND, nil, &idx); |
|
1558 } |
|
1559 #else |
|
1560 INTERPRET(aBlock, 1, nil, HOME COMMA_SND, nil, __MKSMALLINT(tmp)); |
|
1561 #endif |
|
1562 tmp++; |
|
1563 } |
|
1564 RETURN (self); |
|
1565 } |
|
1566 } |
|
1567 /* |
|
1568 * arg is something else - call it with value" |
|
1569 */ |
|
1570 while (tmp <= final) { |
|
1571 if (InterruptPending != nil) interrupt(CONARG); |
|
1572 |
|
1573 (*blockVal.ilc_func)(aBlock, |
|
1574 @symbol(value:), |
|
1575 CON_COMMA nil, &blockVal, |
|
1576 _MKSMALLINT(tmp)); |
|
1577 tmp++; |
|
1578 } |
|
1579 RETURN ( self ); |
|
1580 } |
|
1581 %}. |
|
1582 "/ |
|
1583 "/ arrive here if stop is not a smallInteger |
|
1584 "/ |
|
1585 |
|
1586 ^ super to:stop do:aBlock |
|
1587 |
|
1588 " |
|
1589 1 to:10 do:[:i | i printNewline] |
|
1590 " |
1784 ! ! |
1591 ! ! |
1785 |
1592 |
1786 !SmallInteger class methodsFor:'binary storage'! |
1593 !SmallInteger methodsFor:'misc math'! |
1787 |
1594 |
1788 binaryDefinitionFrom: stream manager: manager |
1595 gcd:anInteger |
1789 "read the binary representation as stored in storeBinaryOn:" |
1596 "return the greatest common divisor (Euclid's algorithm). |
1790 |
1597 This has been redefined here for more speed since due to the |
1791 | value | |
1598 use of gcd in Fraction code, it has become time-critical for |
1792 |
1599 some code. (thanx to MessageTally)" |
1793 value := stream next bitAnd: 16r7F. |
1600 |
1794 value > 16r3F ifTrue: [ |
1601 %{ /* NOCONTEXT */ |
1795 value := value - 16r80 |
1602 |
|
1603 if (__isSmallInteger(anInteger)) { |
|
1604 INT orgArg, ttt, selfInt, temp; |
|
1605 |
|
1606 ttt = orgArg = _intVal(anInteger); |
|
1607 if (ttt) { |
|
1608 selfInt = _intVal(self); |
|
1609 while (ttt != 0) { |
|
1610 temp = selfInt % ttt; |
|
1611 selfInt = ttt; |
|
1612 ttt = temp; |
|
1613 } |
|
1614 /* |
|
1615 * since its not defined in what the sign of |
|
1616 * a modulu result is when the arg is negative, |
|
1617 * change it explicitely here ... |
|
1618 */ |
|
1619 if (orgArg < 0) { |
|
1620 /* result should be negative */ |
|
1621 if (selfInt > 0) selfInt = -selfInt; |
|
1622 } else { |
|
1623 /* result should be positive */ |
|
1624 if (selfInt < 0) selfInt = -selfInt; |
|
1625 } |
|
1626 RETURN ( _MKSMALLINT(selfInt) ); |
|
1627 } |
|
1628 } |
|
1629 %} |
|
1630 . |
|
1631 ^ super gcd:anInteger |
|
1632 ! |
|
1633 |
|
1634 intlog10 |
|
1635 "return the truncation of log10 of the receiver - |
|
1636 stupid implementation; used to find out the number of digits needed |
|
1637 to print a number/and for conversion to a LargeInteger. |
|
1638 Implemented that way, to allow for tiny systems without a Float class |
|
1639 (i.e. without log)." |
|
1640 |
|
1641 self <= 0 ifTrue:[ |
|
1642 self error:'logarithm of negative integer' |
1796 ]. |
1643 ]. |
1797 value := (value bitShift: 8) bitOr: stream next. |
1644 self < 10 ifTrue:[^ 1]. |
1798 value := (value bitShift: 8) bitOr: stream next. |
1645 self < 100 ifTrue:[^ 2]. |
1799 value := (value bitShift: 8) bitOr: stream next. |
1646 self < 1000 ifTrue:[^ 3]. |
1800 ^ value |
1647 self < 10000 ifTrue:[^ 4]. |
|
1648 self < 100000 ifTrue:[^ 5]. |
|
1649 self < 1000000 ifTrue:[^ 6]. |
|
1650 self < 10000000 ifTrue:[^ 7]. |
|
1651 self < 100000000 ifTrue:[^ 8]. |
|
1652 self < 1000000000 ifTrue:[^ 9]. |
|
1653 ^ 10 |
1801 ! ! |
1654 ! ! |
1802 |
1655 |
1803 !SmallInteger methodsFor:'binary storage'! |
1656 !SmallInteger methodsFor:'modulu arithmetic'! |
1804 |
1657 |
1805 hasSpecialBinaryRepresentation |
1658 plus:aNumber |
1806 "return true, if the receiver has a special binary representation" |
1659 "return the sum of the receiver and the argument, as SmallInteger. |
1807 |
1660 The argument must be another SmallInteger. |
1808 ^ true |
1661 If the result overflows the smallInteger range, the value modulu the |
1809 ! |
1662 smallInteger range is returned (i.e. the low bits of the sum). |
1810 |
1663 This is of course not always correct, but some code does a modulu anyway |
1811 storeBinaryOn: stream manager: manager |
1664 and can therefore speed things up by not going through LargeIntegers." |
1812 "append a binary representation onto stream. |
1665 |
1813 Redefined since SmallIntegers are stored as their value with the 32nd bit |
1666 %{ /* NOCONTEXT */ |
1814 set as a tag. |
1667 |
1815 To make the binary file a bit more compact, zeros and single byte ints |
1668 if (__isSmallInteger(aNumber)) { |
1816 are stored with a more compact representation (using special type-codes)." |
1669 RETURN ( _MKSMALLINT((_intVal(self) + _intVal(aNumber)) & 0x7FFFFFFF) ); |
1817 |
1670 } |
1818 self == 0 ifTrue:[ |
1671 %} |
1819 stream nextPut: manager codeForZero. |
1672 . |
1820 ^ self |
1673 self primitiveFailed |
1821 ]. |
1674 ! |
1822 (self between:0 and:255) ifTrue:[ |
1675 |
1823 stream nextPut: manager codeForByteInteger. |
1676 subtract:aNumber |
1824 stream nextPut: self. |
1677 "return the difference of the receiver and the argument, as SmallInteger. |
1825 ^ self |
1678 The argument must be another SmallInteger. |
1826 ]. |
1679 If the result overflows the smallInteger range, the value modulu the |
1827 stream nextPut: (((self bitShift: -24) bitAnd: 16rFF) bitOr: 16r80). |
1680 smallInteger range is returned (i.e. the low bits of the sum). |
1828 stream nextPut: ((self bitShift: -16) bitAnd: 16rFF). |
1681 This is of course not always correct, but some code does a modulu anyway |
1829 stream nextPut: ((self bitShift: -8) bitAnd: 16rFF). |
1682 and can therefore speed things up by not going through LargeIntegers." |
1830 stream nextPut: (self bitAnd: 16rFF) |
1683 |
|
1684 %{ /* NOCONTEXT */ |
|
1685 |
|
1686 if (__isSmallInteger(aNumber)) { |
|
1687 RETURN ( _MKSMALLINT((_intVal(self) - _intVal(aNumber)) & 0x7FFFFFFF) ); |
|
1688 } |
|
1689 %} |
|
1690 . |
|
1691 self primitiveFailed |
|
1692 ! |
|
1693 |
|
1694 times:aNumber |
|
1695 "return the product of the receiver and the argument, as SmallInteger. |
|
1696 The argument must be another SmallInteger. |
|
1697 If the result overflows the smallInteger range, the value modulu the |
|
1698 smallInteger range is returned (i.e. the low bits of the product). |
|
1699 This is of course not always correct, but some code does a modulu anyway |
|
1700 and can therefore speed things up by not going through LargeIntegers." |
|
1701 |
|
1702 %{ /* NOCONTEXT */ |
|
1703 |
|
1704 if (__isSmallInteger(aNumber)) { |
|
1705 RETURN ( _MKSMALLINT((_intVal(self) * _intVal(aNumber)) & 0x7FFFFFFF) ); |
|
1706 } |
|
1707 %} |
|
1708 . |
|
1709 self primitiveFailed |
1831 ! ! |
1710 ! ! |
1832 |
1711 |
1833 !SmallInteger methodsFor:'printing & storing'! |
1712 !SmallInteger methodsFor:'printing & storing'! |
1834 |
1713 |
1835 printOn:aStream |
1714 printOn:aStream |
1836 "append my printstring (base 10) to aStream." |
1715 "append my printstring (base 10) to aStream." |
1837 |
1716 |
1838 aStream nextPutAll:(self printString) |
1717 aStream nextPutAll:(self printString) |
|
1718 ! |
|
1719 |
|
1720 printOn:aStream base:radix |
|
1721 "append my printstring in any number base to aStream. |
|
1722 The radix argument should be between 2 and 36." |
|
1723 |
|
1724 aStream nextPutAll:(self printStringRadix:radix) |
1839 ! |
1725 ! |
1840 |
1726 |
1841 printString |
1727 printString |
1842 "return my printstring (base 10)" |
1728 "return my printstring (base 10)" |
1843 |
1729 |
1977 "123 printfPrintString:'%%6d -> %6d'" |
1856 "123 printfPrintString:'%%6d -> %6d'" |
1978 "123 printfPrintString:'%%x -> %x'" |
1857 "123 printfPrintString:'%%x -> %x'" |
1979 "123 printfPrintString:'%%4x -> %4x'" |
1858 "123 printfPrintString:'%%4x -> %4x'" |
1980 "123 printfPrintString:'%%04x -> %04x'" |
1859 "123 printfPrintString:'%%04x -> %04x'" |
1981 ! ! |
1860 ! ! |
|
1861 |
|
1862 !SmallInteger methodsFor:'testing'! |
|
1863 |
|
1864 between:min and:max |
|
1865 "return true if the receiver is less than or equal to the argument max |
|
1866 and greater than or equal to the argument min. |
|
1867 - reimplemented here for speed" |
|
1868 |
|
1869 %{ /* NOCONTEXT */ |
|
1870 |
|
1871 if (__bothSmallInteger(min, max)) { |
|
1872 REGISTER INT selfVal; |
|
1873 |
|
1874 selfVal = _intVal(self); |
|
1875 if (selfVal < _intVal(min)) { |
|
1876 RETURN ( false ); |
|
1877 } |
|
1878 if (selfVal > _intVal(max)) { |
|
1879 RETURN ( false ); |
|
1880 } |
|
1881 RETURN ( true ); |
|
1882 } |
|
1883 %} |
|
1884 . |
|
1885 (self < min) ifTrue:[^ false]. |
|
1886 (self > max) ifTrue:[^ false]. |
|
1887 ^ true |
|
1888 ! |
|
1889 |
|
1890 even |
|
1891 "return true, if the receiver is even" |
|
1892 |
|
1893 %{ /* NOCONTEXT */ |
|
1894 |
|
1895 #ifdef POSITIVE_ADDRESSES |
|
1896 RETURN ( ((INT)self & 1) ? false : true ); |
|
1897 #else |
|
1898 RETURN ( ((INT)self & ((INT)_MKSMALLINT(1) & ~TAG_INT)) ? false : true ); |
|
1899 #endif |
|
1900 %} |
|
1901 ! |
|
1902 |
|
1903 negative |
|
1904 "return true, if the receiver is less than zero |
|
1905 reimplemented here for speed" |
|
1906 |
|
1907 %{ /* NOCONTEXT */ |
|
1908 |
|
1909 #ifdef POSITIVE_ADDRESSES |
|
1910 RETURN ( (_intVal(self) < 0) ? true : false ); |
|
1911 #else |
|
1912 /* tag bit does not change sign */ |
|
1913 RETURN ( ((INT)(self) < 0) ? true : false ); |
|
1914 #endif |
|
1915 %} |
|
1916 ! |
|
1917 |
|
1918 odd |
|
1919 "return true, if the receiver is odd" |
|
1920 |
|
1921 %{ /* NOCONTEXT */ |
|
1922 |
|
1923 #ifdef POSITIVE_ADDRESSES |
|
1924 RETURN ( ((INT)self & 1) ? true : false ); |
|
1925 #else |
|
1926 RETURN ( ((INT)self & ((INT)_MKSMALLINT(1) & ~TAG_INT)) ? true : false ); |
|
1927 #endif |
|
1928 %} |
|
1929 ! |
|
1930 |
|
1931 positive |
|
1932 "return true, if the receiver is not negative |
|
1933 reimplemented here for speed" |
|
1934 |
|
1935 %{ /* NOCONTEXT */ |
|
1936 |
|
1937 #ifdef POSITIVE_ADDRESSES |
|
1938 RETURN ( (_intVal(self) >= 0) ? true : false ); |
|
1939 #else |
|
1940 /* tag bit does not change sign */ |
|
1941 RETURN ( ((INT)(self) >= 0) ? true : false ); |
|
1942 #endif |
|
1943 %} |
|
1944 ! |
|
1945 |
|
1946 sign |
|
1947 "return the sign of the receiver |
|
1948 reimplemented here for speed" |
|
1949 |
|
1950 %{ /* NOCONTEXT */ |
|
1951 |
|
1952 INT val = _intVal(self); |
|
1953 |
|
1954 if (val < 0) { |
|
1955 RETURN ( _MKSMALLINT(-1) ); |
|
1956 } |
|
1957 if (val > 0) { |
|
1958 RETURN ( _MKSMALLINT(1) ); |
|
1959 } |
|
1960 RETURN ( _MKSMALLINT(0) ); |
|
1961 %} |
|
1962 ! |
|
1963 |
|
1964 strictlyPositive |
|
1965 "return true, if the receiver is greater than zero |
|
1966 reimplemented here for speed" |
|
1967 |
|
1968 %{ /* NOCONTEXT */ |
|
1969 |
|
1970 #ifdef POSITIVE_ADDRESSES |
|
1971 RETURN ( (_intVal(self) > 0) ? true : false ); |
|
1972 #else |
|
1973 /* tag bit does not change sign */ |
|
1974 RETURN ( ((INT)(self) > 0) ? true : false ); |
|
1975 #endif |
|
1976 %} |
|
1977 ! ! |
|
1978 |
|
1979 !SmallInteger class methodsFor:'documentation'! |
|
1980 |
|
1981 version |
|
1982 ^ '$Header: /cvs/stx/stx/libbasic/SmallInteger.st,v 1.40 1995-12-07 21:36:33 cg Exp $' |
|
1983 ! ! |