255 # if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 2) |
255 # if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 2) |
256 # define USE_LONGLONG_FOR_MUL |
256 # define USE_LONGLONG_FOR_MUL |
257 # endif |
257 # endif |
258 |
258 |
259 if (__isSmallInteger(aNumber)) { |
259 if (__isSmallInteger(aNumber)) { |
260 otherValue = __intVal(aNumber); |
260 otherValue = __intVal(aNumber); |
261 |
261 |
262 # if defined(USE_LONGLONG_FOR_MUL) |
262 # if defined(USE_LONGLONG_FOR_MUL) |
263 { |
263 { |
264 # if defined(__alpha__) && !defined(__alpha64__) |
264 # if defined(__alpha__) && !defined(__alpha64__) |
265 # define LONGLONG INT64 |
265 # define LONGLONG INT64 |
266 # else |
266 # else |
267 # define LONGLONG long long |
267 # define LONGLONG long long |
268 # endif |
268 # endif |
269 LONGLONG product; |
269 LONGLONG product; |
270 |
270 |
271 product = (LONGLONG)myValue * (LONGLONG)otherValue; |
271 product = (LONGLONG)myValue * (LONGLONG)otherValue; |
272 if ((product >= (LONGLONG)_MIN_INT) |
272 if ((product >= (LONGLONG)_MIN_INT) |
273 && (product <= (LONGLONG)_MAX_INT)) { |
273 && (product <= (LONGLONG)_MAX_INT)) { |
274 RETURN ( __mkSmallInteger((INT)product) ); |
274 RETURN ( __mkSmallInteger((INT)product) ); |
275 } |
275 } |
276 if (product < 0) { |
276 if (product < 0) { |
277 negative = -1; |
277 negative = -1; |
278 product = -product; |
278 product = -product; |
279 } else { |
279 } else { |
280 negative = 1; |
280 negative = 1; |
281 } |
281 } |
282 productHi = product >> 32; |
282 productHi = product >> 32; |
283 productLow = product & 0xFFFFFFFFLL; |
283 productLow = product & 0xFFFFFFFFLL; |
284 } |
284 } |
285 # else /* no long-long */ |
285 # else /* no long-long */ |
286 negative = 1; |
286 negative = 1; |
287 if (myValue < 0) { |
287 if (myValue < 0) { |
288 negative = -1; |
288 negative = -1; |
289 myValue = -myValue; |
289 myValue = -myValue; |
290 } |
290 } |
291 if (otherValue < 0) { |
291 if (otherValue < 0) { |
292 negative = -negative; |
292 negative = -negative; |
293 otherValue = -otherValue; |
293 otherValue = -otherValue; |
294 } |
294 } |
295 |
295 |
296 # if defined(__GNUC__) && defined(__mc68k__) |
296 # if defined(__GNUC__) && defined(__mc68k__) |
297 asm ("mulu%.l %3,%1:%0" |
297 asm ("mulu%.l %3,%1:%0" |
298 : "=d" ((unsigned long)(productLow)), |
298 : "=d" ((unsigned long)(productLow)), |
299 "=d" ((unsigned long)(productHi)) |
299 "=d" ((unsigned long)(productHi)) |
300 : "%0" ((unsigned long)(myValue)), |
300 : "%0" ((unsigned long)(myValue)), |
301 "dmi" ((unsigned long)(otherValue))); |
301 "dmi" ((unsigned long)(otherValue))); |
302 # else |
302 # else |
303 # if defined (__GNUC__) && defined(__x86__) |
303 # if defined (__GNUC__) && defined(__x86__) |
304 asm ("mull %3" |
304 asm ("mull %3" |
305 : "=a" ((unsigned long)(productLow)), |
305 : "=a" ((unsigned long)(productLow)), |
306 "=d" ((unsigned long)(productHi)) |
306 "=d" ((unsigned long)(productHi)) |
307 : "%0" ((unsigned long)(myValue)), |
307 : "%0" ((unsigned long)(myValue)), |
308 "rm" ((unsigned long)(otherValue))); |
308 "rm" ((unsigned long)(otherValue))); |
309 # else |
309 # else |
310 # if defined(__win32__) && defined(__BORLANDC__) |
310 # if defined(__win32__) && defined(__BORLANDC__) |
311 asm { |
311 asm { |
312 mov eax, myValue |
312 mov eax, myValue |
313 mov edx, otherValue |
313 mov edx, otherValue |
314 mul edx |
314 mul edx |
315 mov productLow, eax |
315 mov productLow, eax |
316 mov productHi, edx |
316 mov productHi, edx |
317 } |
317 } |
318 # else /* generic */ |
318 # else /* generic */ |
319 { |
319 { |
320 unsigned INT pHH, pHL, pLH, pLL; |
320 unsigned INT pHH, pHL, pLH, pLL; |
321 unsigned INT low1, low2, hi1, hi2; |
321 unsigned INT low1, low2, hi1, hi2; |
322 unsigned INT t; |
322 unsigned INT t; |
323 |
323 |
324 /* unsigned multiply myValue * otherValue -> productHi, productLow |
324 /* unsigned multiply myValue * otherValue -> productHi, productLow |
325 * |
325 * |
326 * this is too slow: |
326 * this is too slow: |
327 * since most machines can do 32*32 to 64 bit multiply, |
327 * since most machines can do 32*32 to 64 bit multiply, |
328 * (or at least 32*32 with Overflow check) |
328 * (or at least 32*32 with Overflow check) |
329 * - need more assembler (inline) functions here |
329 * - need more assembler (inline) functions here |
330 */ |
330 */ |
331 # if __POINTER_SIZE__ == 8 |
331 # if __POINTER_SIZE__ == 8 |
332 low1 = low32Bits((unsigned INT)myValue); |
332 low1 = low32Bits((unsigned INT)myValue); |
333 hi1 = hi32Bits((unsigned INT)myValue); |
333 hi1 = hi32Bits((unsigned INT)myValue); |
334 low2 = low32Bits((unsigned INT)otherValue); |
334 low2 = low32Bits((unsigned INT)otherValue); |
335 hi2 = hi32Bits((unsigned INT)otherValue); |
335 hi2 = hi32Bits((unsigned INT)otherValue); |
336 # define LLMASK 0xC000000000000000LL |
336 # define LLMASK 0xC000000000000000LL |
337 # else |
337 # else |
338 low1 = low16Bits((unsigned INT)myValue); |
338 low1 = low16Bits((unsigned INT)myValue); |
339 hi1 = hi16Bits((unsigned INT)myValue); |
339 hi1 = hi16Bits((unsigned INT)myValue); |
340 low2 = low16Bits((unsigned INT)otherValue); |
340 low2 = low16Bits((unsigned INT)otherValue); |
341 hi2 = hi16Bits((unsigned INT)otherValue); |
341 hi2 = hi16Bits((unsigned INT)otherValue); |
342 # define LLMASK 0xC0000000L |
342 # define LLMASK 0xC0000000L |
343 # endif |
343 # endif |
344 |
344 |
345 pLH = low1 * hi2; |
345 pLH = low1 * hi2; |
346 pHL = hi1 * low2; |
346 pHL = hi1 * low2; |
347 pLL = low1 * low2; |
347 pLL = low1 * low2; |
348 pHH = hi1 * hi2; |
348 pHH = hi1 * hi2; |
349 |
349 |
350 /* |
350 /* |
351 * the common case ... |
351 * the common case ... |
352 */ |
352 */ |
353 if ((pHL == 0) |
353 if ((pHL == 0) |
354 && (pLH == 0) |
354 && (pLH == 0) |
355 && (pHH == 0) |
355 && (pHH == 0) |
356 && ((pLL & LLMASK) == 0)) { |
356 && ((pLL & LLMASK) == 0)) { |
357 if (negative < 0) { |
357 if (negative < 0) { |
358 RETURN ( __mkSmallInteger(- ((INT)pLL)) ); |
358 RETURN ( __mkSmallInteger(- ((INT)pLL)) ); |
359 } |
359 } |
360 RETURN ( __mkSmallInteger((INT)pLL) ); |
360 RETURN ( __mkSmallInteger((INT)pLL) ); |
361 } |
361 } |
362 |
362 |
363 /* |
363 /* |
364 * pHH |--------|--------| |
364 * pHH |--------|--------| |
365 * pLH |--------|--------| |
365 * pLH |--------|--------| |
366 * pHL |--------|--------| |
366 * pHL |--------|--------| |
367 * pLL |--------|--------| |
367 * pLL |--------|--------| |
368 */ |
368 */ |
369 |
369 |
370 # if __POINTER_SIZE__ == 8 |
370 # if __POINTER_SIZE__ == 8 |
371 t = low32Bits(pLH) + low32Bits(pHL) + hi32Bits(pLL); |
371 t = low32Bits(pLH) + low32Bits(pHL) + hi32Bits(pLL); |
372 productLow = (t << 32) + low32Bits(pLL); |
372 productLow = (t << 32) + low32Bits(pLL); |
373 productHi = pHH + hi32Bits(t) + hi32Bits(pHL) + hi32Bits(pLH); |
373 productHi = pHH + hi32Bits(t) + hi32Bits(pHL) + hi32Bits(pLH); |
374 # else |
374 # else |
375 t = low16Bits(pLH) + low16Bits(pHL) + hi16Bits(pLL); |
375 t = low16Bits(pLH) + low16Bits(pHL) + hi16Bits(pLL); |
376 productLow = (t << 16) + low16Bits(pLL); |
376 productLow = (t << 16) + low16Bits(pLL); |
377 productHi = pHH + hi16Bits(t) + hi16Bits(pHL) + hi16Bits(pLH); |
377 productHi = pHH + hi16Bits(t) + hi16Bits(pHL) + hi16Bits(pLH); |
378 # endif |
378 # endif |
379 } |
379 } |
380 # endif /* ! __win32__ */ |
380 # endif /* ! __win32__ */ |
381 # endif /* ! (__GNUC__ && __x86__) */ |
381 # endif /* ! (__GNUC__ && __x86__) */ |
382 # endif /* ! (__GNUC__ && __mc68k__) */ |
382 # endif /* ! (__GNUC__ && __mc68k__) */ |
383 |
383 |
384 if (productHi == 0) { |
384 if (productHi == 0) { |
385 if (negative < 0) { |
385 if (negative < 0) { |
386 if (productLow <= -(_MIN_INT)) { |
386 if (productLow <= -(_MIN_INT)) { |
387 RETURN ( __mkSmallInteger(-((INT)productLow)) ); |
387 RETURN ( __mkSmallInteger(-((INT)productLow)) ); |
388 } |
388 } |
389 } else { |
389 } else { |
390 if (productLow <= _MAX_INT) { |
390 if (productLow <= _MAX_INT) { |
391 RETURN ( __mkSmallInteger(productLow) ); |
391 RETURN ( __mkSmallInteger(productLow) ); |
392 } |
392 } |
393 } |
393 } |
394 } |
394 } |
395 # endif /* ! USE_LONGLONG */ |
395 # endif /* ! USE_LONGLONG */ |
396 |
396 |
397 # if __POINTER_SIZE__ == 8 |
397 # if __POINTER_SIZE__ == 8 |
398 RETURN (__MKLARGEINT128(negative, productLow, productHi)); |
398 RETURN (__MKLARGEINT128(negative, productLow, productHi)); |
399 # else |
399 # else |
400 RETURN (__MKLARGEINT64(negative, productLow, productHi)); |
400 RETURN (__MKLARGEINT64(negative, productLow, productHi)); |
401 # endif |
401 # endif |
402 } else if (__isFloatLike(aNumber)) { |
402 } else if (__isFloatLike(aNumber)) { |
403 OBJ newFloat; |
403 OBJ newFloat; |
404 double val = (double)myValue * __floatVal(aNumber); |
404 double val = (double)myValue * __floatVal(aNumber); |
405 |
405 |
406 __qMKFLOAT(newFloat, val); |
406 __qMKFLOAT(newFloat, val); |
407 RETURN ( newFloat ); |
407 RETURN ( newFloat ); |
408 } else if (__isShortFloat(aNumber)) { |
408 } else if (__isShortFloat(aNumber)) { |
409 OBJ newFloat; |
409 OBJ newFloat; |
410 float val = (float)myValue * __shortFloatVal(aNumber); |
410 float val = (float)myValue * __shortFloatVal(aNumber); |
411 |
411 |
412 __qMKSFLOAT(newFloat, val); |
412 __qMKSFLOAT(newFloat, val); |
413 RETURN ( newFloat ); |
413 RETURN ( newFloat ); |
414 } else if (__isFractionLike(aNumber)) { |
414 } else if (__isFractionLike(aNumber)) { |
415 OBJ t = __FractionInstPtr(aNumber)->f_numerator; |
415 OBJ t = __FractionInstPtr(aNumber)->f_numerator; |
416 |
416 |
417 if (myValue == 0) { |
417 if (myValue == 0) { |
418 RETURN(__mkSmallInteger(0)); |
418 RETURN(__mkSmallInteger(0)); |
419 } |
419 } |
420 |
420 |
421 if (__isSmallInteger(t)) { |
421 if (__isSmallInteger(t)) { |
422 INT num = __intVal(t); |
422 INT num = __intVal(t); |
423 t = __FractionInstPtr(aNumber)->f_denominator; |
423 t = __FractionInstPtr(aNumber)->f_denominator; |
424 if (__isSmallInteger(t)) { |
424 if (__isSmallInteger(t)) { |
425 INT prod = myValue * num; |
425 INT prod = myValue * num; |
426 if (prod / myValue == num) { // check for overflow |
426 if (prod / myValue == num) { // check for overflow |
427 INT den = __intVal(t); |
427 INT den = __intVal(t); |
428 INT quo = prod / den; |
428 INT quo = prod / den; |
429 if (quo * den == prod) { // check for integer result |
429 if (quo * den == prod) { // check for integer result |
430 RETURN ( __mkSmallInteger(quo) ); |
430 RETURN ( __mkSmallInteger(quo) ); |
431 } |
431 } |
432 } |
432 } |
433 } |
433 } |
434 } |
434 } |
435 } |
435 } |
436 #endif /* not __SCHTEAM__ */ |
436 #endif /* not __SCHTEAM__ */ |
437 %}. |
437 %}. |
438 ^ aNumber productFromInteger:self |
438 ^ aNumber productFromInteger:self |
439 |
439 |
440 " |
440 " |
441 3 * (1/2) |
441 3 * (1/2) |
442 6 * (1/2) |
442 6 * (1/2) |
443 6 * (-1/2) |
443 6 * (-1/2) |
444 " |
444 " |
445 ! |
445 ! |
446 |
446 |
447 + aNumber |
447 + aNumber |
448 "return the sum of the receiver's value and the argument's value" |
448 "return the sum of the receiver's value and the argument's value" |
561 INT t, val; |
561 INT t, val; |
562 double dval; |
562 double dval; |
563 INT myValue = __intVal(self); |
563 INT myValue = __intVal(self); |
564 |
564 |
565 if (__isSmallInteger(aNumber)) { |
565 if (__isSmallInteger(aNumber)) { |
566 val = __intVal(aNumber); |
566 val = __intVal(aNumber); |
567 if (val != 0) { |
567 if (val != 0) { |
568 t = myValue / val; |
568 t = myValue / val; |
569 # ifdef GOOD_OPTIMIZER |
569 # ifdef GOOD_OPTIMIZER |
570 if (myValue % val == 0) { |
570 if (myValue % val == 0) { |
571 # else |
571 # else |
572 /* this is stupid - all I want is to look for a remainder ... |
572 /* this is stupid - all I want is to look for a remainder ... |
573 but most compilers are too stupid and generate an extra modulus |
573 but most compilers are too stupid and generate an extra modulus |
574 instruction for "if (me % val)". |
574 instruction for "if (me % val)". |
575 Even if most divide instructions already leave the remainder in |
575 Even if most divide instructions already leave the remainder in |
576 some register. |
576 some register. |
577 Therefore I use a multiplication which is faster than a modulo |
577 Therefore I use a multiplication which is faster than a modulo |
578 on most machines. Hint to GNU people :-) |
578 on most machines. Hint to GNU people :-) |
579 */ |
579 */ |
580 if ((t * val) == myValue) { |
580 if ((t * val) == myValue) { |
581 # endif |
581 # endif |
582 RETURN ( __mkSmallInteger(t) ); |
582 RETURN ( __mkSmallInteger(t) ); |
583 } |
583 } |
584 } |
584 } |
585 } else { |
585 } else { |
586 if (__isFloatLike(aNumber)) { |
586 if (__isFloatLike(aNumber)) { |
587 dval = __floatVal(aNumber); |
587 dval = __floatVal(aNumber); |
588 if (dval != 0.0) { |
588 if (dval != 0.0) { |
589 OBJ newFloat; |
589 OBJ newFloat; |
590 double val = (double)myValue / dval; |
590 double val = (double)myValue / dval; |
591 |
591 |
592 __qMKFLOAT(newFloat, val); |
592 __qMKFLOAT(newFloat, val); |
593 RETURN ( newFloat ); |
593 RETURN ( newFloat ); |
594 } |
594 } |
595 } |
595 } |
596 } |
596 } |
597 #endif /* not __SCHTEAM__ */ |
597 #endif /* not __SCHTEAM__ */ |
598 %}. |
598 %}. |
599 aNumber isInteger ifTrue:[ |
599 aNumber isInteger ifTrue:[ |
600 aNumber == 0 ifTrue:[ |
600 aNumber == 0 ifTrue:[ |
601 ^ ZeroDivide raiseRequestWith:thisContext. |
601 ^ ZeroDivide raiseRequestWith:thisContext. |
602 ]. |
602 ]. |
603 ^ Fraction numerator:self denominator:aNumber |
603 ^ Fraction numerator:self denominator:aNumber |
604 ]. |
604 ]. |
605 ^ aNumber quotientFromInteger:self |
605 ^ aNumber quotientFromInteger:self |
606 |
606 |
607 " |
607 " |
608 8 / 4 |
608 8 / 4 |
648 |
649 |
649 INT divisor, rslt; |
650 INT divisor, rslt; |
650 INT dividend = __intVal(self); |
651 INT dividend = __intVal(self); |
651 |
652 |
652 if (__isSmallInteger(aNumber)) { |
653 if (__isSmallInteger(aNumber)) { |
653 divisor = __intVal(aNumber); |
654 divisor = __intVal(aNumber); |
654 if (divisor != 0) { |
655 if (divisor != 0) { |
655 rslt = dividend / divisor; |
656 rslt = dividend / divisor; |
656 /* |
657 /* |
657 * Optimized to speed up positive result |
658 * Optimized to speed up positive result |
658 */ |
659 */ |
659 if (rslt <= 0) { |
660 if (rslt <= 0) { |
660 if (rslt == 0) { |
661 if (rslt == 0) { |
661 if ((dividend ^ divisor) < 0) { |
662 if ((dividend ^ divisor) < 0) { |
662 /* |
663 /* |
663 * result (negative) has been truncated toward 0. |
664 * result (negative) has been truncated toward 0. |
664 * Return -1, because we truncate toward negative inf. |
665 * Return -1, because we truncate toward negative inf. |
665 */ |
666 */ |
666 rslt = -1; |
667 rslt = -1; |
667 } |
668 } |
668 } else { |
669 } else { |
669 /* |
670 /* |
670 * If result (negative) has been truncated toward 0, |
671 * If result (negative) has been truncated toward 0, |
671 * subtract 1, because we truncate toward negative inf. |
672 * subtract 1, because we truncate toward negative inf. |
672 */ |
673 */ |
673 if (divisor > 0) { |
674 if (divisor > 0) { |
674 if (rslt * divisor > dividend) { |
675 if (rslt * divisor > dividend) { |
675 rslt--; |
676 rslt--; |
676 } |
677 } |
677 } else { |
678 } else { |
678 if (rslt * divisor < dividend) { |
679 if (rslt * divisor < dividend) { |
679 rslt--; |
680 rslt--; |
680 } |
681 } |
681 } |
682 } |
682 } |
683 } |
683 } |
684 } |
684 RETURN ( __mkSmallInteger(rslt) ); |
685 RETURN ( __mkSmallInteger(rslt) ); |
685 } |
686 } |
686 } else { |
687 } else { |
687 if (__isFractionLike(aNumber)) { |
688 if (__isFractionLike(aNumber)) { |
688 OBJ t = __FractionInstPtr(aNumber)->f_numerator; |
689 OBJ t = __FractionInstPtr(aNumber)->f_numerator; |
689 if (__isSmallInteger(t)) { |
690 if (__isSmallInteger(t)) { |
690 INT num = __intVal(t); |
691 INT num = __intVal(t); |
691 t = __FractionInstPtr(aNumber)->f_denominator; |
692 t = __FractionInstPtr(aNumber)->f_denominator; |
692 if (__isSmallInteger(t)) { |
693 if (__isSmallInteger(t)) { |
693 INT den = __intVal(t); |
694 INT den = __intVal(t); |
694 INT prod; |
695 INT prod; |
695 #if 0 && defined(__GNUC__) // supported from GCC 5 |
696 #if 0 && defined(__GNUC__) // supported from GCC 5 |
696 if (!__builtin_mul_overflow(myself, den, &prod)) { |
697 if (!__builtin_mul_overflow(myself, den, &prod)) { |
697 goto out; // overflow, try harder... |
698 goto out; // overflow, try harder... |
698 } |
699 } |
699 #else |
700 #else |
700 prod = dividend * den; |
701 prod = dividend * den; |
701 // make sure, that no overflow occurred |
702 // make sure, that no overflow occurred |
702 if (prod / den != dividend) { |
703 if (prod / den != dividend) { |
703 goto out; // overflow, try harder... |
704 goto out; // overflow, try harder... |
704 } |
705 } |
705 #endif |
706 #endif |
706 rslt = prod / num; |
707 rslt = prod / num; |
707 |
708 |
708 /* |
709 /* |
709 * Optimized to speed up positive result |
710 * Optimized to speed up positive result |
710 */ |
711 */ |
711 if (rslt <= 0) { |
712 if (rslt <= 0) { |
712 if (rslt == 0) { |
713 if (rslt == 0) { |
713 if ((dividend ^ num) < 0) { |
714 if ((dividend ^ num) < 0) { |
714 /* |
715 /* |
715 * result (negative) has been truncated toward 0. |
716 * result (negative) has been truncated toward 0. |
716 * Return -1, because we truncate toward negative inf. |
717 * Return -1, because we truncate toward negative inf. |
717 */ |
718 */ |
718 rslt = -1; |
719 rslt = -1; |
719 } |
720 } |
720 } else { |
721 } else { |
721 /* |
722 /* |
722 * If result (negative) has been truncated toward 0, |
723 * If result (negative) has been truncated toward 0, |
723 * subtract 1, because we truncate toward negative inf. |
724 * subtract 1, because we truncate toward negative inf. |
724 */ |
725 */ |
725 if (num > 0) { |
726 if (num > 0) { |
726 if (rslt * num > prod) rslt--; |
727 if (rslt * num > prod) rslt--; |
727 } else { |
728 } else { |
728 if (rslt * num < prod) rslt--; |
729 if (rslt * num < prod) rslt--; |
729 } |
730 } |
730 } |
731 } |
731 } |
732 } |
732 RETURN ( __mkSmallInteger(rslt) ); |
733 RETURN ( __mkSmallInteger(rslt) ); |
733 } |
734 } |
734 } |
735 } |
735 } |
736 } |
736 } |
737 } |
737 out:; |
738 out:; |
738 #endif /* not __SCHTEAM__ */ |
739 #endif /* not __SCHTEAM__ */ |
739 %}. |
740 %}. |
740 (aNumber = 0) ifTrue:[ |
741 (aNumber = 0) ifTrue:[ |
741 ^ ZeroDivide raiseRequestWith:thisContext. |
742 ^ ZeroDivide raiseRequestWith:thisContext. |
742 ]. |
743 ]. |
743 ^ aNumber integerQuotientFromInteger:self |
744 ^ aNumber integerQuotientFromInteger:self |
744 |
745 |
745 " |
746 " |
746 9 // 4 ~~ 2 ifTrue:[self halt]. |
747 9 // 4 ~~ 2 ifTrue:[self halt]. |
898 quo:aNumber |
899 quo:aNumber |
899 "return the integer part of the quotient of the receiver's value |
900 "return the integer part of the quotient of the receiver's value |
900 and the argument's value. The result is truncated towards zero |
901 and the argument's value. The result is truncated towards zero |
901 and negative, if the operands signs differ.. |
902 and negative, if the operands signs differ.. |
902 The following is always true: |
903 The following is always true: |
903 (receiver quo: aNumber) * aNumber + (receiver rem: aNumber) = receiver |
904 (receiver quo: aNumber) * aNumber + (receiver rem: aNumber) = receiver |
904 For positive results, this is the same as #//, |
905 For positive results, this is the same as #//, |
905 for negative results, the remainder is ignored. |
906 for negative results, the remainder is ignored. |
906 I.e.: '9 // 4 = 2' and '-9 // 4 = -3' |
907 I.e.: '9 // 4 = 2' and '-9 // 4 = -3' |
907 in contrast: '9 quo: 4 = 2' and '-9 quo: 4 = -2'" |
908 in contrast: '9 quo: 4 = 2' and '-9 quo: 4 = -2'" |
908 |
909 |
909 %{ /* NOCONTEXT */ |
910 %{ /* NOCONTEXT */ |
910 #ifdef __SCHTEAM__ |
911 #ifdef __SCHTEAM__ |
911 return context._RETURN( self.quotient(aNumber)); |
912 return context._RETURN( self.quotient(aNumber)); |
912 #else |
913 #else |
913 if (__isSmallInteger(aNumber)) { |
914 if (__isSmallInteger(aNumber)) { |
914 INT val = __intVal(aNumber); |
915 INT val = __intVal(aNumber); |
915 if (val != 0) { |
916 if (val != 0) { |
916 RETURN ( __mkSmallInteger(__intVal(self) / val) ); |
917 RETURN ( __mkSmallInteger(__intVal(self) / val) ); |
917 } |
918 } |
918 } else { |
919 } else { |
919 if (__isFractionLike(aNumber)) { |
920 if (__isFractionLike(aNumber)) { |
920 OBJ t = __FractionInstPtr(aNumber)->f_numerator; |
921 OBJ t = __FractionInstPtr(aNumber)->f_numerator; |
921 if (__isSmallInteger(t)) { |
922 if (__isSmallInteger(t)) { |
922 INT num = __intVal(t); |
923 INT num = __intVal(t); |
923 t = __FractionInstPtr(aNumber)->f_denominator; |
924 t = __FractionInstPtr(aNumber)->f_denominator; |
924 if (__isSmallInteger(t)) { |
925 if (__isSmallInteger(t)) { |
925 INT den = __intVal(t); |
926 INT den = __intVal(t); |
926 INT myself = __intVal(self); |
927 INT myself = __intVal(self); |
927 INT prod; |
928 INT prod; |
928 #if 0 && defined(__GNUC__) // supported from GCC 5 |
929 #if 0 && defined(__GNUC__) // supported from GCC 5 |
929 if (__builtin_mul_overflow(myself, den, &prod)) { |
930 if (__builtin_mul_overflow(myself, den, &prod)) { |
930 RETURN ( __mkSmallInteger(prod / num )); |
931 RETURN ( __mkSmallInteger(prod / num )); |
931 } |
932 } |
932 #else |
933 #else |
933 prod = myself * den; |
934 prod = myself * den; |
934 // make sure, that no overflow occurred |
935 // make sure, that no overflow occurred |
935 if (prod / den == myself) { |
936 if (prod / den == myself) { |
936 RETURN ( __mkSmallInteger(prod / num )); |
937 RETURN ( __mkSmallInteger(prod / num )); |
937 } |
938 } |
938 #endif |
939 #endif |
939 } |
940 } |
940 } |
941 } |
941 } |
942 } |
942 } |
943 } |
943 #endif /* not __SCHTEAM__ */ |
944 #endif /* not __SCHTEAM__ */ |
944 %}. |
945 %}. |
945 (aNumber = 0) ifTrue:[ |
946 (aNumber = 0) ifTrue:[ |
946 ^ ZeroDivide raiseRequestWith:thisContext. |
947 ^ ZeroDivide raiseRequestWith:thisContext. |
947 ]. |
948 ]. |
948 ^ self retry:#quo: coercing:aNumber |
949 ^ self retry:#quo: coercing:aNumber |
949 |
950 |
950 " |
951 " |
951 9 // 4 |
952 9 // 4 |
1142 ^ super bitCount. |
1143 ^ super bitCount. |
1143 |
1144 |
1144 " |
1145 " |
1145 |
1146 |
1146 1 to:1000000 do:[:n | |
1147 1 to:1000000 do:[:n | |
1147 self assert:(n bitCount = ((n printStringRadix:2) occurrencesOf:$1)) |
1148 self assert:(n bitCount = ((n printStringRadix:2) occurrencesOf:$1)) |
1148 ]. |
1149 ]. |
1149 |
1150 |
1150 #( 16r00000000 |
1151 #( 16r00000000 |
1151 16r00010000 16r00100000 16r01000000 16r10000000 |
1152 16r00010000 16r00100000 16r01000000 16r10000000 |
1152 16r00020000 16r00200000 16r02000000 16r20000000 |
1153 16r00020000 16r00200000 16r02000000 16r20000000 |
1153 16r00040000 16r00400000 16r04000000 16r40000000 |
1154 16r00040000 16r00400000 16r04000000 16r40000000 |
1154 16r00080000 16r00800000 16r08000000 16r80000000 |
1155 16r00080000 16r00800000 16r08000000 16r80000000 |
1155 |
1156 |
1156 16rFFFFFFFF 16r7FFFFFFF 16r3FFFFFFF 16r1FFFFFFF |
1157 16rFFFFFFFF 16r7FFFFFFF 16r3FFFFFFF 16r1FFFFFFF |
1157 16rEEEEEEEE 16r7EEEEEEE 16r3EEEEEEE 16r1EEEEEEE |
1158 16rEEEEEEEE 16r7EEEEEEE 16r3EEEEEEE 16r1EEEEEEE |
1158 16rDDDDDDDD 16r7DDDDDDD 16r3DDDDDDD 16r1DDDDDDD |
1159 16rDDDDDDDD 16r7DDDDDDD 16r3DDDDDDD 16r1DDDDDDD |
1159 16rCCCCCCCC 16r7CCCCCCC 16r3CCCCCCC 16r1CCCCCCC |
1160 16rCCCCCCCC 16r7CCCCCCC 16r3CCCCCCC 16r1CCCCCCC |
1160 |
1161 |
1161 16r8000000000010000 16r8000000000100000 16r8000000001000000 16r8000000010000000 |
1162 16r8000000000010000 16r8000000000100000 16r8000000001000000 16r8000000010000000 |
1162 16r8000000000020000 16r8000000000200000 16r8000000002000000 16r8000000020000000 |
1163 16r8000000000020000 16r8000000000200000 16r8000000002000000 16r8000000020000000 |
1163 16r8000000000040000 16r8000000000400000 16r8000000004000000 16r8000000040000000 |
1164 16r8000000000040000 16r8000000000400000 16r8000000004000000 16r8000000040000000 |
1164 16r8000000000080000 16r8000000000800000 16r8000000008000000 16r8000000080000000 |
1165 16r8000000000080000 16r8000000000800000 16r8000000008000000 16r8000000080000000 |
1165 |
1166 |
1166 16r80000000FFFFFFFF 16r800000007FFFFFFF 16r800000003FFFFFFF 16r800000001FFFFFFF |
1167 16r80000000FFFFFFFF 16r800000007FFFFFFF 16r800000003FFFFFFF 16r800000001FFFFFFF |
1167 16r80000000EEEEEEEE 16r800000007EEEEEEE 16r800000003EEEEEEE 16r800000001EEEEEEE |
1168 16r80000000EEEEEEEE 16r800000007EEEEEEE 16r800000003EEEEEEE 16r800000001EEEEEEE |
1168 16r80000000DDDDDDDD 16r800000007DDDDDDD 16r800000003DDDDDDD 16r800000001DDDDDDD |
1169 16r80000000DDDDDDDD 16r800000007DDDDDDD 16r800000003DDDDDDD 16r800000001DDDDDDD |
1169 16r80000000CCCCCCCC 16r800000007CCCCCCC 16r800000003CCCCCCC 16r800000001CCCCCCC |
1170 16r80000000CCCCCCCC 16r800000007CCCCCCC 16r800000003CCCCCCC 16r800000001CCCCCCC |
1170 |
1171 |
1171 16rFFFFFFFFFFFFFFFF 16r7FFFFFFFFFFFFFFF 16r3FFFFFFFFFFFFFFF 16r1FFFFFFFFFFFFFFF |
1172 16rFFFFFFFFFFFFFFFF 16r7FFFFFFFFFFFFFFF 16r3FFFFFFFFFFFFFFF 16r1FFFFFFFFFFFFFFF |
1172 ) do:[:n | |
1173 ) do:[:n | |
1173 self assert:(n bitCount = ((n printStringRadix:2) occurrencesOf:$1)) |
1174 self assert:(n bitCount = ((n printStringRadix:2) occurrencesOf:$1)) |
1174 ] |
1175 ] |
1175 |
1176 |
1176 1 to:10000000 do:[:n | |
1177 1 to:10000000 do:[:n | |
1177 (n bitCount) |
1178 (n bitCount) |
1178 ] |
1179 ] |
1179 " |
1180 " |
1180 |
1181 |
1181 "Modified: / 09-01-2012 / 19:12:41 / cg" |
1182 "Modified: / 09-01-2012 / 19:12:41 / cg" |
1182 ! |
1183 ! |
1400 |
1401 |
1401 bitShift:shiftCount |
1402 bitShift:shiftCount |
1402 "return the value of the receiver shifted by shiftCount bits; |
1403 "return the value of the receiver shifted by shiftCount bits; |
1403 leftShift if shiftCount > 0; rightShift otherwise. |
1404 leftShift if shiftCount > 0; rightShift otherwise. |
1404 Notice: the result of bitShift: on negative receivers is not |
1405 Notice: the result of bitShift: on negative receivers is not |
1405 defined in the language standard (since the implementation |
1406 defined in the language standard (since the implementation |
1406 is free to choose any internal representation for integers). |
1407 is free to choose any internal representation for integers). |
1407 However, ST/X preserves the sign." |
1408 However, ST/X preserves the sign." |
1408 |
1409 |
1409 %{ /* NOCONTEXT */ |
1410 %{ /* NOCONTEXT */ |
1410 #ifdef __SCHTEAM__ |
1411 #ifdef __SCHTEAM__ |
1411 return context._RETURN( self.bitShift( shiftCount )); |
1412 return context._RETURN( self.bitShift( shiftCount )); |
1412 #else |
1413 #else |
1413 INT bits, count; |
1414 INT bits, count; |
1414 |
1415 |
1415 if (__isSmallInteger(shiftCount)) { |
1416 if (__isSmallInteger(shiftCount)) { |
1416 bits = __intVal(self); |
1417 bits = __intVal(self); |
1417 if (bits == 0) { |
1418 if (bits == 0) { |
1418 RETURN (self); |
1419 RETURN (self); |
1419 } |
1420 } |
1420 count = __intVal(shiftCount); |
1421 count = __intVal(shiftCount); |
1421 |
1422 |
1422 if (count > 0) { |
1423 if (count > 0) { |
1423 INT sign = 1; |
1424 INT sign = 1; |
1424 if (bits < 0) { |
1425 if (bits < 0) { |
1425 bits = -bits; |
1426 bits = -bits; |
1426 sign = -1; |
1427 sign = -1; |
1427 } |
1428 } |
1428 /* |
1429 /* |
1429 * a left shift |
1430 * a left shift |
1430 */ |
1431 */ |
1431 # if defined(USE_LONGLONG_FOR_SHIFT) |
1432 # if defined(USE_LONGLONG_FOR_SHIFT) |
1432 if (count <= N_INT_BITS) { |
1433 if (count <= N_INT_BITS) { |
1433 unsigned LONGLONG result; |
1434 unsigned LONGLONG result; |
1434 |
1435 |
1435 result = (unsigned LONGLONG)bits; |
1436 result = (unsigned LONGLONG)bits; |
1436 result <<= count; |
1437 result <<= count; |
1437 if (result <= _MAX_INT) { |
1438 if (result <= _MAX_INT) { |
1438 if (sign < 0) { |
1439 if (sign < 0) { |
1439 RETURN ( __MKINT(-result) ); |
1440 RETURN ( __MKINT(-result) ); |
1440 } |
1441 } |
1441 RETURN ( __mkSmallInteger(result) ); |
1442 RETURN ( __mkSmallInteger(result) ); |
1442 } |
1443 } |
1443 { |
1444 { |
1444 RETURN (__MKLARGEINT64(sign, (INT)(result >> 32), (INT)(result & 0xFFFFFFFF))); |
1445 RETURN (__MKLARGEINT64(sign, (INT)(result >> 32), (INT)(result & 0xFFFFFFFF))); |
1445 } |
1446 } |
1446 } |
1447 } |
1447 # else |
1448 # else |
1448 /* |
1449 /* |
1449 * check for overflow |
1450 * check for overflow |
1450 */ |
1451 */ |
1451 if (count < (N_INT_BITS-1)) { |
1452 if (count < (N_INT_BITS-1)) { |
1452 if (! (bits >> (N_INT_BITS - 1 - count))) { |
1453 if (! (bits >> (N_INT_BITS - 1 - count))) { |
1453 INT result = bits << count; |
1454 INT result = bits << count; |
1454 |
1455 |
1455 if (sign < 0) { |
1456 if (sign < 0) { |
1456 RETURN ( __MKINT(-result) ); |
1457 RETURN ( __MKINT(-result) ); |
1457 } |
1458 } |
1458 RETURN ( __mkSmallInteger(result) ); |
1459 RETURN ( __mkSmallInteger(result) ); |
1459 } |
1460 } |
1460 /* |
1461 /* |
1461 * so, there is an overflow ... |
1462 * so, there is an overflow ... |
1462 * handle it as largeInteger |
1463 * handle it as largeInteger |
1463 */ |
1464 */ |
1464 /* FALL THROUGH */ |
1465 /* FALL THROUGH */ |
1465 } |
1466 } |
1466 # endif |
1467 # endif |
1467 } else { |
1468 } else { |
1468 if (count == 0) { |
1469 if (count == 0) { |
1469 RETURN (self); |
1470 RETURN (self); |
1470 } |
1471 } |
1471 |
1472 |
1472 /* |
1473 /* |
1473 * right shifts cannot overflow |
1474 * right shifts cannot overflow |
1474 * |
1475 * |
1475 * some machines ignore shifts bigger than |
1476 * some machines ignore shifts bigger than |
1476 * the number of bits in an int ... |
1477 * the number of bits in an int ... |
1477 */ |
1478 */ |
1478 count = -count; |
1479 count = -count; |
1479 if (count > (N_INT_BITS-1)) { |
1480 if (count > (N_INT_BITS-1)) { |
1480 RETURN (__mkSmallInteger(0)); |
1481 RETURN (__mkSmallInteger(0)); |
1481 } |
1482 } |
1482 |
1483 |
1483 RETURN ( __mkSmallInteger(bits >> count) ); |
1484 RETURN ( __mkSmallInteger(bits >> count) ); |
1484 } |
1485 } |
1485 } |
1486 } |
1486 #endif /* not __SCHTEAM__ */ |
1487 #endif /* not __SCHTEAM__ */ |
1487 %}. |
1488 %}. |
1488 (shiftCount isMemberOf:SmallInteger) ifTrue:[ |
1489 (shiftCount isMemberOf:SmallInteger) ifTrue:[ |
1489 ^ (LargeInteger value:self) bitShift:shiftCount |
1490 ^ (LargeInteger value:self) bitShift:shiftCount |
1490 ]. |
1491 ]. |
1491 ^ self bitShift:shiftCount asInteger "/ is this a good idea ? |
1492 ^ self bitShift:shiftCount asInteger "/ is this a good idea ? |
1492 ! |
1493 ! |
1493 |
1494 |
1494 bitTest:aMask |
1495 bitTest:aMask |
1770 16r1000 lowBit |
1771 16r1000 lowBit |
1771 16r1000000 lowBit |
1772 16r1000000 lowBit |
1772 16r1000000000000000 lowBit |
1773 16r1000000000000000 lowBit |
1773 |
1774 |
1774 Time millisecondsToRun:[ |
1775 Time millisecondsToRun:[ |
1775 1000000 timesRepeat:[ |
1776 1000000 timesRepeat:[ |
1776 2r1000 lowBit |
1777 2r1000 lowBit |
1777 ] |
1778 ] |
1778 ] |
1779 ] |
1779 |
1780 |
1780 Time millisecondsToRun:[ |
1781 Time millisecondsToRun:[ |
1781 1000000 timesRepeat:[ |
1782 1000000 timesRepeat:[ |
1782 2r11110000000 lowBit |
1783 2r11110000000 lowBit |
1783 ] |
1784 ] |
1784 ] |
1785 ] |
1785 |
1786 |
1786 Time millisecondsToRun:[ |
1787 Time millisecondsToRun:[ |
1787 1000000 timesRepeat:[ |
1788 1000000 timesRepeat:[ |
1788 2r1000000000000 lowBit |
1789 2r1000000000000 lowBit |
1789 ] |
1790 ] |
1790 ] |
1791 ] |
1791 |
1792 |
1792 Time millisecondsToRun:[ |
1793 Time millisecondsToRun:[ |
1793 1000000 timesRepeat:[ |
1794 1000000 timesRepeat:[ |
1794 2r1000000000000000000000000000 lowBit |
1795 2r1000000000000000000000000000 lowBit |
1795 ] |
1796 ] |
1796 ] |
1797 ] |
1797 " |
1798 " |
1798 ! |
1799 ! |
1799 |
1800 |
1800 rightShift:shiftCount |
1801 rightShift:shiftCount |
1801 "return the value of the receiver shifted by shiftCount bits; |
1802 "return the value of the receiver shifted by shiftCount bits; |
1802 right shift if shiftCount > 0; left shift otherwise. |
1803 right shift if shiftCount > 0; left shift otherwise. |
1803 Notice: the result of bitShift: on negative receivers is not |
1804 Notice: the result of bitShift: on negative receivers is not |
1804 defined in the language standard (since the implementation |
1805 defined in the language standard (since the implementation |
1805 is free to choose any internal representation for integers). |
1806 is free to choose any internal representation for integers). |
1806 However, ST/X preserves the sign." |
1807 However, ST/X preserves the sign." |
1807 |
1808 |
1808 %{ /* NOCONTEXT */ |
1809 %{ /* NOCONTEXT */ |
1809 #ifdef __SCHTEAM__ |
1810 #ifdef __SCHTEAM__ |
1810 #else |
1811 #else |
1811 INT bits, count; |
1812 INT bits, count; |
1812 |
1813 |
1813 if (__isSmallInteger(shiftCount)) { |
1814 if (__isSmallInteger(shiftCount)) { |
1814 bits = __intVal(self); |
1815 bits = __intVal(self); |
1815 if (bits == 0) { |
1816 if (bits == 0) { |
1816 RETURN (self); |
1817 RETURN (self); |
1817 } |
1818 } |
1818 |
1819 |
1819 count = __intVal(shiftCount); |
1820 count = __intVal(shiftCount); |
1820 |
1821 |
1821 if (count < 0) { |
1822 if (count < 0) { |
1822 /* |
1823 /* |
1823 * a left shift |
1824 * a left shift |
1824 */ |
1825 */ |
1825 count = -count; |
1826 count = -count; |
1826 # if defined(USE_LONGLONG_FOR_SHIFT) |
1827 # if defined(USE_LONGLONG_FOR_SHIFT) |
1827 if (count <= N_INT_BITS) { |
1828 if (count <= N_INT_BITS) { |
1828 unsigned LONGLONG result; |
1829 unsigned LONGLONG result; |
1829 |
1830 |
1830 result = (unsigned LONGLONG)bits; |
1831 result = (unsigned LONGLONG)bits; |
1831 result <<= count; |
1832 result <<= count; |
1832 if (result <= _MAX_INT) { |
1833 if (result <= _MAX_INT) { |
1833 RETURN ( __mkSmallInteger(result) ); |
1834 RETURN ( __mkSmallInteger(result) ); |
1834 } |
1835 } |
1835 { |
1836 { |
1836 RETURN (__MKLARGEINT64(1, (INT)(result >> 32), (INT)(result & 0xFFFFFFFF))); |
1837 RETURN (__MKLARGEINT64(1, (INT)(result >> 32), (INT)(result & 0xFFFFFFFF))); |
1837 } |
1838 } |
1838 } |
1839 } |
1839 # else |
1840 # else |
1840 /* |
1841 /* |
1841 * check for overflow |
1842 * check for overflow |
1842 */ |
1843 */ |
1843 if (count < (N_INT_BITS-1)) { |
1844 if (count < (N_INT_BITS-1)) { |
1844 if (! (bits >> (N_INT_BITS - 1 - count))) { |
1845 if (! (bits >> (N_INT_BITS - 1 - count))) { |
1845 RETURN ( __mkSmallInteger(bits << count) ); |
1846 RETURN ( __mkSmallInteger(bits << count) ); |
1846 } |
1847 } |
1847 /* |
1848 /* |
1848 * so, there is an overflow ... |
1849 * so, there is an overflow ... |
1849 * handle it as largeInteger |
1850 * handle it as largeInteger |
1850 */ |
1851 */ |
1851 /* FALL THROUGH */ |
1852 /* FALL THROUGH */ |
1852 } |
1853 } |
1853 # endif |
1854 # endif |
1854 } else { |
1855 } else { |
1855 if (count == 0) { |
1856 if (count == 0) { |
1856 RETURN (self); |
1857 RETURN (self); |
1857 } |
1858 } |
1858 |
1859 |
1859 /* |
1860 /* |
1860 * right shifts cannot overflow |
1861 * right shifts cannot overflow |
1861 * |
1862 * |
1862 * some machines ignore shifts bigger than |
1863 * some machines ignore shifts bigger than |
1863 * the number of bits in an int ... |
1864 * the number of bits in an int ... |
1864 */ |
1865 */ |
1865 if (count > (N_INT_BITS-1)) { |
1866 if (count > (N_INT_BITS-1)) { |
1866 RETURN (__mkSmallInteger(0)); |
1867 RETURN (__mkSmallInteger(0)); |
1867 } |
1868 } |
1868 |
1869 |
1869 RETURN ( __mkSmallInteger(bits >> count) ); |
1870 RETURN ( __mkSmallInteger(bits >> count) ); |
1870 } |
1871 } |
1871 } |
1872 } |
1872 #endif /* not __SCHTEAM__ */ |
1873 #endif /* not __SCHTEAM__ */ |
1873 %}. |
1874 %}. |
1874 (shiftCount isMemberOf:SmallInteger) ifTrue:[ |
1875 (shiftCount isMemberOf:SmallInteger) ifTrue:[ |
1875 ^ (LargeInteger value:self) rightShift:shiftCount |
1876 ^ (LargeInteger value:self) rightShift:shiftCount |
1876 ]. |
1877 ]. |
1877 ^ self rightShift:shiftCount asInteger "/ is this a good idea ? |
1878 ^ self rightShift:shiftCount asInteger "/ is this a good idea ? |
1878 |
1879 |
1879 |
1880 |
1880 " |
1881 " |
1881 16 rightShift:2 |
1882 16 rightShift:2 |
1882 4 rightShift:-2 |
1883 4 rightShift:-2 |
1883 " |
1884 " |
1884 ! ! |
1885 ! ! |
1885 |
1886 |
1886 !SmallInteger methodsFor:'bit operators - indexed'! |
1887 !SmallInteger methodsFor:'bit operators - indexed'! |
1887 |
1888 |
1888 bitAt:anIntegerIndex |
1889 bitAt:anIntegerIndex |
1889 "return the value of the index's bit (index starts at 1) as 0 or 1. |
1890 "return the value of the index's bit (index starts at 1) as 0 or 1. |
1890 Notice: the result of bitAt: on negative receivers is not |
1891 Notice: the result of bitAt: on negative receivers is not |
1891 defined in the language standard (since the implementation |
1892 defined in the language standard (since the implementation |
1892 is free to choose any internal representation for integers)" |
1893 is free to choose any internal representation for integers)" |
1893 |
1894 |
1894 %{ /* NOCONTEXT */ |
1895 %{ /* NOCONTEXT */ |
1895 #ifdef __SCHTEAM__ |
1896 #ifdef __SCHTEAM__ |
1896 return context._RETURN( self.bitAt(anIntegerIndex)); |
1897 return context._RETURN( self.bitAt(anIntegerIndex)); |
1897 #else |
1898 #else |
1898 if (__isSmallInteger(anIntegerIndex)) { |
1899 if (__isSmallInteger(anIntegerIndex)) { |
1899 INT idx = __smallIntegerVal(anIntegerIndex); |
1900 INT idx = __smallIntegerVal(anIntegerIndex); |
1900 if (idx > 0) { |
1901 if (idx > 0) { |
1901 if (idx > N_INT_BITS) { |
1902 if (idx > N_INT_BITS) { |
1902 RETURN(__mkSmallInteger(0)); |
1903 RETURN(__mkSmallInteger(0)); |
1903 } |
1904 } |
1904 RETURN((__smallIntegerVal(self) & ((INT)1 << (idx-1))) ? __mkSmallInteger(1) : __mkSmallInteger(0)); |
1905 RETURN((__smallIntegerVal(self) & ((INT)1 << (idx-1))) ? __mkSmallInteger(1) : __mkSmallInteger(0)); |
1905 } |
1906 } |
1906 } |
1907 } |
1907 #endif /* not __SCHTEAM__ */ |
1908 #endif /* not __SCHTEAM__ */ |
1908 %}. |
1909 %}. |
1909 |
1910 |
1910 ^ SubscriptOutOfBoundsError |
1911 ^ SubscriptOutOfBoundsError |
1911 raiseRequestWith:anIntegerIndex |
1912 raiseRequestWith:anIntegerIndex |
1912 errorString:'index out of bounds' |
1913 errorString:'index out of bounds' |
1913 |
1914 |
1914 " |
1915 " |
1915 16r000000001 bitAt:0 -> error |
1916 16r000000001 bitAt:0 -> error |
1916 16r000000001 bitAt:1 |
1917 16r000000001 bitAt:1 |
1917 16r000000001 bitAt:2 |
1918 16r000000001 bitAt:2 |
2409 could have simply created a 4-byte largeinteger and normalize it. |
2410 could have simply created a 4-byte largeinteger and normalize it. |
2410 The code below does the normalize right away, avoiding the |
2411 The code below does the normalize right away, avoiding the |
2411 overhead of producing any intermediate byte-arrays (and the scanning) |
2412 overhead of producing any intermediate byte-arrays (and the scanning) |
2412 " |
2413 " |
2413 self == 0 ifTrue: [ |
2414 self == 0 ifTrue: [ |
2414 ^ ByteArray with:0. |
2415 ^ ByteArray with:0. |
2415 ]. |
2416 ]. |
2416 |
2417 |
2417 self < 0 ifTrue: [ |
2418 self < 0 ifTrue: [ |
2418 absValue := self negated |
2419 absValue := self negated |
2419 ] ifFalse: [ |
2420 ] ifFalse: [ |
2420 absValue := self. |
2421 absValue := self. |
2421 ]. |
2422 ]. |
2422 |
2423 |
2423 b1 := absValue bitAnd:16rFF. |
2424 b1 := absValue bitAnd:16rFF. |
2424 absValue := absValue bitShift:-8. |
2425 absValue := absValue bitShift:-8. |
2425 absValue == 0 ifTrue:[ |
2426 absValue == 0 ifTrue:[ |
2426 digitByteArray := ByteArray with:b1 |
2427 digitByteArray := ByteArray with:b1 |
2427 ] ifFalse:[ |
2428 ] ifFalse:[ |
2428 b2 := absValue bitAnd:16rFF. |
2429 b2 := absValue bitAnd:16rFF. |
2429 absValue := absValue bitShift:-8. |
2430 absValue := absValue bitShift:-8. |
2430 absValue == 0 ifTrue:[ |
2431 absValue == 0 ifTrue:[ |
2431 digitByteArray := ByteArray with:b1 with:b2 |
2432 digitByteArray := ByteArray with:b1 with:b2 |
2432 ] ifFalse:[ |
2433 ] ifFalse:[ |
2433 b3 := absValue bitAnd:16rFF. |
2434 b3 := absValue bitAnd:16rFF. |
2434 absValue := absValue bitShift:-8. |
2435 absValue := absValue bitShift:-8. |
2435 absValue == 0 ifTrue:[ |
2436 absValue == 0 ifTrue:[ |
2436 digitByteArray := ByteArray with:b1 with:b2 with:b3 |
2437 digitByteArray := ByteArray with:b1 with:b2 with:b3 |
2437 ] ifFalse:[ |
2438 ] ifFalse:[ |
2438 b4 := absValue bitAnd:16rFF. |
2439 b4 := absValue bitAnd:16rFF. |
2439 absValue := absValue bitShift:-8. |
2440 absValue := absValue bitShift:-8. |
2440 absValue == 0 ifTrue:[ |
2441 absValue == 0 ifTrue:[ |
2441 digitByteArray := ByteArray with:b1 with:b2 with:b3 with:b4 |
2442 digitByteArray := ByteArray with:b1 with:b2 with:b3 with:b4 |
2442 ] ifFalse:[ |
2443 ] ifFalse:[ |
2443 b5 := absValue bitAnd:16rFF. |
2444 b5 := absValue bitAnd:16rFF. |
2444 absValue := absValue bitShift:-8. |
2445 absValue := absValue bitShift:-8. |
2445 absValue == 0 ifTrue:[ |
2446 absValue == 0 ifTrue:[ |
2446 digitByteArray := ByteArray new:5. |
2447 digitByteArray := ByteArray new:5. |
2447 digitByteArray at:1 put:b1. |
2448 digitByteArray at:1 put:b1. |
2448 digitByteArray at:2 put:b2. |
2449 digitByteArray at:2 put:b2. |
2449 digitByteArray at:3 put:b3. |
2450 digitByteArray at:3 put:b3. |
2450 digitByteArray at:4 put:b4. |
2451 digitByteArray at:4 put:b4. |
2451 digitByteArray at:5 put:b5. |
2452 digitByteArray at:5 put:b5. |
2452 ] ifFalse:[ |
2453 ] ifFalse:[ |
2453 b6 := absValue bitAnd:16rFF. |
2454 b6 := absValue bitAnd:16rFF. |
2454 absValue := absValue bitShift:-8. |
2455 absValue := absValue bitShift:-8. |
2455 absValue == 0 ifTrue:[ |
2456 absValue == 0 ifTrue:[ |
2456 digitByteArray := ByteArray new:6. |
2457 digitByteArray := ByteArray new:6. |
2457 digitByteArray at:1 put:b1. |
2458 digitByteArray at:1 put:b1. |
2458 digitByteArray at:2 put:b2. |
2459 digitByteArray at:2 put:b2. |
2459 digitByteArray at:3 put:b3. |
2460 digitByteArray at:3 put:b3. |
2460 digitByteArray at:4 put:b4. |
2461 digitByteArray at:4 put:b4. |
2461 digitByteArray at:5 put:b5. |
2462 digitByteArray at:5 put:b5. |
2462 digitByteArray at:6 put:b6. |
2463 digitByteArray at:6 put:b6. |
2463 ] ifFalse:[ |
2464 ] ifFalse:[ |
2464 b7 := absValue bitAnd:16rFF. |
2465 b7 := absValue bitAnd:16rFF. |
2465 absValue := absValue bitShift:-8. |
2466 absValue := absValue bitShift:-8. |
2466 absValue == 0 ifTrue:[ |
2467 absValue == 0 ifTrue:[ |
2467 digitByteArray := ByteArray new:7. |
2468 digitByteArray := ByteArray new:7. |
2468 digitByteArray at:1 put:b1. |
2469 digitByteArray at:1 put:b1. |
2469 digitByteArray at:2 put:b2. |
2470 digitByteArray at:2 put:b2. |
2470 digitByteArray at:3 put:b3. |
2471 digitByteArray at:3 put:b3. |
2471 digitByteArray at:4 put:b4. |
2472 digitByteArray at:4 put:b4. |
2472 digitByteArray at:5 put:b5. |
2473 digitByteArray at:5 put:b5. |
2473 digitByteArray at:6 put:b6. |
2474 digitByteArray at:6 put:b6. |
2474 digitByteArray at:7 put:b7. |
2475 digitByteArray at:7 put:b7. |
2475 ] ifFalse:[ |
2476 ] ifFalse:[ |
2476 digitByteArray := ByteArray new:8. |
2477 digitByteArray := ByteArray new:8. |
2477 digitByteArray at:1 put:b1. |
2478 digitByteArray at:1 put:b1. |
2478 digitByteArray at:2 put:b2. |
2479 digitByteArray at:2 put:b2. |
2479 digitByteArray at:3 put:b3. |
2480 digitByteArray at:3 put:b3. |
2480 digitByteArray at:4 put:b4. |
2481 digitByteArray at:4 put:b4. |
2481 digitByteArray at:5 put:b5. |
2482 digitByteArray at:5 put:b5. |
2482 digitByteArray at:6 put:b6. |
2483 digitByteArray at:6 put:b6. |
2483 digitByteArray at:7 put:b7. |
2484 digitByteArray at:7 put:b7. |
2484 digitByteArray at:8 put:absValue. |
2485 digitByteArray at:8 put:absValue. |
2485 ] |
2486 ] |
2486 ] |
2487 ] |
2487 ] |
2488 ] |
2488 ] |
2489 ] |
2489 ] |
2490 ] |
2490 ] |
2491 ] |
2491 ]. |
2492 ]. |
2492 |
2493 |
2493 ^ digitByteArray |
2494 ^ digitByteArray |
2494 |
2495 |
2495 " |
2496 " |
2517 could have simply created a 4-byte largeinteger and normalize it. |
2518 could have simply created a 4-byte largeinteger and normalize it. |
2518 The code below does the normalize right away, avoiding the |
2519 The code below does the normalize right away, avoiding the |
2519 overhead of producing any intermediate byte-arrays (and the scanning) |
2520 overhead of producing any intermediate byte-arrays (and the scanning) |
2520 " |
2521 " |
2521 self == 0 ifTrue: [ |
2522 self == 0 ifTrue: [ |
2522 ^ ByteArray with:0. |
2523 ^ ByteArray with:0. |
2523 ]. |
2524 ]. |
2524 |
2525 |
2525 self < 0 ifTrue: [ |
2526 self < 0 ifTrue: [ |
2526 absValue := self negated |
2527 absValue := self negated |
2527 ] ifFalse: [ |
2528 ] ifFalse: [ |
2528 absValue := self. |
2529 absValue := self. |
2529 ]. |
2530 ]. |
2530 |
2531 |
2531 b1 := absValue bitAnd:16rFF. |
2532 b1 := absValue bitAnd:16rFF. |
2532 absValue := absValue bitShift:-8. |
2533 absValue := absValue bitShift:-8. |
2533 absValue == 0 ifTrue:[ |
2534 absValue == 0 ifTrue:[ |
2534 digitByteArray := ByteArray with:b1 |
2535 digitByteArray := ByteArray with:b1 |
2535 ] ifFalse:[ |
2536 ] ifFalse:[ |
2536 b2 := absValue bitAnd:16rFF. |
2537 b2 := absValue bitAnd:16rFF. |
2537 absValue := absValue bitShift:-8. |
2538 absValue := absValue bitShift:-8. |
2538 absValue == 0 ifTrue:[ |
2539 absValue == 0 ifTrue:[ |
2539 digitByteArray := ByteArray with:b2 with:b1 |
2540 digitByteArray := ByteArray with:b2 with:b1 |
2540 ] ifFalse:[ |
2541 ] ifFalse:[ |
2541 b3 := absValue bitAnd:16rFF. |
2542 b3 := absValue bitAnd:16rFF. |
2542 absValue := absValue bitShift:-8. |
2543 absValue := absValue bitShift:-8. |
2543 absValue == 0 ifTrue:[ |
2544 absValue == 0 ifTrue:[ |
2544 digitByteArray := ByteArray with:b3 with:b2 with:b1 |
2545 digitByteArray := ByteArray with:b3 with:b2 with:b1 |
2545 ] ifFalse:[ |
2546 ] ifFalse:[ |
2546 b4 := absValue bitAnd:16rFF. |
2547 b4 := absValue bitAnd:16rFF. |
2547 absValue := absValue bitShift:-8. |
2548 absValue := absValue bitShift:-8. |
2548 absValue == 0 ifTrue:[ |
2549 absValue == 0 ifTrue:[ |
2549 digitByteArray := ByteArray with:b4 with:b3 with:b2 with:b1 |
2550 digitByteArray := ByteArray with:b4 with:b3 with:b2 with:b1 |
2550 ] ifFalse:[ |
2551 ] ifFalse:[ |
2551 b5 := absValue bitAnd:16rFF. |
2552 b5 := absValue bitAnd:16rFF. |
2552 absValue := absValue bitShift:-8. |
2553 absValue := absValue bitShift:-8. |
2553 absValue == 0 ifTrue:[ |
2554 absValue == 0 ifTrue:[ |
2554 digitByteArray := ByteArray new:5. |
2555 digitByteArray := ByteArray new:5. |
2555 digitByteArray at:1 put:b5. |
2556 digitByteArray at:1 put:b5. |
2556 digitByteArray at:2 put:b4. |
2557 digitByteArray at:2 put:b4. |
2557 digitByteArray at:3 put:b3. |
2558 digitByteArray at:3 put:b3. |
2558 digitByteArray at:4 put:b2. |
2559 digitByteArray at:4 put:b2. |
2559 digitByteArray at:5 put:b1. |
2560 digitByteArray at:5 put:b1. |
2560 ] ifFalse:[ |
2561 ] ifFalse:[ |
2561 b6 := absValue bitAnd:16rFF. |
2562 b6 := absValue bitAnd:16rFF. |
2562 absValue := absValue bitShift:-8. |
2563 absValue := absValue bitShift:-8. |
2563 absValue == 0 ifTrue:[ |
2564 absValue == 0 ifTrue:[ |
2564 digitByteArray := ByteArray new:6. |
2565 digitByteArray := ByteArray new:6. |
2565 digitByteArray at:1 put:b6. |
2566 digitByteArray at:1 put:b6. |
2566 digitByteArray at:2 put:b5. |
2567 digitByteArray at:2 put:b5. |
2567 digitByteArray at:3 put:b4. |
2568 digitByteArray at:3 put:b4. |
2568 digitByteArray at:4 put:b3. |
2569 digitByteArray at:4 put:b3. |
2569 digitByteArray at:5 put:b2. |
2570 digitByteArray at:5 put:b2. |
2570 digitByteArray at:6 put:b1. |
2571 digitByteArray at:6 put:b1. |
2571 ] ifFalse:[ |
2572 ] ifFalse:[ |
2572 b7 := absValue bitAnd:16rFF. |
2573 b7 := absValue bitAnd:16rFF. |
2573 absValue := absValue bitShift:-8. |
2574 absValue := absValue bitShift:-8. |
2574 absValue == 0 ifTrue:[ |
2575 absValue == 0 ifTrue:[ |
2575 digitByteArray := ByteArray new:7. |
2576 digitByteArray := ByteArray new:7. |
2576 digitByteArray at:1 put:b7. |
2577 digitByteArray at:1 put:b7. |
2577 digitByteArray at:2 put:b6. |
2578 digitByteArray at:2 put:b6. |
2578 digitByteArray at:3 put:b5. |
2579 digitByteArray at:3 put:b5. |
2579 digitByteArray at:4 put:b4. |
2580 digitByteArray at:4 put:b4. |
2580 digitByteArray at:5 put:b3. |
2581 digitByteArray at:5 put:b3. |
2581 digitByteArray at:6 put:b2. |
2582 digitByteArray at:6 put:b2. |
2582 digitByteArray at:7 put:b1. |
2583 digitByteArray at:7 put:b1. |
2583 ] ifFalse:[ |
2584 ] ifFalse:[ |
2584 digitByteArray := ByteArray new:8. |
2585 digitByteArray := ByteArray new:8. |
2585 digitByteArray at:1 put:absValue. |
2586 digitByteArray at:1 put:absValue. |
2586 digitByteArray at:2 put:b7. |
2587 digitByteArray at:2 put:b7. |
2587 digitByteArray at:3 put:b6. |
2588 digitByteArray at:3 put:b6. |
2588 digitByteArray at:4 put:b5. |
2589 digitByteArray at:4 put:b5. |
2589 digitByteArray at:5 put:b4. |
2590 digitByteArray at:5 put:b4. |
2590 digitByteArray at:6 put:b3. |
2591 digitByteArray at:6 put:b3. |
2591 digitByteArray at:7 put:b2. |
2592 digitByteArray at:7 put:b2. |
2592 digitByteArray at:8 put:b1. |
2593 digitByteArray at:8 put:b1. |
2593 ] |
2594 ] |
2594 ] |
2595 ] |
2595 ] |
2596 ] |
2596 ] |
2597 ] |
2597 ] |
2598 ] |
2598 ] |
2599 ] |
2599 ]. |
2600 ]. |
2600 |
2601 |
2601 ^ digitByteArray |
2602 ^ digitByteArray |
2602 |
2603 |
2603 " |
2604 " |
3267 REGISTER INT tmp; |
3268 REGISTER INT tmp; |
3268 static struct inlineCache blockVal = __ILC0(0); |
3269 static struct inlineCache blockVal = __ILC0(0); |
3269 |
3270 |
3270 tmp = __intVal(self); |
3271 tmp = __intVal(self); |
3271 if (tmp > 0) { |
3272 if (tmp > 0) { |
3272 if (__isBlockLike(aBlock) |
3273 if (__isBlockLike(aBlock) |
3273 && (__BlockInstPtr(aBlock)->b_nargs == __mkSmallInteger(0))) { |
3274 && (__BlockInstPtr(aBlock)->b_nargs == __mkSmallInteger(0))) { |
3274 { |
3275 { |
3275 REGISTER OBJFUNC codeVal; |
3276 REGISTER OBJFUNC codeVal; |
3276 |
3277 |
3277 /* |
3278 /* |
3278 * specially tuned version for compiled blocks, |
3279 * specially tuned version for compiled blocks, |
3279 * (the most common case) |
3280 * (the most common case) |
3280 */ |
3281 */ |
3281 if (((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
3282 if (((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
3282 # ifdef PARANOIA |
3283 # ifdef PARANOIA |
3283 && (! ((INT)(__BlockInstPtr(aBlock)->b_flags) & __MASKSMALLINT(F_DYNAMIC))) |
3284 && (! ((INT)(__BlockInstPtr(aBlock)->b_flags) & __MASKSMALLINT(F_DYNAMIC))) |
3284 # endif |
3285 # endif |
3285 ) { |
3286 ) { |
3286 |
3287 |
3287 # ifdef NEW_BLOCK_CALL |
3288 # ifdef NEW_BLOCK_CALL |
3288 |
3289 |
3289 # define BLOCK_ARG aBlock |
3290 # define BLOCK_ARG aBlock |
3290 |
3291 |
3291 # else |
3292 # else |
3292 |
3293 |
3293 # define BLOCK_ARG rHome |
3294 # define BLOCK_ARG rHome |
3294 REGISTER OBJ rHome; |
3295 REGISTER OBJ rHome; |
3295 |
3296 |
3296 /* |
3297 /* |
3297 * home on stack - no need to refetch |
3298 * home on stack - no need to refetch |
3298 */ |
3299 */ |
3299 rHome = __BlockInstPtr(aBlock)->b_home; |
3300 rHome = __BlockInstPtr(aBlock)->b_home; |
3300 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) |
3301 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) |
3301 # endif |
3302 # endif |
3302 { |
3303 { |
3303 # ifdef __UNROLL_LOOPS__ |
3304 # ifdef __UNROLL_LOOPS__ |
3304 |
3305 |
3305 /* |
3306 /* |
3306 * you are not supposed to program like this - I know what I do |
3307 * you are not supposed to program like this - I know what I do |
3307 */ |
3308 */ |
3308 while (tmp > 8) { |
3309 while (tmp > 8) { |
3309 if (InterruptPending != nil) goto interrupted0; |
3310 if (InterruptPending != nil) goto interrupted0; |
3310 continue0: |
3311 continue0: |
3311 (*codeVal)(BLOCK_ARG); |
3312 (*codeVal)(BLOCK_ARG); |
3312 if (InterruptPending != nil) goto interrupted1; |
3313 if (InterruptPending != nil) goto interrupted1; |
3313 continue1: |
3314 continue1: |
3314 (*codeVal)(BLOCK_ARG); |
3315 (*codeVal)(BLOCK_ARG); |
3315 if (InterruptPending != nil) goto interrupted2; |
3316 if (InterruptPending != nil) goto interrupted2; |
3316 continue2: |
3317 continue2: |
3317 (*codeVal)(BLOCK_ARG); |
3318 (*codeVal)(BLOCK_ARG); |
3318 if (InterruptPending != nil) goto interrupted3; |
3319 if (InterruptPending != nil) goto interrupted3; |
3319 continue3: |
3320 continue3: |
3320 (*codeVal)(BLOCK_ARG); |
3321 (*codeVal)(BLOCK_ARG); |
3321 if (InterruptPending != nil) goto interrupted4; |
3322 if (InterruptPending != nil) goto interrupted4; |
3322 continue4: |
3323 continue4: |
3323 (*codeVal)(BLOCK_ARG); |
3324 (*codeVal)(BLOCK_ARG); |
3324 if (InterruptPending != nil) goto interrupted5; |
3325 if (InterruptPending != nil) goto interrupted5; |
3325 continue5: |
3326 continue5: |
3326 (*codeVal)(BLOCK_ARG); |
3327 (*codeVal)(BLOCK_ARG); |
3327 if (InterruptPending != nil) goto interrupted6; |
3328 if (InterruptPending != nil) goto interrupted6; |
3328 continue6: |
3329 continue6: |
3329 (*codeVal)(BLOCK_ARG); |
3330 (*codeVal)(BLOCK_ARG); |
3330 if (InterruptPending != nil) goto interrupted7; |
3331 if (InterruptPending != nil) goto interrupted7; |
3331 continue7: |
3332 continue7: |
3332 (*codeVal)(BLOCK_ARG); |
3333 (*codeVal)(BLOCK_ARG); |
3333 tmp -= 8; |
3334 tmp -= 8; |
3334 } |
3335 } |
3335 # endif /* __UNROLL_LOOPS__ */ |
3336 # endif /* __UNROLL_LOOPS__ */ |
3336 do { |
3337 do { |
3337 if (InterruptPending != nil) goto interruptedX; |
3338 if (InterruptPending != nil) goto interruptedX; |
3338 continueX: |
3339 continueX: |
3339 (*codeVal)(BLOCK_ARG); |
3340 (*codeVal)(BLOCK_ARG); |
3340 } while(--tmp); |
3341 } while(--tmp); |
3341 |
3342 |
3342 RETURN (self); |
3343 RETURN (self); |
3343 if (0) { |
3344 if (0) { |
3344 # ifdef __UNROLL_LOOPS__ |
3345 # ifdef __UNROLL_LOOPS__ |
3345 interrupted0: |
3346 interrupted0: |
3346 __interruptL(@line); goto continue0; |
3347 __interruptL(@line); goto continue0; |
3347 interrupted1: |
3348 interrupted1: |
3348 __interruptL(@line); goto continue1; |
3349 __interruptL(@line); goto continue1; |
3349 interrupted2: |
3350 interrupted2: |
3350 __interruptL(@line); goto continue2; |
3351 __interruptL(@line); goto continue2; |
3351 interrupted3: |
3352 interrupted3: |
3352 __interruptL(@line); goto continue3; |
3353 __interruptL(@line); goto continue3; |
3353 interrupted4: |
3354 interrupted4: |
3354 __interruptL(@line); goto continue4; |
3355 __interruptL(@line); goto continue4; |
3355 interrupted5: |
3356 interrupted5: |
3356 __interruptL(@line); goto continue5; |
3357 __interruptL(@line); goto continue5; |
3357 interrupted6: |
3358 interrupted6: |
3358 __interruptL(@line); goto continue6; |
3359 __interruptL(@line); goto continue6; |
3359 interrupted7: |
3360 interrupted7: |
3360 __interruptL(@line); goto continue7; |
3361 __interruptL(@line); goto continue7; |
3361 # endif /* __UNROLL_LOOPS__ */ |
3362 # endif /* __UNROLL_LOOPS__ */ |
3362 interruptedX: |
3363 interruptedX: |
3363 __interruptL(@line); goto continueX; |
3364 __interruptL(@line); goto continueX; |
3364 } |
3365 } |
3365 } |
3366 } |
3366 } |
3367 } |
3367 } |
3368 } |
3368 |
3369 |
3369 # undef BLOCK_ARG |
3370 # undef BLOCK_ARG |
3370 |
3371 |
3371 # ifdef NEW_BLOCK_CALL |
3372 # ifdef NEW_BLOCK_CALL |
3372 # define BLOCK_ARG aBlock |
3373 # define BLOCK_ARG aBlock |
3374 # else |
3375 # else |
3375 # define BLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3376 # define BLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3376 # define IBLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3377 # define IBLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3377 # endif |
3378 # endif |
3378 |
3379 |
3379 /* |
3380 /* |
3380 * sorry - must check for the blocks code within the loops; |
3381 * sorry - must check for the blocks code within the loops; |
3381 * it could be recompiled or flushed (in the interrupt) |
3382 * it could be recompiled or flushed (in the interrupt) |
3382 */ |
3383 */ |
3383 do { |
3384 do { |
3384 REGISTER OBJFUNC codeVal; |
3385 REGISTER OBJFUNC codeVal; |
3385 |
3386 |
3386 if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
3387 if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
3387 /* |
3388 /* |
3388 * arg is a compiled block with code - |
3389 * arg is a compiled block with code - |
3389 * directly call it without going through Block>>value |
3390 * directly call it without going through Block>>value |
3390 * however, if there is an interrupt, refetch the code pointer. |
3391 * however, if there is an interrupt, refetch the code pointer. |
3391 */ |
3392 */ |
3392 /* stay here, while no interrupts are pending ... */ |
3393 /* stay here, while no interrupts are pending ... */ |
3393 do { |
3394 do { |
3394 (*codeVal)(BLOCK_ARG); |
3395 (*codeVal)(BLOCK_ARG); |
3395 if (InterruptPending != nil) goto outerLoop; |
3396 if (InterruptPending != nil) goto outerLoop; |
3396 } while (--tmp); |
3397 } while (--tmp); |
3397 RETURN (self); |
3398 RETURN (self); |
3398 } else { |
3399 } else { |
3399 if (InterruptPending != nil) __interruptL(@line); |
3400 if (InterruptPending != nil) __interruptL(@line); |
3400 |
3401 |
3401 if (__BlockInstPtr(aBlock)->b_bytecodes != nil) { |
3402 if (__BlockInstPtr(aBlock)->b_bytecodes != nil) { |
3402 /* |
3403 /* |
3403 * arg is a compiled block with bytecode - |
3404 * arg is a compiled block with bytecode - |
3404 * directly call interpreter without going through Block>>value |
3405 * directly call interpreter without going through Block>>value |
3405 */ |
3406 */ |
3406 __interpret(aBlock, 0, nil, IBLOCK_ARG, nil, nil); |
3407 __interpret(aBlock, 0, nil, IBLOCK_ARG, nil, nil); |
3407 } else { |
3408 } else { |
3408 /* |
3409 /* |
3409 * arg is something else - call it with #value |
3410 * arg is something else - call it with #value |
3410 */ |
3411 */ |
3411 (*blockVal.ilc_func)(aBlock, @symbol(value), nil, &blockVal); |
3412 (*blockVal.ilc_func)(aBlock, @symbol(value), nil, &blockVal); |
3412 } |
3413 } |
3413 } |
3414 } |
3414 outerLoop: ; |
3415 outerLoop: ; |
3415 } while (--tmp); |
3416 } while (--tmp); |
3416 |
3417 |
3417 # undef BLOCK_ARG |
3418 # undef BLOCK_ARG |
3418 # undef IBLOCK_ARG |
3419 # undef IBLOCK_ARG |
3419 |
3420 |
3420 RETURN (self); |
3421 RETURN (self); |
3421 } |
3422 } |
3422 |
3423 |
3423 /* |
3424 /* |
3424 * not a block-like thingy - call it with #value |
3425 * not a block-like thingy - call it with #value |
3425 */ |
3426 */ |
3426 do { |
3427 do { |
3427 if (InterruptPending != nil) __interruptL(@line); |
3428 if (InterruptPending != nil) __interruptL(@line); |
3428 (*blockVal.ilc_func)(aBlock, @symbol(value), nil, &blockVal); |
3429 (*blockVal.ilc_func)(aBlock, @symbol(value), nil, &blockVal); |
3429 } while(--tmp); |
3430 } while(--tmp); |
3430 RETURN (self); |
3431 RETURN (self); |
3431 } |
3432 } |
3432 #endif |
3433 #endif |
3433 %}. |
3434 %}. |
3434 ^ super timesRepeat:aBlock |
3435 ^ super timesRepeat:aBlock |
3435 |
3436 |
3450 REGISTER INT tmp, step; |
3451 REGISTER INT tmp, step; |
3451 REGISTER INT final; |
3452 REGISTER INT final; |
3452 static struct inlineCache blockVal = __ILC1(0); |
3453 static struct inlineCache blockVal = __ILC1(0); |
3453 |
3454 |
3454 if (__bothSmallInteger(incr, stop)) { |
3455 if (__bothSmallInteger(incr, stop)) { |
3455 tmp = __intVal(self); |
3456 tmp = __intVal(self); |
3456 final = __intVal(stop); |
3457 final = __intVal(stop); |
3457 step = __intVal(incr); |
3458 step = __intVal(incr); |
3458 |
3459 |
3459 if (__isBlockLike(aBlock) |
3460 if (__isBlockLike(aBlock) |
3460 && (__BlockInstPtr(aBlock)->b_nargs == __mkSmallInteger(1))) { |
3461 && (__BlockInstPtr(aBlock)->b_nargs == __mkSmallInteger(1))) { |
3461 { |
3462 { |
3462 REGISTER OBJFUNC codeVal; |
3463 REGISTER OBJFUNC codeVal; |
3463 |
3464 |
3464 /* |
3465 /* |
3465 * specially tuned version for static compiled blocks, called with |
3466 * specially tuned version for static compiled blocks, called with |
3466 * home on the stack (the most common case) |
3467 * home on the stack (the most common case) |
3467 */ |
3468 */ |
3468 if (((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
3469 if (((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
3469 # ifdef PARANOIA |
3470 # ifdef PARANOIA |
3470 && (! ((INT)(__BlockInstPtr(aBlock)->b_flags) & __MASKSMALLINT(F_DYNAMIC))) |
3471 && (! ((INT)(__BlockInstPtr(aBlock)->b_flags) & __MASKSMALLINT(F_DYNAMIC))) |
3471 # endif |
3472 # endif |
3472 ) { |
3473 ) { |
3473 |
3474 |
3474 # ifdef NEW_BLOCK_CALL |
3475 # ifdef NEW_BLOCK_CALL |
3475 |
3476 |
3476 # define BLOCK_ARG aBlock |
3477 # define BLOCK_ARG aBlock |
3477 |
3478 |
3478 # else |
3479 # else |
3479 |
3480 |
3480 # define BLOCK_ARG rHome |
3481 # define BLOCK_ARG rHome |
3481 REGISTER OBJ rHome; |
3482 REGISTER OBJ rHome; |
3482 rHome = __BlockInstPtr(aBlock)->b_home; |
3483 rHome = __BlockInstPtr(aBlock)->b_home; |
3483 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) |
3484 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) |
3484 |
3485 |
3485 # endif |
3486 # endif |
3486 { |
3487 { |
3487 if (step < 0) { |
3488 if (step < 0) { |
3488 if (step == -1) { |
3489 if (step == -1) { |
3489 while (tmp >= final) { |
3490 while (tmp >= final) { |
3490 if (InterruptPending != nil) __interruptL(@line); |
3491 if (InterruptPending != nil) __interruptL(@line); |
3491 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3492 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3492 tmp--; |
3493 tmp--; |
3493 } |
3494 } |
3494 } else { |
3495 } else { |
3495 while (tmp >= final) { |
3496 while (tmp >= final) { |
3496 if (InterruptPending != nil) __interruptL(@line); |
3497 if (InterruptPending != nil) __interruptL(@line); |
3497 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3498 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3498 tmp += step; |
3499 tmp += step; |
3499 } |
3500 } |
3500 } |
3501 } |
3501 } else { |
3502 } else { |
3502 if (step == 1) { |
3503 if (step == 1) { |
3503 while (tmp <= final) { |
3504 while (tmp <= final) { |
3504 if (InterruptPending != nil) __interruptL(@line); |
3505 if (InterruptPending != nil) __interruptL(@line); |
3505 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3506 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3506 tmp++; |
3507 tmp++; |
3507 } |
3508 } |
3508 } else { |
3509 } else { |
3509 while (tmp <= final) { |
3510 while (tmp <= final) { |
3510 if (InterruptPending != nil) __interruptL(@line); |
3511 if (InterruptPending != nil) __interruptL(@line); |
3511 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3512 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3512 tmp += step; |
3513 tmp += step; |
3513 } |
3514 } |
3514 } |
3515 } |
3515 } |
3516 } |
3516 RETURN (self); |
3517 RETURN (self); |
3517 } |
3518 } |
3518 } |
3519 } |
3519 } |
3520 } |
3520 |
3521 |
3521 /* |
3522 /* |
3522 * sorry - must check for the blocks code within the loops; |
3523 * sorry - must check for the blocks code within the loops; |
3523 * it could be recompiled or flushed (in the interrupt) |
3524 * it could be recompiled or flushed (in the interrupt) |
3524 */ |
3525 */ |
3525 |
3526 |
3526 # undef BLOCK_ARG |
3527 # undef BLOCK_ARG |
3527 |
3528 |
3528 # ifdef NEW_BLOCK_CALL |
3529 # ifdef NEW_BLOCK_CALL |
3529 # define BLOCK_ARG aBlock |
3530 # define BLOCK_ARG aBlock |
3531 # else |
3532 # else |
3532 # define BLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3533 # define BLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3533 # define IBLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3534 # define IBLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3534 # endif |
3535 # endif |
3535 |
3536 |
3536 if (step < 0) { |
3537 if (step < 0) { |
3537 while (tmp >= final) { |
3538 while (tmp >= final) { |
3538 REGISTER OBJFUNC codeVal; |
3539 REGISTER OBJFUNC codeVal; |
3539 |
3540 |
3540 if (InterruptPending != nil) __interruptL(@line); |
3541 if (InterruptPending != nil) __interruptL(@line); |
3541 |
3542 |
3542 if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
3543 if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
3543 /* |
3544 /* |
3544 * arg is a compiled block with code - |
3545 * arg is a compiled block with code - |
3545 * directly call it without going through Block>>value |
3546 * directly call it without going through Block>>value |
3546 */ |
3547 */ |
3547 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3548 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3548 } else { |
3549 } else { |
3549 if (__BlockInstPtr(aBlock)->b_bytecodes != nil) { |
3550 if (__BlockInstPtr(aBlock)->b_bytecodes != nil) { |
3550 /* |
3551 /* |
3551 * arg is a compiled block with bytecode - |
3552 * arg is a compiled block with bytecode - |
3552 * directly call interpreter without going through Block>>value |
3553 * directly call interpreter without going through Block>>value |
3553 */ |
3554 */ |
3554 # ifdef PASS_ARG_POINTER |
3555 # ifdef PASS_ARG_POINTER |
3555 { |
3556 { |
3556 OBJ idx; |
3557 OBJ idx; |
3557 |
3558 |
3558 idx = __mkSmallInteger(tmp); |
3559 idx = __mkSmallInteger(tmp); |
3559 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &idx); |
3560 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &idx); |
3560 } |
3561 } |
3561 # else |
3562 # else |
3562 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, __mkSmallInteger(tmp)); |
3563 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, __mkSmallInteger(tmp)); |
3563 # endif |
3564 # endif |
3564 |
3565 |
3565 } else { |
3566 } else { |
3566 /* |
3567 /* |
3567 * arg is something else - call it with #value |
3568 * arg is something else - call it with #value |
3568 */ |
3569 */ |
3569 (*blockVal.ilc_func)(aBlock, @symbol(value:), nil, &blockVal, __mkSmallInteger(tmp)); |
3570 (*blockVal.ilc_func)(aBlock, @symbol(value:), nil, &blockVal, __mkSmallInteger(tmp)); |
3570 } |
3571 } |
3571 } |
3572 } |
3572 tmp += step; |
3573 tmp += step; |
3573 } |
3574 } |
3574 } else { |
3575 } else { |
3575 while (tmp <= final) { |
3576 while (tmp <= final) { |
3576 REGISTER OBJFUNC codeVal; |
3577 REGISTER OBJFUNC codeVal; |
3577 |
3578 |
3578 if (InterruptPending != nil) __interruptL(@line); |
3579 if (InterruptPending != nil) __interruptL(@line); |
3579 |
3580 |
3580 if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
3581 if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
3581 /* |
3582 /* |
3582 * arg is a compiled block with code - |
3583 * arg is a compiled block with code - |
3583 * directly call it without going through Block>>value |
3584 * directly call it without going through Block>>value |
3584 */ |
3585 */ |
3585 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3586 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3586 } else { |
3587 } else { |
3587 if (__BlockInstPtr(aBlock)->b_bytecodes != nil) { |
3588 if (__BlockInstPtr(aBlock)->b_bytecodes != nil) { |
3588 /* |
3589 /* |
3589 * arg is a compiled block with bytecode - |
3590 * arg is a compiled block with bytecode - |
3590 * directly call interpreter without going through Block>>value |
3591 * directly call interpreter without going through Block>>value |
3591 */ |
3592 */ |
3592 # ifdef PASS_ARG_POINTER |
3593 # ifdef PASS_ARG_POINTER |
3593 { |
3594 { |
3594 OBJ idx; |
3595 OBJ idx; |
3595 |
3596 |
3596 idx = __mkSmallInteger(tmp); |
3597 idx = __mkSmallInteger(tmp); |
3597 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &idx); |
3598 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &idx); |
3598 } |
3599 } |
3599 # else |
3600 # else |
3600 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, __mkSmallInteger(tmp)); |
3601 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, __mkSmallInteger(tmp)); |
3601 # endif |
3602 # endif |
3602 |
3603 |
3603 } else { |
3604 } else { |
3604 /* |
3605 /* |
3605 * arg is something else - call it with #value: |
3606 * arg is something else - call it with #value: |
3606 */ |
3607 */ |
3607 (*blockVal.ilc_func)(aBlock, @symbol(value:), nil, &blockVal, __mkSmallInteger(tmp)); |
3608 (*blockVal.ilc_func)(aBlock, @symbol(value:), nil, &blockVal, __mkSmallInteger(tmp)); |
3608 } |
3609 } |
3609 } |
3610 } |
3610 tmp += step; |
3611 tmp += step; |
3611 } |
3612 } |
3612 } |
3613 } |
3613 |
3614 |
3614 # undef BLOCK_ARG |
3615 # undef BLOCK_ARG |
3615 # undef IBLOCK_ARG |
3616 # undef IBLOCK_ARG |
3616 |
3617 |
3617 } else { |
3618 } else { |
3618 /* |
3619 /* |
3619 * arg is something else - call it with #value: |
3620 * arg is something else - call it with #value: |
3620 */ |
3621 */ |
3621 if (step < 0) { |
3622 if (step < 0) { |
3622 while (tmp >= final) { |
3623 while (tmp >= final) { |
3623 if (InterruptPending != nil) __interruptL(@line); |
3624 if (InterruptPending != nil) __interruptL(@line); |
3624 |
3625 |
3625 (*blockVal.ilc_func)(aBlock, |
3626 (*blockVal.ilc_func)(aBlock, |
3626 @symbol(value:), |
3627 @symbol(value:), |
3627 nil, &blockVal, |
3628 nil, &blockVal, |
3628 __mkSmallInteger(tmp)); |
3629 __mkSmallInteger(tmp)); |
3629 tmp += step; |
3630 tmp += step; |
3630 } |
3631 } |
3631 } else { |
3632 } else { |
3632 while (tmp <= final) { |
3633 while (tmp <= final) { |
3633 if (InterruptPending != nil) __interruptL(@line); |
3634 if (InterruptPending != nil) __interruptL(@line); |
3634 |
3635 |
3635 (*blockVal.ilc_func)(aBlock, |
3636 (*blockVal.ilc_func)(aBlock, |
3636 @symbol(value:), |
3637 @symbol(value:), |
3637 nil, &blockVal, |
3638 nil, &blockVal, |
3638 __mkSmallInteger(tmp)); |
3639 __mkSmallInteger(tmp)); |
3639 tmp += step; |
3640 tmp += step; |
3640 } |
3641 } |
3641 } |
3642 } |
3642 } |
3643 } |
3643 RETURN ( self ); |
3644 RETURN ( self ); |
3644 } |
3645 } |
3645 #endif |
3646 #endif |
3646 %}. |
3647 %}. |
3647 "/ |
3648 "/ |
3648 "/ arrive here if stop is not a smallInteger |
3649 "/ arrive here if stop is not a smallInteger |
3665 REGISTER INT tmp; |
3666 REGISTER INT tmp; |
3666 INT final; |
3667 INT final; |
3667 static struct inlineCache blockVal = __ILC1(0); |
3668 static struct inlineCache blockVal = __ILC1(0); |
3668 |
3669 |
3669 if (__isSmallInteger(stop)) { |
3670 if (__isSmallInteger(stop)) { |
3670 tmp = __intVal(self); |
3671 tmp = __intVal(self); |
3671 final = __intVal(stop); |
3672 final = __intVal(stop); |
3672 |
3673 |
3673 if (__isBlockLike(aBlock) |
3674 if (__isBlockLike(aBlock) |
3674 && (__BlockInstPtr(aBlock)->b_nargs == __mkSmallInteger(1))) { |
3675 && (__BlockInstPtr(aBlock)->b_nargs == __mkSmallInteger(1))) { |
3675 { |
3676 { |
3676 /* |
3677 /* |
3677 * specially tuned version for the most common case, |
3678 * specially tuned version for the most common case, |
3678 * where called with home on the stack |
3679 * where called with home on the stack |
3679 */ |
3680 */ |
3680 REGISTER OBJFUNC codeVal; |
3681 REGISTER OBJFUNC codeVal; |
3681 |
3682 |
3682 if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
3683 if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
3683 |
3684 |
3684 # ifdef NEW_BLOCK_CALL |
3685 # ifdef NEW_BLOCK_CALL |
3685 |
3686 |
3686 # define BLOCK_ARG aBlock |
3687 # define BLOCK_ARG aBlock |
3687 |
3688 |
3688 # else |
3689 # else |
3689 |
3690 |
3690 # define BLOCK_ARG rHome |
3691 # define BLOCK_ARG rHome |
3691 REGISTER OBJ rHome; |
3692 REGISTER OBJ rHome; |
3692 rHome = __BlockInstPtr(aBlock)->b_home; |
3693 rHome = __BlockInstPtr(aBlock)->b_home; |
3693 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) |
3694 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) |
3694 # endif |
3695 # endif |
3695 { |
3696 { |
3696 |
3697 |
3697 # ifdef PARANOIA |
3698 # ifdef PARANOIA |
3698 if (! ((INT)(__BlockInstPtr(aBlock)->b_flags) & __MASKSMALLINT(F_DYNAMIC))) |
3699 if (! ((INT)(__BlockInstPtr(aBlock)->b_flags) & __MASKSMALLINT(F_DYNAMIC))) |
3699 # endif |
3700 # endif |
3700 { |
3701 { |
3701 /* |
3702 /* |
3702 * static compiled blocks ... |
3703 * static compiled blocks ... |
3703 */ |
3704 */ |
3704 # ifdef __UNROLL_LOOPS__ |
3705 # ifdef __UNROLL_LOOPS__ |
3705 /* |
3706 /* |
3706 * The following code is designed to run as fast as possible; |
3707 * The following code is designed to run as fast as possible; |
3707 * - taken branches only if interrupts are pending |
3708 * - taken branches only if interrupts are pending |
3708 * - only forward branches (which are usually predicted as not taken) |
3709 * - only forward branches (which are usually predicted as not taken) |
3709 * - unrolled the loop |
3710 * - unrolled the loop |
3710 * |
3711 * |
3711 * you are not supposed to program like this - I know what I do |
3712 * you are not supposed to program like this - I know what I do |
3712 */ |
3713 */ |
3713 # if TAG_INT==1 |
3714 # if TAG_INT==1 |
3714 INT t8 = (INT)(__mkSmallInteger(tmp+8)); |
3715 INT t8 = (INT)(__mkSmallInteger(tmp+8)); |
3715 tmp = (INT)(__mkSmallInteger(tmp)); |
3716 tmp = (INT)(__mkSmallInteger(tmp)); |
3716 final = (INT)(__mkSmallInteger(final)); |
3717 final = (INT)(__mkSmallInteger(final)); |
3717 # else |
3718 # else |
3718 INT t8 = tmp+8; |
3719 INT t8 = tmp+8; |
3719 # endif |
3720 # endif |
3720 |
3721 |
3721 for (;;) { |
3722 for (;;) { |
3722 |
3723 |
3723 while (t8 <= final) { |
3724 while (t8 <= final) { |
3724 # if TAG_INT==1 |
3725 # if TAG_INT==1 |
3725 t8 += (INT)(__MASKSMALLINT(8)); |
3726 t8 += (INT)(__MASKSMALLINT(8)); |
3726 # else |
3727 # else |
3727 t8 += 8; |
3728 t8 += 8; |
3728 # endif |
3729 # endif |
3729 if (InterruptPending != nil) goto interrupted0; |
3730 if (InterruptPending != nil) goto interrupted0; |
3730 continue0: |
3731 continue0: |
3731 # if TAG_INT==1 |
3732 # if TAG_INT==1 |
3732 (*codeVal)(BLOCK_ARG, tmp); |
3733 (*codeVal)(BLOCK_ARG, tmp); |
3733 # else |
3734 # else |
3734 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3735 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3735 # endif |
3736 # endif |
3736 if (InterruptPending != nil) goto interrupted1; |
3737 if (InterruptPending != nil) goto interrupted1; |
3737 continue1: |
3738 continue1: |
3738 # if TAG_INT==1 |
3739 # if TAG_INT==1 |
3739 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(1)) ); |
3740 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(1)) ); |
3740 # else |
3741 # else |
3741 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+1)); |
3742 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+1)); |
3742 # endif |
3743 # endif |
3743 if (InterruptPending != nil) goto interrupted2; |
3744 if (InterruptPending != nil) goto interrupted2; |
3744 continue2: |
3745 continue2: |
3745 # if TAG_INT==1 |
3746 # if TAG_INT==1 |
3746 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(2)) ); |
3747 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(2)) ); |
3747 # else |
3748 # else |
3748 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+2)); |
3749 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+2)); |
3749 # endif |
3750 # endif |
3750 if (InterruptPending != nil) goto interrupted3; |
3751 if (InterruptPending != nil) goto interrupted3; |
3751 continue3: |
3752 continue3: |
3752 # if TAG_INT==1 |
3753 # if TAG_INT==1 |
3753 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(3)) ); |
3754 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(3)) ); |
3754 # else |
3755 # else |
3755 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+3)); |
3756 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+3)); |
3756 # endif |
3757 # endif |
3757 if (InterruptPending != nil) goto interrupted4; |
3758 if (InterruptPending != nil) goto interrupted4; |
3758 continue4: |
3759 continue4: |
3759 # if TAG_INT==1 |
3760 # if TAG_INT==1 |
3760 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(4)) ); |
3761 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(4)) ); |
3761 # else |
3762 # else |
3762 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+4)); |
3763 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+4)); |
3763 # endif |
3764 # endif |
3764 if (InterruptPending != nil) goto interrupted5; |
3765 if (InterruptPending != nil) goto interrupted5; |
3765 continue5: |
3766 continue5: |
3766 # if TAG_INT==1 |
3767 # if TAG_INT==1 |
3767 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(5)) ); |
3768 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(5)) ); |
3768 # else |
3769 # else |
3769 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+5)); |
3770 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+5)); |
3770 # endif |
3771 # endif |
3771 if (InterruptPending != nil) goto interrupted6; |
3772 if (InterruptPending != nil) goto interrupted6; |
3772 continue6: |
3773 continue6: |
3773 # if TAG_INT==1 |
3774 # if TAG_INT==1 |
3774 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(6)) ); |
3775 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(6)) ); |
3775 # else |
3776 # else |
3776 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+6)); |
3777 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+6)); |
3777 # endif |
3778 # endif |
3778 if (InterruptPending != nil) goto interrupted7; |
3779 if (InterruptPending != nil) goto interrupted7; |
3779 continue7: |
3780 continue7: |
3780 # if TAG_INT==1 |
3781 # if TAG_INT==1 |
3781 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(7)) ); |
3782 (*codeVal)(BLOCK_ARG, tmp+(INT)(__MASKSMALLINT(7)) ); |
3782 # else |
3783 # else |
3783 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+7)); |
3784 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp+7)); |
3784 # endif |
3785 # endif |
3785 |
3786 |
3786 # if TAG_INT==1 |
3787 # if TAG_INT==1 |
3787 tmp += (INT)(__MASKSMALLINT(8)); |
3788 tmp += (INT)(__MASKSMALLINT(8)); |
3788 # else |
3789 # else |
3789 tmp += 8; |
3790 tmp += 8; |
3790 # endif |
3791 # endif |
3791 } |
3792 } |
3792 while (tmp <= final) { |
3793 while (tmp <= final) { |
3793 if (InterruptPending != nil) goto interruptedX; |
3794 if (InterruptPending != nil) goto interruptedX; |
3794 continueX: |
3795 continueX: |
3795 # if TAG_INT==1 |
3796 # if TAG_INT==1 |
3796 (*codeVal)(BLOCK_ARG, tmp); |
3797 (*codeVal)(BLOCK_ARG, tmp); |
3797 tmp += (INT)(__MASKSMALLINT(1)); |
3798 tmp += (INT)(__MASKSMALLINT(1)); |
3798 # else |
3799 # else |
3799 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3800 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3800 tmp++; |
3801 tmp++; |
3801 # endif |
3802 # endif |
3802 } |
3803 } |
3803 RETURN (self); |
3804 RETURN (self); |
3804 |
3805 |
3805 if (0) { |
3806 if (0) { |
3806 /* |
3807 /* |
3807 * no discussion about those gotos ... |
3808 * no discussion about those gotos ... |
3808 * ... its better for your CPU's pipelines |
3809 * ... its better for your CPU's pipelines |
3809 * (if you dont understand why, just dont argue). |
3810 * (if you dont understand why, just dont argue). |
3810 */ |
3811 */ |
3811 interrupted7: |
3812 interrupted7: |
3812 __interruptL(@line); goto continue7; |
3813 __interruptL(@line); goto continue7; |
3813 interrupted6: |
3814 interrupted6: |
3814 __interruptL(@line); goto continue6; |
3815 __interruptL(@line); goto continue6; |
3815 interrupted5: |
3816 interrupted5: |
3816 __interruptL(@line); goto continue5; |
3817 __interruptL(@line); goto continue5; |
3817 interrupted4: |
3818 interrupted4: |
3818 __interruptL(@line); goto continue4; |
3819 __interruptL(@line); goto continue4; |
3819 interrupted3: |
3820 interrupted3: |
3820 __interruptL(@line); goto continue3; |
3821 __interruptL(@line); goto continue3; |
3821 interrupted2: |
3822 interrupted2: |
3822 __interruptL(@line); goto continue2; |
3823 __interruptL(@line); goto continue2; |
3823 interrupted1: |
3824 interrupted1: |
3824 __interruptL(@line); goto continue1; |
3825 __interruptL(@line); goto continue1; |
3825 interrupted0: |
3826 interrupted0: |
3826 __interruptL(@line); goto continue0; |
3827 __interruptL(@line); goto continue0; |
3827 interruptedX: |
3828 interruptedX: |
3828 __interruptL(@line); goto continueX; |
3829 __interruptL(@line); goto continueX; |
3829 } |
3830 } |
3830 } |
3831 } |
3831 # else |
3832 # else |
3832 while (tmp <= final) { |
3833 while (tmp <= final) { |
3833 if (InterruptPending != nil) __interruptL(@line); |
3834 if (InterruptPending != nil) __interruptL(@line); |
3834 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3835 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3835 tmp ++; |
3836 tmp ++; |
3836 } |
3837 } |
3837 RETURN (self); |
3838 RETURN (self); |
3838 # endif /* __UNROLL_LOOPS__ */ |
3839 # endif /* __UNROLL_LOOPS__ */ |
3839 } |
3840 } |
3840 |
3841 |
3841 /* |
3842 /* |
3842 * mhmh - seems to be a block with dynamic code |
3843 * mhmh - seems to be a block with dynamic code |
3843 * must refetch, to allow dynamic recompilation or code flush. |
3844 * must refetch, to allow dynamic recompilation or code flush. |
3844 */ |
3845 */ |
3845 while (tmp <= final) { |
3846 while (tmp <= final) { |
3846 if (InterruptPending != nil) __interruptL(@line); |
3847 if (InterruptPending != nil) __interruptL(@line); |
3847 if ((codeVal = __BlockInstPtr(aBlock)->b_code) == (OBJFUNC)nil) break; |
3848 if ((codeVal = __BlockInstPtr(aBlock)->b_code) == (OBJFUNC)nil) break; |
3848 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3849 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3849 tmp ++; |
3850 tmp ++; |
3850 } |
3851 } |
3851 |
3852 |
3852 if (tmp > final) { |
3853 if (tmp > final) { |
3853 RETURN (self); |
3854 RETURN (self); |
3854 } |
3855 } |
3855 } |
3856 } |
3856 } |
3857 } |
3857 } |
3858 } |
3858 |
3859 |
3859 # undef BLOCK_ARG |
3860 # undef BLOCK_ARG |
3860 |
3861 |
3861 # ifdef NEW_BLOCK_CALL |
3862 # ifdef NEW_BLOCK_CALL |
3862 # define BLOCK_ARG aBlock |
3863 # define BLOCK_ARG aBlock |
3864 # else |
3865 # else |
3865 # define BLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3866 # define BLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3866 # define IBLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3867 # define IBLOCK_ARG (__BlockInstPtr(aBlock)->b_home) |
3867 # endif |
3868 # endif |
3868 |
3869 |
3869 /* |
3870 /* |
3870 * sorry - must check for the blocks code within the loops; |
3871 * sorry - must check for the blocks code within the loops; |
3871 * it could be recompiled or flushed (in the interrupt) |
3872 * it could be recompiled or flushed (in the interrupt) |
3872 */ |
3873 */ |
3873 while (tmp <= final) { |
3874 while (tmp <= final) { |
3874 REGISTER OBJFUNC codeVal; |
3875 REGISTER OBJFUNC codeVal; |
3875 |
3876 |
3876 if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
3877 if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) { |
3877 /* |
3878 /* |
3878 * arg is a compiled block with code - |
3879 * arg is a compiled block with code - |
3879 * directly call it without going through Block>>value |
3880 * directly call it without going through Block>>value |
3880 */ |
3881 */ |
3881 |
3882 |
3882 /* stay here, while no interrupts are pending ... */ |
3883 /* stay here, while no interrupts are pending ... */ |
3883 do { |
3884 do { |
3884 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3885 (*codeVal)(BLOCK_ARG, __mkSmallInteger(tmp)); |
3885 if (InterruptPending != nil) goto outerLoop; |
3886 if (InterruptPending != nil) goto outerLoop; |
3886 tmp++; |
3887 tmp++; |
3887 } while (tmp <= final); |
3888 } while (tmp <= final); |
3888 RETURN (self); |
3889 RETURN (self); |
3889 } else { |
3890 } else { |
3890 if (InterruptPending != nil) __interruptL(@line); |
3891 if (InterruptPending != nil) __interruptL(@line); |
3891 |
3892 |
3892 if (__BlockInstPtr(aBlock)->b_bytecodes != nil) { |
3893 if (__BlockInstPtr(aBlock)->b_bytecodes != nil) { |
3893 /* |
3894 /* |
3894 * arg is a compiled block with bytecode - |
3895 * arg is a compiled block with bytecode - |
3895 * directly call interpreter without going through Block>>value |
3896 * directly call interpreter without going through Block>>value |
3896 */ |
3897 */ |
3897 # ifdef PASS_ARG_POINTER |
3898 # ifdef PASS_ARG_POINTER |
3898 { |
3899 { |
3899 OBJ idx; |
3900 OBJ idx; |
3900 |
3901 |
3901 idx = __mkSmallInteger(tmp); |
3902 idx = __mkSmallInteger(tmp); |
3902 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &idx); |
3903 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &idx); |
3903 } |
3904 } |
3904 # else |
3905 # else |
3905 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, __mkSmallInteger(tmp)); |
3906 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, __mkSmallInteger(tmp)); |
3906 # endif |
3907 # endif |
3907 |
3908 |
3908 } else { |
3909 } else { |
3909 /* |
3910 /* |
3910 * arg is something else - call it with #value: |
3911 * arg is something else - call it with #value: |
3911 */ |
3912 */ |
3912 (*blockVal.ilc_func)(aBlock, @symbol(value:), nil, &blockVal, __mkSmallInteger(tmp)); |
3913 (*blockVal.ilc_func)(aBlock, @symbol(value:), nil, &blockVal, __mkSmallInteger(tmp)); |
3913 } |
3914 } |
3914 } |
3915 } |
3915 outerLoop: ; |
3916 outerLoop: ; |
3916 tmp++; |
3917 tmp++; |
3917 } |
3918 } |
3918 |
3919 |
3919 # undef BLOCK_ARG |
3920 # undef BLOCK_ARG |
3920 # undef IBLOCK_ARG |
3921 # undef IBLOCK_ARG |
3921 |
3922 |
3922 RETURN (self); |
3923 RETURN (self); |
3923 } |
3924 } |
3924 /* |
3925 /* |
3925 * arg is something else - call it with #value: |
3926 * arg is something else - call it with #value: |
3926 */ |
3927 */ |
3927 while (tmp <= final) { |
3928 while (tmp <= final) { |
3928 if (InterruptPending != nil) __interruptL(@line); |
3929 if (InterruptPending != nil) __interruptL(@line); |
3929 |
3930 |
3930 (*blockVal.ilc_func)(aBlock, |
3931 (*blockVal.ilc_func)(aBlock, |
3931 @symbol(value:), |
3932 @symbol(value:), |
3932 nil, &blockVal, |
3933 nil, &blockVal, |
3933 __mkSmallInteger(tmp)); |
3934 __mkSmallInteger(tmp)); |
3934 tmp++; |
3935 tmp++; |
3935 } |
3936 } |
3936 RETURN ( self ); |
3937 RETURN ( self ); |
3937 } |
3938 } |
3938 #endif /* not __SCHTEAM__ */ |
3939 #endif /* not __SCHTEAM__ */ |
3939 %}. |
3940 %}. |
3940 |
3941 |
3941 "/ |
3942 "/ |
4008 " |
4009 " |
4009 ! |
4010 ! |
4010 |
4011 |
4011 divMod:aNumber |
4012 divMod:aNumber |
4012 "return an array filled with |
4013 "return an array filled with |
4013 (self // aNumber) and (self \\ aNumber). |
4014 (self // aNumber) and (self \\ aNumber). |
4014 The returned remainder has the same sign as aNumber. |
4015 The returned remainder has the same sign as aNumber. |
4015 The following is always true: |
4016 The following is always true: |
4016 (receiver // something) * something + (receiver \\ something) = receiver |
4017 (receiver // something) * something + (receiver \\ something) = receiver |
4017 |
4018 |
4018 Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3. |
4019 Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3. |
4019 Especially surprising: |
4020 Especially surprising: |
4020 -1 \\ 10 -> 9 (because -(1/10) is truncated towards next smaller integer, which is -1, |
4021 -1 \\ 10 -> 9 (because -(1/10) is truncated towards next smaller integer, which is -1, |
4021 and -1 multiplied by 10 gives -10, so we have to add 9 to get the original -1). |
4022 and -1 multiplied by 10 gives -10, so we have to add 9 to get the original -1). |
4022 -10 \\ 3 -> 2 (because -(10/3) is truncated towards next smaller integer, which is -4, |
4023 -10 \\ 3 -> 2 (because -(10/3) is truncated towards next smaller integer, which is -4, |
4023 and -4 * 4 gives -12, so we need to add 2 to get the original -10. |
4024 and -4 * 4 gives -12, so we need to add 2 to get the original -10. |
4024 |
4025 |
4025 This is redefined here for more performance" |
4026 This is redefined here for more performance" |
4026 |
4027 |
4027 %{ /* NOCONTEXT */ |
4028 %{ /* NOCONTEXT */ |
4028 #ifndef __SCHTEAM__ |
4029 #ifndef __SCHTEAM__ |
4029 INT val, div, mod, mySelf; |
4030 INT val, div, mod, mySelf; |
4030 |
4031 |
4031 if (__isSmallInteger(aNumber) |
4032 if (__isSmallInteger(aNumber) |
4032 && ((val = __intVal(aNumber)) > 0) |
4033 && ((val = __intVal(aNumber)) > 0) |
4033 && ((mySelf = __intVal(self)) >= 0)) { |
4034 && ((mySelf = __intVal(self)) >= 0)) { |
4034 div = mySelf / val; |
4035 div = mySelf / val; |
4035 mod = mySelf % val; |
4036 mod = mySelf % val; |
4036 |
4037 |
4037 RETURN (__ARRAY_WITH2( __mkSmallInteger(div), __mkSmallInteger(mod))); |
4038 RETURN (__ARRAY_WITH2( __mkSmallInteger(div), __mkSmallInteger(mod))); |
4038 } |
4039 } |
4039 #endif |
4040 #endif |
4040 %}. |
4041 %}. |
4041 ^ super divMod:aNumber |
4042 ^ super divMod:aNumber |
4042 |
4043 |
4123 to print a number/and for conversion to a LargeInteger. |
4124 to print a number/and for conversion to a LargeInteger. |
4124 Implemented that way, to allow for tiny systems (PDAs) without a Float class |
4125 Implemented that way, to allow for tiny systems (PDAs) without a Float class |
4125 (i.e. without log)." |
4126 (i.e. without log)." |
4126 |
4127 |
4127 self > 0 ifTrue:[ |
4128 self > 0 ifTrue:[ |
4128 self < 10000 ifTrue:[ |
4129 self < 10000 ifTrue:[ |
4129 self < 10 ifTrue:[^ 0]. |
4130 self < 10 ifTrue:[^ 0]. |
4130 self < 100 ifTrue:[^ 1]. |
4131 self < 100 ifTrue:[^ 1]. |
4131 self < 1000 ifTrue:[^ 2]. |
4132 self < 1000 ifTrue:[^ 2]. |
4132 ^ 3 |
4133 ^ 3 |
4133 ]. |
4134 ]. |
4134 self < 100000000 ifTrue:[ |
4135 self < 100000000 ifTrue:[ |
4135 self < 100000 ifTrue:[^ 4]. |
4136 self < 100000 ifTrue:[^ 4]. |
4136 self < 1000000 ifTrue:[^ 5]. |
4137 self < 1000000 ifTrue:[^ 5]. |
4137 self < 10000000 ifTrue:[^ 6]. |
4138 self < 10000000 ifTrue:[^ 6]. |
4138 ^ 7 |
4139 ^ 7 |
4139 ]. |
4140 ]. |
4140 self < 1000000000 ifTrue:[^ 8]. |
4141 self < 1000000000 ifTrue:[^ 8]. |
4141 SmallInteger maxBytes == 4 ifTrue:[ |
4142 SmallInteger maxBytes == 4 ifTrue:[ |
4142 "/ on a 32 bit machine, SmallInt cannot be larger |
4143 "/ on a 32 bit machine, SmallInt cannot be larger |
4143 ^ 9 |
4144 ^ 9 |
4144 ]. |
4145 ]. |
4145 |
4146 |
4146 "/ 64 bit machine |
4147 "/ 64 bit machine |
4147 self < 100000000000000 ifTrue:[ |
4148 self < 100000000000000 ifTrue:[ |
4148 self < 10000000000 ifTrue:[^ 9]. |
4149 self < 10000000000 ifTrue:[^ 9]. |
4149 self < 100000000000 ifTrue:[^ 10]. |
4150 self < 100000000000 ifTrue:[^ 10]. |
4150 self < 1000000000000 ifTrue:[^ 11]. |
4151 self < 1000000000000 ifTrue:[^ 11]. |
4151 self < 10000000000000 ifTrue:[^ 12]. |
4152 self < 10000000000000 ifTrue:[^ 12]. |
4152 ^ 13 |
4153 ^ 13 |
4153 ]. |
4154 ]. |
4154 self < 1000000000000000 ifTrue:[^ 14]. |
4155 self < 1000000000000000 ifTrue:[^ 14]. |
4155 self < 10000000000000000 ifTrue:[^ 15]. |
4156 self < 10000000000000000 ifTrue:[^ 15]. |
4156 self < 100000000000000000 ifTrue:[^ 16]. |
4157 self < 100000000000000000 ifTrue:[^ 16]. |
4157 self < 1000000000000000000 ifTrue:[^ 17]. |
4158 self < 1000000000000000000 ifTrue:[^ 17]. |
4158 ^ 18. |
4159 ^ 18. |
4159 ]. |
4160 ]. |
4160 |
4161 |
4161 ^ self class |
4162 ^ self class |
4162 raise:#domainErrorSignal |
4163 raise:#domainErrorSignal |
4163 receiver:self |
4164 receiver:self |
4164 selector:#intlog10 |
4165 selector:#intlog10 |
4165 arguments:#() |
4166 arguments:#() |
4166 errorString:'logarithm of negative integer' |
4167 errorString:'logarithm of negative integer' |
4167 |
4168 |
4168 " |
4169 " |
4169 99 intlog10 |
4170 99 intlog10 |
4170 100 intlog10 |
4171 100 intlog10 |
4171 101 intlog10 |
4172 101 intlog10 |
4197 INT _100s = 0, _10s = 0, _1s = 0; |
4198 INT _100s = 0, _10s = 0, _1s = 0; |
4198 INT b = __intVal(self); |
4199 INT b = __intVal(self); |
4199 unsigned INT rslt; |
4200 unsigned INT rslt; |
4200 |
4201 |
4201 if (b <= 99999999) { |
4202 if (b <= 99999999) { |
4202 if (b <= 255) { |
4203 if (b <= 255) { |
4203 // the most common case: convert bytes |
4204 // the most common case: convert bytes |
4204 for (i=7; i>=0; i--) { |
4205 for (i=7; i>=0; i--) { |
4205 if (_100s >= 5) _100s += 3; |
4206 if (_100s >= 5) _100s += 3; |
4206 if (_10s >= 5) _10s += 3; |
4207 if (_10s >= 5) _10s += 3; |
4207 if (_1s >= 5) _1s += 3; |
4208 if (_1s >= 5) _1s += 3; |
4208 |
4209 |
4209 _100s = (_100s<<1) | (_10s >> 3 & 1); _100s &= 0xF; |
4210 _100s = (_100s<<1) | (_10s >> 3 & 1); _100s &= 0xF; |
4210 _10s = (_10s<<1) | (_1s >> 3 & 1); _10s &= 0xF; |
4211 _10s = (_10s<<1) | (_1s >> 3 & 1); _10s &= 0xF; |
4211 _1s = (_1s<<1) | (b >> 7 & 1); _1s &= 0xF; |
4212 _1s = (_1s<<1) | (b >> 7 & 1); _1s &= 0xF; |
4212 b <<= 1; |
4213 b <<= 1; |
4213 } |
4214 } |
4214 rslt = (_100s<<8) | (_10s<<4) | _1s; |
4215 rslt = (_100s<<8) | (_10s<<4) | _1s; |
4215 RETURN (__MKSMALLINT( rslt) ); |
4216 RETURN (__MKSMALLINT( rslt) ); |
4216 } |
4217 } |
4217 |
4218 |
4218 for (i=26; i>=0; i--) { |
4219 for (i=26; i>=0; i--) { |
4219 if (_10000000s >= 5) _10000000s += 3; |
4220 if (_10000000s >= 5) _10000000s += 3; |
4220 if (_1000000s >= 5) _1000000s += 3; |
4221 if (_1000000s >= 5) _1000000s += 3; |
4221 if (_100000s >= 5) _100000s += 3; |
4222 if (_100000s >= 5) _100000s += 3; |
4222 if (_10000s >= 5) _10000s += 3; |
4223 if (_10000s >= 5) _10000s += 3; |
4223 if (_1000s >= 5) _1000s += 3; |
4224 if (_1000s >= 5) _1000s += 3; |
4224 if (_100s >= 5) _100s += 3; |
4225 if (_100s >= 5) _100s += 3; |
4225 if (_10s >= 5) _10s += 3; |
4226 if (_10s >= 5) _10s += 3; |
4226 if (_1s >= 5) _1s += 3; |
4227 if (_1s >= 5) _1s += 3; |
4227 |
4228 |
4228 _10000000s = (_10000000s<<1) | (_1000000s >> 3 & 1); _10000000s &= 0xF; |
4229 _10000000s = (_10000000s<<1) | (_1000000s >> 3 & 1); _10000000s &= 0xF; |
4229 _1000000s = (_1000000s<<1) | (_100000s >> 3 & 1); _1000000s &= 0xF; |
4230 _1000000s = (_1000000s<<1) | (_100000s >> 3 & 1); _1000000s &= 0xF; |
4230 _100000s = (_100000s<<1) | (_10000s >> 3 & 1); _100000s &= 0xF; |
4231 _100000s = (_100000s<<1) | (_10000s >> 3 & 1); _100000s &= 0xF; |
4231 _10000s = (_10000s<<1) | (_1000s >> 3 & 1); _10000s &= 0xF; |
4232 _10000s = (_10000s<<1) | (_1000s >> 3 & 1); _10000s &= 0xF; |
4232 _1000s = (_1000s<<1) | (_100s >> 3 & 1); _1000s &= 0xF; |
4233 _1000s = (_1000s<<1) | (_100s >> 3 & 1); _1000s &= 0xF; |
4233 _100s = (_100s<<1) | (_10s >> 3 & 1); _100s &= 0xF; |
4234 _100s = (_100s<<1) | (_10s >> 3 & 1); _100s &= 0xF; |
4234 _10s = (_10s<<1) | (_1s >> 3 & 1); _10s &= 0xF; |
4235 _10s = (_10s<<1) | (_1s >> 3 & 1); _10s &= 0xF; |
4235 _1s = (_1s<<1) | (b >> 26 & 1); _1s &= 0xF; |
4236 _1s = (_1s<<1) | (b >> 26 & 1); _1s &= 0xF; |
4236 b <<= 1; |
4237 b <<= 1; |
4237 } |
4238 } |
4238 |
4239 |
4239 rslt = (_10000000s<<28) |
4240 rslt = (_10000000s<<28) |
4240 | (_1000000s<<24) | (_100000s<<20) | (_10000s<<16) |
4241 | (_1000000s<<24) | (_100000s<<20) | (_10000s<<16) |
4241 | (_1000s<<12) | (_100s<<8) | (_10s<<4) | _1s; |
4242 | (_1000s<<12) | (_100s<<8) | (_10s<<4) | _1s; |
4242 RETURN (__MKUINT( rslt) ); |
4243 RETURN (__MKUINT( rslt) ); |
4243 } |
4244 } |
4244 #endif |
4245 #endif |
4245 %}. |
4246 %}. |
4246 ^ super asBCD. |
4247 ^ super asBCD. |
4247 |
4248 |
4362 int __base = base.intValue().abs(); |
4363 int __base = base.intValue().abs(); |
4363 long myValue = self.longValue(); |
4364 long myValue = self.longValue(); |
4364 java.lang.String __s; |
4365 java.lang.String __s; |
4365 |
4366 |
4366 switch (__base) { |
4367 switch (__base) { |
4367 case 2: |
4368 case 2: |
4368 __s = java.lang.Long.toBinaryString(myValue); |
4369 __s = java.lang.Long.toBinaryString(myValue); |
4369 break; |
4370 break; |
4370 |
4371 |
4371 case 8: |
4372 case 8: |
4372 __s = java.lang.Long.toOctalString(myValue); |
4373 __s = java.lang.Long.toOctalString(myValue); |
4373 break; |
4374 break; |
4374 |
4375 |
4375 case 10: |
4376 case 10: |
4376 __s = java.lang.Long.toString(myValue); |
4377 __s = java.lang.Long.toString(myValue); |
4377 break; |
4378 break; |
4378 |
4379 |
4379 case 16: |
4380 case 16: |
4380 __s = java.lang.Long.toHexString(myValue); |
4381 __s = java.lang.Long.toHexString(myValue); |
4381 break; |
4382 break; |
4382 |
4383 |
4383 default: |
4384 default: |
4384 { |
4385 { |
4385 boolean negative = false; |
4386 boolean negative = false; |
4386 __s = ""; |
4387 __s = ""; |
4387 |
4388 |
4388 if ((__base > 36) || (__base < 2)) { |
4389 if ((__base > 36) || (__base < 2)) { |
4389 throw new SmalltalkError("invalid base: ", base); |
4390 throw new SmalltalkError("invalid base: ", base); |
4390 } |
4391 } |
4391 if (myValue < 0) { |
4392 if (myValue < 0) { |
4392 negative = true; |
4393 negative = true; |
4393 myValue = -myValue; |
4394 myValue = -myValue; |
4394 } |
4395 } |
4395 while (myValue != 0) { |
4396 while (myValue != 0) { |
4396 int digit; |
4397 int digit; |
4397 char ch; |
4398 char ch; |
4398 |
4399 |
4399 digit = (int)(myValue % __base); |
4400 digit = (int)(myValue % __base); |
4400 if (digit <= 9) { |
4401 if (digit <= 9) { |
4401 ch = (char)('0' + digit); |
4402 ch = (char)('0' + digit); |
4402 } else { |
4403 } else { |
4403 ch = (char)('A' + digit - 10); |
4404 ch = (char)('A' + digit - 10); |
4404 } |
4405 } |
4405 __s = ch + __s; |
4406 __s = ch + __s; |
4406 myValue = myValue / __base; |
4407 myValue = myValue / __base; |
4407 } |
4408 } |
4408 if (negative) { |
4409 if (negative) { |
4409 __s = "-" + __s; |
4410 __s = "-" + __s; |
4410 } |
4411 } |
4411 break; |
4412 break; |
4412 } |
4413 } |
4413 } |
4414 } |
4414 return context._RETURN( new STString( __s )); |
4415 return context._RETURN( new STString( __s )); |
4415 #else |
4416 #else |
4416 static char ucDigits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
4417 static char ucDigits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
4417 static char lcDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; |
4418 static char lcDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; |
4418 |
4419 |
4419 if (__isSmallInteger(base)) { |
4420 if (__isSmallInteger(base)) { |
4420 char *digits; |
4421 char *digits; |
4421 INT __base; |
4422 INT __base; |
4422 |
4423 |
4423 if (self == __MKSMALLINT(0)) { |
4424 if (self == __MKSMALLINT(0)) { |
4424 RETURN (@global(ZeroString)); |
4425 RETURN (@global(ZeroString)); |
4425 } |
4426 } |
4426 __base = __intVal(base); |
4427 __base = __intVal(base); |
4427 if (__base < 0) { |
4428 if (__base < 0) { |
4428 __base = - __base; |
4429 __base = - __base; |
4429 digits = lcDigits; |
4430 digits = lcDigits; |
4430 } else { |
4431 } else { |
4431 digits = ucDigits; |
4432 digits = ucDigits; |
4432 } |
4433 } |
4433 |
4434 |
4434 if ((__base < sizeof(ucDigits)) && (__base > 1)) { |
4435 if ((__base < sizeof(ucDigits)) && (__base > 1)) { |
4435 char buffer[64+5]; /* for 64bit machines, base 2, plus sign, plus 0-byte */ |
4436 char buffer[64+5]; /* for 64bit machines, base 2, plus sign, plus 0-byte */ |
4436 char *cp; |
4437 char *cp; |
4437 OBJ newString; |
4438 OBJ newString; |
4438 int negative = 0; |
4439 int negative = 0; |
4439 INT myValue = __intVal(self); |
4440 INT myValue = __intVal(self); |
4440 |
4441 |
4441 if (myValue < 0) { |
4442 if (myValue < 0) { |
4442 negative = 1; |
4443 negative = 1; |
4443 myValue = -myValue; |
4444 myValue = -myValue; |
4444 } |
4445 } |
4445 cp = buffer + sizeof(buffer) - 1; |
4446 cp = buffer + sizeof(buffer) - 1; |
4446 *cp-- = '\0'; |
4447 *cp-- = '\0'; |
4447 for (; myValue != 0; cp--) { |
4448 for (; myValue != 0; cp--) { |
4448 *cp = digits[myValue % __base]; |
4449 *cp = digits[myValue % __base]; |
4449 myValue /= __base; |
4450 myValue /= __base; |
4450 } |
4451 } |
4451 if (negative) { |
4452 if (negative) { |
4452 *cp-- = '-'; |
4453 *cp-- = '-'; |
4453 } |
4454 } |
4454 newString = __MKSTRING_L(cp+1, (buffer + sizeof(buffer) - 2 - cp)); |
4455 newString = __MKSTRING_L(cp+1, (buffer + sizeof(buffer) - 2 - cp)); |
4455 if (newString != nil) { |
4456 if (newString != nil) { |
4456 RETURN (newString); |
4457 RETURN (newString); |
4457 } |
4458 } |
4458 } |
4459 } |
4459 } |
4460 } |
4460 #endif /* not __SCHTEAM__ */ |
4461 #endif /* not __SCHTEAM__ */ |
4461 %}. |
4462 %}. |
4462 "/ arrive here, for bad base, |
4463 "/ arrive here, for bad base, |
4463 "/ or when having memory problems (i.e. no space for string) ... |
4464 "/ or when having memory problems (i.e. no space for string) ... |
4766 # if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 2) |
4767 # if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 2) |
4767 # define USE_LONGLONG_FOR_MUL |
4768 # define USE_LONGLONG_FOR_MUL |
4768 # endif |
4769 # endif |
4769 |
4770 |
4770 if (__isSmallInteger(aNumber)) { |
4771 if (__isSmallInteger(aNumber)) { |
4771 myValue = __intVal(self); |
4772 myValue = __intVal(self); |
4772 otherValue = __intVal(aNumber); |
4773 otherValue = __intVal(aNumber); |
4773 |
4774 |
4774 # if defined(USE_LONGLONG_FOR_MUL) |
4775 # if defined(USE_LONGLONG_FOR_MUL) |
4775 { |
4776 { |
4776 # if defined(__alpha__) && !defined(__alpha64__) |
4777 # if defined(__alpha__) && !defined(__alpha64__) |
4777 # define LONGLONG INT64 |
4778 # define LONGLONG INT64 |
4778 # else |
4779 # else |
4779 # define LONGLONG long long |
4780 # define LONGLONG long long |
4780 # endif |
4781 # endif |
4781 LONGLONG product; |
4782 LONGLONG product; |
4782 |
4783 |
4783 product = (LONGLONG)myValue * (LONGLONG)otherValue; |
4784 product = (LONGLONG)myValue * (LONGLONG)otherValue; |
4784 if (product < 0) { |
4785 if (product < 0) { |
4785 RETURN ( __mkSmallInteger(-(INT)(-product & _MAX_INT))); |
4786 RETURN ( __mkSmallInteger(-(INT)(-product & _MAX_INT))); |
4786 } |
4787 } |
4787 RETURN ( __mkSmallInteger((INT)(product & _MAX_INT))); |
4788 RETURN ( __mkSmallInteger((INT)(product & _MAX_INT))); |
4788 } |
4789 } |
4789 # else /* no long-long */ |
4790 # else /* no long-long */ |
4790 negative = 1; |
4791 negative = 1; |
4791 if (myValue < 0) { |
4792 if (myValue < 0) { |
4792 negative = -1; |
4793 negative = -1; |
4793 myValue = -myValue; |
4794 myValue = -myValue; |
4794 } |
4795 } |
4795 if (otherValue < 0) { |
4796 if (otherValue < 0) { |
4796 negative = -negative; |
4797 negative = -negative; |
4797 otherValue = -otherValue; |
4798 otherValue = -otherValue; |
4798 } |
4799 } |
4799 |
4800 |
4800 # if defined(__GNUC__) && defined(__mc68k__) |
4801 # if defined(__GNUC__) && defined(__mc68k__) |
4801 asm ("mulu%.l %3,%1:%0" |
4802 asm ("mulu%.l %3,%1:%0" |
4802 : "=d" ((unsigned long)(productLow)), |
4803 : "=d" ((unsigned long)(productLow)), |
4803 "=d" ((unsigned long)(productHi)) |
4804 "=d" ((unsigned long)(productHi)) |
4804 : "%0" ((unsigned long)(myValue)), |
4805 : "%0" ((unsigned long)(myValue)), |
4805 "dmi" ((unsigned long)(otherValue))); |
4806 "dmi" ((unsigned long)(otherValue))); |
4806 # else |
4807 # else |
4807 # if defined (__GNUC__) && defined(__x86__) |
4808 # if defined (__GNUC__) && defined(__x86__) |
4808 asm ("mull %3" |
4809 asm ("mull %3" |
4809 : "=a" ((unsigned long)(productLow)), |
4810 : "=a" ((unsigned long)(productLow)), |
4810 "=d" ((unsigned long)(productHi)) |
4811 "=d" ((unsigned long)(productHi)) |
4811 : "%0" ((unsigned long)(myValue)), |
4812 : "%0" ((unsigned long)(myValue)), |
4812 "rm" ((unsigned long)(otherValue))); |
4813 "rm" ((unsigned long)(otherValue))); |
4813 # else |
4814 # else |
4814 # if defined(__win32__) && defined(__BORLANDC__) |
4815 # if defined(__win32__) && defined(__BORLANDC__) |
4815 asm { |
4816 asm { |
4816 mov eax, myValue |
4817 mov eax, myValue |
4817 mov edx, otherValue |
4818 mov edx, otherValue |
4818 mul edx |
4819 mul edx |
4819 mov productLow, eax |
4820 mov productLow, eax |
4820 mov productHi, edx |
4821 mov productHi, edx |
4821 } |
4822 } |
4822 # else /* generic */ |
4823 # else /* generic */ |
4823 { |
4824 { |
4824 unsigned INT pHH, pHL, pLH, pLL; |
4825 unsigned INT pHH, pHL, pLH, pLL; |
4825 unsigned INT low1, low2, hi1, hi2; |
4826 unsigned INT low1, low2, hi1, hi2; |
4826 unsigned INT t; |
4827 unsigned INT t; |
4827 |
4828 |
4828 /* unsigned multiply myValue * otherValue -> productHi, productLow |
4829 /* unsigned multiply myValue * otherValue -> productHi, productLow |
4829 * |
4830 * |
4830 * this is too slow: |
4831 * this is too slow: |
4831 * since most machines can do 32*32 to 64 bit multiply, |
4832 * since most machines can do 32*32 to 64 bit multiply, |
4832 * (or at least 32*32 with Overflow check) |
4833 * (or at least 32*32 with Overflow check) |
4833 * - need more assembler (inline) functions here |
4834 * - need more assembler (inline) functions here |
4834 */ |
4835 */ |
4835 # if __POINTER_SIZE__ == 8 |
4836 # if __POINTER_SIZE__ == 8 |
4836 low1 = low32Bits((unsigned INT)myValue); |
4837 low1 = low32Bits((unsigned INT)myValue); |
4837 hi1 = hi32Bits((unsigned INT)myValue); |
4838 hi1 = hi32Bits((unsigned INT)myValue); |
4838 low2 = low32Bits((unsigned INT)otherValue); |
4839 low2 = low32Bits((unsigned INT)otherValue); |
4839 hi2 = hi32Bits((unsigned INT)otherValue); |
4840 hi2 = hi32Bits((unsigned INT)otherValue); |
4840 # undef LLMASK |
4841 # undef LLMASK |
4841 # define LLMASK 0xC000000000000000LL |
4842 # define LLMASK 0xC000000000000000LL |
4842 # else |
4843 # else |
4843 low1 = low16Bits((unsigned INT)myValue); |
4844 low1 = low16Bits((unsigned INT)myValue); |
4844 hi1 = hi16Bits((unsigned INT)myValue); |
4845 hi1 = hi16Bits((unsigned INT)myValue); |
4845 low2 = low16Bits((unsigned INT)otherValue); |
4846 low2 = low16Bits((unsigned INT)otherValue); |
4846 hi2 = hi16Bits((unsigned INT)otherValue); |
4847 hi2 = hi16Bits((unsigned INT)otherValue); |
4847 # define LLMASK 0xC0000000 |
4848 # define LLMASK 0xC0000000 |
4848 # endif |
4849 # endif |
4849 |
4850 |
4850 pLH = low1 * hi2; |
4851 pLH = low1 * hi2; |
4851 pHL = hi1 * low2; |
4852 pHL = hi1 * low2; |
4852 pLL = low1 * low2; |
4853 pLL = low1 * low2; |
4853 pHH = hi1 * hi2; |
4854 pHH = hi1 * hi2; |
4854 |
4855 |
4855 /* |
4856 /* |
4856 * the common case ... |
4857 * the common case ... |
4857 */ |
4858 */ |
4858 if ((pHL == 0) |
4859 if ((pHL == 0) |
4859 && (pLH == 0) |
4860 && (pLH == 0) |
4860 && (pHH == 0) |
4861 && (pHH == 0) |
4861 && ((pLL & LLMASK) == 0)) { |
4862 && ((pLL & LLMASK) == 0)) { |
4862 if (negative < 0) { |
4863 if (negative < 0) { |
4863 RETURN ( __mkSmallInteger(- ((INT)pLL)) ); |
4864 RETURN ( __mkSmallInteger(- ((INT)pLL)) ); |
4864 } |
4865 } |
4865 RETURN ( __mkSmallInteger((INT)pLL) ); |
4866 RETURN ( __mkSmallInteger((INT)pLL) ); |
4866 } |
4867 } |
4867 |
4868 |
4868 /* |
4869 /* |
4869 * pHH |--------|--------| |
4870 * pHH |--------|--------| |
4870 * pLH |--------|--------| |
4871 * pLH |--------|--------| |
4871 * pHL |--------|--------| |
4872 * pHL |--------|--------| |
4872 * pLL |--------|--------| |
4873 * pLL |--------|--------| |
4873 */ |
4874 */ |
4874 |
4875 |
4875 # if __POINTER_SIZE__ == 8 |
4876 # if __POINTER_SIZE__ == 8 |
4876 t = low32Bits(pLH) + low32Bits(pHL) + hi32Bits(pLL); |
4877 t = low32Bits(pLH) + low32Bits(pHL) + hi32Bits(pLL); |
4877 productLow = (t << 32) + low32Bits(pLL); |
4878 productLow = (t << 32) + low32Bits(pLL); |
4878 productHi = pHH + hi32Bits(t) + hi32Bits(pHL) + hi32Bits(pLH); |
4879 productHi = pHH + hi32Bits(t) + hi32Bits(pHL) + hi32Bits(pLH); |
4879 # else |
4880 # else |
4880 t = low16Bits(pLH) + low16Bits(pHL) + hi16Bits(pLL); |
4881 t = low16Bits(pLH) + low16Bits(pHL) + hi16Bits(pLL); |
4881 productLow = (t << 16) + low16Bits(pLL); |
4882 productLow = (t << 16) + low16Bits(pLL); |
4882 productHi = pHH + hi16Bits(t) + hi16Bits(pHL) + hi16Bits(pLH); |
4883 productHi = pHH + hi16Bits(t) + hi16Bits(pHL) + hi16Bits(pLH); |
4883 # endif |
4884 # endif |
4884 } |
4885 } |
4885 # endif /* ! __win32__ */ |
4886 # endif /* ! __win32__ */ |
4886 # endif /* ! (__GNUC__ && __x86__) */ |
4887 # endif /* ! (__GNUC__ && __x86__) */ |
4887 # endif /* ! (__GNUC__ && __mc68k__) */ |
4888 # endif /* ! (__GNUC__ && __mc68k__) */ |
4888 |
4889 |
4889 if (negative < 0) { |
4890 if (negative < 0) { |
4890 RETURN ( __mkSmallInteger(-(INT)(productLow & _MAX_INT))); |
4891 RETURN ( __mkSmallInteger(-(INT)(productLow & _MAX_INT))); |
4891 } |
4892 } |
4892 RETURN ( __mkSmallInteger((INT)(productLow & _MAX_INT))); |
4893 RETURN ( __mkSmallInteger((INT)(productLow & _MAX_INT))); |
4893 # endif /* ! USE_LONGLONG */ |
4894 # endif /* ! USE_LONGLONG */ |
4894 } |
4895 } |
4895 #endif /* not __SCHTEAM__ */ |
4896 #endif /* not __SCHTEAM__ */ |
4896 %}. |
4897 %}. |
4897 |
4898 |
4898 self primitiveFailed |
4899 self primitiveFailed |
4899 |
4900 |
4900 " |
4901 " |
4901 5 times:-1 |
4902 5 times:-1 |
4902 5 times:1 |
4903 5 times:1 |
4903 self maxVal-1 times:2 |
4904 self maxVal-1 times:2 |
4904 self maxVal-1 times:-2 |
4905 self maxVal-1 times:-2 |
4905 self maxVal-1 * 2 bitAnd:16r3fffffff |
4906 self maxVal-1 * 2 bitAnd:16r3fffffff |
4906 " |
4907 " |
4907 ! ! |
4908 ! ! |
4908 |
4909 |
4909 !SmallInteger methodsFor:'special modulo bit operators'! |
4910 !SmallInteger methodsFor:'special modulo bit operators'! |
4910 |
4911 |