387 " |
386 " |
388 this is the common case, subtracting a SmallInteger. |
387 this is the common case, subtracting a SmallInteger. |
389 Use a special method for this case ... |
388 Use a special method for this case ... |
390 " |
389 " |
391 ((numberClass := aNumber class) == SmallInteger) ifTrue:[ |
390 ((numberClass := aNumber class) == SmallInteger) ifTrue:[ |
392 sign > 0 ifTrue:[ |
391 sign > 0 ifTrue:[ |
393 aNumber > 0 ifTrue:[ |
392 aNumber > 0 ifTrue:[ |
394 ^ self absFastMinus:aNumber sign:1 |
393 ^ self absFastMinus:aNumber sign:1 |
395 ]. |
394 ]. |
396 ^ self absFastPlus:aNumber sign:1 |
395 ^ self absFastPlus:aNumber sign:1 |
397 ]. |
396 ]. |
398 aNumber > 0 ifTrue:[ |
397 aNumber > 0 ifTrue:[ |
399 ^ self absFastPlus:aNumber sign:-1 |
398 ^ self absFastPlus:aNumber sign:-1 |
400 ]. |
399 ]. |
401 ^ self absFastMinus:aNumber sign:-1 |
400 ^ self absFastMinus:aNumber sign:-1 |
402 ]. |
401 ]. |
403 |
402 |
404 " |
403 " |
405 if the argument is not a largeInteger, coerce |
404 if the argument is not a largeInteger, coerce |
406 " |
405 " |
407 (numberClass == self class) ifFalse:[ |
406 (numberClass == self class) ifFalse:[ |
408 ^ self retry:#- coercing:aNumber |
407 ^ self retry:#- coercing:aNumber |
409 ]. |
408 ]. |
410 |
409 |
411 otherSign := aNumber sign. |
410 otherSign := aNumber sign. |
412 (sign > 0) ifTrue:[ |
411 (sign > 0) ifTrue:[ |
413 "I am positive" |
412 "I am positive" |
414 (otherSign > 0) ifTrue:[ |
413 (otherSign > 0) ifTrue:[ |
415 "+large - +large" |
414 "+large - +large" |
416 ^ self absMinus:aNumber sign:1 |
415 ^ self absMinus:aNumber sign:1 |
417 ]. |
416 ]. |
418 (otherSign < 0) ifTrue:[ |
417 (otherSign < 0) ifTrue:[ |
419 "+large - -large" |
418 "+large - -large" |
420 ^ self absPlus:aNumber sign:1 |
419 ^ self absPlus:aNumber sign:1 |
421 ]. |
420 ]. |
422 "should not happen" |
421 "should not happen" |
423 ^ self |
422 ^ self |
424 ]. |
423 ]. |
425 "I am negative" |
424 "I am negative" |
426 (otherSign > 0) ifTrue:[ |
425 (otherSign > 0) ifTrue:[ |
427 "-large - +large" |
426 "-large - +large" |
428 ^ self absPlus:aNumber sign:-1 |
427 ^ self absPlus:aNumber sign:-1 |
429 ]. |
428 ]. |
430 (otherSign < 0) ifTrue:[ |
429 (otherSign < 0) ifTrue:[ |
431 "-large - -large" |
430 "-large - -large" |
432 ^ self absMinus:aNumber sign:-1 |
431 ^ self absMinus:aNumber sign:-1 |
433 ]. |
432 ]. |
434 ^ self |
433 ^ self |
435 |
434 |
436 " |
435 " |
437 12345678901234567890 - 0 |
436 12345678901234567890 - 0 |
2977 OBJ _digitByteArray = __INST(digitByteArray); |
2976 OBJ _digitByteArray = __INST(digitByteArray); |
2978 |
2977 |
2979 if (__isByteArray(_digitByteArray) |
2978 if (__isByteArray(_digitByteArray) |
2980 && __isByteArray(otherDigitByteArray) |
2979 && __isByteArray(otherDigitByteArray) |
2981 && __isByteArray(resultDigitByteArray)) { |
2980 && __isByteArray(resultDigitByteArray)) { |
2982 int __len1 = __intVal(len1); |
2981 int __len1 = __intVal(len1); |
2983 int __len2 = __intVal(len2); |
2982 int __len2 = __intVal(len2); |
2984 int __minLen = __len1 < __len2 ? __len1 : __len2; |
2983 int __minLen = __len1 < __len2 ? __len1 : __len2; |
2985 int __index, __borrow = 0; |
2984 int __index, __borrow = 0; |
2986 INT __diff; |
2985 INT __diff; |
2987 unsigned char *__myDigits, *__otherDigits, *__resultDigits; |
2986 unsigned char *__myDigits, *__otherDigits, *__resultDigits; |
2988 |
2987 |
2989 ok = true; |
2988 ok = true; |
2990 |
2989 |
2991 __resultDigits = __ByteArrayInstPtr(resultDigitByteArray)->ba_element; |
2990 __resultDigits = __ByteArrayInstPtr(resultDigitByteArray)->ba_element; |
2992 __otherDigits = __ByteArrayInstPtr(otherDigitByteArray)->ba_element; |
2991 __otherDigits = __ByteArrayInstPtr(otherDigitByteArray)->ba_element; |
2993 __myDigits = __ByteArrayInstPtr(_digitByteArray)->ba_element; |
2992 __myDigits = __ByteArrayInstPtr(_digitByteArray)->ba_element; |
2994 |
2993 |
2995 __index = 1; |
2994 __index = 1; |
2996 |
2995 |
2997 #if defined(__LSBFIRST__) |
2996 #if defined(__LSBFIRST__) |
2998 # if __POINTER_SIZE__ == 8 |
2997 # if __POINTER_SIZE__ == 8 |
2999 /* |
2998 /* |
3000 * subtract int-wise |
2999 * subtract int-wise |
3001 */ |
3000 */ |
3002 while ((__index+3) <= __minLen) { |
3001 while ((__index+3) <= __minLen) { |
3003 /* do not make this into one expression - ask cg why */ |
3002 /* do not make this into one expression - ask cg why */ |
3004 __diff = ((unsigned int *)(__myDigits+__index-1))[0]; |
3003 __diff = ((unsigned int *)(__myDigits+__index-1))[0]; |
3005 __diff -= ((unsigned int *)(__otherDigits+__index-1))[0]; |
3004 __diff -= ((unsigned int *)(__otherDigits+__index-1))[0]; |
3006 __diff -= __borrow; |
3005 __diff -= __borrow; |
3007 |
3006 |
3008 if (__diff >= 0) { |
3007 if (__diff >= 0) { |
3009 __borrow = 0; |
3008 __borrow = 0; |
3010 } else { |
3009 } else { |
3011 __borrow = 1; |
3010 __borrow = 1; |
3012 /* __diff += 0x10000; */ |
3011 /* __diff += 0x10000; */ |
3013 } |
3012 } |
3014 ((unsigned int *)(__resultDigits+__index-1))[0] = __diff; |
3013 ((unsigned int *)(__resultDigits+__index-1))[0] = __diff; |
3015 __index += 4; |
3014 __index += 4; |
3016 } |
3015 } |
3017 # endif /* 64bit */ |
3016 # endif /* 64bit */ |
3018 |
3017 |
3019 /* |
3018 /* |
3020 * subtract short-wise |
3019 * subtract short-wise |
3021 */ |
3020 */ |
3022 while (__index < __minLen) { /* i.e. index+1 <= minLen */ |
3021 while (__index < __minLen) { /* i.e. index+1 <= minLen */ |
3023 /* do not make this into one expression - ask cg why */ |
3022 /* do not make this into one expression - ask cg why */ |
3024 __diff = ((unsigned short *)(__myDigits+__index-1))[0]; |
3023 __diff = ((unsigned short *)(__myDigits+__index-1))[0]; |
3025 __diff -= ((unsigned short *)(__otherDigits+__index-1))[0]; |
3024 __diff -= ((unsigned short *)(__otherDigits+__index-1))[0]; |
3026 __diff -= __borrow; |
3025 __diff -= __borrow; |
3027 if (__diff >= 0) { |
3026 if (__diff >= 0) { |
3028 __borrow = 0; |
3027 __borrow = 0; |
3029 } else { |
3028 } else { |
3030 __borrow = 1; |
3029 __borrow = 1; |
3031 /* __diff += 0x10000; */ |
3030 /* __diff += 0x10000; */ |
3032 } |
3031 } |
3033 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3032 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3034 __index += 2; |
3033 __index += 2; |
3035 } |
3034 } |
3036 |
3035 |
3037 if (__index == __minLen) { |
3036 if (__index == __minLen) { |
3038 /* one of the operands has odd length - cannot continue short-wise */ |
3037 /* one of the operands has odd length - cannot continue short-wise */ |
3039 } else { |
3038 } else { |
3040 if (__len1 > __len2) { |
3039 if (__len1 > __len2) { |
3041 while (__index < __len1) { |
3040 while (__index < __len1) { |
3042 /* do not make this into one expression - ask cg why */ |
3041 /* do not make this into one expression - ask cg why */ |
3043 __diff = ((unsigned short *)(__myDigits+__index-1))[0]; |
3042 __diff = ((unsigned short *)(__myDigits+__index-1))[0]; |
3044 __diff -= __borrow; |
3043 __diff -= __borrow; |
3045 if (__diff >= 0) { |
3044 if (__diff >= 0) { |
3046 __borrow = 0; |
3045 __borrow = 0; |
3047 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3046 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3048 __index += 2; |
3047 __index += 2; |
3049 |
3048 |
3050 /* copy over rest */ |
3049 /* copy over rest */ |
3051 while (__index < __len1) { |
3050 while (__index < __len1) { |
3052 ((unsigned short *)(__resultDigits+__index-1))[0] = ((unsigned short *)(__myDigits+__index-1))[0]; |
3051 ((unsigned short *)(__resultDigits+__index-1))[0] = ((unsigned short *)(__myDigits+__index-1))[0]; |
3053 __index+=2; |
3052 __index+=2; |
3054 } |
3053 } |
3055 if (__index <= __len1) { |
3054 if (__index <= __len1) { |
3056 __resultDigits[__index-1] = __myDigits[__index-1]; |
3055 __resultDigits[__index-1] = __myDigits[__index-1]; |
3057 __index++; |
3056 __index++; |
3058 } |
3057 } |
3059 break; |
3058 break; |
3060 } |
3059 } |
3061 __borrow = 1; |
3060 __borrow = 1; |
3062 /* __diff += 0x10000; */ |
3061 /* __diff += 0x10000; */ |
3063 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3062 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3064 __index += 2; |
3063 __index += 2; |
3065 } |
3064 } |
3066 } else { |
3065 } else { |
3067 if (__len2 > __len1) { |
3066 if (__len2 > __len1) { |
3068 while (__index < __len2) { |
3067 while (__index < __len2) { |
3069 /* do not make this into one expression - ask cg why */ |
3068 /* do not make this into one expression - ask cg why */ |
3070 __diff = 0; |
3069 __diff = 0; |
3071 __diff -= ((unsigned short *)(__otherDigits+__index-1))[0]; |
3070 __diff -= ((unsigned short *)(__otherDigits+__index-1))[0]; |
3072 __diff -= __borrow; |
3071 __diff -= __borrow; |
3073 if (__diff >= 0) { |
3072 if (__diff >= 0) { |
3074 __borrow = 0; |
3073 __borrow = 0; |
3075 } else { |
3074 } else { |
3076 __borrow = 1; |
3075 __borrow = 1; |
3077 /* __diff += 0x10000; */ |
3076 /* __diff += 0x10000; */ |
3078 } |
3077 } |
3079 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3078 ((unsigned short *)(__resultDigits+__index-1))[0] = __diff; |
3080 __index += 2; |
3079 __index += 2; |
3081 } |
3080 } |
3082 } |
3081 } |
3083 } |
3082 } |
3084 } |
3083 } |
3085 #endif |
3084 #endif |
3086 /* |
3085 /* |
3087 * subtract byte-wise |
3086 * subtract byte-wise |
3088 */ |
3087 */ |
3089 while (__index <= __minLen) { |
3088 while (__index <= __minLen) { |
3090 /* do not make this into one expression - ask cg why */ |
3089 /* do not make this into one expression - ask cg why */ |
3091 __diff = __myDigits[__index-1]; |
3090 __diff = __myDigits[__index-1]; |
3092 __diff -= __otherDigits[__index-1]; |
3091 __diff -= __otherDigits[__index-1]; |
3093 __diff -= __borrow; |
3092 __diff -= __borrow; |
3094 if (__diff >= 0) { |
3093 if (__diff >= 0) { |
3095 __borrow = 0; |
3094 __borrow = 0; |
3096 } else { |
3095 } else { |
3097 __borrow = 1; |
3096 __borrow = 1; |
3098 /* __diff += 0x100; */ |
3097 /* __diff += 0x100; */ |
3099 } |
3098 } |
3100 __resultDigits[__index-1] = __diff; |
3099 __resultDigits[__index-1] = __diff; |
3101 __index++; |
3100 __index++; |
3102 } |
3101 } |
3103 |
3102 |
3104 if (__len1 > __len2) { |
3103 if (__len1 > __len2) { |
3105 while (__index <= __len1) { |
3104 while (__index <= __len1) { |
3106 /* do not make this into one expression - ask cg why */ |
3105 /* do not make this into one expression - ask cg why */ |
3107 __diff = __myDigits[__index-1]; |
3106 __diff = __myDigits[__index-1]; |
3108 __diff -= __borrow; |
3107 __diff -= __borrow; |
3109 if (__diff >= 0) { |
3108 if (__diff >= 0) { |
3110 __borrow = 0; |
3109 __borrow = 0; |
3111 /* copy over rest */ |
3110 /* copy over rest */ |
3112 __resultDigits[__index-1] = __diff; |
3111 __resultDigits[__index-1] = __diff; |
3113 __index++; |
3112 __index++; |
3114 while (__index <= __len1) { |
3113 while (__index <= __len1) { |
3115 __resultDigits[__index-1] = __myDigits[__index-1]; |
3114 __resultDigits[__index-1] = __myDigits[__index-1]; |
3116 __index++; |
3115 __index++; |
3117 } |
3116 } |
3118 break; |
3117 break; |
3119 } |
3118 } |
3120 __borrow = 1; |
3119 __borrow = 1; |
3121 /* __diff += 0x100; */ |
3120 /* __diff += 0x100; */ |
3122 __resultDigits[__index-1] = __diff; |
3121 __resultDigits[__index-1] = __diff; |
3123 __index++; |
3122 __index++; |
3124 } |
3123 } |
3125 } else { |
3124 } else { |
3126 if (__len2 > __len1) { |
3125 if (__len2 > __len1) { |
3127 while (__index <= __len2) { |
3126 while (__index <= __len2) { |
3128 /* do not make this into one expression - ask cg why */ |
3127 /* do not make this into one expression - ask cg why */ |
3129 __diff = 0; |
3128 __diff = 0; |
3130 __diff -= __otherDigits[__index-1]; |
3129 __diff -= __otherDigits[__index-1]; |
3131 __diff -= __borrow; |
3130 __diff -= __borrow; |
3132 if (__diff >= 0) { |
3131 if (__diff >= 0) { |
3133 __borrow = 0; |
3132 __borrow = 0; |
3134 } else { |
3133 } else { |
3135 __borrow = 1; |
3134 __borrow = 1; |
3136 /* __diff += 0x100; */ |
3135 /* __diff += 0x100; */ |
3137 } |
3136 } |
3138 __resultDigits[__index-1] = __diff; |
3137 __resultDigits[__index-1] = __diff; |
3139 __index++; |
3138 __index++; |
3140 } |
3139 } |
3141 } |
3140 } |
3142 } |
3141 } |
3143 borrow = __mkSmallInteger(__borrow); |
3142 borrow = __mkSmallInteger(__borrow); |
3144 index = __mkSmallInteger(__index); |
3143 index = __mkSmallInteger(__index); |
3145 lastDigit = __mkSmallInteger(__resultDigits[__intVal(lResult)-1]); |
3144 lastDigit = __mkSmallInteger(__resultDigits[__intVal(lResult)-1]); |
3146 } |
3145 } |
3147 %}. |
3146 %}. |
3148 ok == true ifFalse:[ |
3147 ok == true ifFalse:[ |
3149 index := 1. |
3148 index := 1. |
3150 borrow := 0. |
3149 borrow := 0. |
3151 |
3150 |
3152 done := false. |
3151 done := false. |
3153 [done] whileFalse:[ |
3152 [done] whileFalse:[ |
3154 diff := borrow. |
3153 diff := borrow. |
3155 (index <= len1) ifTrue:[ |
3154 (index <= len1) ifTrue:[ |
3156 diff := diff + (digitByteArray basicAt:index). |
3155 diff := diff + (digitByteArray basicAt:index). |
3157 (index <= len2) ifTrue:[ |
3156 (index <= len2) ifTrue:[ |
3158 diff := diff - (otherDigitByteArray basicAt:index) |
3157 diff := diff - (otherDigitByteArray basicAt:index) |
3159 ] |
3158 ] |
3160 ] ifFalse:[ |
3159 ] ifFalse:[ |
3161 (index <= len2) ifTrue:[ |
3160 (index <= len2) ifTrue:[ |
3162 diff := diff - (otherDigitByteArray basicAt:index) |
3161 diff := diff - (otherDigitByteArray basicAt:index) |
3163 ] ifFalse:[ |
3162 ] ifFalse:[ |
3164 "end reached" |
3163 "end reached" |
3165 done := true |
3164 done := true |
3166 ] |
3165 ] |
3167 ]. |
3166 ]. |
3168 |
3167 |
3169 "/ workaround for |
3168 "/ workaround for |
3170 "/ gcc code generator bug |
3169 "/ gcc code generator bug |
3171 |
3170 |
3172 (diff >= 0) ifTrue:[ |
3171 (diff >= 0) ifTrue:[ |
3173 borrow := 0 |
3172 borrow := 0 |
3174 ] ifFalse:[ |
3173 ] ifFalse:[ |
3175 borrow := -1. |
3174 borrow := -1. |
3176 diff := diff + 16r100 |
3175 diff := diff + 16r100 |
3177 ]. |
3176 ]. |
3178 |
3177 |
3179 "/ (diff < 0) ifTrue:[ |
3178 "/ (diff < 0) ifTrue:[ |
3180 "/ borrow := -1. |
3179 "/ borrow := -1. |
3181 "/ diff := diff + 16r100 |
3180 "/ diff := diff + 16r100 |
3182 "/ ] ifFalse:[ |
3181 "/ ] ifFalse:[ |
3183 "/ borrow := 0 |
3182 "/ borrow := 0 |
3184 "/ ]. |
3183 "/ ]. |
3185 |
3184 |
3186 resultDigitByteArray basicAt:index put:diff. |
3185 resultDigitByteArray basicAt:index put:diff. |
3187 index := index + 1 |
3186 index := index + 1 |
3188 ]. |
3187 ]. |
3189 lastDigit := resultDigitByteArray basicAt:lResult. |
3188 lastDigit := resultDigitByteArray basicAt:lResult. |
3190 ]. |
3189 ]. |
3191 |
3190 |
3192 (borrow ~~ 0) ifTrue:[ |
3191 (borrow ~~ 0) ifTrue:[ |
3193 "/ must generate 255's complement |
3192 "/ must generate 255's complement |
3194 |
3193 |
3195 result sign:-1. |
3194 result sign:newSign negated. |
3196 [index <= lResult] whileTrue:[ |
3195 [index <= lResult] whileTrue:[ |
3197 resultDigitByteArray basicAt:index put:16rFF. |
3196 resultDigitByteArray basicAt:index put:16rFF. |
3198 index := index + 1. |
3197 index := index + 1. |
3199 ]. |
3198 ]. |
3200 index := lResult. |
3199 index := lResult. |
3201 [index > 0] whileTrue:[ |
3200 [index > 0] whileTrue:[ |
3202 resultDigitByteArray basicAt:index put:(255 - (resultDigitByteArray at:index)). |
3201 resultDigitByteArray basicAt:index put:(255 - (resultDigitByteArray at:index)). |
3203 index := index - 1. |
3202 index := index - 1. |
3204 ]. |
3203 ]. |
3205 |
3204 |
3206 index := 1. |
3205 index := 1. |
3207 carry := 1. |
3206 carry := 1. |
3208 [carry ~~ 0] whileTrue:[ |
3207 [carry ~~ 0] whileTrue:[ |
3209 (index <= lResult) ifTrue:[ |
3208 (index <= lResult) ifTrue:[ |
3210 carry := (resultDigitByteArray basicAt:index) + carry. |
3209 carry := (resultDigitByteArray basicAt:index) + carry. |
3211 ]. |
3210 ]. |
3212 resultDigitByteArray basicAt:index put:(carry bitAnd:16rFF). |
3211 resultDigitByteArray basicAt:index put:(carry bitAnd:16rFF). |
3213 carry := carry bitShift:-8. |
3212 carry := carry bitShift:-8. |
3214 index := index + 1 |
3213 index := index + 1 |
3215 ]. |
3214 ]. |
3216 lastDigit := resultDigitByteArray basicAt:lResult. |
3215 lastDigit := resultDigitByteArray basicAt:lResult. |
3217 ]. |
3216 ]. |
3218 (lastDigit ~~ 0 and:[lResult > SmallInteger maxBytes]) ifTrue:[ |
3217 (lastDigit ~~ 0 and:[lResult > SmallInteger maxBytes]) ifTrue:[ |
3219 ^ result |
3218 ^ result |
3220 ]. |
3219 ]. |
3221 ^ result compressed |
3220 ^ result compressed |
3222 |
3221 |
3223 "Modified: 5.11.1996 / 14:09:25 / cg" |
3222 "Modified: 5.11.1996 / 14:09:25 / cg" |
3224 ! |
3223 ! |