2358 anInteger == 0 ifTrue:[^ 0]. |
2376 anInteger == 0 ifTrue:[^ 0]. |
2359 anInteger == 1 ifTrue:[^ self]. |
2377 anInteger == 1 ifTrue:[^ self]. |
2360 |
2378 |
2361 num := anInteger abs. |
2379 num := anInteger abs. |
2362 (num > 16r3FFFFF) ifTrue:[ |
2380 (num > 16r3FFFFF) ifTrue:[ |
2363 "if num is too big (so that multiplying by a byte could create a Large)" |
2381 "if num is too big (so that multiplying by a byte could create a Large)" |
2364 |
2382 |
2365 ^ anInteger retry:#* coercing:self |
2383 ^ anInteger retry:#* coercing:self |
2366 ]. |
2384 ]. |
2367 |
2385 |
2368 len := digitByteArray size. |
2386 len := digitByteArray size. |
2369 |
2387 |
2370 val := num. |
2388 val := num. |
2371 val <= 16rFF ifTrue:[ |
2389 val <= 16rFF ifTrue:[ |
2372 lResult := len + 1. |
2390 lResult := len + 1. |
2373 ] ifFalse:[ |
2391 ] ifFalse:[ |
2374 val <= 16rFFFF ifTrue:[ |
2392 val <= 16rFFFF ifTrue:[ |
2375 lResult := len + 2 |
2393 lResult := len + 2 |
2376 ] ifFalse:[ |
2394 ] ifFalse:[ |
2377 val <= 16rFFFFFF ifTrue:[ |
2395 val <= 16rFFFFFF ifTrue:[ |
2378 lResult := len + 4. |
2396 lResult := len + 4. |
2379 ] ifFalse:[ |
2397 ] ifFalse:[ |
2380 lResult := len + 6. |
2398 lResult := len + 6. |
2381 ] |
2399 ] |
2382 ] |
2400 ] |
2383 ]. |
2401 ]. |
2384 resultDigitByteArray := ByteArray uninitializedNew:lResult. |
2402 resultDigitByteArray := ByteArray uninitializedNew:lResult. |
2385 result := self class basicNew setDigits:resultDigitByteArray. |
2403 result := self class basicNew setDigits:resultDigitByteArray. |
2386 |
2404 |
2387 anInteger < 0 ifTrue:[ |
2405 anInteger < 0 ifTrue:[ |
2388 sign > 0 ifTrue:[ |
2406 sign > 0 ifTrue:[ |
2389 result setSign:-1 |
2407 result setSign:-1 |
2390 ]. |
2408 ]. |
2391 ] ifFalse:[ |
2409 ] ifFalse:[ |
2392 sign < 0 ifTrue:[ |
2410 sign < 0 ifTrue:[ |
2393 result setSign:sign |
2411 result setSign:sign |
2394 ] |
2412 ] |
2395 ]. |
2413 ]. |
2396 |
2414 |
2397 ok := false. |
2415 ok := false. |
2398 %{ |
2416 %{ |
2399 OBJ __digitByteArray = __INST(digitByteArray); |
2417 OBJ __digitByteArray = __INST(digitByteArray); |
2400 |
2418 |
2401 if (__isSmallInteger(len) |
2419 if (__isSmallInteger(len) |
2402 && __isByteArray(__digitByteArray) |
2420 && __isByteArray(__digitByteArray) |
2403 && __isByteArray(resultDigitByteArray)) { |
2421 && __isByteArray(resultDigitByteArray)) { |
2404 INT _l = __intVal(len); |
2422 INT _l = __intVal(len); |
2405 INT _v = __intVal(val); |
2423 INT _v = __intVal(val); |
2406 unsigned INT _carry = 0; |
2424 unsigned INT _carry = 0; |
2407 unsigned INT _prod; |
2425 unsigned INT _prod; |
2408 unsigned char *digitP = __ByteArrayInstPtr(__digitByteArray)->ba_element; |
2426 unsigned char *digitP = __ByteArrayInstPtr(__digitByteArray)->ba_element; |
2409 unsigned char *resultP = __ByteArrayInstPtr(resultDigitByteArray)->ba_element; |
2427 unsigned char *resultP = __ByteArrayInstPtr(resultDigitByteArray)->ba_element; |
2410 |
2428 |
2411 /* |
2429 /* |
2412 * skipping zeros does not help much (a few percent) on |
2430 * skipping zeros does not help much (a few percent) on |
2413 * a P5 or other CPUS with a fast multiplier. |
2431 * a P5 or other CPUS with a fast multiplier. |
2414 * It may make more of a difference on CPUs with slower 0-multiply. |
2432 * It may make more of a difference on CPUs with slower 0-multiply. |
2415 */ |
2433 */ |
2416 while ((_l >= sizeof(INT)) && (((unsigned INT *)digitP)[0] == 0)) { |
2434 while ((_l >= sizeof(INT)) && (((unsigned INT *)digitP)[0] == 0)) { |
2417 ((unsigned INT *)resultP)[0] = 0; |
2435 ((unsigned INT *)resultP)[0] = 0; |
2418 digitP += sizeof(INT); |
2436 digitP += sizeof(INT); |
2419 resultP += sizeof(INT); |
2437 resultP += sizeof(INT); |
2420 _l -= sizeof(INT); |
2438 _l -= sizeof(INT); |
2421 } |
2439 } |
2422 |
2440 |
2423 #if defined(__LSBFIRST__) |
2441 #if defined(__LSBFIRST__) |
2424 # if defined (__GNUC__) && defined(__i386__) && (__POINTER_SIZE__ == 4) |
2442 # if defined (__GNUC__) && defined(__i386__) && (__POINTER_SIZE__ == 4) |
2425 /* |
2443 /* |
2426 * can do it long-word-wise; |
2444 * can do it long-word-wise; |
2427 * 32*32 -> 64 multiplication |
2445 * 32*32 -> 64 multiplication |
2428 */ |
2446 */ |
2429 while (_l > 3) { |
2447 while (_l > 3) { |
2430 unsigned __pHi, __pLow; |
2448 unsigned __pHi, __pLow; |
2431 unsigned __digit; |
2449 unsigned __digit; |
2432 |
2450 |
2433 /* |
2451 /* |
2434 * max: 0xFFFF.FFFF * 0xFFFF.FFFF -> 0xFFFF.FFFE.0000.0001 |
2452 * max: 0xFFFF.FFFF * 0xFFFF.FFFF -> 0xFFFF.FFFE.0000.0001 |
2435 * + maxCarry (0xFFFF.FFFF) -> 0xFFFF.FFFF.0000.0000 |
2453 * + maxCarry (0xFFFF.FFFF) -> 0xFFFF.FFFF.0000.0000 |
2436 */ |
2454 */ |
2437 __digit = ((unsigned long *)digitP)[0]; |
2455 __digit = ((unsigned long *)digitP)[0]; |
2438 asm ("mull %3 \n\ |
2456 asm ("mull %3 \n\ |
2439 addl %4,%%eax \n\ |
2457 addl %4,%%eax \n\ |
2440 adcl $0,%%edx" |
2458 adcl $0,%%edx" |
2441 : "=a" (__pLow), |
2459 : "=a" (__pLow), |
2442 "=d" (__pHi) |
2460 "=d" (__pHi) |
2443 : "0" (__digit), |
2461 : "0" (__digit), |
2444 "1" ((unsigned long)(_v)), |
2462 "1" ((unsigned long)(_v)), |
2445 "rm" ((unsigned long)(_carry)) ); |
2463 "rm" ((unsigned long)(_carry)) ); |
2446 |
2464 |
2447 ((unsigned long *)resultP)[0] = __pLow; |
2465 ((unsigned long *)resultP)[0] = __pLow; |
2448 _carry = __pHi; |
2466 _carry = __pHi; |
2449 digitP += 4; |
2467 digitP += 4; |
2450 resultP += 4; |
2468 resultP += 4; |
2451 _l -= 4; |
2469 _l -= 4; |
2452 } |
2470 } |
2453 # else /* not GNU-i386 */ |
2471 # else /* not GNU-i386 */ |
2454 # if defined(WIN32) && defined(__BORLANDC__) && defined(__i386__) && (__POINTER_SIZE__ == 4) |
2472 # if defined(WIN32) && defined(__BORLANDC__) && defined(__i386__) && (__POINTER_SIZE__ == 4) |
2455 /* |
2473 /* |
2456 * can do it long-word-wise; |
2474 * can do it long-word-wise; |
2457 * 32*32 -> 64 multiplication |
2475 * 32*32 -> 64 multiplication |
2458 */ |
2476 */ |
2459 while (_l > 3) { |
2477 while (_l > 3) { |
2460 unsigned __pLow; |
2478 unsigned __pLow; |
2461 unsigned digit; |
2479 unsigned digit; |
2462 |
2480 |
2463 /* |
2481 /* |
2464 * max: 0xFFFF.FFFF * 0xFFFF.FFFF -> 0xFFFF.FFFE.0000.0001 |
2482 * max: 0xFFFF.FFFF * 0xFFFF.FFFF -> 0xFFFF.FFFE.0000.0001 |
2465 * + maxCarry (0xFFFF.FFFF) -> 0xFFFF.FFFF.0000.0000 |
2483 * + maxCarry (0xFFFF.FFFF) -> 0xFFFF.FFFF.0000.0000 |
2466 */ |
2484 */ |
2467 /* |
2485 /* |
2468 digit = ((unsigned long *)digitP)[0]; |
2486 digit = ((unsigned long *)digitP)[0]; |
2469 edx::eax = (digit * _v); |
2487 edx::eax = (digit * _v); |
2470 edx::eax += _carry; |
2488 edx::eax += _carry; |
2471 ((unsigned long *)resultP)[0] = eax; -- pLow |
2489 ((unsigned long *)resultP)[0] = eax; -- pLow |
2472 _carry = edx; -- pHigh |
2490 _carry = edx; -- pHigh |
2473 digitP += 4; |
2491 digitP += 4; |
2474 resultP += 4; |
2492 resultP += 4; |
2475 */ |
2493 */ |
2476 digit = ((unsigned long *)digitP)[0]; |
2494 digit = ((unsigned long *)digitP)[0]; |
2477 asm { |
2495 asm { |
2478 mov eax, digit |
2496 mov eax, digit |
2479 mov edx, _v |
2497 mov edx, _v |
2480 mul edx |
2498 mul edx |
2481 add eax, _carry |
2499 add eax, _carry |
2482 adc edx, 0 |
2500 adc edx, 0 |
2483 mov __pLow, eax |
2501 mov __pLow, eax |
2484 mov _carry, edx |
2502 mov _carry, edx |
2485 } |
2503 } |
2486 |
2504 |
2487 ((unsigned long *)resultP)[0] = __pLow; |
2505 ((unsigned long *)resultP)[0] = __pLow; |
2488 digitP += 4; |
2506 digitP += 4; |
2489 resultP += 4; |
2507 resultP += 4; |
2490 _l -= 4; |
2508 _l -= 4; |
2491 } |
2509 } |
2492 # else /* not WIN32-i386 */ |
2510 # else /* not WIN32-i386 */ |
2493 # if defined(INT64) |
2511 # if defined(INT64) |
2494 if (_v <= 0xFFFFFFFFL) { |
2512 if (_v <= 0xFFFFFFFFL) { |
2495 /* |
2513 /* |
2496 * have a 64bit int type ... good |
2514 * have a 64bit int type ... good |
2497 */ |
2515 */ |
2498 UINT64 _prod64; |
2516 UINT64 _prod64; |
2499 |
2517 |
2500 /* have 64bit ints; can do it int-wise |
2518 /* have 64bit ints; can do it int-wise |
2501 * |
2519 * |
2502 * max: 0xFFFFFFFF * 0xFFFFFFFF -> 0xFFFFFFFE.0001 |
2520 * max: 0xFFFFFFFF * 0xFFFFFFFF -> 0xFFFFFFFE.0001 |
2503 * + maxCarry (0xFFFFFFFF) -> 0xFFFFFFFF.0000 |
2521 * + maxCarry (0xFFFFFFFF) -> 0xFFFFFFFF.0000 |
2504 */ |
2522 */ |
2505 while (_l > 3) { |
2523 while (_l > 3) { |
2506 unsigned __t; |
2524 unsigned __t; |
2507 |
2525 |
2508 __t = ((unsigned *)digitP)[0]; |
2526 __t = ((unsigned *)digitP)[0]; |
2509 digitP += 4; |
2527 digitP += 4; |
2510 _prod64 = (INT64)_v; |
2528 _prod64 = (INT64)_v; |
2511 _prod64 *= __t; |
2529 _prod64 *= __t; |
2512 _prod64 += _carry; |
2530 _prod64 += _carry; |
2513 ((unsigned *)resultP)[0] = _prod64 /* & 0xFFFFFFFFL */; |
2531 ((unsigned *)resultP)[0] = _prod64 /* & 0xFFFFFFFFL */; |
2514 _carry = _prod64 >> 32; |
2532 _carry = _prod64 >> 32; |
2515 resultP += 4; |
2533 resultP += 4; |
2516 _l -= 4; |
2534 _l -= 4; |
2517 } |
2535 } |
2518 if (_l > 1) { |
2536 if (_l > 1) { |
2519 unsigned short __t; |
2537 unsigned short __t; |
2520 |
2538 |
2521 __t = ((unsigned short *)digitP)[0]; |
2539 __t = ((unsigned short *)digitP)[0]; |
2522 digitP += 2; |
2540 digitP += 2; |
2523 _prod64 = (INT64)_v; |
2541 _prod64 = (INT64)_v; |
2524 _prod64 *= __t; |
2542 _prod64 *= __t; |
2525 _prod64 += _carry; |
2543 _prod64 += _carry; |
2526 ((unsigned short *)resultP)[0] = _prod64 /* & 0xFFFF */; |
2544 ((unsigned short *)resultP)[0] = _prod64 /* & 0xFFFF */; |
2527 _carry = _prod64 >> 16; |
2545 _carry = _prod64 >> 16; |
2528 resultP += 2; |
2546 resultP += 2; |
2529 _l -= 2; |
2547 _l -= 2; |
2530 } |
2548 } |
2531 if (_l > 0) { |
2549 if (_l > 0) { |
2532 _prod64 = *digitP++ * _v + _carry; |
2550 _prod64 = *digitP++ * _v + _carry; |
2533 *resultP++ = _prod64 /* & 0xFF */; |
2551 *resultP++ = _prod64 /* & 0xFF */; |
2534 _carry = _prod64 >> 8; |
2552 _carry = _prod64 >> 8; |
2535 _l--; |
2553 _l--; |
2536 } |
2554 } |
2537 } |
2555 } |
2538 # else /* no INT64 type */ |
2556 # else /* no INT64 type */ |
2539 if (_v <= 0xFFFF) { |
2557 if (_v <= 0xFFFF) { |
2540 /* can do it short-wise |
2558 /* can do it short-wise |
2541 * |
2559 * |
2542 * max: 0xFFFF * 0xFFFF -> 0xFFFE.0001 |
2560 * max: 0xFFFF * 0xFFFF -> 0xFFFE.0001 |
2543 * + maxCarry (0xFFFF) -> 0xFFFF.0000 |
2561 * + maxCarry (0xFFFF) -> 0xFFFF.0000 |
2544 */ |
2562 */ |
2545 while (_l > 1) { |
2563 while (_l > 1) { |
2546 _prod = ((unsigned short *)digitP)[0] * _v + _carry; |
2564 _prod = ((unsigned short *)digitP)[0] * _v + _carry; |
2547 ((unsigned short *)resultP)[0] = _prod /* & 0xFFFF */; |
2565 ((unsigned short *)resultP)[0] = _prod /* & 0xFFFF */; |
2548 _carry = _prod >> 16; |
2566 _carry = _prod >> 16; |
2549 digitP += 2; |
2567 digitP += 2; |
2550 resultP += 2; |
2568 resultP += 2; |
2551 _l -= 2; |
2569 _l -= 2; |
2552 } |
2570 } |
2553 } |
2571 } |
2554 # endif /* no INT64 */ |
2572 # endif /* no INT64 */ |
2555 # endif /* not WIN32-i386 */ |
2573 # endif /* not WIN32-i386 */ |
2556 # endif /* not GNU-i386 */ |
2574 # endif /* not GNU-i386 */ |
2557 #else /* not LSB_FIRST */ |
2575 #else /* not LSB_FIRST */ |
2558 |
2576 |
2559 # ifdef __mips__ |
2577 # ifdef __mips__ |
2560 # define LOAD_WORD_WISE |
2578 # define LOAD_WORD_WISE |
2561 /* no, STORE_WORD_WISE makes it slower */ |
2579 /* no, STORE_WORD_WISE makes it slower */ |
2562 # endif |
2580 # endif |
2563 |
2581 |
2564 if (_v <= 0xFFFF) { |
2582 if (_v <= 0xFFFF) { |
2565 /* can do it short-wise |
2583 /* can do it short-wise |
2566 * |
2584 * |
2567 * max: 0xFFFF * 0xFFFF -> 0xFFFE.0001 |
2585 * max: 0xFFFF * 0xFFFF -> 0xFFFE.0001 |
2568 * + maxCarry (0xFFFF) -> 0xFFFF.0000 |
2586 * + maxCarry (0xFFFF) -> 0xFFFF.0000 |
2569 */ |
2587 */ |
2570 while (_l > 1) { |
2588 while (_l > 1) { |
2571 unsigned int t; |
2589 unsigned int t; |
2572 |
2590 |
2573 #if defined(LOAD_WORD_WISE) |
2591 #if defined(LOAD_WORD_WISE) |
2574 /* better fetch short-wise */ |
2592 /* better fetch short-wise */ |
2575 t = ((unsigned short *)digitP)[0]; |
2593 t = ((unsigned short *)digitP)[0]; |
2576 digitP += 2; |
2594 digitP += 2; |
2577 t = ((t >> 8) | (t << 8)) & 0xFFFF; |
2595 t = ((t >> 8) | (t << 8)) & 0xFFFF; |
2578 #else |
2596 #else |
2579 t = (digitP[1]<<8) + digitP[0]; |
2597 t = (digitP[1]<<8) + digitP[0]; |
2580 digitP += 2; |
2598 digitP += 2; |
2581 #endif |
2599 #endif |
2582 _prod = t * _v + _carry; |
2600 _prod = t * _v + _carry; |
2583 _carry = _prod >> 16; |
2601 _carry = _prod >> 16; |
2584 #if defined(STORE_WORD_WISE) |
2602 #if defined(STORE_WORD_WISE) |
2585 /* better store short-wise */ |
2603 /* better store short-wise */ |
2586 _prod = ((_prod >> 8) | (_prod << 8)) & 0xFFFF; |
2604 _prod = ((_prod >> 8) | (_prod << 8)) & 0xFFFF; |
2587 ((unsigned short *)resultP)[0] = _prod; |
2605 ((unsigned short *)resultP)[0] = _prod; |
2588 #else |
2606 #else |
2589 resultP[0] = _prod /* & 0xFF */; |
2607 resultP[0] = _prod /* & 0xFF */; |
2590 resultP[1] = (_prod>>8) /* & 0xFF */; |
2608 resultP[1] = (_prod>>8) /* & 0xFF */; |
2591 #endif |
2609 #endif |
2592 resultP += 2; |
2610 resultP += 2; |
2593 _l -= 2; |
2611 _l -= 2; |
2594 } |
2612 } |
2595 } |
2613 } |
2596 |
2614 |
2597 #endif /* LSB_FIRST */ |
2615 #endif /* LSB_FIRST */ |
2598 |
2616 |
2599 /* |
2617 /* |
2600 * rest is done byte-wise |
2618 * rest is done byte-wise |
2601 */ |
2619 */ |
2602 while (_l > 0) { |
2620 while (_l > 0) { |
2603 _prod = *digitP++ * _v + _carry; |
2621 _prod = *digitP++ * _v + _carry; |
2604 *resultP++ = _prod /* & 0xFF */; |
2622 *resultP++ = _prod /* & 0xFF */; |
2605 _carry = _prod >> 8; |
2623 _carry = _prod >> 8; |
2606 _l--; |
2624 _l--; |
2607 } |
2625 } |
2608 |
2626 |
2609 _l = __intVal(lResult) - __intVal(len); |
2627 _l = __intVal(lResult) - __intVal(len); |
2610 |
2628 |
2611 /* |
2629 /* |
2612 * remaining carry |
2630 * remaining carry |
2613 */ |
2631 */ |
2614 while (_carry) { |
2632 while (_carry) { |
2615 *resultP++ = _carry /* & 0xFF */; |
2633 *resultP++ = _carry /* & 0xFF */; |
2616 _carry >>= 8; |
2634 _carry >>= 8; |
2617 _l--; |
2635 _l--; |
2618 } |
2636 } |
2619 |
2637 |
2620 /* |
2638 /* |
2621 * remaining zeros |
2639 * remaining zeros |
2622 */ |
2640 */ |
2623 while (_l--) { |
2641 while (_l--) { |
2624 *resultP++ = 0; |
2642 *resultP++ = 0; |
2625 } |
2643 } |
2626 |
2644 |
2627 /* |
2645 /* |
2628 * need compress ? |
2646 * need compress ? |
2629 */ |
2647 */ |
2630 if (resultP[-1]) { |
2648 if (resultP[-1]) { |
2631 /* |
2649 /* |
2632 * no |
2650 * no |
2633 */ |
2651 */ |
2634 RETURN(result); |
2652 RETURN(result); |
2635 } |
2653 } |
2636 |
2654 |
2637 ok = true; |
2655 ok = true; |
2638 } |
2656 } |
2639 %}. |
2657 %}. |
2640 " |
2658 " |
2641 fall back - normally not reached |
2659 fall back - normally not reached |
2642 (could make it a primitive-failure as well) |
2660 (could make it a primitive-failure as well) |
2643 " |
2661 " |
2644 ok ifFalse:[ |
2662 ok ifFalse:[ |
2645 carry := 0. |
2663 carry := 0. |
2646 1 to:len do:[:i | |
2664 1 to:len do:[:i | |
2647 prod := (digitByteArray basicAt:i) * val + carry. |
2665 prod := (digitByteArray basicAt:i) * val + carry. |
2648 resultDigitByteArray basicAt:i put:(prod bitAnd:16rFF). |
2666 resultDigitByteArray basicAt:i put:(prod bitAnd:16rFF). |
2649 carry := prod bitShift:-8. |
2667 carry := prod bitShift:-8. |
2650 ]. |
2668 ]. |
2651 [carry ~~ 0] whileTrue:[ |
2669 [carry ~~ 0] whileTrue:[ |
2652 len := len + 1. |
2670 len := len + 1. |
2653 resultDigitByteArray basicAt:len put:(carry bitAnd:16rFF). |
2671 resultDigitByteArray basicAt:len put:(carry bitAnd:16rFF). |
2654 carry := carry bitShift:-8 |
2672 carry := carry bitShift:-8 |
2655 ]. |
2673 ]. |
2656 [len < lResult] whileTrue:[ |
2674 [len < lResult] whileTrue:[ |
2657 len := len + 1. |
2675 len := len + 1. |
2658 resultDigitByteArray basicAt:len put:0 |
2676 resultDigitByteArray basicAt:len put:0 |
2659 ] |
2677 ] |
2660 ]. |
2678 ]. |
2661 ^ result compressed |
2679 ^ result compressed |
2662 ! |
2680 ! |
2663 |
2681 |
2664 sumFromInteger:anInteger |
2682 sumFromInteger:anInteger |
3073 borrow := aSmallInteger abs. |
3091 borrow := aSmallInteger abs. |
3074 |
3092 |
3075 %{ |
3093 %{ |
3076 if (__isByteArray(__INST(digitByteArray)) |
3094 if (__isByteArray(__INST(digitByteArray)) |
3077 && __isByteArray(resultDigitByteArray)) { |
3095 && __isByteArray(resultDigitByteArray)) { |
3078 unsigned INT __borrow = __intVal(borrow); |
3096 unsigned INT __borrow = __intVal(borrow); |
3079 INT __diff; |
3097 INT __diff; |
3080 int __index = 1; |
3098 int __index = 1; |
3081 int __len = __intVal(len); |
3099 int __len = __intVal(len); |
3082 unsigned char *__digitP = __ByteArrayInstPtr(__INST(digitByteArray))->ba_element; |
3100 unsigned char *__digitP = __ByteArrayInstPtr(__INST(digitByteArray))->ba_element; |
3083 unsigned char *__resultP = __ByteArrayInstPtr(resultDigitByteArray)->ba_element; |
3101 unsigned char *__resultP = __ByteArrayInstPtr(resultDigitByteArray)->ba_element; |
3084 int __len3; |
3102 int __len3; |
3085 |
3103 |
3086 #if defined(__LSBFIRST__) |
3104 #if defined(__LSBFIRST__) |
3087 # if (__POINTER_SIZE__ == 8) |
3105 # if (__POINTER_SIZE__ == 8) |
3088 /* |
3106 /* |
3089 * subtract int-wise |
3107 * subtract int-wise |
3090 */ |
3108 */ |
3091 __len3 = __len - 3; |
3109 __len3 = __len - 3; |
3092 while (__index < __len3) { |
3110 while (__index < __len3) { |
3093 /* do not make this into one expression - ask cg why */ |
3111 /* do not make this into one expression - ask cg why */ |
3094 __diff = ((unsigned int *)(__digitP + __index-1))[0]; |
3112 __diff = ((unsigned int *)(__digitP + __index-1))[0]; |
3095 __diff -= (__borrow & 0xFFFFFFFFL); |
3113 __diff -= (__borrow & 0xFFFFFFFFL); |
3096 __borrow >>= 32; |
3114 __borrow >>= 32; |
3097 if (__diff < 0) { |
3115 if (__diff < 0) { |
3098 /* __diff += 0x100000000; */ |
3116 /* __diff += 0x100000000; */ |
3099 __borrow++; |
3117 __borrow++; |
3100 } |
3118 } |
3101 ((unsigned int *)(__resultP+__index-1))[0] = __diff; |
3119 ((unsigned int *)(__resultP+__index-1))[0] = __diff; |
3102 __index += 4; |
3120 __index += 4; |
3103 } |
3121 } |
3104 # endif |
3122 # endif |
3105 /* |
3123 /* |
3106 * subtract short-wise |
3124 * subtract short-wise |
3107 */ |
3125 */ |
3108 while (__index < __len) { |
3126 while (__index < __len) { |
3109 /* do not make this into one expression - ask cg why */ |
3127 /* do not make this into one expression - ask cg why */ |
3110 __diff = ((unsigned short *)(__digitP+__index-1))[0]; |
3128 __diff = ((unsigned short *)(__digitP+__index-1))[0]; |
3111 __diff -= (__borrow & 0xFFFF); |
3129 __diff -= (__borrow & 0xFFFF); |
3112 __borrow >>= 16; |
3130 __borrow >>= 16; |
3113 if (__diff < 0) { |
3131 if (__diff < 0) { |
3114 /* __diff += 0x10000; */ |
3132 /* __diff += 0x10000; */ |
3115 __borrow++; |
3133 __borrow++; |
3116 } else { |
3134 } else { |
3117 if (__borrow == 0) { |
3135 if (__borrow == 0) { |
3118 ((unsigned short *)(__resultP+__index-1))[0] = __diff; |
3136 ((unsigned short *)(__resultP+__index-1))[0] = __diff; |
3119 __index += 2; |
3137 __index += 2; |
3120 |
3138 |
3121 /* nothing more to subtract .. */ |
3139 /* nothing more to subtract .. */ |
3122 while (__index < __len) { |
3140 while (__index < __len) { |
3123 ((unsigned short *)(__resultP+__index-1))[0] = ((unsigned short *)(__digitP+__index-1))[0]; |
3141 ((unsigned short *)(__resultP+__index-1))[0] = ((unsigned short *)(__digitP+__index-1))[0]; |
3124 __index += 2; |
3142 __index += 2; |
3125 } |
3143 } |
3126 if (__index <= __len) { |
3144 if (__index <= __len) { |
3127 __resultP[__index-1] = __digitP[__index-1]; |
3145 __resultP[__index-1] = __digitP[__index-1]; |
3128 } |
3146 } |
3129 break; |
3147 break; |
3130 } |
3148 } |
3131 } |
3149 } |
3132 ((unsigned short *)(__resultP+__index-1))[0] = __diff; |
3150 ((unsigned short *)(__resultP+__index-1))[0] = __diff; |
3133 __index += 2; |
3151 __index += 2; |
3134 } |
3152 } |
3135 #endif |
3153 #endif |
3136 /* |
3154 /* |
3137 * subtract byte-wise |
3155 * subtract byte-wise |
3138 */ |
3156 */ |
3139 while (__index <= __len) { |
3157 while (__index <= __len) { |
3140 __diff = __digitP[__index-1]; |
3158 __diff = __digitP[__index-1]; |
3141 __diff -= (__borrow & 0xFF); |
3159 __diff -= (__borrow & 0xFF); |
3142 __borrow >>= 8; |
3160 __borrow >>= 8; |
3143 if (__diff < 0) { |
3161 if (__diff < 0) { |
3144 /* __diff += 0x100; */ |
3162 /* __diff += 0x100; */ |
3145 __borrow++; |
3163 __borrow++; |
3146 } else { |
3164 } else { |
3147 if (__borrow == 0) { |
3165 if (__borrow == 0) { |
3148 __resultP[__index-1] = __diff; |
3166 __resultP[__index-1] = __diff; |
3149 __index++; |
3167 __index++; |
3150 |
3168 |
3151 /* nothing more to subtract .. */ |
3169 /* nothing more to subtract .. */ |
3152 while (__index <= __len) { |
3170 while (__index <= __len) { |
3153 __resultP[__index-1] = __digitP[__index-1]; |
3171 __resultP[__index-1] = __digitP[__index-1]; |
3154 __index++; |
3172 __index++; |
3155 } |
3173 } |
3156 break; |
3174 break; |
3157 } |
3175 } |
3158 } |
3176 } |
3159 __resultP[__index-1] = __diff; |
3177 __resultP[__index-1] = __diff; |
3160 __index++; |
3178 __index++; |
3161 } |
3179 } |
3162 lastDigit = __mkSmallInteger( __resultP[__index-1-1] ); |
3180 lastDigit = __mkSmallInteger( __resultP[__index-1-1] ); |
3163 ok = true; |
3181 ok = true; |
3164 } |
3182 } |
3165 %}. |
3183 %}. |
3166 |
3184 |
3167 ok == true ifFalse:[ "/ cannot happen |
3185 ok == true ifFalse:[ "/ cannot happen |
3168 index := 1. |
3186 index := 1. |
3169 [borrow ~~ 0] whileTrue:[ |
3187 [borrow ~~ 0] whileTrue:[ |
3170 (index <= len) ifTrue:[ |
3188 (index <= len) ifTrue:[ |
3171 diff := (digitByteArray basicAt:index) - (borrow bitAnd:16rFF). |
3189 diff := (digitByteArray basicAt:index) - (borrow bitAnd:16rFF). |
3172 borrow := borrow bitShift:-8. |
3190 borrow := borrow bitShift:-8. |
3173 diff < 0 ifTrue:[ |
3191 diff < 0 ifTrue:[ |
3174 diff := diff + 256. |
3192 diff := diff + 256. |
3175 borrow := borrow + 1. |
3193 borrow := borrow + 1. |
3176 ] |
3194 ] |
3177 ] ifFalse:[ |
3195 ] ifFalse:[ |
3178 diff := borrow bitAnd:255. |
3196 diff := borrow bitAnd:255. |
3179 borrow := borrow bitShift:-8. |
3197 borrow := borrow bitShift:-8. |
3180 ]. |
3198 ]. |
3181 resultDigitByteArray basicAt:index put:(lastDigit := diff). |
3199 resultDigitByteArray basicAt:index put:(lastDigit := diff). |
3182 index := index + 1 |
3200 index := index + 1 |
3183 ]. |
3201 ]. |
3184 [index <= len] whileTrue:[ |
3202 [index <= len] whileTrue:[ |
3185 resultDigitByteArray basicAt:index put:(lastDigit := digitByteArray basicAt:index). |
3203 resultDigitByteArray basicAt:index put:(lastDigit := digitByteArray basicAt:index). |
3186 index := index + 1 |
3204 index := index + 1 |
3187 ]. |
3205 ]. |
3188 (index <= rsltLen) ifTrue:[ |
3206 (index <= rsltLen) ifTrue:[ |
3189 lastDigit := 0. |
3207 lastDigit := 0. |
3190 ] |
3208 ] |
3191 ]. |
3209 ]. |
3192 |
3210 |
3193 (lastDigit == 0 or:[rsltLen <= SmallInteger maxBytes]) ifTrue:[ |
3211 (lastDigit == 0 or:[rsltLen <= SmallInteger maxBytes]) ifTrue:[ |
3194 ^ result compressed. |
3212 ^ result compressed. |
3195 ]. |
3213 ]. |
3196 ^ result |
3214 ^ result |
3197 |
3215 |
3198 " |
3216 " |
3199 12345678900000000000 absFastMinus:1 sign:1 |
3217 12345678900000000000 absFastMinus:1 sign:1 |
3256 |
3274 |
3257 %{ |
3275 %{ |
3258 if (__isByteArray(__INST(digitByteArray)) |
3276 if (__isByteArray(__INST(digitByteArray)) |
3259 && __isByteArray(resultDigitByteArray) |
3277 && __isByteArray(resultDigitByteArray) |
3260 && __isSmallInteger(aSmallInteger)) { |
3278 && __isSmallInteger(aSmallInteger)) { |
3261 /* carry is NOT unsigned (see negation below) */ |
3279 /* carry is NOT unsigned (see negation below) */ |
3262 INT __carry = __intVal(aSmallInteger); |
3280 INT __carry = __intVal(aSmallInteger); |
3263 int __index = 1; |
3281 int __index = 1; |
3264 int __len = __intVal(len); |
3282 int __len = __intVal(len); |
3265 unsigned char *__src = (unsigned char *)(__ByteArrayInstPtr(__INST(digitByteArray))->ba_element); |
3283 unsigned char *__src = (unsigned char *)(__ByteArrayInstPtr(__INST(digitByteArray))->ba_element); |
3266 unsigned char *__dst = (unsigned char *)(__ByteArrayInstPtr(resultDigitByteArray)->ba_element); |
3284 unsigned char *__dst = (unsigned char *)(__ByteArrayInstPtr(resultDigitByteArray)->ba_element); |
3267 INT __ptrDelta = __dst - __src; |
3285 INT __ptrDelta = __dst - __src; |
3268 unsigned char *__srcLast = __src + __len - 1; |
3286 unsigned char *__srcLast = __src + __len - 1; |
3269 int __rsltLen = __intVal(rsltLen); |
3287 int __rsltLen = __intVal(rsltLen); |
3270 |
3288 |
3271 if (__carry < 0) { |
3289 if (__carry < 0) { |
3272 __carry = -__carry; |
3290 __carry = -__carry; |
3273 } |
3291 } |
3274 |
3292 |
3275 #if defined(__LSBFIRST__) |
3293 #if defined(__LSBFIRST__) |
3276 # if defined(__i386__) && defined(__GNUC__) && (__POINTER_SIZE__ == 4) |
3294 # if defined(__i386__) && defined(__GNUC__) && (__POINTER_SIZE__ == 4) |
3277 # if 0 /* NOTICE - the code below is 20% slower ... - why */ |
3295 # if 0 /* NOTICE - the code below is 20% slower ... - why */ |
3278 /* |
3296 /* |
3279 * add long-wise |
3297 * add long-wise |
3280 */ |
3298 */ |
3281 asm(" jecxz nothingToDo \n\ |
3299 asm(" jecxz nothingToDo \n\ |
3282 movl %%eax, %%esi /* __src input */ \n\ |
3300 movl %%eax, %%esi /* __src input */ \n\ |
3283 movl %%ebx, %%edi /* __dst input */ \n\ |
3301 movl %%ebx, %%edi /* __dst input */ \n\ |
3284 \n\ |
3302 \n\ |
3285 /* the first 4-byte int */ \n\ |
3303 /* the first 4-byte int */ \n\ |
3286 lodsl /* fetch */ \n\ |
3304 lodsl /* fetch */ \n\ |
3287 addl %%edx, %%eax /* add */ \n\ |
3305 addl %%edx, %%eax /* add */ \n\ |
3288 stosl /* store */ \n\ |
3306 stosl /* store */ \n\ |
3289 leal -1(%%ecx),%%ecx /* do not clobber carry */ \n\ |
3307 leal -1(%%ecx),%%ecx /* do not clobber carry */ \n\ |
3290 jecxz doneLoop /* any more ? */ \n\ |
3308 jecxz doneLoop /* any more ? */ \n\ |
3291 /* remaining 4-byte ints */ \n\ |
3309 /* remaining 4-byte ints */ \n\ |
3292 jmp addLoop \n\ |
3310 jmp addLoop \n\ |
3293 \n\ |
3311 \n\ |
3294 .align 8 \n\ |
3312 .align 8 \n\ |
3295 addLoop: \n\ |
3313 addLoop: \n\ |
3296 movl 0(%%esi), %%ebx /* fetch */ \n\ |
3314 movl 0(%%esi), %%ebx /* fetch */ \n\ |
3297 jnc copyLoop2 \n\ |
3315 jnc copyLoop2 \n\ |
3298 movl $0, %%eax \n\ |
3316 movl $0, %%eax \n\ |
3299 leal 4(%%esi), %%esi \n\ |
3317 leal 4(%%esi), %%esi \n\ |
3300 adcl %%ebx, %%eax /* & add carry from prev int */\n\ |
3318 adcl %%ebx, %%eax /* & add carry from prev int */\n\ |
3301 leal 8(%%edi), %%edi \n\ |
3319 leal 8(%%edi), %%edi \n\ |
3302 movl %%eax, -8(%%edi) /* store */ \n\ |
3320 movl %%eax, -8(%%edi) /* store */ \n\ |
3303 leal -1(%%ecx),%%ecx /* do not clobber carry */ \n\ |
3321 leal -1(%%ecx),%%ecx /* do not clobber carry */ \n\ |
3304 jecxz doneLoop /* any more ? */ \n\ |
3322 jecxz doneLoop /* any more ? */ \n\ |
3305 \n\ |
3323 \n\ |
3306 movl 0(%%esi), %%ebx /* fetch */ \n\ |
3324 movl 0(%%esi), %%ebx /* fetch */ \n\ |
3307 movl $0, %%eax \n\ |
3325 movl $0, %%eax \n\ |
3308 leal 4(%%esi), %%esi \ |
3326 leal 4(%%esi), %%esi \ |
3309 adcl %%ebx, %%eax /* & add carry from prev int */\n\ |
3327 adcl %%ebx, %%eax /* & add carry from prev int */\n\ |
3310 movl %%eax, -4(%%edi) /* store */ \n\ |
3328 movl %%eax, -4(%%edi) /* store */ \n\ |
3311 \n\ |
3329 \n\ |
3312 loop addLoop \n\ |
3330 loop addLoop \n\ |
3313 jmp doneLoop \n\ |
3331 jmp doneLoop \n\ |
3314 \n\ |
3332 \n\ |
3315 .align 8 \n\ |
3333 .align 8 \n\ |
3316 copyLoop: \n\ |
3334 copyLoop: \n\ |
3317 movl 0(%%esi), %%ebx \n\ |
3335 movl 0(%%esi), %%ebx \n\ |
3318 copyLoop2: \n\ |
3336 copyLoop2: \n\ |
3319 add $4, %%esi \n\ |
3337 add $4, %%esi \n\ |
3320 add $4, %%edi \n\ |
3338 add $4, %%edi \n\ |
3321 movl %%ebx, -4(%%edi) \n\ |
3339 movl %%ebx, -4(%%edi) \n\ |
3322 loop copyLoop \n\ |
3340 loop copyLoop \n\ |
3323 \n\ |
3341 \n\ |
3324 doneLoop: \n\ |
3342 doneLoop: \n\ |
3325 movl $0, %%edx /* do not clobber carry (xorl clears it) */ \n\ |
3343 movl $0, %%edx /* do not clobber carry (xorl clears it) */ \n\ |
3326 adcl $0, %%edx \n\ |
3344 adcl $0, %%edx \n\ |
3327 movl %%esi, %%eax /* __src output */ \n\ |
3345 movl %%esi, %%eax /* __src output */ \n\ |
3328 nothingToDo: \n\ |
3346 nothingToDo: \n\ |
3329 " : "=d" ((unsigned long)(__carry)), |
3347 " : "=d" ((unsigned long)(__carry)), |
3330 "=a" (__src) |
3348 "=a" (__src) |
3331 : "1" (__src), |
3349 : "1" (__src), |
3332 "b" (__dst), |
3350 "b" (__dst), |
3333 "c" (__len / 4), |
3351 "c" (__len / 4), |
3334 "0" (__carry) |
3352 "0" (__carry) |
3335 : "esi", "edi"); |
3353 : "esi", "edi"); |
3336 |
3354 |
3337 # else |
3355 # else |
3338 { |
3356 { |
3339 unsigned char *__srcLastX; |
3357 unsigned char *__srcLastX; |
3340 |
3358 |
3341 __srcLastX = __srcLast - 3 - 4; |
3359 __srcLastX = __srcLast - 3 - 4; |
3342 while (__src <= __srcLastX) { |
3360 while (__src <= __srcLastX) { |
3343 unsigned int __sum, __sum2; |
3361 unsigned int __sum, __sum2; |
3344 unsigned __digit1, __digit2; |
3362 unsigned __digit1, __digit2; |
3345 |
3363 |
3346 __digit1 = ((unsigned *)__src)[0]; |
3364 __digit1 = ((unsigned *)__src)[0]; |
3347 __digit2 = ((unsigned *)__src)[1]; |
3365 __digit2 = ((unsigned *)__src)[1]; |
3348 asm ("addl %%edx,%%ecx \n\ |
3366 asm ("addl %%edx,%%ecx \n\ |
3349 adcl $0, %%eax \n\ |
3367 adcl $0, %%eax \n\ |
3350 movl $0, %%edx \n\ |
3368 movl $0, %%edx \n\ |
3351 adcl $0, %%edx" |
3369 adcl $0, %%edx" |
3352 : "=d" ((unsigned long)(__carry)), |
3370 : "=d" ((unsigned long)(__carry)), |
3353 "=c" ((unsigned long)(__sum)), |
3371 "=c" ((unsigned long)(__sum)), |
3354 "=a" ((unsigned long)(__sum2)) |
3372 "=a" ((unsigned long)(__sum2)) |
3355 : "0" ((unsigned long)(__carry)), |
3373 : "0" ((unsigned long)(__carry)), |
3356 "1" (__digit1), |
3374 "1" (__digit1), |
3357 "2" (__digit2)); |
3375 "2" (__digit2)); |
3358 |
3376 |
3359 ((unsigned int *)(__src + __ptrDelta))[0] = __sum; |
3377 ((unsigned int *)(__src + __ptrDelta))[0] = __sum; |
3360 ((unsigned int *)(__src + __ptrDelta))[1] = __sum2; |
3378 ((unsigned int *)(__src + __ptrDelta))[1] = __sum2; |
3361 |
3379 |
3362 __src += 8; |
3380 __src += 8; |
3363 |
3381 |
3364 if (__carry == 0) { |
3382 if (__carry == 0) { |
3365 while (__src <= __srcLastX) { |
3383 while (__src <= __srcLastX) { |
3366 /* copy over words */ |
3384 /* copy over words */ |
3367 ((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0]; |
3385 ((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0]; |
3368 ((unsigned int *)(__src + __ptrDelta))[1] = ((unsigned int *)__src)[1]; |
3386 ((unsigned int *)(__src + __ptrDelta))[1] = ((unsigned int *)__src)[1]; |
3369 __src += 8; |
3387 __src += 8; |
3370 } |
3388 } |
3371 while (__src <= __srcLast) { |
3389 while (__src <= __srcLast) { |
3372 /* copy over bytes */ |
3390 /* copy over bytes */ |
3373 __src[__ptrDelta] = __src[0]; |
3391 __src[__ptrDelta] = __src[0]; |
3374 __src ++; |
3392 __src ++; |
3375 } |
3393 } |
3376 goto doneSource; |
3394 goto doneSource; |
3377 } |
3395 } |
3378 } |
3396 } |
3379 |
3397 |
3380 __srcLastX = __srcLastX + 4; |
3398 __srcLastX = __srcLastX + 4; |
3381 if (__src <= __srcLastX) { |
3399 if (__src <= __srcLastX) { |
3382 unsigned int __sum, __digit; |
3400 unsigned int __sum, __digit; |
3383 |
3401 |
3384 __digit = ((unsigned *)__src)[0]; |
3402 __digit = ((unsigned *)__src)[0]; |
3385 |
3403 |
3386 asm ("addl %%eax,%%edx \n\ |
3404 asm ("addl %%eax,%%edx \n\ |
3387 movl $0,%%eax \n\ |
3405 movl $0,%%eax \n\ |
3388 adcl $0,%%eax" |
3406 adcl $0,%%eax" |
3389 : "=a" ((unsigned long)(__carry)), |
3407 : "=a" ((unsigned long)(__carry)), |
3390 "=d" ((unsigned long)(__sum)) |
3408 "=d" ((unsigned long)(__sum)) |
3391 : "0" ((unsigned long)(__carry)), |
3409 : "0" ((unsigned long)(__carry)), |
3392 "1" (__digit) ); |
3410 "1" (__digit) ); |
3393 |
3411 |
3394 ((unsigned int *)(__src + __ptrDelta))[0] = __sum; |
3412 ((unsigned int *)(__src + __ptrDelta))[0] = __sum; |
3395 __src += 4; |
3413 __src += 4; |
3396 |
3414 |
3397 if (__carry == 0) { |
3415 if (__carry == 0) { |
3398 while (__src <= __srcLast) { |
3416 while (__src <= __srcLast) { |
3399 /* copy over bytes */ |
3417 /* copy over bytes */ |
3400 __src[__ptrDelta] = __src[0]; |
3418 __src[__ptrDelta] = __src[0]; |
3401 __src ++; |
3419 __src ++; |
3402 } |
3420 } |
3403 goto doneSource; |
3421 goto doneSource; |
3404 } |
3422 } |
3405 } |
3423 } |
3406 } |
3424 } |
3407 # endif |
3425 # endif |
3408 # else /* not i386-GNUC */ |
3426 # else /* not i386-GNUC */ |
3409 # if defined(WIN32) && defined(__BORLANDC__) && defined(__i386__) && (__POINTER_SIZE__ == 4) |
3427 # if defined(WIN32) && defined(__BORLANDC__) && defined(__i386__) && (__POINTER_SIZE__ == 4) |
3410 { |
3428 { |
3411 unsigned char *__srcLast4; |
3429 unsigned char *__srcLast4; |
3412 |
3430 |
3413 /* |
3431 /* |
3414 * add long-wise |
3432 * add long-wise |
3415 */ |
3433 */ |
3416 __srcLast4 = __srcLast - 3; |
3434 __srcLast4 = __srcLast - 3; |
3417 while (__src <= __srcLast4) { |
3435 while (__src <= __srcLast4) { |
3418 unsigned int __sum; |
3436 unsigned int __sum; |
3419 |
3437 |
3420 __sum = ((unsigned int *)__src)[0]; |
3438 __sum = ((unsigned int *)__src)[0]; |
3421 asm { |
3439 asm { |
3422 mov eax, __sum |
3440 mov eax, __sum |
3423 add eax, __carry |
3441 add eax, __carry |
3424 mov edx, 0 |
3442 mov edx, 0 |
3425 adc edx, 0 |
3443 adc edx, 0 |
3426 mov __sum, eax |
3444 mov __sum, eax |
3427 mov __carry, edx |
3445 mov __carry, edx |
3428 } |
3446 } |
3429 |
3447 |
3430 ((unsigned int *)(__src + __ptrDelta))[0] = __sum; |
3448 ((unsigned int *)(__src + __ptrDelta))[0] = __sum; |
3431 __src += 4; |
3449 __src += 4; |
3432 if (__carry == 0) { |
3450 if (__carry == 0) { |
3433 while (__src <= __srcLast4) { |
3451 while (__src <= __srcLast4) { |
3434 /* copy over words */ |
3452 /* copy over words */ |
3435 ((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0]; |
3453 ((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0]; |
3436 __src += 4; |
3454 __src += 4; |
3437 } |
3455 } |
3438 while (__src <= __srcLast) { |
3456 while (__src <= __srcLast) { |
3439 /* copy over bytes */ |
3457 /* copy over bytes */ |
3440 __src[__ptrDelta] = __src[0]; |
3458 __src[__ptrDelta] = __src[0]; |
3441 __src ++; |
3459 __src ++; |
3442 } |
3460 } |
3443 goto doneSource; |
3461 goto doneSource; |
3444 } |
3462 } |
3445 } |
3463 } |
3446 } |
3464 } |
3447 # else /* not i386-WIN32 */ |
3465 # else /* not i386-WIN32 */ |
3448 # if defined(__LSBFIRST__) && (__POINTER_SIZE__ == 8) |
3466 # if defined(__LSBFIRST__) && (__POINTER_SIZE__ == 8) |
3449 { |
3467 { |
3450 unsigned char *__srcLast4; |
3468 unsigned char *__srcLast4; |
3451 |
3469 |
3452 /* |
3470 /* |
3453 * add long-wise |
3471 * add long-wise |
3454 */ |
3472 */ |
3455 __srcLast4 = __srcLast - 3; |
3473 __srcLast4 = __srcLast - 3; |
3456 while (__src <= __srcLast4) { |
3474 while (__src <= __srcLast4) { |
3457 unsigned INT __sum; |
3475 unsigned INT __sum; |
3458 |
3476 |
3459 __sum = ((unsigned int *)__src)[0] + __carry; |
3477 __sum = ((unsigned int *)__src)[0] + __carry; |
3460 ((unsigned int *)(__src + __ptrDelta))[0] = __sum /* & 0xFFFF */; |
3478 ((unsigned int *)(__src + __ptrDelta))[0] = __sum /* & 0xFFFF */; |
3461 __src += 4; |
3479 __src += 4; |
3462 __carry = __sum >> 32; |
3480 __carry = __sum >> 32; |
3463 if (__carry == 0) { |
3481 if (__carry == 0) { |
3464 while (__src <= __srcLast4) { |
3482 while (__src <= __srcLast4) { |
3465 /* copy over words */ |
3483 /* copy over words */ |
3466 ((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0]; |
3484 ((unsigned int *)(__src + __ptrDelta))[0] = ((unsigned int *)__src)[0]; |
3467 __src += 4; |
3485 __src += 4; |
3468 } |
3486 } |
3469 while (__src <= __srcLast) { |
3487 while (__src <= __srcLast) { |
3470 /* copy over bytes */ |
3488 /* copy over bytes */ |
3471 __src[__ptrDelta] = __src[0]; |
3489 __src[__ptrDelta] = __src[0]; |
3472 __src ++; |
3490 __src ++; |
3473 } |
3491 } |
3474 goto doneSource; |
3492 goto doneSource; |
3475 } |
3493 } |
3476 } |
3494 } |
3477 } |
3495 } |
3478 # endif /* LSB+64bit */ |
3496 # endif /* LSB+64bit */ |
3479 # endif /* __i386__ & WIN32 */ |
3497 # endif /* __i386__ & WIN32 */ |
3480 # endif /* __i386__ & GNUC */ |
3498 # endif /* __i386__ & GNUC */ |
3481 |
3499 |
3482 /* |
3500 /* |
3483 * add short-wise |
3501 * add short-wise |
3484 */ |
3502 */ |
3485 while (__src < __srcLast) { |
3503 while (__src < __srcLast) { |
3486 __carry += ((unsigned short *)__src)[0]; |
3504 __carry += ((unsigned short *)__src)[0]; |
3487 ((unsigned short *)(__src + __ptrDelta))[0] = __carry /* & 0xFFFF */; |
3505 ((unsigned short *)(__src + __ptrDelta))[0] = __carry /* & 0xFFFF */; |
3488 __carry >>= 16; |
3506 __carry >>= 16; |
3489 __src += 2; |
3507 __src += 2; |
3490 } |
3508 } |
3491 /* |
3509 /* |
3492 * last (odd) byte |
3510 * last (odd) byte |
3493 */ |
3511 */ |
3494 if (__src <= __srcLast) { |
3512 if (__src <= __srcLast) { |
3495 __carry += __src[0]; |
3513 __carry += __src[0]; |
3496 __src[__ptrDelta] = __carry /* & 0xFF */; |
3514 __src[__ptrDelta] = __carry /* & 0xFF */; |
3497 __carry >>= 8; |
3515 __carry >>= 8; |
3498 __src++; |
3516 __src++; |
3499 } |
3517 } |
3500 #else /* not __LSBFIRST__ */ |
3518 #else /* not __LSBFIRST__ */ |
3501 |
3519 |
3502 /* |
3520 /* |
3503 * add byte-wise |
3521 * add byte-wise |
3504 */ |
3522 */ |
3505 while (__src <= __srcLast) { |
3523 while (__src <= __srcLast) { |
3506 __carry += __src[0]; |
3524 __carry += __src[0]; |
3507 __src[__ptrDelta] = __carry /* & 0xFF */; |
3525 __src[__ptrDelta] = __carry /* & 0xFF */; |
3508 __src++; |
3526 __src++; |
3509 __carry >>= 8; |
3527 __carry >>= 8; |
3510 |
3528 |
3511 if (__carry == 0) { |
3529 if (__carry == 0) { |
3512 while (__src <= __srcLast) { |
3530 while (__src <= __srcLast) { |
3513 /* copy over rest */ |
3531 /* copy over rest */ |
3514 __src[__ptrDelta] = __src[0]; |
3532 __src[__ptrDelta] = __src[0]; |
3515 __src++; |
3533 __src++; |
3516 } |
3534 } |
3517 goto doneSource; |
3535 goto doneSource; |
3518 } |
3536 } |
3519 } |
3537 } |
3520 #endif /* __LSBFIRST__ */ |
3538 #endif /* __LSBFIRST__ */ |
3521 |
3539 |
3522 doneSource: ; |
3540 doneSource: ; |
3523 /* |
3541 /* |
3524 * now, at most one other byte is to be stored ... |
3542 * now, at most one other byte is to be stored ... |
3525 */ |
3543 */ |
3526 if (__len < __rsltLen) { |
3544 if (__len < __rsltLen) { |
3527 __src[__ptrDelta] = __carry /* & 0xFF */; |
3545 __src[__ptrDelta] = __carry /* & 0xFF */; |
3528 __src++; |
3546 __src++; |
3529 } |
3547 } |
3530 |
3548 |
3531 if (__src[__ptrDelta-1]) { /* lastDigit */ |
3549 if (__src[__ptrDelta-1]) { /* lastDigit */ |
3532 RETURN (result); |
3550 RETURN (result); |
3533 } |
3551 } |
3534 ok = true; |
3552 ok = true; |
3535 } |
3553 } |
3536 %}. |
3554 %}. |
3537 |
3555 |
3538 ok ~~ true ifTrue:[ |
3556 ok ~~ true ifTrue:[ |
3539 index := 1. |
3557 index := 1. |
3540 carry := aSmallInteger abs. |
3558 carry := aSmallInteger abs. |
3541 |
3559 |
3542 [carry ~~ 0] whileTrue:[ |
3560 [carry ~~ 0] whileTrue:[ |
3543 (index <= len) ifTrue:[ |
3561 (index <= len) ifTrue:[ |
3544 carry := (digitByteArray basicAt:index) + carry. |
3562 carry := (digitByteArray basicAt:index) + carry. |
3545 ]. |
3563 ]. |
3546 resultDigitByteArray basicAt:index put:(lastDigit := carry bitAnd:16rFF). |
3564 resultDigitByteArray basicAt:index put:(lastDigit := carry bitAnd:16rFF). |
3547 carry := carry bitShift:-8. |
3565 carry := carry bitShift:-8. |
3548 index := index + 1 |
3566 index := index + 1 |
3549 ]. |
3567 ]. |
3550 |
3568 |
3551 (index <= rsltLen) ifTrue:[ |
3569 (index <= rsltLen) ifTrue:[ |
3552 [index <= len] whileTrue:[ |
3570 [index <= len] whileTrue:[ |
3553 resultDigitByteArray basicAt:index put:(digitByteArray basicAt:index). |
3571 resultDigitByteArray basicAt:index put:(digitByteArray basicAt:index). |
3554 index := index + 1 |
3572 index := index + 1 |
3555 ]. |
3573 ]. |
3556 lastDigit := 0. |
3574 lastDigit := 0. |
3557 ]. |
3575 ]. |
3558 |
3576 |
3559 (lastDigit ~~ 0 and:[rsltLen > SmallInteger maxBytes]) ifTrue:[ |
3577 (lastDigit ~~ 0 and:[rsltLen > SmallInteger maxBytes]) ifTrue:[ |
3560 ^ result |
3578 ^ result |
3561 ]. |
3579 ]. |
3562 ]. |
3580 ]. |
3563 |
3581 |
3564 ^ result compressed |
3582 ^ result compressed |
3565 |
3583 |
3566 "Modified: 24.3.1997 / 21:32:41 / cg" |
3584 "Modified: 24.3.1997 / 21:32:41 / cg" |
3812 OBJ _digitByteArray = __INST(digitByteArray); |
3830 OBJ _digitByteArray = __INST(digitByteArray); |
3813 |
3831 |
3814 if (__isByteArray(_digitByteArray) |
3832 if (__isByteArray(_digitByteArray) |
3815 && __isByteArray(otherDigitByteArray) |
3833 && __isByteArray(otherDigitByteArray) |
3816 && __isByteArray(resultDigitByteArray)) { |
3834 && __isByteArray(resultDigitByteArray)) { |
3817 int __len1 = __intVal(len1); |
3835 int __len1 = __intVal(len1); |
3818 int __len2 = __intVal(len2); |
3836 int __len2 = __intVal(len2); |
3819 int __minLen = __len1 < __len2 ? __len1 : __len2; |
3837 int __minLen = __len1 < __len2 ? __len1 : __len2; |
3820 int __index, __borrow = 0; |
3838 int __index, __borrow = 0; |
3821 INT __diff; |
3839 INT __diff; |
3822 unsigned char *__myDigits, *__otherDigits, *__resultDigits; |
3840 unsigned char *__myDigits, *__otherDigits, *__resultDigits; |
3823 |
3841 |
3824 ok = true; |
3842 ok = true; |
3825 |
3843 |
3826 __resultDigits = __ByteArrayInstPtr(resultDigitByteArray)->ba_element; |
3844 __resultDigits = __ByteArrayInstPtr(resultDigitByteArray)->ba_element; |
3827 __otherDigits = __ByteArrayInstPtr(otherDigitByteArray)->ba_element; |
3845 __otherDigits = __ByteArrayInstPtr(otherDigitByteArray)->ba_element; |
3828 __myDigits = __ByteArrayInstPtr(_digitByteArray)->ba_element; |
3846 __myDigits = __ByteArrayInstPtr(_digitByteArray)->ba_element; |
3829 |
3847 |
3830 __index = 1; |
3848 __index = 1; |
3831 |
3849 |
3832 #if defined(__LSBFIRST__) |
3850 #if defined(__LSBFIRST__) |
3833 # if __POINTER_SIZE__ == 8 |
3851 # if __POINTER_SIZE__ == 8 |
3834 /* |
3852 /* |
3835 * subtract int-wise |
3853 * subtract int-wise |
3836 */ |
3854 */ |
3837 while ((__index+3) <= __minLen) { |
3855 while ((__index+3) <= __minLen) { |
3838 /* do not make this into one expression - ask cg why */ |
3856 /* do not make this into one expression - ask cg why */ |
3839 __diff = ((unsigned int *)(__myDigits+__index-1))[0]; |
3857 __diff = ((unsigned int *)(__myDigits+__index-1))[0]; |
3840 __diff -= ((unsigned int *)(__otherDigits+__index-1))[0]; |
3858 __diff -= ((unsigned int *)(__otherDigits+__index-1))[0]; |
3841 __diff -= __borrow; |
3859 __diff -= __borrow; |
3842 |
3860 |
3843 if (__diff >= 0) { |
3861 if (__diff >= 0) { |
3844 __borrow = 0; |
3862 __borrow = 0; |
3845 } else { |
3863 } else { |
3846 __borrow = 1; |
3864 __borrow = 1; |
3847 /* __diff += 0x10000; */ |
3865 /* __diff += 0x10000; */ |
3848 } |
3866 } |
3849 ((unsigned int *)(__resultDigits+__index-1))[0] = __diff; |
3867 ((unsigned int *)(__resultDigits+__index-1))[0] = __diff; |
3850 __index += 4; |
3868 __index += 4; |
3851 } |
3869 } |
3852 # endif /* 64bit */ |
3870 # endif /* 64bit */ |
3853 |
3871 |
3854 /* |
3872 /* |
3855 * subtract short-wise |
3873 * subtract short-wise |
3856 */ |
3874 */ |
3857 while (__index < __minLen) { /* i.e. index+1 <= minLen */ |
3875 while (__index < __minLen) { /* i.e. index+1 <= minLen */ |
3858 /* do not make this into one expression - ask cg why */ |
3876 /* do not make this into one expression - ask cg why */ |
3859 __diff = ((unsigned short *)(__myDigits+__index-1))[0]; |
3877 __diff = ((unsigned short *)(__myDigits+__index-1))[0]; |
3860 __diff -= ((unsigned short *)(__otherDigits+__index-1))[0]; |
3878 __diff -= ((unsigned short *)(__otherDigits+__index-1))[0]; |
3861 __diff -= __borrow; |
3879 __diff -= __borrow; |
3862 if (__diff >= 0) { |
3880 if (__diff >= 0) { |
3863 __borrow = 0; |
3881 __borrow = 0; |
3864 } else { |
3882 } else { |
3865 __borrow = 1; |
3883 __borrow = 1; |
3866 /* __diff += 0x10000; */ |
3884 /* __diff += 0x10000; */ |
3867 } |
3885 } |
3868 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3886 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3869 __index += 2; |
3887 __index += 2; |
3870 } |
3888 } |
3871 |
3889 |
3872 if (__index == __minLen) { |
3890 if (__index == __minLen) { |
3873 /* one of the operands has odd length - cannot continue short-wise */ |
3891 /* one of the operands has odd length - cannot continue short-wise */ |
3874 } else { |
3892 } else { |
3875 if (__len1 > __len2) { |
3893 if (__len1 > __len2) { |
3876 while (__index < __len1) { |
3894 while (__index < __len1) { |
3877 /* do not make this into one expression - ask cg why */ |
3895 /* do not make this into one expression - ask cg why */ |
3878 __diff = ((unsigned short *)(__myDigits+__index-1))[0]; |
3896 __diff = ((unsigned short *)(__myDigits+__index-1))[0]; |
3879 __diff -= __borrow; |
3897 __diff -= __borrow; |
3880 if (__diff >= 0) { |
3898 if (__diff >= 0) { |
3881 __borrow = 0; |
3899 __borrow = 0; |
3882 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3900 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3883 __index += 2; |
3901 __index += 2; |
3884 |
3902 |
3885 /* copy over rest */ |
3903 /* copy over rest */ |
3886 while (__index < __len1) { |
3904 while (__index < __len1) { |
3887 ((unsigned short *)(__resultDigits+__index-1))[0] = ((unsigned short *)(__myDigits+__index-1))[0]; |
3905 ((unsigned short *)(__resultDigits+__index-1))[0] = ((unsigned short *)(__myDigits+__index-1))[0]; |
3888 __index+=2; |
3906 __index+=2; |
3889 } |
3907 } |
3890 if (__index <= __len1) { |
3908 if (__index <= __len1) { |
3891 __resultDigits[__index-1] = __myDigits[__index-1]; |
3909 __resultDigits[__index-1] = __myDigits[__index-1]; |
3892 __index++; |
3910 __index++; |
3893 } |
3911 } |
3894 break; |
3912 break; |
3895 } |
3913 } |
3896 __borrow = 1; |
3914 __borrow = 1; |
3897 /* __diff += 0x10000; */ |
3915 /* __diff += 0x10000; */ |
3898 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3916 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3899 __index += 2; |
3917 __index += 2; |
3900 } |
3918 } |
3901 } else { |
3919 } else { |
3902 if (__len2 > __len1) { |
3920 if (__len2 > __len1) { |
3903 while (__index < __len2) { |
3921 while (__index < __len2) { |
3904 /* do not make this into one expression - ask cg why */ |
3922 /* do not make this into one expression - ask cg why */ |
3905 __diff = 0; |
3923 __diff = 0; |
3906 __diff -= ((unsigned short *)(__otherDigits+__index-1))[0]; |
3924 __diff -= ((unsigned short *)(__otherDigits+__index-1))[0]; |
3907 __diff -= __borrow; |
3925 __diff -= __borrow; |
3908 if (__diff >= 0) { |
3926 if (__diff >= 0) { |
3909 __borrow = 0; |
3927 __borrow = 0; |
3910 } else { |
3928 } else { |
3911 __borrow = 1; |
3929 __borrow = 1; |
3912 /* __diff += 0x10000; */ |
3930 /* __diff += 0x10000; */ |
3913 } |
3931 } |
3914 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3932 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3915 __index += 2; |
3933 __index += 2; |
3916 } |
3934 } |
3917 } |
3935 } |
3918 } |
3936 } |
3919 } |
3937 } |
3920 #endif |
3938 #endif |
3921 /* |
3939 /* |
3922 * subtract byte-wise |
3940 * subtract byte-wise |
3923 */ |
3941 */ |
3924 while (__index <= __minLen) { |
3942 while (__index <= __minLen) { |
3925 /* do not make this into one expression - ask cg why */ |
3943 /* do not make this into one expression - ask cg why */ |
3926 __diff = __myDigits[__index-1]; |
3944 __diff = __myDigits[__index-1]; |
3927 __diff -= __otherDigits[__index-1]; |
3945 __diff -= __otherDigits[__index-1]; |
3928 __diff -= __borrow; |
3946 __diff -= __borrow; |
3929 if (__diff >= 0) { |
3947 if (__diff >= 0) { |
3930 __borrow = 0; |
3948 __borrow = 0; |
3931 } else { |
3949 } else { |
3932 __borrow = 1; |
3950 __borrow = 1; |
3933 /* __diff += 0x100; */ |
3951 /* __diff += 0x100; */ |
3934 } |
3952 } |
3935 __resultDigits[__index-1] = __diff; |
3953 __resultDigits[__index-1] = __diff; |
3936 __index++; |
3954 __index++; |
3937 } |
3955 } |
3938 |
3956 |
3939 if (__len1 > __len2) { |
3957 if (__len1 > __len2) { |
3940 while (__index <= __len1) { |
3958 while (__index <= __len1) { |
3941 /* do not make this into one expression - ask cg why */ |
3959 /* do not make this into one expression - ask cg why */ |
3942 __diff = __myDigits[__index-1]; |
3960 __diff = __myDigits[__index-1]; |
3943 __diff -= __borrow; |
3961 __diff -= __borrow; |
3944 if (__diff >= 0) { |
3962 if (__diff >= 0) { |
3945 __borrow = 0; |
3963 __borrow = 0; |
3946 /* copy over rest */ |
3964 /* copy over rest */ |
3947 __resultDigits[__index-1] = __diff; |
3965 __resultDigits[__index-1] = __diff; |
3948 __index++; |
3966 __index++; |
3949 while (__index <= __len1) { |
3967 while (__index <= __len1) { |
3950 __resultDigits[__index-1] = __myDigits[__index-1]; |
3968 __resultDigits[__index-1] = __myDigits[__index-1]; |
3951 __index++; |
3969 __index++; |
3952 } |
3970 } |
3953 break; |
3971 break; |
3954 } |
3972 } |
3955 __borrow = 1; |
3973 __borrow = 1; |
3956 /* __diff += 0x100; */ |
3974 /* __diff += 0x100; */ |
3957 __resultDigits[__index-1] = __diff; |
3975 __resultDigits[__index-1] = __diff; |
3958 __index++; |
3976 __index++; |
3959 } |
3977 } |
3960 } else { |
3978 } else { |
3961 if (__len2 > __len1) { |
3979 if (__len2 > __len1) { |
3962 while (__index <= __len2) { |
3980 while (__index <= __len2) { |
3963 /* do not make this into one expression - ask cg why */ |
3981 /* do not make this into one expression - ask cg why */ |
3964 __diff = 0; |
3982 __diff = 0; |
3965 __diff -= __otherDigits[__index-1]; |
3983 __diff -= __otherDigits[__index-1]; |
3966 __diff -= __borrow; |
3984 __diff -= __borrow; |
3967 if (__diff >= 0) { |
3985 if (__diff >= 0) { |
3968 __borrow = 0; |
3986 __borrow = 0; |
3969 } else { |
3987 } else { |
3970 __borrow = 1; |
3988 __borrow = 1; |
3971 /* __diff += 0x100; */ |
3989 /* __diff += 0x100; */ |
3972 } |
3990 } |
3973 __resultDigits[__index-1] = __diff; |
3991 __resultDigits[__index-1] = __diff; |
3974 __index++; |
3992 __index++; |
3975 } |
3993 } |
3976 } |
3994 } |
3977 } |
3995 } |
3978 borrow = __mkSmallInteger(__borrow); |
3996 borrow = __mkSmallInteger(__borrow); |
3979 index = __mkSmallInteger(__index); |
3997 index = __mkSmallInteger(__index); |
3980 lastDigit = __mkSmallInteger(__resultDigits[__intVal(lResult)-1]); |
3998 lastDigit = __mkSmallInteger(__resultDigits[__intVal(lResult)-1]); |
3981 } |
3999 } |
3982 %}. |
4000 %}. |
3983 ok == true ifFalse:[ |
4001 ok == true ifFalse:[ |
3984 index := 1. |
4002 index := 1. |
3985 borrow := 0. |
4003 borrow := 0. |
3986 |
4004 |
3987 done := false. |
4005 done := false. |
3988 [done] whileFalse:[ |
4006 [done] whileFalse:[ |
3989 diff := borrow. |
4007 diff := borrow. |
3990 (index <= len1) ifTrue:[ |
4008 (index <= len1) ifTrue:[ |
3991 diff := diff + (digitByteArray basicAt:index). |
4009 diff := diff + (digitByteArray basicAt:index). |
3992 (index <= len2) ifTrue:[ |
4010 (index <= len2) ifTrue:[ |
3993 diff := diff - (otherDigitByteArray basicAt:index) |
4011 diff := diff - (otherDigitByteArray basicAt:index) |
3994 ] |
4012 ] |
3995 ] ifFalse:[ |
4013 ] ifFalse:[ |
3996 (index <= len2) ifTrue:[ |
4014 (index <= len2) ifTrue:[ |
3997 diff := diff - (otherDigitByteArray basicAt:index) |
4015 diff := diff - (otherDigitByteArray basicAt:index) |
3998 ] ifFalse:[ |
4016 ] ifFalse:[ |
3999 "end reached" |
4017 "end reached" |
4000 done := true |
4018 done := true |
4001 ] |
4019 ] |
4002 ]. |
4020 ]. |
4003 |
4021 |
4004 "/ workaround for |
4022 "/ workaround for |
4005 "/ gcc code generator bug |
4023 "/ gcc code generator bug |
4006 |
4024 |
4007 (diff >= 0) ifTrue:[ |
4025 (diff >= 0) ifTrue:[ |
4008 borrow := 0 |
4026 borrow := 0 |
4009 ] ifFalse:[ |
4027 ] ifFalse:[ |
4010 borrow := -1. |
4028 borrow := -1. |
4011 diff := diff + 16r100 |
4029 diff := diff + 16r100 |
4012 ]. |
4030 ]. |
4013 |
4031 |
4014 "/ (diff < 0) ifTrue:[ |
4032 "/ (diff < 0) ifTrue:[ |
4015 "/ borrow := -1. |
4033 "/ borrow := -1. |
4016 "/ diff := diff + 16r100 |
4034 "/ diff := diff + 16r100 |
4017 "/ ] ifFalse:[ |
4035 "/ ] ifFalse:[ |
4018 "/ borrow := 0 |
4036 "/ borrow := 0 |
4019 "/ ]. |
4037 "/ ]. |
4020 |
4038 |
4021 resultDigitByteArray basicAt:index put:diff. |
4039 resultDigitByteArray basicAt:index put:diff. |
4022 index := index + 1 |
4040 index := index + 1 |
4023 ]. |
4041 ]. |
4024 lastDigit := resultDigitByteArray basicAt:lResult. |
4042 lastDigit := resultDigitByteArray basicAt:lResult. |
4025 ]. |
4043 ]. |
4026 |
4044 |
4027 (borrow ~~ 0) ifTrue:[ |
4045 (borrow ~~ 0) ifTrue:[ |
4028 "/ must generate 255's complement |
4046 "/ must generate 255's complement |
4029 |
4047 |
4030 result sign:newSign negated. |
4048 result sign:newSign negated. |
4031 [index <= lResult] whileTrue:[ |
4049 [index <= lResult] whileTrue:[ |
4032 resultDigitByteArray basicAt:index put:16rFF. |
4050 resultDigitByteArray basicAt:index put:16rFF. |
4033 index := index + 1. |
4051 index := index + 1. |
4034 ]. |
4052 ]. |
4035 index := lResult. |
4053 index := lResult. |
4036 [index > 0] whileTrue:[ |
4054 [index > 0] whileTrue:[ |
4037 resultDigitByteArray basicAt:index put:(255 - (resultDigitByteArray at:index)). |
4055 resultDigitByteArray basicAt:index put:(255 - (resultDigitByteArray at:index)). |
4038 index := index - 1. |
4056 index := index - 1. |
4039 ]. |
4057 ]. |
4040 |
4058 |
4041 index := 1. |
4059 index := 1. |
4042 carry := 1. |
4060 carry := 1. |
4043 [carry ~~ 0] whileTrue:[ |
4061 [carry ~~ 0] whileTrue:[ |
4044 (index <= lResult) ifTrue:[ |
4062 (index <= lResult) ifTrue:[ |
4045 carry := (resultDigitByteArray basicAt:index) + carry. |
4063 carry := (resultDigitByteArray basicAt:index) + carry. |
4046 ]. |
4064 ]. |
4047 resultDigitByteArray basicAt:index put:(carry bitAnd:16rFF). |
4065 resultDigitByteArray basicAt:index put:(carry bitAnd:16rFF). |
4048 carry := carry bitShift:-8. |
4066 carry := carry bitShift:-8. |
4049 index := index + 1 |
4067 index := index + 1 |
4050 ]. |
4068 ]. |
4051 lastDigit := resultDigitByteArray basicAt:lResult. |
4069 lastDigit := resultDigitByteArray basicAt:lResult. |
4052 ]. |
4070 ]. |
4053 (lastDigit == 0 or:[lResult <= SmallInteger maxBytes]) ifTrue:[ |
4071 (lastDigit == 0 or:[lResult <= SmallInteger maxBytes]) ifTrue:[ |
4054 ^ result compressed. |
4072 ^ result compressed. |
4055 ]. |
4073 ]. |
4056 ^ result |
4074 ^ result |
4057 |
4075 |
4058 "Modified: 5.11.1996 / 14:09:25 / cg" |
4076 "Modified: 5.11.1996 / 14:09:25 / cg" |
4059 ! |
4077 ! |
4427 %{ |
4445 %{ |
4428 OBJ _digitByteArray = __INST(digitByteArray); |
4446 OBJ _digitByteArray = __INST(digitByteArray); |
4429 |
4447 |
4430 if (__isByteArray(_digitByteArray) |
4448 if (__isByteArray(_digitByteArray) |
4431 && __isByteArray(otherDigitByteArray)) { |
4449 && __isByteArray(otherDigitByteArray)) { |
4432 int _len1, _len2, _newLen; |
4450 int _len1, _len2, _newLen; |
4433 unsigned char *_myDigits, *_otherDigits, *_newDigits; |
4451 unsigned char *_myDigits, *_otherDigits, *_newDigits; |
4434 int _index, _carry; |
4452 int _index, _carry; |
4435 int _comLen; |
4453 int _comLen; |
4436 |
4454 |
4437 _len1 = __byteArraySize(_digitByteArray); |
4455 _len1 = __byteArraySize(_digitByteArray); |
4438 _len2 = __byteArraySize(otherDigitByteArray); |
4456 _len2 = __byteArraySize(otherDigitByteArray); |
4439 |
4457 |
4440 _otherDigits = __ByteArrayInstPtr(otherDigitByteArray)->ba_element; |
4458 _otherDigits = __ByteArrayInstPtr(otherDigitByteArray)->ba_element; |
4441 _myDigits = __ByteArrayInstPtr(_digitByteArray)->ba_element; |
4459 _myDigits = __ByteArrayInstPtr(_digitByteArray)->ba_element; |
4442 |
4460 |
4443 if (_len1 < _len2) { |
4461 if (_len1 < _len2) { |
4444 _comLen = _len1; |
4462 _comLen = _len1; |
4445 _newLen = _len2; |
4463 _newLen = _len2; |
4446 if (_otherDigits[_len2 - 1] == 0xFF) _newLen++; |
4464 if (_otherDigits[_len2 - 1] == 0xFF) _newLen++; |
4447 } else if (_len2 < _len1) { |
4465 } else if (_len2 < _len1) { |
4448 _comLen = _len2; |
4466 _comLen = _len2; |
4449 _newLen = _len1; |
4467 _newLen = _len1; |
4450 if (_myDigits[_len1 - 1] == 0xFF) _newLen++; |
4468 if (_myDigits[_len1 - 1] == 0xFF) _newLen++; |
4451 } else { |
4469 } else { |
4452 /* |
4470 /* |
4453 * there can only be an overflow from the high bytes, |
4471 * there can only be an overflow from the high bytes, |
4454 * if their sum is >= 255 |
4472 * if their sum is >= 255 |
4455 * (with sum==255, a carry could still occur from the next lower bytes) |
4473 * (with sum==255, a carry could still occur from the next lower bytes) |
4456 */ |
4474 */ |
4457 _newLen = _len1; |
4475 _newLen = _len1; |
4458 if ((_otherDigits[_len2 - 1] + _myDigits[_len1 - 1]) >= 0xFF) { |
4476 if ((_otherDigits[_len2 - 1] + _myDigits[_len1 - 1]) >= 0xFF) { |
4459 _newLen++; |
4477 _newLen++; |
4460 } else { |
4478 } else { |
4461 if (_newLen == sizeof(INT)) { |
4479 if (_newLen == sizeof(INT)) { |
4462 OBJ _uint; |
4480 OBJ _uint; |
4463 |
4481 |
4464 /* |
4482 /* |
4465 * two word-sized numbers, no carry - a very common case ... |
4483 * two word-sized numbers, no carry - a very common case ... |
4466 */ |
4484 */ |
4467 #if defined(__LSB_FIRST__) |
4485 #if defined(__LSB_FIRST__) |
4468 unsigned INT _sum = *(unsigned INT *)_otherDigits + *(unsigned INT *)_myDigits; |
4486 unsigned INT _sum = *(unsigned INT *)_otherDigits + *(unsigned INT *)_myDigits; |
4469 #else |
4487 #else |
4470 unsigned INT _sum = __unsignedLongIntVal(self) + __unsignedLongIntVal(aLargeInteger); |
4488 unsigned INT _sum = __unsignedLongIntVal(self) + __unsignedLongIntVal(aLargeInteger); |
4471 #endif /* not LSB_FIRST */ |
4489 #endif /* not LSB_FIRST */ |
4472 if (_sum <= _MAX_INT) { |
4490 if (_sum <= _MAX_INT) { |
4473 _uint = __mkSmallInteger(_sum * __intVal(newSign)); |
4491 _uint = __mkSmallInteger(_sum * __intVal(newSign)); |
4474 } else { |
4492 } else { |
4475 _uint = __MKULARGEINT(_sum); |
4493 _uint = __MKULARGEINT(_sum); |
4476 __LargeIntegerInstPtr(_uint)->l_sign = newSign; |
4494 __LargeIntegerInstPtr(_uint)->l_sign = newSign; |
4477 } |
4495 } |
4478 RETURN (_uint); |
4496 RETURN (_uint); |
4479 } |
4497 } |
4480 } |
4498 } |
4481 _comLen = _len1; |
4499 _comLen = _len1; |
4482 } |
4500 } |
4483 resultDigitByteArray = __BYTEARRAY_UNINITIALIZED_NEW_INT(_newLen); |
4501 resultDigitByteArray = __BYTEARRAY_UNINITIALIZED_NEW_INT(_newLen); |
4484 |
4502 |
4485 /* |
4503 /* |
4486 * must refetch - GC could have been invoked |
4504 * must refetch - GC could have been invoked |
4487 */ |
4505 */ |
4488 _digitByteArray = __INST(digitByteArray); |
4506 _digitByteArray = __INST(digitByteArray); |
4489 |
4507 |
4490 _myDigits = __ByteArrayInstPtr(_digitByteArray)->ba_element; |
4508 _myDigits = __ByteArrayInstPtr(_digitByteArray)->ba_element; |
4491 _otherDigits = __ByteArrayInstPtr(otherDigitByteArray)->ba_element; |
4509 _otherDigits = __ByteArrayInstPtr(otherDigitByteArray)->ba_element; |
4492 _newDigits = __ByteArrayInstPtr(resultDigitByteArray)->ba_element; |
4510 _newDigits = __ByteArrayInstPtr(resultDigitByteArray)->ba_element; |
4493 |
4511 |
4494 /* |
4512 /* |
4495 * add them ... |
4513 * add them ... |
4496 */ |
4514 */ |
4497 _index = 1; |
4515 _index = 1; |
4498 _carry = 0; |
4516 _carry = 0; |
4499 |
4517 |
4500 #if defined(__LSBFIRST__) |
4518 #if defined(__LSBFIRST__) |
4501 # if (__POINTER_SIZE__ == 8) && defined(__GNUC__) |
4519 # if (__POINTER_SIZE__ == 8) && defined(__GNUC__) |
4502 # if 0 /* not faster (on alpha) */ |
4520 # if 0 /* not faster (on alpha) */ |
4503 { |
4521 { |
4504 int _comLen7; |
4522 int _comLen7; |
4505 |
4523 |
4506 /* |
4524 /* |
4507 * have a 64bit integers; |
4525 * have a 64bit integers; |
4508 * add quad-wise |
4526 * add quad-wise |
4509 * accessing bytes at: [index-1][index][index+1]..[index+6] |
4527 * accessing bytes at: [index-1][index][index+1]..[index+6] |
4510 */ |
4528 */ |
4511 _comLen7 = _comLen - 3 - 4; |
4529 _comLen7 = _comLen - 3 - 4; |
4512 while (_index <= _comLen7) { |
4530 while (_index <= _comLen7) { |
4513 UINT64 _sum, _t1, _t2; |
4531 UINT64 _sum, _t1, _t2; |
4514 |
4532 |
4515 asm ("addq %5,%6,%1 /* sum */ \n\ |
4533 asm ("addq %5,%6,%1 /* sum */ \n\ |
4516 addq %0,%1,%1 /* plus carryIn */ \n\ |
4534 addq %0,%1,%1 /* plus carryIn */ \n\ |
4517 cmpult %1,%5,%2 /* was there a carry ? */ \n\ |
4535 cmpult %1,%5,%2 /* was there a carry ? */ \n\ |
4518 cmpult %1,%6,%3 /* was there a carry ? */ \n\ |
4536 cmpult %1,%6,%3 /* was there a carry ? */ \n\ |
4519 bis %2,%3,%0 /* carryOut */ \n\ |
4537 bis %2,%3,%0 /* carryOut */ \n\ |
4520 " |
4538 " |
4521 : "=r" (_carry), |
4539 : "=r" (_carry), |
4522 "=r" (_sum), |
4540 "=r" (_sum), |
4523 "r" (_t1), |
4541 "r" (_t1), |
4524 "r" (_t2) |
4542 "r" (_t2) |
4525 : "r" (_carry), |
4543 : "r" (_carry), |
4526 "r" (((unsigned long *)(&(_myDigits[_index - 1])))[0]), |
4544 "r" (((unsigned long *)(&(_myDigits[_index - 1])))[0]), |
4527 "r" (((unsigned long *)(&(_otherDigits[_index - 1])))[0]) |
4545 "r" (((unsigned long *)(&(_otherDigits[_index - 1])))[0]) |
4528 ); |
4546 ); |
4529 /* _sum = _sum & 0xFFFFFFFF; */ |
4547 /* _sum = _sum & 0xFFFFFFFF; */ |
4530 ((unsigned long *)(&(_newDigits[_index - 1])))[0] = _sum; |
4548 ((unsigned long *)(&(_newDigits[_index - 1])))[0] = _sum; |
4531 _index += 8; |
4549 _index += 8; |
4532 } |
4550 } |
4533 } |
4551 } |
4534 # endif |
4552 # endif |
4535 # endif /* 64bit */ |
4553 # endif /* 64bit */ |
4536 |
4554 |
4537 # if (__POINTER_SIZE__ == 8) |
4555 # if (__POINTER_SIZE__ == 8) |
4538 # if 0 /* not faster (on alpha) */ |
4556 # if 0 /* not faster (on alpha) */ |
4539 { |
4557 { |
4540 int _comLen7; |
4558 int _comLen7; |
4541 |
4559 |
4542 /* |
4560 /* |
4543 * have a 64bit integers; |
4561 * have a 64bit integers; |
4544 * add quad-wise |
4562 * add quad-wise |
4545 * accessing bytes at: [index-1][index][index+1]..[index+6] |
4563 * accessing bytes at: [index-1][index][index+1]..[index+6] |
4546 */ |
4564 */ |
4547 _comLen7 = _comLen - 3 - 4; |
4565 _comLen7 = _comLen - 3 - 4; |
4548 while (_index <= _comLen7) { |
4566 while (_index <= _comLen7) { |
4549 UINT64 _sum, _t1, _t2; |
4567 UINT64 _sum, _t1, _t2; |
4550 |
4568 |
4551 _t1 = ((UINT64 *)(&(_myDigits[_index - 1])))[0]; |
4569 _t1 = ((UINT64 *)(&(_myDigits[_index - 1])))[0]; |
4552 _t2 = ((UINT64 *)(&(_otherDigits[_index - 1])))[0]; |
4570 _t2 = ((UINT64 *)(&(_otherDigits[_index - 1])))[0]; |
4553 _sum = _t1 + _t2 + _carry; |
4571 _sum = _t1 + _t2 + _carry; |
4554 ((UINT64 *)(&(_newDigits[_index - 1])))[0] = _sum; |
4572 ((UINT64 *)(&(_newDigits[_index - 1])))[0] = _sum; |
4555 _carry = (_sum < _t1) | (_sum < _t2); |
4573 _carry = (_sum < _t1) | (_sum < _t2); |
4556 _index += 8; |
4574 _index += 8; |
4557 } |
4575 } |
4558 } |
4576 } |
4559 # endif |
4577 # endif |
4560 # endif /* 64bit */ |
4578 # endif /* 64bit */ |
4561 |
4579 |
4562 # ifdef UINT64 |
4580 # ifdef UINT64 |
4563 { |
4581 { |
4564 int _comLen3; |
4582 int _comLen3; |
4565 |
4583 |
4566 /* |
4584 /* |
4567 * have a 64bit integer type; |
4585 * have a 64bit integer type; |
4568 * add int-wise |
4586 * add int-wise |
4569 * accessing bytes at: [index-1][index][index+1][index+2] |
4587 * accessing bytes at: [index-1][index][index+1][index+2] |
4570 */ |
4588 */ |
4571 _comLen3 = _comLen - 3; |
4589 _comLen3 = _comLen - 3; |
4572 while (_index <= _comLen3) { |
4590 while (_index <= _comLen3) { |
4573 UINT64 _sum; |
4591 UINT64 _sum; |
4574 |
4592 |
4575 /* do not merge the 3 lines below into one - |
4593 /* do not merge the 3 lines below into one - |
4576 * (will do sign extension then, which is wrong here) |
4594 * (will do sign extension then, which is wrong here) |
4577 */ |
4595 */ |
4578 _sum = (unsigned)_carry; |
4596 _sum = (unsigned)_carry; |
4579 _sum += ((unsigned int *)(&(_myDigits[_index - 1])))[0]; |
4597 _sum += ((unsigned int *)(&(_myDigits[_index - 1])))[0]; |
4580 _sum += ((unsigned int *)(&(_otherDigits[_index - 1])))[0]; |
4598 _sum += ((unsigned int *)(&(_otherDigits[_index - 1])))[0]; |
4581 _carry = _sum >> 32; |
4599 _carry = _sum >> 32; |
4582 /* _sum = _sum & 0xFFFFFFFF; */ |
4600 /* _sum = _sum & 0xFFFFFFFF; */ |
4583 ((unsigned int *)(&(_newDigits[_index - 1])))[0] = _sum; |
4601 ((unsigned int *)(&(_newDigits[_index - 1])))[0] = _sum; |
4584 _index += 4; |
4602 _index += 4; |
4585 } |
4603 } |
4586 } |
4604 } |
4587 # else |
4605 # else |
4588 # if defined(__i386__) && defined(__GNUC__) && (__POINTER_SIZE__ == 4) |
4606 # if defined(__i386__) && defined(__GNUC__) && (__POINTER_SIZE__ == 4) |
4589 { |
4607 { |
4590 int _comLen3; |
4608 int _comLen3; |
4591 |
4609 |
4592 _comLen3 = _comLen - 3 - 4; |
4610 _comLen3 = _comLen - 3 - 4; |
4593 while (_index <= _comLen3) { |
4611 while (_index <= _comLen3) { |
4594 unsigned int _sum, _sum2; |
4612 unsigned int _sum, _sum2; |
4595 unsigned int __in1A, __in1B, __in2A, __in2B; |
4613 unsigned int __in1A, __in1B, __in2A, __in2B; |
4596 |
4614 |
4597 __in1A = ((unsigned int *)(&(_myDigits[_index - 1])))[0]; |
4615 __in1A = ((unsigned int *)(&(_myDigits[_index - 1])))[0]; |
4598 __in2A = ((unsigned int *)(&(_myDigits[_index - 1])))[1]; |
4616 __in2A = ((unsigned int *)(&(_myDigits[_index - 1])))[1]; |
4599 __in1B = ((unsigned int *)(&(_otherDigits[_index - 1])))[0]; |
4617 __in1B = ((unsigned int *)(&(_otherDigits[_index - 1])))[0]; |
4600 __in2B = ((unsigned int *)(&(_otherDigits[_index - 1])))[1]; |
4618 __in2B = ((unsigned int *)(&(_otherDigits[_index - 1])))[1]; |
4601 |
4619 |
4602 asm ("addl %%edx,%%eax \n\ |
4620 asm ("addl %%edx,%%eax \n\ |
4603 movl $0,%%edx \n\ |
4621 movl $0,%%edx \n\ |
4604 adcl $0,%%edx \n\ |
4622 adcl $0,%%edx \n\ |
4605 addl %5,%%eax \n\ |
4623 addl %5,%%eax \n\ |
4606 adcl $0,%%edx \n\ |
4624 adcl $0,%%edx \n\ |
4607 \n\ |
4625 \n\ |
4608 addl %%edx,%%ecx \n\ |
4626 addl %%edx,%%ecx \n\ |
4609 movl $0,%%edx \n\ |
4627 movl $0,%%edx \n\ |
4610 adcl $0,%%edx \n\ |
4628 adcl $0,%%edx \n\ |
4611 addl %7,%%ecx \n\ |
4629 addl %7,%%ecx \n\ |
4612 adcl $0,%%edx \n\ |
4630 adcl $0,%%edx \n\ |
4613 " |
4631 " |
4614 : "=d" (_carry), |
4632 : "=d" (_carry), |
4615 "=a" (_sum), |
4633 "=a" (_sum), |
4616 "=c" (_sum2) |
4634 "=c" (_sum2) |
4617 : "0" (_carry), |
4635 : "0" (_carry), |
4618 "1" (__in1A), |
4636 "1" (__in1A), |
4619 "rm" (__in1B), |
4637 "rm" (__in1B), |
4620 "2" (__in2A), |
4638 "2" (__in2A), |
4621 "rm" (__in2B) |
4639 "rm" (__in2B) |
4622 ); |
4640 ); |
4623 |
4641 |
4624 ((unsigned *)(&(_newDigits[_index - 1])))[0] = _sum; |
4642 ((unsigned *)(&(_newDigits[_index - 1])))[0] = _sum; |
4625 ((unsigned *)(&(_newDigits[_index - 1])))[1] = _sum2; |
4643 ((unsigned *)(&(_newDigits[_index - 1])))[1] = _sum2; |
4626 _index += 8; |
4644 _index += 8; |
4627 } |
4645 } |
4628 /* |
4646 /* |
4629 * add int-wise |
4647 * add int-wise |
4630 * accessing bytes at: [index-1][index][index+1][index+2] |
4648 * accessing bytes at: [index-1][index][index+1][index+2] |
4631 */ |
4649 */ |
4632 _comLen3 = _comLen3 + 4; |
4650 _comLen3 = _comLen3 + 4; |
4633 if (_index <= _comLen3) { |
4651 if (_index <= _comLen3) { |
4634 unsigned int _sum; |
4652 unsigned int _sum; |
4635 unsigned int __inA, __inB; |
4653 unsigned int __inA, __inB; |
4636 |
4654 |
4637 __inA = ((unsigned int *)(&(_myDigits[_index - 1])))[0]; |
4655 __inA = ((unsigned int *)(&(_myDigits[_index - 1])))[0]; |
4638 __inB = ((unsigned int *)(&(_otherDigits[_index - 1])))[0]; |
4656 __inB = ((unsigned int *)(&(_otherDigits[_index - 1])))[0]; |
4639 |
4657 |
4640 asm ("addl %%edx,%%eax \n\ |
4658 asm ("addl %%edx,%%eax \n\ |
4641 movl $0,%%edx \n\ |
4659 movl $0,%%edx \n\ |
4642 adcl $0,%%edx \n\ |
4660 adcl $0,%%edx \n\ |
4643 addl %4,%%eax \n\ |
4661 addl %4,%%eax \n\ |
4644 adcl $0,%%edx" |
4662 adcl $0,%%edx" |
4645 : "=d" (_carry), |
4663 : "=d" (_carry), |
4646 "=a" (_sum) |
4664 "=a" (_sum) |
4647 : "0" (_carry), |
4665 : "0" (_carry), |
4648 "1" (__inA), |
4666 "1" (__inA), |
4649 "rm" (__inB) |
4667 "rm" (__inB) |
4650 ); |
4668 ); |
4651 |
4669 |
4652 ((unsigned *)(&(_newDigits[_index - 1])))[0] = _sum; |
4670 ((unsigned *)(&(_newDigits[_index - 1])))[0] = _sum; |
4653 _index += 4; |
4671 _index += 4; |
4654 } |
4672 } |
4655 } |
4673 } |
4656 # endif /* __i386__ && GNUC */ |
4674 # endif /* __i386__ && GNUC */ |
4657 # if defined(WIN32) && defined(__BORLANDC__) && defined(__i386__) && (__POINTER_SIZE__ == 4) |
4675 # if defined(WIN32) && defined(__BORLANDC__) && defined(__i386__) && (__POINTER_SIZE__ == 4) |
4658 { |
4676 { |
4659 int _comLen3; |
4677 int _comLen3; |
4660 |
4678 |
4661 /* |
4679 /* |
4662 * add long-wise |
4680 * add long-wise |
4663 * accessing bytes at: [index-1][index][index+1][index+2] |
4681 * accessing bytes at: [index-1][index][index+1][index+2] |
4664 */ |
4682 */ |
4665 _comLen3 = _comLen - 3; |
4683 _comLen3 = _comLen - 3; |
4666 while (_index <= _comLen3) { |
4684 while (_index <= _comLen3) { |
4667 unsigned int _sum, _v1, _v2; |
4685 unsigned int _sum, _v1, _v2; |
4668 |
4686 |
4669 _v1 = ((unsigned int *)(&(_myDigits[_index - 1])))[0]; |
4687 _v1 = ((unsigned int *)(&(_myDigits[_index - 1])))[0]; |
4670 _v2 = ((unsigned int *)(&(_otherDigits[_index - 1])))[0]; |
4688 _v2 = ((unsigned int *)(&(_otherDigits[_index - 1])))[0]; |
4671 asm { |
4689 asm { |
4672 mov eax, _v1 |
4690 mov eax, _v1 |
4673 add eax, _v2 |
4691 add eax, _v2 |
4674 mov edx, 0 |
4692 mov edx, 0 |
4675 adc edx, 0 |
4693 adc edx, 0 |
4676 add eax, _carry |
4694 add eax, _carry |
4677 adc edx, 0 |
4695 adc edx, 0 |
4678 mov _carry, edx |
4696 mov _carry, edx |
4679 mov _sum, eax |
4697 mov _sum, eax |
4680 } |
4698 } |
4681 |
4699 |
4682 ((unsigned *)(&(_newDigits[_index - 1])))[0] = _sum; |
4700 ((unsigned *)(&(_newDigits[_index - 1])))[0] = _sum; |
4683 _index += 4; |
4701 _index += 4; |
4684 } |
4702 } |
4685 } |
4703 } |
4686 # endif /* __i386__ && WIN32 */ |
4704 # endif /* __i386__ && WIN32 */ |
4687 # endif /* INT64 */ |
4705 # endif /* INT64 */ |
4688 /* |
4706 /* |
4689 * add short-wise |
4707 * add short-wise |
4690 * accessing bytes at: [index-1][index] |
4708 * accessing bytes at: [index-1][index] |
4691 */ |
4709 */ |
4692 while (_index < _comLen) { |
4710 while (_index < _comLen) { |
4693 unsigned int _sum; |
4711 unsigned int _sum; |
4694 |
4712 |
4695 _sum = _carry |
4713 _sum = _carry |
4696 + ((unsigned short *)(&(_myDigits[_index - 1])))[0] |
4714 + ((unsigned short *)(&(_myDigits[_index - 1])))[0] |
4697 + ((unsigned short *)(&(_otherDigits[_index - 1])))[0]; |
4715 + ((unsigned short *)(&(_otherDigits[_index - 1])))[0]; |
4698 _carry = _sum >> 16; |
4716 _carry = _sum >> 16; |
4699 /* _sum = _sum & 0xFFFF; */ |
4717 /* _sum = _sum & 0xFFFF; */ |
4700 *(unsigned short *)(&(_newDigits[_index - 1])) = _sum; |
4718 *(unsigned short *)(&(_newDigits[_index - 1])) = _sum; |
4701 _index += 2; |
4719 _index += 2; |
4702 } |
4720 } |
4703 #else |
4721 #else |
4704 # ifdef __sparc__ |
4722 # ifdef __sparc__ |
4705 /* |
4723 /* |
4706 * add short-wise |
4724 * add short-wise |
4707 * accessing bytes at: [index-1][index] |
4725 * accessing bytes at: [index-1][index] |
4708 */ |
4726 */ |
4709 while (_index < _comLen) { |
4727 while (_index < _comLen) { |
4710 unsigned int _sum; |
4728 unsigned int _sum; |
4711 unsigned short _v1, _v2; |
4729 unsigned short _v1, _v2; |
4712 |
4730 |
4713 _v1 = ((unsigned short *)(&(_myDigits[_index - 1])))[0]; |
4731 _v1 = ((unsigned short *)(&(_myDigits[_index - 1])))[0]; |
4714 _v2 = ((unsigned short *)(&(_otherDigits[_index - 1])))[0]; |
4732 _v2 = ((unsigned short *)(&(_otherDigits[_index - 1])))[0]; |
4715 _sum = _carry + (_v1>>8) + (_v2>>8); |
4733 _sum = _carry + (_v1>>8) + (_v2>>8); |
4716 _carry = _sum >> 8; |
4734 _carry = _sum >> 8; |
4717 _newDigits[_index - 1] = _sum; |
4735 _newDigits[_index - 1] = _sum; |
4718 |
4736 |
4719 _sum = _carry + (_v1 & 0xFF) + (_v2 & 0xFF); |
4737 _sum = _carry + (_v1 & 0xFF) + (_v2 & 0xFF); |
4720 _carry = _sum >> 8; |
4738 _carry = _sum >> 8; |
4721 _newDigits[_index] = _sum; |
4739 _newDigits[_index] = _sum; |
4722 _index += 2; |
4740 _index += 2; |
4723 } |
4741 } |
4724 # endif |
4742 # endif |
4725 #endif /* __LSBFIRST__ */ |
4743 #endif /* __LSBFIRST__ */ |
4726 |
4744 |
4727 /* |
4745 /* |
4728 * add byte-wise |
4746 * add byte-wise |
4729 */ |
4747 */ |
4730 while (_index <= _comLen) { |
4748 while (_index <= _comLen) { |
4731 unsigned int _sum; |
4749 unsigned int _sum; |
4732 |
4750 |
4733 _sum = _carry |
4751 _sum = _carry |
4734 + _myDigits[_index - 1] |
4752 + _myDigits[_index - 1] |
4735 + _otherDigits[_index - 1]; |
4753 + _otherDigits[_index - 1]; |
4736 _carry = _sum >> 8; |
4754 _carry = _sum >> 8; |
4737 /* _sum = _sum & 0xFF; */ |
4755 /* _sum = _sum & 0xFF; */ |
4738 _newDigits[_index - 1] = _sum; |
4756 _newDigits[_index - 1] = _sum; |
4739 _index++; |
4757 _index++; |
4740 } |
4758 } |
4741 |
4759 |
4742 /* |
4760 /* |
4743 * rest |
4761 * rest |
4744 */ |
4762 */ |
4745 if (_len1 > _len2) { |
4763 if (_len1 > _len2) { |
4746 #if defined(__LSBFIRST__) |
4764 #if defined(__LSBFIRST__) |
4747 if (_index <= _len1) { |
4765 if (_index <= _len1) { |
4748 if ((_index - 1) & 1) { |
4766 if ((_index - 1) & 1) { |
4749 /* odd byte */ |
4767 /* odd byte */ |
4750 unsigned int _sum; |
4768 unsigned int _sum; |
4751 |
4769 |
4752 _sum = _carry + _myDigits[_index - 1]; |
4770 _sum = _carry + _myDigits[_index - 1]; |
4753 _carry = _sum >> 8; |
4771 _carry = _sum >> 8; |
4754 /* _sum = _sum & 0xFF; */ |
4772 /* _sum = _sum & 0xFF; */ |
4755 _newDigits[_index - 1] = _sum; |
4773 _newDigits[_index - 1] = _sum; |
4756 _index++; |
4774 _index++; |
4757 } |
4775 } |
4758 |
4776 |
4759 while (_index < _len1) { |
4777 while (_index < _len1) { |
4760 /* shorts */ |
4778 /* shorts */ |
4761 unsigned int _sum; |
4779 unsigned int _sum; |
4762 |
4780 |
4763 _sum = _carry + *(unsigned short *)(&(_myDigits[_index - 1])); |
4781 _sum = _carry + *(unsigned short *)(&(_myDigits[_index - 1])); |
4764 _carry = _sum >> 16; |
4782 _carry = _sum >> 16; |
4765 /* _sum = _sum & 0xFFFF; */ |
4783 /* _sum = _sum & 0xFFFF; */ |
4766 *(unsigned short *)(&(_newDigits[_index - 1])) = _sum; |
4784 *(unsigned short *)(&(_newDigits[_index - 1])) = _sum; |
4767 _index += 2; |
4785 _index += 2; |
4768 } |
4786 } |
4769 |
4787 |
4770 if (_index <= _len1) { |
4788 if (_index <= _len1) { |
4771 /* last byte */ |
4789 /* last byte */ |
4772 unsigned int _sum; |
4790 unsigned int _sum; |
4773 |
4791 |
4774 _sum = _carry + _myDigits[_index - 1]; |
4792 _sum = _carry + _myDigits[_index - 1]; |
4775 _carry = _sum >> 8; |
4793 _carry = _sum >> 8; |
4776 /* _sum = _sum & 0xFF; */ |
4794 /* _sum = _sum & 0xFF; */ |
4777 _newDigits[_index - 1] = _sum; |
4795 _newDigits[_index - 1] = _sum; |
4778 _index++; |
4796 _index++; |
4779 } |
4797 } |
4780 } |
4798 } |
4781 #else |
4799 #else |
4782 while (_index <= _len1) { |
4800 while (_index <= _len1) { |
4783 unsigned int _sum; |
4801 unsigned int _sum; |
4784 |
4802 |
4785 _sum = _carry + _myDigits[_index - 1]; |
4803 _sum = _carry + _myDigits[_index - 1]; |
4786 _carry = _sum >> 8; |
4804 _carry = _sum >> 8; |
4787 /* _sum = _sum & 0xFF; */ |
4805 /* _sum = _sum & 0xFF; */ |
4788 _newDigits[_index - 1] = _sum; |
4806 _newDigits[_index - 1] = _sum; |
4789 _index++; |
4807 _index++; |
4790 } |
4808 } |
4791 #endif /* not LSB */ |
4809 #endif /* not LSB */ |
4792 } else { |
4810 } else { |
4793 if (_len2 > _len1) { |
4811 if (_len2 > _len1) { |
4794 #if defined(__LSBFIRST__) |
4812 #if defined(__LSBFIRST__) |
4795 if (_index <= _len2) { |
4813 if (_index <= _len2) { |
4796 if ((_index - 1) & 1) { |
4814 if ((_index - 1) & 1) { |
4797 /* odd byte */ |
4815 /* odd byte */ |
4798 unsigned int _sum; |
4816 unsigned int _sum; |
4799 |
4817 |
4800 _sum = _carry + _otherDigits[_index - 1]; |
4818 _sum = _carry + _otherDigits[_index - 1]; |
4801 _carry = _sum >> 8; |
4819 _carry = _sum >> 8; |
4802 /* _sum = _sum & 0xFF; */ |
4820 /* _sum = _sum & 0xFF; */ |
4803 _newDigits[_index - 1] = _sum; |
4821 _newDigits[_index - 1] = _sum; |
4804 _index++; |
4822 _index++; |
4805 } |
4823 } |
4806 |
4824 |
4807 while (_index < _len2) { |
4825 while (_index < _len2) { |
4808 /* shorts */ |
4826 /* shorts */ |
4809 unsigned int _sum; |
4827 unsigned int _sum; |
4810 |
4828 |
4811 _sum = _carry + *(unsigned short *)(&(_otherDigits[_index - 1])); |
4829 _sum = _carry + *(unsigned short *)(&(_otherDigits[_index - 1])); |
4812 _carry = _sum >> 16; |
4830 _carry = _sum >> 16; |
4813 /* _sum = _sum & 0xFFFF; */ |
4831 /* _sum = _sum & 0xFFFF; */ |
4814 *(unsigned short *)(&(_newDigits[_index - 1])) = _sum; |
4832 *(unsigned short *)(&(_newDigits[_index - 1])) = _sum; |
4815 _index += 2; |
4833 _index += 2; |
4816 } |
4834 } |
4817 |
4835 |
4818 if (_index <= _len2) { |
4836 if (_index <= _len2) { |
4819 /* last byte */ |
4837 /* last byte */ |
4820 unsigned int _sum; |
4838 unsigned int _sum; |
4821 |
4839 |
4822 _sum = _carry + _otherDigits[_index - 1]; |
4840 _sum = _carry + _otherDigits[_index - 1]; |
4823 _carry = _sum >> 8; |
4841 _carry = _sum >> 8; |
4824 /* _sum = _sum & 0xFF; */ |
4842 /* _sum = _sum & 0xFF; */ |
4825 _newDigits[_index - 1] = _sum; |
4843 _newDigits[_index - 1] = _sum; |
4826 _index++; |
4844 _index++; |
4827 } |
4845 } |
4828 } |
4846 } |
4829 #else |
4847 #else |
4830 while (_index <= _len2) { |
4848 while (_index <= _len2) { |
4831 unsigned int _sum; |
4849 unsigned int _sum; |
4832 |
4850 |
4833 _sum = _carry + _otherDigits[_index - 1]; |
4851 _sum = _carry + _otherDigits[_index - 1]; |
4834 _carry = _sum >> 8; |
4852 _carry = _sum >> 8; |
4835 /* _sum = _sum & 0xFF; */ |
4853 /* _sum = _sum & 0xFF; */ |
4836 _newDigits[_index - 1] = _sum; |
4854 _newDigits[_index - 1] = _sum; |
4837 _index++; |
4855 _index++; |
4838 } |
4856 } |
4839 #endif /* not LSB */ |
4857 #endif /* not LSB */ |
4840 } |
4858 } |
4841 } |
4859 } |
4842 |
4860 |
4843 while (_index <= _newLen) { |
4861 while (_index <= _newLen) { |
4844 unsigned int _sum; |
4862 unsigned int _sum; |
4845 |
4863 |
4846 _sum = _carry; |
4864 _sum = _carry; |
4847 _carry = _sum >> 8; |
4865 _carry = _sum >> 8; |
4848 /* _sum = _sum & 0xFF; */ |
4866 /* _sum = _sum & 0xFF; */ |
4849 _newDigits[_index - 1] = _sum; |
4867 _newDigits[_index - 1] = _sum; |
4850 _index++; |
4868 _index++; |
4851 } |
4869 } |
4852 } |
4870 } |
4853 %}. |
4871 %}. |
4854 resultDigitByteArray notNil ifTrue:[ |
4872 resultDigitByteArray notNil ifTrue:[ |
4855 result := self class basicNew. |
4873 result := self class basicNew. |
4856 result setDigits:resultDigitByteArray. |
4874 result setDigits:resultDigitByteArray. |
4857 result setSign:newSign. |
4875 result setSign:newSign. |
4858 ] ifFalse:[ |
4876 ] ifFalse:[ |
4859 len1 := digitByteArray size. |
4877 len1 := digitByteArray size. |
4860 len2 := otherDigitByteArray size. |
4878 len2 := otherDigitByteArray size. |
4861 |
4879 |
4862 "/ earlier versions estimated the newLength as: |
4880 "/ earlier versions estimated the newLength as: |
4863 "/ (len1 max:len2) + 1 |
4881 "/ (len1 max:len2) + 1 |
4864 "/ and reduced the result. |
4882 "/ and reduced the result. |
4865 "/ however, if one of the addends is smaller, |
4883 "/ however, if one of the addends is smaller, |
4866 "/ the result will never require another digit, |
4884 "/ the result will never require another digit, |
4867 "/ if the highest digit of the larger addent is |
4885 "/ if the highest digit of the larger addent is |
4868 "/ not equal to 255. Therefore, in most cases, |
4886 "/ not equal to 255. Therefore, in most cases, |
4869 "/ we can avoid the computation and resizing |
4887 "/ we can avoid the computation and resizing |
4870 "/ in #reduced. |
4888 "/ in #reduced. |
4871 |
4889 |
4872 len1 < len2 ifTrue:[ |
4890 len1 < len2 ifTrue:[ |
4873 newLen := len2. |
4891 newLen := len2. |
4874 (otherDigitByteArray at:len2) == 16rFF ifTrue:[ |
4892 (otherDigitByteArray at:len2) == 16rFF ifTrue:[ |
4875 newLen := newLen + 1 |
4893 newLen := newLen + 1 |
4876 ] |
4894 ] |
4877 ] ifFalse:[ |
4895 ] ifFalse:[ |
4878 len2 < len1 ifTrue:[ |
4896 len2 < len1 ifTrue:[ |
4879 newLen := len1. |
4897 newLen := len1. |
4880 (digitByteArray at:len1) == 16rFF ifTrue:[ |
4898 (digitByteArray at:len1) == 16rFF ifTrue:[ |
4881 newLen := newLen + 1 |
4899 newLen := newLen + 1 |
4882 ] |
4900 ] |
4883 ] ifFalse:[ |
4901 ] ifFalse:[ |
4884 newLen := len1 + 1. |
4902 newLen := len1 + 1. |
4885 ] |
4903 ] |
4886 ]. |
4904 ]. |
4887 |
4905 |
4888 result := self class basicNew numberOfDigits:newLen. |
4906 result := self class basicNew numberOfDigits:newLen. |
4889 result sign:newSign. |
4907 result sign:newSign. |
4890 resultDigitByteArray := result digitBytes. |
4908 resultDigitByteArray := result digitBytes. |
4891 |
4909 |
4892 index := 1. |
4910 index := 1. |
4893 carry := 0. |
4911 carry := 0. |
4894 |
4912 |
4895 done := false. |
4913 done := false. |
4896 [done] whileFalse:[ |
4914 [done] whileFalse:[ |
4897 sum := carry. |
4915 sum := carry. |
4898 (index <= len1) ifTrue:[ |
4916 (index <= len1) ifTrue:[ |
4899 sum := sum + (digitByteArray basicAt:index). |
4917 sum := sum + (digitByteArray basicAt:index). |
4900 (index <= len2) ifTrue:[ |
4918 (index <= len2) ifTrue:[ |
4901 sum := sum + (otherDigitByteArray basicAt:index) |
4919 sum := sum + (otherDigitByteArray basicAt:index) |
4902 ] |
4920 ] |
4903 ] ifFalse:[ |
4921 ] ifFalse:[ |
4904 (index <= len2) ifTrue:[ |
4922 (index <= len2) ifTrue:[ |
4905 sum := sum + (otherDigitByteArray basicAt:index) |
4923 sum := sum + (otherDigitByteArray basicAt:index) |
4906 ] ifFalse:[ |
4924 ] ifFalse:[ |
4907 "end reached" |
4925 "end reached" |
4908 done := true |
4926 done := true |
4909 ] |
4927 ] |
4910 ]. |
4928 ]. |
4911 (sum >= 16r100) ifTrue:[ |
4929 (sum >= 16r100) ifTrue:[ |
4912 carry := 1. |
4930 carry := 1. |
4913 sum := sum - 16r100 |
4931 sum := sum - 16r100 |
4914 ] ifFalse:[ |
4932 ] ifFalse:[ |
4915 carry := 0 |
4933 carry := 0 |
4916 ]. |
4934 ]. |
4917 resultDigitByteArray basicAt:index put:sum. |
4935 resultDigitByteArray basicAt:index put:sum. |
4918 index := index + 1 |
4936 index := index + 1 |
4919 ]. |
4937 ]. |
4920 ]. |
4938 ]. |
4921 |
4939 |
4922 ^ result compressed |
4940 ^ result compressed |
4923 |
4941 |
4924 "Modified: 11.8.1997 / 03:23:37 / cg" |
4942 "Modified: 11.8.1997 / 03:23:37 / cg" |