LargeInteger.st
changeset 19655 8347118fe041
parent 19650 84b875892f4a
child 19662 1d6b7f21e0aa
child 19860 324edacff5cc
equal deleted inserted replaced
19654:f07bf67efc5c 19655:8347118fe041
       
     1 "{ Encoding: utf8 }"
       
     2 
     1 "
     3 "
     2  COPYRIGHT (c) 1994 by Claus Gittinger
     4  COPYRIGHT (c) 1994 by Claus Gittinger
     3 	      All Rights Reserved
     5 	      All Rights Reserved
     4 
     6 
     5  This software is furnished under a license and may be used
     7  This software is furnished under a license and may be used
   312 
   314 
   313     "LargeInteger value:3689"
   315     "LargeInteger value:3689"
   314 
   316 
   315     "Modified: / 8.5.1998 / 21:40:41 / cg"
   317     "Modified: / 8.5.1998 / 21:40:41 / cg"
   316 ! !
   318 ! !
   317 
       
   318 
       
   319 
   319 
   320 !LargeInteger class methodsFor:'queries'!
   320 !LargeInteger class methodsFor:'queries'!
   321 
   321 
   322 isBuiltInClass
   322 isBuiltInClass
   323     "return true if this class is known by the run-time-system.
   323     "return true if this class is known by the run-time-system.
  3325     "/ the following code only works with
  3325     "/ the following code only works with
  3326     "/ smallIntegers in the range _MIN_INT+255 .. _MAX_INT-255
  3326     "/ smallIntegers in the range _MIN_INT+255 .. _MAX_INT-255
  3327 
  3327 
  3328     ((aSmallInteger < (SmallInteger minVal + 255))
  3328     ((aSmallInteger < (SmallInteger minVal + 255))
  3329     or:[aSmallInteger > (SmallInteger maxVal - 255)]) ifTrue:[
  3329     or:[aSmallInteger > (SmallInteger maxVal - 255)]) ifTrue:[
  3330 	^ self absMinus:(self class value:aSmallInteger) sign:newSign.
  3330         ^ self absMinus:(self class value:aSmallInteger) sign:newSign.
  3331     ].
  3331     ].
  3332 
  3332 
  3333     len := digitByteArray size.
  3333     len := digitByteArray size.
  3334 
  3334 
  3335     rsltLen := len "+ 1".
  3335     rsltLen := len "+ 1".
  3339     borrow := aSmallInteger abs.
  3339     borrow := aSmallInteger abs.
  3340 
  3340 
  3341 %{
  3341 %{
  3342     if (__isByteArray(__INST(digitByteArray))
  3342     if (__isByteArray(__INST(digitByteArray))
  3343      && __isByteArray(resultDigitByteArray)) {
  3343      && __isByteArray(resultDigitByteArray)) {
  3344 	unsigned INT __borrow = __intVal(borrow);
  3344         unsigned INT __borrow = __intVal(borrow);
  3345 	INT __diff;
  3345         INT __diff;
  3346 	int __index = 1;
  3346         int __index = 1;
  3347 	int __len = __intVal(len);
  3347         int __len = __intVal(len);
  3348 	unsigned char *__digitP = __ByteArrayInstPtr(__INST(digitByteArray))->ba_element;
  3348         unsigned char *__digitP = __ByteArrayInstPtr(__INST(digitByteArray))->ba_element;
  3349 	unsigned char *__resultP = __ByteArrayInstPtr(resultDigitByteArray)->ba_element;
  3349         unsigned char *__resultP = __ByteArrayInstPtr(resultDigitByteArray)->ba_element;
  3350 	int __len3;
  3350         int __len3;
  3351 
  3351 
  3352 #if defined(__LSBFIRST__)
  3352 #if defined(__LSBFIRST__)
  3353 # if (__POINTER_SIZE__ == 8)
  3353 # if (__POINTER_SIZE__ == 8)
  3354 	/*
  3354         /*
  3355 	 * subtract int-wise
  3355          * subtract int-wise
  3356 	 */
  3356          */
  3357 	__len3 = __len - 3;
  3357         __len3 = __len - 3;
  3358 	while (__index < __len3) {
  3358         while (__index < __len3) {
  3359 	    /* do not make this into one expression - ask cg why */
  3359             /* do not make this into one expression - ask cg why */
  3360 	    __diff = ((unsigned int *)(__digitP + __index-1))[0];
  3360             __diff = ((unsigned int *)(__digitP + __index-1))[0];
  3361 	    __diff -= (__borrow & 0xFFFFFFFFL);
  3361             __diff -= (__borrow & 0xFFFFFFFFL);
  3362 	    __borrow >>= 32;
  3362             __borrow >>= 32;
  3363 	    if (__diff < 0) {
  3363             ((unsigned int *)(__resultP+__index-1))[0] = __diff;
  3364 		/* __diff += 0x100000000; */
  3364             __index += 4;
  3365 		__borrow++;
  3365             if (__diff < 0) {
  3366 	    }
  3366                 /* __diff += 0x100000000; */
  3367 	    ((unsigned int *)(__resultP+__index-1))[0] = __diff;
  3367                 __borrow++;
  3368 	    __index += 4;
  3368             } else {
  3369 	}
  3369                 if (__borrow == 0) {
       
  3370                     /* nothing more to subtract .. */
       
  3371                     while (__index < __len3) {
       
  3372                         ((unsigned int *)(__resultP+__index-1))[0] = ((unsigned int *)(__digitP+__index-1))[0];
       
  3373                         __index += 4;
       
  3374                     }
       
  3375                     if (__index < __len) {
       
  3376                         ((unsigned short *)(__resultP+__index-1))[0] = ((unsigned short *)(__digitP+__index-1))[0];
       
  3377                         __index += 2;
       
  3378                     }
       
  3379                     if (__index <= __len) {
       
  3380                         __resultP[__index-1] = __digitP[__index-1];
       
  3381                     }
       
  3382                     break;
       
  3383                 }
       
  3384             }
       
  3385         }
  3370 # endif
  3386 # endif
  3371 	/*
  3387         /*
  3372 	 * subtract short-wise
  3388          * subtract short-wise
  3373 	 */
  3389          */
  3374 	while (__index < __len) {
  3390         while (__index < __len) {
  3375 	    /* do not make this into one expression - ask cg why */
  3391             /* do not make this into one expression - ask cg why */
  3376 	    __diff = ((unsigned short *)(__digitP+__index-1))[0];
  3392             __diff = ((unsigned short *)(__digitP+__index-1))[0];
  3377 	    __diff -= (__borrow & 0xFFFF);
  3393             __diff -= (__borrow & 0xFFFF);
  3378 	    __borrow >>= 16;
  3394             __borrow >>= 16;
  3379 	    if (__diff < 0) {
  3395             ((unsigned short *)(__resultP+__index-1))[0] = __diff;
  3380 		/* __diff += 0x10000; */
  3396             __index += 2;
  3381 		__borrow++;
  3397             if (__diff < 0) {
  3382 	    } else {
  3398                 /* __diff += 0x10000; */
  3383 		if (__borrow == 0) {
  3399                 __borrow++;
  3384 		    ((unsigned short *)(__resultP+__index-1))[0] = __diff;
  3400             } else {
  3385 		    __index += 2;
  3401                 if (__borrow == 0) {
  3386 
  3402                     /* nothing more to subtract .. */
  3387 		    /* nothing more to subtract .. */
  3403                     while (__index < __len) {
  3388 		    while (__index < __len) {
  3404                         ((unsigned short *)(__resultP+__index-1))[0] = ((unsigned short *)(__digitP+__index-1))[0];
  3389 			((unsigned short *)(__resultP+__index-1))[0] = ((unsigned short *)(__digitP+__index-1))[0];
  3405                         __index += 2;
  3390 			__index += 2;
  3406                     }
  3391 		    }
  3407                     if (__index <= __len) {
  3392 		    if (__index <= __len) {
  3408                         __resultP[__index-1] = __digitP[__index-1];
  3393 			__resultP[__index-1] = __digitP[__index-1];
  3409                     }
  3394 		    }
  3410                     break;
  3395 		    break;
  3411                 }
  3396 		}
  3412             }
  3397 	    }
  3413         }
  3398 	    ((unsigned short *)(__resultP+__index-1))[0] = __diff;
       
  3399 	    __index += 2;
       
  3400 	}
       
  3401 #endif
  3414 #endif
  3402 	/*
  3415         /*
  3403 	 * subtract byte-wise
  3416          * subtract byte-wise
  3404 	 */
  3417          */
  3405 	while (__index <= __len) {
  3418         while (__index <= __len) {
  3406 	    __diff = __digitP[__index-1];
  3419             __diff = __digitP[__index-1];
  3407 	    __diff -= (__borrow & 0xFF);
  3420             __diff -= (__borrow & 0xFF);
  3408 	    __borrow >>= 8;
  3421             __borrow >>= 8;
  3409 	    if (__diff < 0) {
  3422             __resultP[__index-1] = __diff;
  3410 		/* __diff += 0x100; */
  3423             __index++;
  3411 		__borrow++;
  3424             if (__diff < 0) {
  3412 	    } else {
  3425                 /* __diff += 0x100; */
  3413 		if (__borrow == 0) {
  3426                 __borrow++;
  3414 		    __resultP[__index-1] = __diff;
  3427             } else {
  3415 		    __index++;
  3428                 if (__borrow == 0) {
  3416 
  3429                     /* nothing more to subtract .. */
  3417 		    /* nothing more to subtract .. */
  3430                     while (__index <= __len) {
  3418 		    while (__index <= __len) {
  3431                         __resultP[__index-1] = __digitP[__index-1];
  3419 			__resultP[__index-1] = __digitP[__index-1];
  3432                         __index++;
  3420 			__index++;
  3433                     }
  3421 		    }
  3434                     break;
  3422 		    break;
  3435                 }
  3423 		}
  3436             }
  3424 	    }
  3437         }
  3425 	    __resultP[__index-1] = __diff;
  3438         lastDigit = __mkSmallInteger( __resultP[__index-1-1] );
  3426 	    __index++;
  3439         ok = true;
  3427 	}
       
  3428 	lastDigit = __mkSmallInteger( __resultP[__index-1-1] );
       
  3429 	ok = true;
       
  3430     }
  3440     }
  3431 %}.
  3441 %}.
  3432 
  3442 
  3433     ok == true ifFalse:[        "/ cannot happen
  3443     ok == true ifFalse:[        "/ cannot happen
  3434 	index := 1.
  3444         index := 1.
  3435 	[borrow ~~ 0] whileTrue:[
  3445         [borrow ~~ 0] whileTrue:[
  3436 	    (index <= len) ifTrue:[
  3446             (index <= len) ifTrue:[
  3437 		diff := (digitByteArray basicAt:index) - (borrow bitAnd:16rFF).
  3447                 diff := (digitByteArray basicAt:index) - (borrow bitAnd:16rFF).
  3438 		borrow := borrow bitShift:-8.
  3448                 borrow := borrow bitShift:-8.
  3439 		diff < 0 ifTrue:[
  3449                 diff < 0 ifTrue:[
  3440 		    diff := diff + 256.
  3450                     diff := diff + 256.
  3441 		    borrow := borrow + 1.
  3451                     borrow := borrow + 1.
  3442 		]
  3452                 ]
  3443 	    ] ifFalse:[
  3453             ] ifFalse:[
  3444 		diff := borrow bitAnd:255.
  3454                 diff := borrow bitAnd:255.
  3445 		borrow := borrow bitShift:-8.
  3455                 borrow := borrow bitShift:-8.
  3446 	    ].
  3456             ].
  3447 	    resultDigitByteArray basicAt:index put:(lastDigit := diff).
  3457             resultDigitByteArray basicAt:index put:(lastDigit := diff).
  3448 	    index := index + 1
  3458             index := index + 1
  3449 	].
  3459         ].
  3450 	[index <= len] whileTrue:[
  3460         [index <= len] whileTrue:[
  3451 	    resultDigitByteArray basicAt:index put:(lastDigit := digitByteArray basicAt:index).
  3461             resultDigitByteArray basicAt:index put:(lastDigit := digitByteArray basicAt:index).
  3452 	    index := index + 1
  3462             index := index + 1
  3453 	].
  3463         ].
  3454 	(index <= rsltLen) ifTrue:[
  3464         (index <= rsltLen) ifTrue:[
  3455 	    lastDigit := 0.
  3465             lastDigit := 0.
  3456 	]
  3466         ]
  3457     ].
  3467     ].
  3458 
  3468 
  3459     (lastDigit == 0 or:[rsltLen <= SmallInteger maxBytes]) ifTrue:[
  3469     (lastDigit == 0 or:[rsltLen <= SmallInteger maxBytes]) ifTrue:[
  3460 	^ result compressed.
  3470         ^ result compressed.
  3461     ].
  3471     ].
  3462     ^ result
  3472     ^ result
  3463 
  3473 
  3464     "
  3474     "
  3465      12345678900000000000 absFastMinus:1 sign:1
  3475      12345678900000000000 absFastMinus:1 sign:1
  3490     "/ the following code only works with
  3500     "/ the following code only works with
  3491     "/ smallIntegers in the range _MIN_INT+255 .. _MAX_INT-255
  3501     "/ smallIntegers in the range _MIN_INT+255 .. _MAX_INT-255
  3492 
  3502 
  3493     ((aSmallInteger < (SmallInteger minVal + 255))
  3503     ((aSmallInteger < (SmallInteger minVal + 255))
  3494     or:[aSmallInteger > (SmallInteger maxVal - 255)]) ifTrue:[
  3504     or:[aSmallInteger > (SmallInteger maxVal - 255)]) ifTrue:[
  3495 	^ self absPlus:(self class value:aSmallInteger) sign:newSign.
  3505         ^ self absPlus:(self class value:aSmallInteger) sign:newSign.
  3496     ].
  3506     ].
  3497 
  3507 
  3498     len := rsltLen := digitByteArray size.
  3508     len := rsltLen := digitByteArray size.
  3499     "/
  3509     "/
  3500     "/ there can only be an overflow from the high byte,
  3510     "/ there can only be an overflow from the high byte,
  3501     "/ if it is 255 (since the other number is definitely smaller)
  3511     "/ if it is 255 (since the other number is definitely smaller)
  3502     "/
  3512     "/
  3503     (digitByteArray at:len) == 16rFF ifTrue:[
  3513     (digitByteArray at:len) == 16rFF ifTrue:[
  3504 	rsltLen := len + 1.
  3514         rsltLen := len + 1.
  3505     ] ifFalse:[
  3515     ] ifFalse:[
  3506 	"/ or the argument has something in the high byte ..
  3516         "/ or the argument has something in the high byte ..
  3507 %{
  3517 %{
  3508 #if __POINTER_SIZE__ == 8
  3518 #if __POINTER_SIZE__ == 8
  3509 	if (__intVal(aSmallInteger) & 0xFF00000000000000L) {
  3519         if (__intVal(aSmallInteger) & 0xFF00000000000000L) {
  3510 	    rsltLen = __mkSmallInteger(__intVal(len) + 1);
  3520             rsltLen = __mkSmallInteger(__intVal(len) + 1);
  3511 	}
  3521         }
  3512 #else
  3522 #else
  3513 	if (__intVal(aSmallInteger) & 0xFF000000) {
  3523         if (__intVal(aSmallInteger) & 0xFF000000) {
  3514 	    rsltLen = __mkSmallInteger(__intVal(len) + 1);
  3524             rsltLen = __mkSmallInteger(__intVal(len) + 1);
  3515 	}
  3525         }
  3516 #endif
  3526 #endif
  3517 %}
  3527 %}
  3518     ].
  3528     ].
  3519 
  3529 
  3520     result := self class basicNew numberOfDigits:rsltLen sign:newSign.
  3530     result := self class basicNew numberOfDigits:rsltLen sign:newSign.
  3522 
  3532 
  3523 %{
  3533 %{
  3524     if (__isByteArray(__INST(digitByteArray))
  3534     if (__isByteArray(__INST(digitByteArray))
  3525      && __isByteArray(resultDigitByteArray)
  3535      && __isByteArray(resultDigitByteArray)
  3526      && __isSmallInteger(aSmallInteger)) {
  3536      && __isSmallInteger(aSmallInteger)) {
  3527 	/* carry is NOT unsigned (see negation below) */
  3537         /* carry is NOT unsigned (see negation below) */
  3528 	INT __carry = __intVal(aSmallInteger);
  3538         INT __carry = __intVal(aSmallInteger);
  3529 	int __index = 1;
  3539         int __index = 1;
  3530 	int __len = __intVal(len);
  3540         int __len = __intVal(len);
  3531 	unsigned char *__src = (unsigned char *)(__ByteArrayInstPtr(__INST(digitByteArray))->ba_element);
  3541         unsigned char *__src = (unsigned char *)(__ByteArrayInstPtr(__INST(digitByteArray))->ba_element);
  3532 	unsigned char *__dst = (unsigned char *)(__ByteArrayInstPtr(resultDigitByteArray)->ba_element);
  3542         unsigned char *__dst = (unsigned char *)(__ByteArrayInstPtr(resultDigitByteArray)->ba_element);
  3533 	INT __ptrDelta = __dst - __src;
  3543         INT __ptrDelta = __dst - __src;
  3534 	unsigned char *__srcLast = __src + __len - 1;
  3544         unsigned char *__srcLast = __src + __len - 1;
  3535 	int __rsltLen = __intVal(rsltLen);
  3545         int __rsltLen = __intVal(rsltLen);
  3536 
  3546 
  3537 	if (__carry < 0) {
  3547         if (__carry < 0) {
  3538 	    __carry = -__carry;
  3548             __carry = -__carry;
  3539 	}
  3549         }
  3540 
  3550 
  3541 #if defined(__LSBFIRST__)
  3551 #if defined(__LSBFIRST__)
  3542 # if defined(__i386__) && defined(__GNUC__) && (__POINTER_SIZE__ == 4)
  3552 # if defined(__i386__) && defined(__GNUC__) && (__POINTER_SIZE__ == 4)
  3543 #  if 0 /* NOTICE - the code below is 20% slower ... - why */
  3553 #  if 0 /* NOTICE - the code below is 20% slower ... - why */
  3544 	/*
  3554         /*
  3545 	 * add long-wise
  3555          * add long-wise
  3546 	 */
  3556          */
  3547 	asm("  jecxz nothingToDo                                      \n\
  3557         asm("  jecxz nothingToDo                                      \n\
  3548 	       movl  %%eax, %%esi      /* __src input */              \n\
  3558                movl  %%eax, %%esi      /* __src input */              \n\
  3549 	       movl  %%ebx, %%edi      /* __dst input */              \n\
  3559                movl  %%ebx, %%edi      /* __dst input */              \n\
  3550 								      \n\
  3560                                                                       \n\
  3551 	       /* the first 4-byte int */                             \n\
  3561                /* the first 4-byte int */                             \n\
  3552 	       lodsl                   /* fetch */                    \n\
  3562                lodsl                   /* fetch */                    \n\
  3553 	       addl  %%edx, %%eax      /* add */                      \n\
  3563                addl  %%edx, %%eax      /* add */                      \n\
  3554 	       stosl                   /* store */                    \n\
  3564                stosl                   /* store */                    \n\
  3555 	       leal  -1(%%ecx),%%ecx   /* do not clobber carry */     \n\
  3565                leal  -1(%%ecx),%%ecx   /* do not clobber carry */     \n\
  3556 	       jecxz doneLoop          /* any more ? */               \n\
  3566                jecxz doneLoop          /* any more ? */               \n\
  3557 	       /* remaining 4-byte ints */                            \n\
  3567                /* remaining 4-byte ints */                            \n\
  3558 	       jmp   addLoop                                          \n\
  3568                jmp   addLoop                                          \n\
  3559 								      \n\
  3569                                                                       \n\
  3560 	       .align 8                                               \n\
  3570                .align 8                                               \n\
  3561 	     addLoop:                                                 \n\
  3571              addLoop:                                                 \n\
  3562 	       movl  0(%%esi), %%ebx   /* fetch  */                   \n\
  3572                movl  0(%%esi), %%ebx   /* fetch  */                   \n\
  3563 	       jnc   copyLoop2                                        \n\
  3573                jnc   copyLoop2                                        \n\
  3564 	       movl  $0, %%eax                                        \n\
  3574                movl  $0, %%eax                                        \n\
  3565 	       leal  4(%%esi), %%esi                                  \n\
  3575                leal  4(%%esi), %%esi                                  \n\
  3566 	       adcl  %%ebx, %%eax      /* & add carry from prev int */\n\
  3576                adcl  %%ebx, %%eax      /* & add carry from prev int */\n\
  3567 	       leal  8(%%edi), %%edi                                  \n\
  3577                leal  8(%%edi), %%edi                                  \n\
  3568 	       movl  %%eax, -8(%%edi)  /* store */                    \n\
  3578                movl  %%eax, -8(%%edi)  /* store */                    \n\
  3569 	       leal  -1(%%ecx),%%ecx   /* do not clobber carry */     \n\
  3579                leal  -1(%%ecx),%%ecx   /* do not clobber carry */     \n\
  3570 	       jecxz doneLoop          /* any more ? */               \n\
  3580                jecxz doneLoop          /* any more ? */               \n\
  3571 								      \n\
  3581                                                                       \n\
  3572 	       movl  0(%%esi), %%ebx   /* fetch  */                   \n\
  3582                movl  0(%%esi), %%ebx   /* fetch  */                   \n\
  3573 	       movl  $0, %%eax                                        \n\
  3583                movl  $0, %%eax                                        \n\
  3574 	       leal  4(%%esi), %%esi                                  \
  3584                leal  4(%%esi), %%esi                                  \
  3575 	       adcl  %%ebx, %%eax      /* & add carry from prev int */\n\
  3585                adcl  %%ebx, %%eax      /* & add carry from prev int */\n\
  3576 	       movl  %%eax, -4(%%edi)  /* store */                    \n\
  3586                movl  %%eax, -4(%%edi)  /* store */                    \n\
  3577 								      \n\
  3587                                                                       \n\
  3578 	       loop  addLoop                                          \n\
  3588                loop  addLoop                                          \n\
  3579 	       jmp   doneLoop                                         \n\
  3589                jmp   doneLoop                                         \n\
  3580 								      \n\
  3590                                                                       \n\
  3581 	       .align 8                                               \n\
  3591                .align 8                                               \n\
  3582 	     copyLoop:                                                \n\
  3592              copyLoop:                                                \n\
  3583 	       movl  0(%%esi), %%ebx                                  \n\
  3593                movl  0(%%esi), %%ebx                                  \n\
  3584 	     copyLoop2:                                               \n\
  3594              copyLoop2:                                               \n\
  3585 	       add   $4, %%esi                                        \n\
  3595                add   $4, %%esi                                        \n\
  3586 	       add   $4, %%edi                                        \n\
  3596                add   $4, %%edi                                        \n\
  3587 	       movl  %%ebx, -4(%%edi)                                 \n\
  3597                movl  %%ebx, -4(%%edi)                                 \n\
  3588 	       loop  copyLoop                                         \n\
  3598                loop  copyLoop                                         \n\
  3589 								      \n\
  3599                                                                       \n\
  3590 	     doneLoop:                                                \n\
  3600              doneLoop:                                                \n\
  3591 	       movl  $0, %%edx         /* do not clobber carry (xorl clears it) */   \n\
  3601                movl  $0, %%edx         /* do not clobber carry (xorl clears it) */   \n\
  3592 	       adcl  $0, %%edx                                        \n\
  3602                adcl  $0, %%edx                                        \n\
  3593 	       movl  %%esi, %%eax      /* __src output */             \n\
  3603                movl  %%esi, %%eax      /* __src output */             \n\
  3594 	     nothingToDo:                                             \n\
  3604              nothingToDo:                                             \n\
  3595 	    " : "=d"  ((unsigned long)(__carry)),
  3605             " : "=d"  ((unsigned long)(__carry)),
  3596 		"=a"  (__src)
  3606                 "=a"  (__src)
  3597 	      : "1"   (__src),
  3607               : "1"   (__src),
  3598 		"b"   (__dst),
  3608                 "b"   (__dst),
  3599 		"c"   (__len / 4),
  3609                 "c"   (__len / 4),
  3600 		"0"   (__carry)
  3610                 "0"   (__carry)
  3601 	      : "esi", "edi");
  3611               : "esi", "edi");
  3602 
  3612 
  3603 #  else
  3613 #  else
  3604 	{
  3614         {
  3605 	    unsigned char *__srcLastX;
  3615             unsigned char *__srcLastX;
  3606 
  3616 
  3607 	    __srcLastX = __srcLast - 3 - 4;
  3617             __srcLastX = __srcLast - 3 - 4;
  3608 	    while (__src <= __srcLastX) {
  3618             while (__src <= __srcLastX) {
  3609 		unsigned int __sum, __sum2;
  3619                 unsigned int __sum, __sum2;
  3610 		unsigned __digit1, __digit2;
  3620                 unsigned __digit1, __digit2;
  3611 
  3621 
  3612 		__digit1 = ((unsigned *)__src)[0];
  3622                 __digit1 = ((unsigned *)__src)[0];
  3613 		__digit2 = ((unsigned *)__src)[1];
  3623                 __digit2 = ((unsigned *)__src)[1];
  3614 		asm ("addl %%edx,%%ecx          \n\
  3624                 asm ("addl %%edx,%%ecx          \n\
  3615 		      adcl $0, %%eax            \n\
  3625                       adcl $0, %%eax            \n\
  3616 		      movl $0, %%edx            \n\
  3626                       movl $0, %%edx            \n\
  3617 		      adcl $0, %%edx"
  3627                       adcl $0, %%edx"
  3618 			: "=d"  ((unsigned long)(__carry)),
  3628                         : "=d"  ((unsigned long)(__carry)),
  3619 			  "=c"  ((unsigned long)(__sum)),
  3629                           "=c"  ((unsigned long)(__sum)),
  3620 			  "=a"  ((unsigned long)(__sum2))
  3630                           "=a"  ((unsigned long)(__sum2))
  3621 			: "0"   ((unsigned long)(__carry)),
  3631                         : "0"   ((unsigned long)(__carry)),
  3622 			  "1"   (__digit1),
  3632                           "1"   (__digit1),
  3623 			  "2"   (__digit2));
  3633                           "2"   (__digit2));
  3624 
  3634 
  3625 		((unsigned int *)(__src + __ptrDelta))[0] = __sum;
  3635                 ((unsigned int *)(__src + __ptrDelta))[0] = __sum;
  3626 		((unsigned int *)(__src + __ptrDelta))[1] = __sum2;
  3636                 ((unsigned int *)(__src + __ptrDelta))[1] = __sum2;
  3627 
  3637 
  3628 		__src += 8;
  3638                 __src += 8;
  3629 
  3639 
  3630 		if (__carry == 0) {
  3640                 if (__carry == 0) {
  3631 		    while (__src <= __srcLastX) {
  3641                     while (__src <= __srcLastX) {
  3632 			/* copy over words */
  3642                         /* copy over words */
  3633 			((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0];
  3643                         ((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0];
  3634 			((unsigned int *)(__src + __ptrDelta))[1] = ((unsigned int *)__src)[1];
  3644                         ((unsigned int *)(__src + __ptrDelta))[1] = ((unsigned int *)__src)[1];
  3635 			__src += 8;
  3645                         __src += 8;
  3636 		    }
  3646                     }
  3637 		    while (__src <= __srcLast) {
  3647                     while (__src <= __srcLast) {
  3638 			/* copy over bytes */
  3648                         /* copy over bytes */
  3639 			__src[__ptrDelta] = __src[0];
  3649                         __src[__ptrDelta] = __src[0];
  3640 			__src ++;
  3650                         __src ++;
  3641 		    }
  3651                     }
  3642 		    goto doneSource;
  3652                     goto doneSource;
  3643 		}
  3653                 }
  3644 	    }
  3654             }
  3645 
  3655 
  3646 	    __srcLastX = __srcLastX + 4;
  3656             __srcLastX = __srcLastX + 4;
  3647 	    if (__src <= __srcLastX) {
  3657             if (__src <= __srcLastX) {
  3648 		unsigned int __sum, __digit;
  3658                 unsigned int __sum, __digit;
  3649 
  3659 
  3650 		__digit = ((unsigned *)__src)[0];
  3660                 __digit = ((unsigned *)__src)[0];
  3651 
  3661 
  3652 		asm ("addl %%eax,%%edx  \n\
  3662                 asm ("addl %%eax,%%edx  \n\
  3653 		      movl $0,%%eax     \n\
  3663                       movl $0,%%eax     \n\
  3654 		      adcl $0,%%eax"
  3664                       adcl $0,%%eax"
  3655 			: "=a"  ((unsigned long)(__carry)),
  3665                         : "=a"  ((unsigned long)(__carry)),
  3656 			  "=d"  ((unsigned long)(__sum))
  3666                           "=d"  ((unsigned long)(__sum))
  3657 			: "0"   ((unsigned long)(__carry)),
  3667                         : "0"   ((unsigned long)(__carry)),
  3658 			  "1"   (__digit) );
  3668                           "1"   (__digit) );
  3659 
  3669 
  3660 		((unsigned int *)(__src + __ptrDelta))[0] = __sum;
  3670                 ((unsigned int *)(__src + __ptrDelta))[0] = __sum;
  3661 		__src += 4;
  3671                 __src += 4;
  3662 
  3672 
  3663 		if (__carry == 0) {
  3673                 if (__carry == 0) {
  3664 		    while (__src <= __srcLast) {
  3674                     while (__src <= __srcLast) {
  3665 			/* copy over bytes */
  3675                         /* copy over bytes */
  3666 			__src[__ptrDelta] = __src[0];
  3676                         __src[__ptrDelta] = __src[0];
  3667 			__src ++;
  3677                         __src ++;
  3668 		    }
  3678                     }
  3669 		    goto doneSource;
  3679                     goto doneSource;
  3670 		}
  3680                 }
  3671 	    }
  3681             }
  3672 	}
  3682         }
  3673 #  endif
  3683 #  endif
  3674 # else /* not i386-GNUC */
  3684 # else /* not i386-GNUC */
  3675 #  if defined(WIN32) && defined(__BORLANDC__) && defined(__i386__) && (__POINTER_SIZE__ == 4)
  3685 #  if defined(WIN32) && defined(__BORLANDC__) && defined(__i386__) && (__POINTER_SIZE__ == 4)
  3676 	{
  3686         {
  3677 	    unsigned char *__srcLast4;
  3687             unsigned char *__srcLast4;
  3678 
  3688 
  3679 	    /*
  3689             /*
  3680 	     * add long-wise
  3690              * add long-wise
  3681 	     */
  3691              */
  3682 	    __srcLast4 = __srcLast - 3;
  3692             __srcLast4 = __srcLast - 3;
  3683 	    while (__src <= __srcLast4) {
  3693             while (__src <= __srcLast4) {
  3684 		unsigned int __sum;
  3694                 unsigned int __sum;
  3685 
  3695 
  3686 		__sum = ((unsigned int *)__src)[0];
  3696                 __sum = ((unsigned int *)__src)[0];
  3687 		asm {
  3697                 asm {
  3688 		      mov eax, __sum
  3698                       mov eax, __sum
  3689 		      add eax, __carry
  3699                       add eax, __carry
  3690 		      mov edx, 0
  3700                       mov edx, 0
  3691 		      adc edx, 0
  3701                       adc edx, 0
  3692 		      mov __sum, eax
  3702                       mov __sum, eax
  3693 		      mov __carry, edx
  3703                       mov __carry, edx
  3694 		    }
  3704                     }
  3695 
  3705 
  3696 		((unsigned int *)(__src + __ptrDelta))[0] = __sum;
  3706                 ((unsigned int *)(__src + __ptrDelta))[0] = __sum;
  3697 		__src += 4;
  3707                 __src += 4;
  3698 		if (__carry == 0) {
  3708                 if (__carry == 0) {
  3699 		    while (__src <= __srcLast4) {
  3709                     while (__src <= __srcLast4) {
  3700 			/* copy over words */
  3710                         /* copy over words */
  3701 			((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0];
  3711                         ((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0];
  3702 			__src += 4;
  3712                         __src += 4;
  3703 		    }
  3713                     }
  3704 		    while (__src <= __srcLast) {
  3714                     while (__src <= __srcLast) {
  3705 			/* copy over bytes */
  3715                         /* copy over bytes */
  3706 			__src[__ptrDelta] = __src[0];
  3716                         __src[__ptrDelta] = __src[0];
  3707 			__src ++;
  3717                         __src ++;
  3708 		    }
  3718                     }
  3709 		    goto doneSource;
  3719                     goto doneSource;
  3710 		}
  3720                 }
  3711 	    }
  3721             }
  3712 	}
  3722         }
  3713 #  else /* not i386-WIN32 */
  3723 #  else /* not i386-WIN32 */
  3714 #   if defined(__LSBFIRST__) && (__POINTER_SIZE__ == 8)
  3724 #   if defined(__LSBFIRST__) && (__POINTER_SIZE__ == 8)
  3715 	{
  3725         {
  3716 	    unsigned char *__srcLast4;
  3726             unsigned char *__srcLast4;
  3717 
  3727 
  3718 	    /*
  3728             /*
  3719 	     * add long-wise
  3729              * add long-wise
  3720 	     */
  3730              */
  3721 	    __srcLast4 = __srcLast - 3;
  3731             __srcLast4 = __srcLast - 3;
  3722 	    while (__src <= __srcLast4) {
  3732             while (__src <= __srcLast4) {
  3723 		unsigned INT __sum;
  3733                 unsigned INT __sum;
  3724 
  3734 
  3725 		__sum = ((unsigned int *)__src)[0] + __carry;
  3735                 __sum = (INT)(((unsigned int *)__src)[0]);
  3726 		((unsigned int *)(__src + __ptrDelta))[0] = __sum /* & 0xFFFF */;
  3736                 __sum += __carry;
  3727 		__src += 4;
  3737                 ((unsigned int *)(__src + __ptrDelta))[0] = __sum /* & 0xFFFF */;
  3728 		__carry = __sum >> 32;
  3738                 __src += 4;
  3729 		if (__carry == 0) {
  3739                 __carry = __sum >> 32;
  3730 		    while (__src <= __srcLast4) {
  3740                 if (__carry == 0) {
  3731 			/* copy over words */
  3741                     while (__src <= __srcLast4) {
  3732 			((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0];
  3742                         /* copy over words */
  3733 			__src += 4;
  3743                         ((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0];
  3734 		    }
  3744                         __src += 4;
  3735 		    while (__src <= __srcLast) {
  3745                     }
  3736 			/* copy over bytes */
  3746                     while (__src <= __srcLast) {
  3737 			__src[__ptrDelta] = __src[0];
  3747                         /* copy over bytes */
  3738 			__src ++;
  3748                         __src[__ptrDelta] = __src[0];
  3739 		    }
  3749                         __src ++;
  3740 		    goto doneSource;
  3750                     }
  3741 		}
  3751                     goto doneSource;
  3742 	    }
  3752                 }
  3743 	}
  3753             }
       
  3754         }
  3744 #   endif /* LSB+64bit */
  3755 #   endif /* LSB+64bit */
  3745 #  endif /* __i386__ & WIN32 */
  3756 #  endif /* __i386__ & WIN32 */
  3746 # endif /* __i386__ & GNUC */
  3757 # endif /* __i386__ & GNUC */
  3747 
  3758 
  3748 	/*
  3759         /*
  3749 	 * add short-wise
  3760          * add short-wise
  3750 	 */
  3761          */
  3751 	while (__src < __srcLast) {
  3762         while (__src < __srcLast) {
  3752 	    __carry += ((unsigned short *)__src)[0];
  3763             __carry += ((unsigned short *)__src)[0];
  3753 	    ((unsigned short *)(__src + __ptrDelta))[0] = __carry /* & 0xFFFF */;
  3764             ((unsigned short *)(__src + __ptrDelta))[0] = __carry /* & 0xFFFF */;
  3754 	    __carry >>= 16;
  3765             __carry >>= 16;
  3755 	    __src += 2;
  3766             __src += 2;
  3756 	}
  3767         }
  3757 	/*
  3768         /*
  3758 	 * last (odd) byte
  3769          * last (odd) byte
  3759 	 */
  3770          */
  3760 	if (__src <= __srcLast) {
  3771         if (__src <= __srcLast) {
  3761 	    __carry += __src[0];
  3772             __carry += __src[0];
  3762 	    __src[__ptrDelta] = __carry /* & 0xFF */;
  3773             __src[__ptrDelta] = __carry /* & 0xFF */;
  3763 	    __carry >>= 8;
  3774             __carry >>= 8;
  3764 	    __src++;
  3775             __src++;
  3765 	}
  3776         }
  3766 #else /* not __LSBFIRST__ */
  3777 #else /* not __LSBFIRST__ */
  3767 
  3778 
  3768 	/*
  3779         /*
  3769 	 * add byte-wise
  3780          * add byte-wise
  3770 	 */
  3781          */
  3771 	while (__src <= __srcLast) {
  3782         while (__src <= __srcLast) {
  3772 	    __carry += __src[0];
  3783             __carry += __src[0];
  3773 	    __src[__ptrDelta] = __carry /* & 0xFF */;
  3784             __src[__ptrDelta] = __carry /* & 0xFF */;
  3774 	    __src++;
  3785             __src++;
  3775 	    __carry >>= 8;
  3786             __carry >>= 8;
  3776 
  3787 
  3777 	    if (__carry == 0) {
  3788             if (__carry == 0) {
  3778 		while (__src <= __srcLast) {
  3789                 while (__src <= __srcLast) {
  3779 		    /* copy over rest */
  3790                     /* copy over rest */
  3780 		    __src[__ptrDelta] = __src[0];
  3791                     __src[__ptrDelta] = __src[0];
  3781 		    __src++;
  3792                     __src++;
  3782 		}
  3793                 }
  3783 		goto doneSource;
  3794                 goto doneSource;
  3784 	    }
  3795             }
  3785 	}
  3796         }
  3786 #endif /* __LSBFIRST__ */
  3797 #endif /* __LSBFIRST__ */
  3787 
  3798 
  3788     doneSource: ;
  3799     doneSource: ;
  3789 	/*
  3800         /*
  3790 	 * now, at most one other byte is to be stored ...
  3801          * now, at most one other byte is to be stored ...
  3791 	 */
  3802          */
  3792 	if (__len < __rsltLen) {
  3803         if (__len < __rsltLen) {
  3793 	    __src[__ptrDelta] = __carry /* & 0xFF */;
  3804             __src[__ptrDelta] = __carry /* & 0xFF */;
  3794 	    __src++;
  3805             __src++;
  3795 	}
  3806         }
  3796 
  3807 
  3797 	if (__src[__ptrDelta-1]) {      /* lastDigit */
  3808         if (__src[__ptrDelta-1] != 0) {      /* lastDigit */
  3798 	    RETURN (result);
  3809             RETURN (result);
  3799 	}
  3810         }
  3800 	ok = true;
  3811         // must compress
       
  3812         ok = true;
  3801     }
  3813     }
  3802 %}.
  3814 %}.
  3803 
  3815 
  3804     ok ~~ true ifTrue:[
  3816     ok ~~ true ifTrue:[
  3805 	index := 1.
  3817         index := 1.
  3806 	carry := aSmallInteger abs.
  3818         carry := aSmallInteger abs.
  3807 
  3819 
  3808 	[carry ~~ 0] whileTrue:[
  3820         [carry ~~ 0] whileTrue:[
  3809 	    (index <= len) ifTrue:[
  3821             (index <= len) ifTrue:[
  3810 		carry := (digitByteArray basicAt:index) + carry.
  3822                 carry := (digitByteArray basicAt:index) + carry.
  3811 	    ].
  3823             ].
  3812 	    resultDigitByteArray basicAt:index put:(lastDigit := carry bitAnd:16rFF).
  3824             resultDigitByteArray basicAt:index put:(lastDigit := carry bitAnd:16rFF).
  3813 	    carry := carry bitShift:-8.
  3825             carry := carry bitShift:-8.
  3814 	    index := index + 1
  3826             index := index + 1
  3815 	].
  3827         ].
  3816 
  3828 
  3817 	(index <= rsltLen) ifTrue:[
  3829         (index <= rsltLen) ifTrue:[
  3818 	    [index <= len] whileTrue:[
  3830             [index <= len] whileTrue:[
  3819 		resultDigitByteArray basicAt:index put:(digitByteArray basicAt:index).
  3831                 resultDigitByteArray basicAt:index put:(digitByteArray basicAt:index).
  3820 		index := index + 1
  3832                 index := index + 1
  3821 	    ].
  3833             ].
  3822 	    lastDigit := 0.
  3834             lastDigit := 0.
  3823 	].
  3835         ].
  3824 
  3836 
  3825 	(lastDigit ~~ 0 and:[rsltLen > SmallInteger maxBytes]) ifTrue:[
  3837         (lastDigit ~~ 0 and:[rsltLen > SmallInteger maxBytes]) ifTrue:[
  3826 	    ^ result
  3838             ^ result
  3827 	].
  3839         ].
  3828     ].
  3840     ].
  3829 
  3841 
  3830     ^ result compressed
  3842     ^ result compressed
  3831 
  3843 
  3832     "Modified: 24.3.1997 / 21:32:41 / cg"
  3844     "Modified: 24.3.1997 / 21:32:41 / cg"