211 #if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 2) |
211 #if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 2) |
212 # define USE_LONGLONG_FOR_MUL |
212 # define USE_LONGLONG_FOR_MUL |
213 #endif |
213 #endif |
214 |
214 |
215 if (__isSmallInteger(aNumber)) { |
215 if (__isSmallInteger(aNumber)) { |
216 myValue = __intVal(self); |
216 myValue = __intVal(self); |
217 otherValue = __intVal(aNumber); |
217 otherValue = __intVal(aNumber); |
218 |
218 |
219 #if defined(USE_LONGLONG_FOR_MUL) |
219 #if defined(USE_LONGLONG_FOR_MUL) |
220 { |
220 { |
221 # if defined(__alpha__) && !defined(__alpha64__) |
221 # if defined(__alpha__) && !defined(__alpha64__) |
222 # define LONGLONG INT64 |
222 # define LONGLONG INT64 |
223 # else |
223 # else |
224 # define LONGLONG long long |
224 # define LONGLONG long long |
225 # endif |
225 # endif |
226 LONGLONG product; |
226 LONGLONG product; |
227 |
227 |
228 product = (LONGLONG)myValue * (LONGLONG)otherValue; |
228 product = (LONGLONG)myValue * (LONGLONG)otherValue; |
229 if ((product >= (LONGLONG)_MIN_INT) |
229 if ((product >= (LONGLONG)_MIN_INT) |
230 && (product <= (LONGLONG)_MAX_INT)) { |
230 && (product <= (LONGLONG)_MAX_INT)) { |
231 RETURN ( __mkSmallInteger((INT)product) ); |
231 RETURN ( __mkSmallInteger((INT)product) ); |
232 } |
232 } |
233 if (product < 0) { |
233 if (product < 0) { |
234 negative = -1; |
234 negative = -1; |
235 product = -product; |
235 product = -product; |
236 } else { |
236 } else { |
237 negative = 1; |
237 negative = 1; |
238 } |
238 } |
239 productHi = product >> 32; |
239 productHi = product >> 32; |
240 productLow = product & 0xFFFFFFFFL; |
240 productLow = product & 0xFFFFFFFFL; |
241 } |
241 } |
242 #else /* no long-long */ |
242 #else /* no long-long */ |
243 negative = 1; |
243 negative = 1; |
244 if (myValue < 0) { |
244 if (myValue < 0) { |
245 negative = -1; |
245 negative = -1; |
246 myValue = -myValue; |
246 myValue = -myValue; |
247 } |
247 } |
248 if (otherValue < 0) { |
248 if (otherValue < 0) { |
249 negative = -negative; |
249 negative = -negative; |
250 otherValue = -otherValue; |
250 otherValue = -otherValue; |
251 } |
251 } |
252 |
252 |
253 # if defined(__GNUC__) && defined(__mc68k__) |
253 # if defined(__GNUC__) && defined(__mc68k__) |
254 asm ("mulu%.l %3,%1:%0" |
254 asm ("mulu%.l %3,%1:%0" |
255 : "=d" ((unsigned long)(productLow)), |
255 : "=d" ((unsigned long)(productLow)), |
256 "=d" ((unsigned long)(productHi)) |
256 "=d" ((unsigned long)(productHi)) |
257 : "%0" ((unsigned long)(myValue)), |
257 : "%0" ((unsigned long)(myValue)), |
258 "dmi" ((unsigned long)(otherValue))); |
258 "dmi" ((unsigned long)(otherValue))); |
259 # else |
259 # else |
260 # if defined (__GNUC__) && defined(__i386__) |
260 # if defined (__GNUC__) && defined(__i386__) |
261 asm ("mull %3" |
261 asm ("mull %3" |
262 : "=a" ((unsigned long)(productLow)), |
262 : "=a" ((unsigned long)(productLow)), |
263 "=d" ((unsigned long)(productHi)) |
263 "=d" ((unsigned long)(productHi)) |
264 : "%0" ((unsigned long)(myValue)), |
264 : "%0" ((unsigned long)(myValue)), |
265 "rm" ((unsigned long)(otherValue))); |
265 "rm" ((unsigned long)(otherValue))); |
266 # else |
266 # else |
267 # if defined(WIN32) && defined(__BORLANDC__) |
267 # if defined(WIN32) && defined(__BORLANDC__) |
268 asm { |
268 asm { |
269 mov eax, myValue |
269 mov eax, myValue |
270 mov edx, otherValue |
270 mov edx, otherValue |
271 mul edx |
271 mul edx |
272 mov productLow, eax |
272 mov productLow, eax |
273 mov productHi, edx |
273 mov productHi, edx |
274 } |
274 } |
275 # else /* generic */ |
275 # else /* generic */ |
276 { |
276 { |
277 unsigned INT pHH, pHL, pLH, pLL; |
277 unsigned INT pHH, pHL, pLH, pLL; |
278 unsigned INT low1, low2, hi1, hi2; |
278 unsigned INT low1, low2, hi1, hi2; |
279 unsigned INT t; |
279 unsigned INT t; |
280 |
280 |
281 /* unsigned multiply myValue * otherValue -> productHi, productLow |
281 /* unsigned multiply myValue * otherValue -> productHi, productLow |
282 * |
282 * |
283 * this is too slow: |
283 * this is too slow: |
284 * since most machines can do 32*32 to 64 bit multiply, |
284 * since most machines can do 32*32 to 64 bit multiply, |
285 * (or at least 32*32 with Overflow check) |
285 * (or at least 32*32 with Overflow check) |
286 * - need more assembler (inline) functions here |
286 * - need more assembler (inline) functions here |
287 */ |
287 */ |
288 # if __POINTER_SIZE__ == 8 |
288 # if __POINTER_SIZE__ == 8 |
289 low1 = low32Bits((unsigned INT)myValue); |
289 low1 = low32Bits((unsigned INT)myValue); |
290 hi1 = hi32Bits((unsigned INT)myValue); |
290 hi1 = hi32Bits((unsigned INT)myValue); |
291 low2 = low32Bits((unsigned INT)otherValue); |
291 low2 = low32Bits((unsigned INT)otherValue); |
292 hi2 = hi32Bits((unsigned INT)otherValue); |
292 hi2 = hi32Bits((unsigned INT)otherValue); |
293 # define LLMASK 0xC000000000000000L |
293 # define LLMASK 0xC000000000000000L |
294 # else |
294 # else |
295 low1 = low16Bits((unsigned INT)myValue); |
295 low1 = low16Bits((unsigned INT)myValue); |
296 hi1 = hi16Bits((unsigned INT)myValue); |
296 hi1 = hi16Bits((unsigned INT)myValue); |
297 low2 = low16Bits((unsigned INT)otherValue); |
297 low2 = low16Bits((unsigned INT)otherValue); |
298 hi2 = hi16Bits((unsigned INT)otherValue); |
298 hi2 = hi16Bits((unsigned INT)otherValue); |
299 # define LLMASK 0xC0000000 |
299 # define LLMASK 0xC0000000 |
300 # endif |
300 # endif |
301 |
301 |
302 pLH = low1 * hi2; |
302 pLH = low1 * hi2; |
303 pHL = hi1 * low2; |
303 pHL = hi1 * low2; |
304 pLL = low1 * low2; |
304 pLL = low1 * low2; |
305 pHH = hi1 * hi2; |
305 pHH = hi1 * hi2; |
306 |
306 |
307 /* |
307 /* |
308 * the common case ... |
308 * the common case ... |
309 */ |
309 */ |
310 if ((pHL == 0) |
310 if ((pHL == 0) |
311 && (pLH == 0) |
311 && (pLH == 0) |
312 && (pHH == 0) |
312 && (pHH == 0) |
313 && ((pLL & LLMASK) == 0)) { |
313 && ((pLL & LLMASK) == 0)) { |
314 if (negative < 0) { |
314 if (negative < 0) { |
315 RETURN ( __mkSmallInteger(- ((INT)pLL)) ); |
315 RETURN ( __mkSmallInteger(- ((INT)pLL)) ); |
316 } |
316 } |
317 RETURN ( __mkSmallInteger((INT)pLL) ); |
317 RETURN ( __mkSmallInteger((INT)pLL) ); |
318 } |
318 } |
319 |
319 |
320 /* |
320 /* |
321 * pHH |--------|--------| |
321 * pHH |--------|--------| |
322 * pLH |--------|--------| |
322 * pLH |--------|--------| |
323 * pHL |--------|--------| |
323 * pHL |--------|--------| |
324 * pLL |--------|--------| |
324 * pLL |--------|--------| |
325 */ |
325 */ |
326 |
326 |
327 # if __POINTER_SIZE__ == 8 |
327 # if __POINTER_SIZE__ == 8 |
328 t = low32Bits(pLH) + low32Bits(pHL) + hi32Bits(pLL); |
328 t = low32Bits(pLH) + low32Bits(pHL) + hi32Bits(pLL); |
329 productLow = (t << 32) + low32Bits(pLL); |
329 productLow = (t << 32) + low32Bits(pLL); |
330 productHi = pHH + hi32Bits(t) + hi32Bits(pHL) + hi32Bits(pLH); |
330 productHi = pHH + hi32Bits(t) + hi32Bits(pHL) + hi32Bits(pLH); |
331 # else |
331 # else |
332 t = low16Bits(pLH) + low16Bits(pHL) + hi16Bits(pLL); |
332 t = low16Bits(pLH) + low16Bits(pHL) + hi16Bits(pLL); |
333 productLow = (t << 16) + low16Bits(pLL); |
333 productLow = (t << 16) + low16Bits(pLL); |
334 productHi = pHH + hi16Bits(t) + hi16Bits(pHL) + hi16Bits(pLH); |
334 productHi = pHH + hi16Bits(t) + hi16Bits(pHL) + hi16Bits(pLH); |
335 # endif |
335 # endif |
336 } |
336 } |
337 # endif /* ! WIN32 */ |
337 # endif /* ! WIN32 */ |
338 # endif /* ! (__GNUC__ && __i386__) */ |
338 # endif /* ! (__GNUC__ && __i386__) */ |
339 # endif /* ! (__GNUC__ && __mc68k__) */ |
339 # endif /* ! (__GNUC__ && __mc68k__) */ |
340 |
340 |
341 if (productHi == 0) { |
341 if (productHi == 0) { |
342 if (negative < 0) { |
342 if (negative < 0) { |
343 if (productLow <= -(_MIN_INT)) { |
343 if (productLow <= -(_MIN_INT)) { |
344 RETURN ( __mkSmallInteger(-((INT)productLow)) ); |
344 RETURN ( __mkSmallInteger(-((INT)productLow)) ); |
345 } |
345 } |
346 } else { |
346 } else { |
347 if (productLow <= _MAX_INT) { |
347 if (productLow <= _MAX_INT) { |
348 RETURN ( __mkSmallInteger(productLow) ); |
348 RETURN ( __mkSmallInteger(productLow) ); |
349 } |
349 } |
350 } |
350 } |
351 } |
351 } |
352 #endif /* ! USE_LONGLONG */ |
352 #endif /* ! USE_LONGLONG */ |
353 |
353 |
354 #if __POINTER_SIZE__ == 8 |
354 #if __POINTER_SIZE__ == 8 |
355 RETURN (__MKLARGEINT128(negative, productLow, productHi)); |
355 RETURN (__MKLARGEINT128(negative, productLow, productHi)); |
356 #else |
356 #else |
357 RETURN (__MKLARGEINT64(negative, productLow, productHi)); |
357 RETURN (__MKLARGEINT64(negative, productLow, productHi)); |
358 #endif |
358 #endif |
359 } else if (__isFloatLike(aNumber)) { |
359 } else if (__isFloatLike(aNumber)) { |
360 OBJ newFloat; |
360 OBJ newFloat; |
361 double val = (double)__intVal(self) * __floatVal(aNumber); |
361 double val = (double)__intVal(self) * __floatVal(aNumber); |
362 |
362 |
363 __qMKFLOAT(newFloat, val); |
363 __qMKFLOAT(newFloat, val); |
364 RETURN ( newFloat ); |
364 RETURN ( newFloat ); |
365 } else if (__isShortFloat(aNumber)) { |
365 } else if (__isShortFloat(aNumber)) { |
366 OBJ newFloat; |
366 OBJ newFloat; |
367 float val = (float)__intVal(self) * __shortFloatVal(aNumber); |
367 float val = (float)__intVal(self) * __shortFloatVal(aNumber); |
368 |
368 |
369 __qMKSFLOAT(newFloat, val); |
369 __qMKSFLOAT(newFloat, val); |
370 RETURN ( newFloat ); |
370 RETURN ( newFloat ); |
371 } |
371 } |
372 %}. |
372 %}. |
373 ^ aNumber productFromInteger:self |
373 ^ aNumber productFromInteger:self |
374 ! |
374 ! |
375 |
375 |
561 */ |
561 */ |
562 |
562 |
563 INT dividend, divisor, rslt; |
563 INT dividend, divisor, rslt; |
564 |
564 |
565 if (__isSmallInteger(aNumber)) { |
565 if (__isSmallInteger(aNumber)) { |
566 divisor = __intVal(aNumber); |
566 divisor = __intVal(aNumber); |
567 if (divisor != 0) { |
567 if (divisor != 0) { |
568 dividend = __intVal(self); |
568 dividend = __intVal(self); |
569 rslt = dividend / divisor; |
569 rslt = dividend / divisor; |
570 /* |
570 /* |
571 * Optimized to speed up positive result |
571 * Optimized to speed up positive result |
572 */ |
572 */ |
573 if (rslt <= 0) { |
573 if (rslt <= 0) { |
574 if (rslt == 0) { |
574 if (rslt == 0) { |
575 if ((dividend ^ divisor) < 0) { |
575 if ((dividend ^ divisor) < 0) { |
576 /* |
576 /* |
577 * result (negative) has been truncated toward 0. |
577 * result (negative) has been truncated toward 0. |
578 * Return -1, because we truncate toward negative inf. |
578 * Return -1, because we truncate toward negative inf. |
579 */ |
579 */ |
580 rslt = -1; |
580 rslt = -1; |
581 } |
581 } |
582 } else { |
582 } else { |
583 /* |
583 /* |
584 * If result (negative) has been truncated toward 0, |
584 * If result (negative) has been truncated toward 0, |
585 * subtract 1, because we truncate toward negative inf. |
585 * subtract 1, because we truncate toward negative inf. |
586 */ |
586 */ |
587 if (divisor > 0) { |
587 if (divisor > 0) { |
588 if (rslt * divisor > dividend) { |
588 if (rslt * divisor > dividend) { |
589 rslt--; |
589 rslt--; |
590 } |
590 } |
591 } else { |
591 } else { |
592 if (rslt * divisor < dividend) { |
592 if (rslt * divisor < dividend) { |
593 rslt--; |
593 rslt--; |
594 } |
594 } |
595 } |
595 } |
596 } |
596 } |
597 } |
597 } |
598 RETURN ( __mkSmallInteger(rslt) ); |
598 RETURN ( __mkSmallInteger(rslt) ); |
599 } |
599 } |
600 } else { |
600 } else { |
601 if (__isFraction(aNumber)) { |
601 if (__isFraction(aNumber)) { |
602 OBJ t; |
602 OBJ t; |
603 INT num, den; |
603 INT num, den; |
604 |
604 |
605 t = __FractionInstPtr(aNumber)->f_numerator; |
605 t = __FractionInstPtr(aNumber)->f_numerator; |
606 if (__isSmallInteger(t)) { |
606 if (__isSmallInteger(t)) { |
607 num = __intVal(t); |
607 num = __intVal(t); |
608 t = __FractionInstPtr(aNumber)->f_denominator; |
608 t = __FractionInstPtr(aNumber)->f_denominator; |
609 if (__isSmallInteger(t)) { |
609 if (__isSmallInteger(t)) { |
610 den = __intVal(t); |
610 den = __intVal(t); |
611 RETURN ( __mkSmallInteger(__intVal(self) * den / num )); |
611 RETURN ( __mkSmallInteger(__intVal(self) * den / num )); |
612 } |
612 } |
613 } |
613 } |
614 } |
614 } |
615 } |
615 } |
616 %}. |
616 %}. |
617 (aNumber = 0) ifTrue:[ |
617 (aNumber = 0) ifTrue:[ |
618 ^ ZeroDivide raiseRequestWith:thisContext. |
618 ^ ZeroDivide raiseRequestWith:thisContext. |
619 ]. |
619 ]. |
620 ^ aNumber integerQuotientFromInteger:self |
620 ^ aNumber integerQuotientFromInteger:self |
621 |
621 |
622 " |
622 " |
623 9 // 4 ~~ 2 ifTrue:[self halt]. |
623 9 // 4 ~~ 2 ifTrue:[self halt]. |
662 */ |
662 */ |
663 |
663 |
664 INT dividend, divisor, rem; |
664 INT dividend, divisor, rem; |
665 |
665 |
666 if (__isSmallInteger(aNumber) |
666 if (__isSmallInteger(aNumber) |
667 && (divisor = __intVal(aNumber)) != 0) { |
667 && (divisor = __intVal(aNumber)) != 0) { |
668 /* |
668 /* |
669 * Note that the sign of something modulo a negative number is undefined |
669 * Note that the sign of something modulo a negative number is undefined |
670 * in C! |
670 * in C! |
671 */ |
671 */ |
672 dividend = __intVal(self); |
672 dividend = __intVal(self); |
673 rem = dividend % divisor; |
673 rem = dividend % divisor; |
674 if (rem) { |
674 if (rem) { |
675 if ((rem ^ divisor) < 0) { |
675 if ((rem ^ divisor) < 0) { |
676 /* sign of remainder is different from sign of divisor */ |
676 /* sign of remainder is different from sign of divisor */ |
677 rem = -rem; |
677 rem = -rem; |
678 } |
678 } |
679 if ((dividend ^ divisor) < 0) { |
679 if ((dividend ^ divisor) < 0) { |
680 /* different signs, so division would have returned a |
680 /* different signs, so division would have returned a |
681 * negative number. |
681 * negative number. |
682 * C rounds toward zero, this code will simulate |
682 * C rounds toward zero, this code will simulate |
683 * rounding towards negative infinity. |
683 * rounding towards negative infinity. |
684 */ |
684 */ |
685 rem = divisor - rem; |
685 rem = divisor - rem; |
686 } |
686 } |
687 } |
687 } |
688 RETURN ( __mkSmallInteger(rem) ); |
688 RETURN ( __mkSmallInteger(rem) ); |
689 } |
689 } |
690 %}. |
690 %}. |
691 (aNumber = 0) ifTrue:[ |
691 (aNumber = 0) ifTrue:[ |
692 ^ ZeroDivide raiseRequestWith:thisContext. |
692 ^ ZeroDivide raiseRequestWith:thisContext. |
693 ]. |
693 ]. |
694 ^ aNumber moduloFromInteger:self |
694 ^ aNumber moduloFromInteger:self |
695 |
695 |
696 " |
696 " |
697 9 \\ 4 == 1 ifFalse:[self halt]. |
697 9 \\ 4 == 1 ifFalse:[self halt]. |
1411 |
1411 |
1412 rightShift:shiftCount |
1412 rightShift:shiftCount |
1413 "return the value of the receiver shifted by shiftCount bits; |
1413 "return the value of the receiver shifted by shiftCount bits; |
1414 right shift if shiftCount > 0; left shift otherwise. |
1414 right shift if shiftCount > 0; left shift otherwise. |
1415 Notice: the result of bitShift: on negative receivers is not |
1415 Notice: the result of bitShift: on negative receivers is not |
1416 defined in the language standard (since the implementation |
1416 defined in the language standard (since the implementation |
1417 is free to choose any internal representation for integers). |
1417 is free to choose any internal representation for integers). |
1418 However, ST/X preserves the sign." |
1418 However, ST/X preserves the sign." |
1419 |
1419 |
1420 %{ /* NOCONTEXT */ |
1420 %{ /* NOCONTEXT */ |
1421 |
1421 |
1422 INT bits, count; |
1422 INT bits, count; |
1423 |
1423 |
1424 if (__isSmallInteger(shiftCount)) { |
1424 if (__isSmallInteger(shiftCount)) { |
1425 bits = __intVal(self); |
1425 bits = __intVal(self); |
1426 if (bits == 0) { |
1426 if (bits == 0) { |
1427 RETURN (self); |
1427 RETURN (self); |
1428 } |
1428 } |
1429 |
1429 |
1430 count = __intVal(shiftCount); |
1430 count = __intVal(shiftCount); |
1431 |
1431 |
1432 if (count < 0) { |
1432 if (count < 0) { |
1433 /* |
1433 /* |
1434 * a left shift |
1434 * a left shift |
1435 */ |
1435 */ |
1436 count = -count; |
1436 count = -count; |
1437 #if defined(USE_LONGLONG_FOR_SHIFT) |
1437 #if defined(USE_LONGLONG_FOR_SHIFT) |
1438 if (count <= N_INT_BITS) { |
1438 if (count <= N_INT_BITS) { |
1439 unsigned LONGLONG result; |
1439 unsigned LONGLONG result; |
1440 |
1440 |
1441 result = (unsigned LONGLONG)bits; |
1441 result = (unsigned LONGLONG)bits; |
1442 result <<= count; |
1442 result <<= count; |
1443 if (result <= _MAX_INT) { |
1443 if (result <= _MAX_INT) { |
1444 RETURN ( __mkSmallInteger(result) ); |
1444 RETURN ( __mkSmallInteger(result) ); |
1445 } |
1445 } |
1446 { |
1446 { |
1447 RETURN (__MKLARGEINT64(1, (INT)(result >> 32), (INT)(result & 0xFFFFFFFF))); |
1447 RETURN (__MKLARGEINT64(1, (INT)(result >> 32), (INT)(result & 0xFFFFFFFF))); |
1448 } |
1448 } |
1449 } |
1449 } |
1450 #else |
1450 #else |
1451 /* |
1451 /* |
1452 * check for overflow |
1452 * check for overflow |
1453 */ |
1453 */ |
1454 if (count < (N_INT_BITS-1)) { |
1454 if (count < (N_INT_BITS-1)) { |
1455 if (! (bits >> (N_INT_BITS - 1 - count))) { |
1455 if (! (bits >> (N_INT_BITS - 1 - count))) { |
1456 RETURN ( __mkSmallInteger(bits << count) ); |
1456 RETURN ( __mkSmallInteger(bits << count) ); |
1457 } |
1457 } |
1458 /* |
1458 /* |
1459 * so, there is an overflow ... |
1459 * so, there is an overflow ... |
1460 * handle it as largeInteger |
1460 * handle it as largeInteger |
1461 */ |
1461 */ |
1462 /* FALL THROUGH */ |
1462 /* FALL THROUGH */ |
1463 } |
1463 } |
1464 #endif |
1464 #endif |
1465 } else { |
1465 } else { |
1466 if (count == 0) { |
1466 if (count == 0) { |
1467 RETURN (self); |
1467 RETURN (self); |
1468 } |
1468 } |
1469 |
1469 |
1470 /* |
1470 /* |
1471 * right shifts cannot overflow |
1471 * right shifts cannot overflow |
1472 * |
1472 * |
1473 * some machines ignore shifts bigger than |
1473 * some machines ignore shifts bigger than |
1474 * the number of bits in an int ... |
1474 * the number of bits in an int ... |
1475 */ |
1475 */ |
1476 if (count > (N_INT_BITS-1)) { |
1476 if (count > (N_INT_BITS-1)) { |
1477 RETURN (__mkSmallInteger(0)); |
1477 RETURN (__mkSmallInteger(0)); |
1478 } |
1478 } |
1479 |
1479 |
1480 RETURN ( __mkSmallInteger(bits >> count) ); |
1480 RETURN ( __mkSmallInteger(bits >> count) ); |
1481 } |
1481 } |
1482 } |
1482 } |
1483 %}. |
1483 %}. |
1484 (shiftCount isMemberOf:SmallInteger) ifTrue:[ |
1484 (shiftCount isMemberOf:SmallInteger) ifTrue:[ |
1485 ^ (LargeInteger value:self) rightShift:shiftCount |
1485 ^ (LargeInteger value:self) rightShift:shiftCount |
1486 ]. |
1486 ]. |
1487 ^ self rightShift:(1 coerce:shiftCount) "/ is this a good idea ? |
1487 ^ self rightShift:(1 coerce:shiftCount) "/ is this a good idea ? |
1488 |
1488 |
1489 |
1489 |
1490 " |
1490 " |
1491 16 rightShift:2 |
1491 16 rightShift:2 |
1492 4 rightShift:-2 |
1492 4 rightShift:-2 |
1493 " |
1493 " |
1494 ! |
1494 ! |
1495 |
1495 |
1496 setBit:anInteger |
1496 setBit:anInteger |
1497 "return a new integer where the specified bit is on. |
1497 "return a new integer where the specified bit is on. |
1925 could have simply created a 4-byte largeinteger and normalize it. |
1925 could have simply created a 4-byte largeinteger and normalize it. |
1926 The code below does the normalize right away, avoiding the |
1926 The code below does the normalize right away, avoiding the |
1927 overhead of producing any intermediate byte-arrays (and the scanning) |
1927 overhead of producing any intermediate byte-arrays (and the scanning) |
1928 " |
1928 " |
1929 self == 0 ifTrue: [ |
1929 self == 0 ifTrue: [ |
1930 ^ ByteArray with:0. |
1930 ^ ByteArray with:0. |
1931 ]. |
1931 ]. |
1932 |
1932 |
1933 self < 0 ifTrue: [ |
1933 self < 0 ifTrue: [ |
1934 absValue := self negated |
1934 absValue := self negated |
1935 ] ifFalse: [ |
1935 ] ifFalse: [ |
1936 absValue := self. |
1936 absValue := self. |
1937 ]. |
1937 ]. |
1938 |
1938 |
1939 b1 := absValue bitAnd:16rFF. |
1939 b1 := absValue bitAnd:16rFF. |
1940 absValue := absValue bitShift:-8. |
1940 absValue := absValue bitShift:-8. |
1941 absValue == 0 ifTrue:[ |
1941 absValue == 0 ifTrue:[ |
1942 digitByteArray := ByteArray with:b1 |
1942 digitByteArray := ByteArray with:b1 |
1943 ] ifFalse:[ |
1943 ] ifFalse:[ |
1944 b2 := absValue bitAnd:16rFF. |
1944 b2 := absValue bitAnd:16rFF. |
1945 absValue := absValue bitShift:-8. |
1945 absValue := absValue bitShift:-8. |
1946 absValue == 0 ifTrue:[ |
1946 absValue == 0 ifTrue:[ |
1947 digitByteArray := ByteArray with:b1 with:b2 |
1947 digitByteArray := ByteArray with:b1 with:b2 |
1948 ] ifFalse:[ |
1948 ] ifFalse:[ |
1949 b3 := absValue bitAnd:16rFF. |
1949 b3 := absValue bitAnd:16rFF. |
1950 absValue := absValue bitShift:-8. |
1950 absValue := absValue bitShift:-8. |
1951 absValue == 0 ifTrue:[ |
1951 absValue == 0 ifTrue:[ |
1952 digitByteArray := ByteArray with:b1 with:b2 with:b3 |
1952 digitByteArray := ByteArray with:b1 with:b2 with:b3 |
1953 ] ifFalse:[ |
1953 ] ifFalse:[ |
1954 b4 := absValue bitAnd:16rFF. |
1954 b4 := absValue bitAnd:16rFF. |
1955 absValue := absValue bitShift:-8. |
1955 absValue := absValue bitShift:-8. |
1956 absValue == 0 ifTrue:[ |
1956 absValue == 0 ifTrue:[ |
1957 digitByteArray := ByteArray with:b1 with:b2 with:b3 with:b4 |
1957 digitByteArray := ByteArray with:b1 with:b2 with:b3 with:b4 |
1958 ] ifFalse:[ |
1958 ] ifFalse:[ |
1959 b5 := absValue bitAnd:16rFF. |
1959 b5 := absValue bitAnd:16rFF. |
1960 absValue := absValue bitShift:-8. |
1960 absValue := absValue bitShift:-8. |
1961 absValue == 0 ifTrue:[ |
1961 absValue == 0 ifTrue:[ |
1962 digitByteArray := ByteArray new:5. |
1962 digitByteArray := ByteArray new:5. |
1963 digitByteArray at:1 put:b1. |
1963 digitByteArray at:1 put:b1. |
1964 digitByteArray at:2 put:b2. |
1964 digitByteArray at:2 put:b2. |
1965 digitByteArray at:3 put:b3. |
1965 digitByteArray at:3 put:b3. |
1966 digitByteArray at:4 put:b4. |
1966 digitByteArray at:4 put:b4. |
1967 digitByteArray at:5 put:b5. |
1967 digitByteArray at:5 put:b5. |
1968 ] ifFalse:[ |
1968 ] ifFalse:[ |
1969 b6 := absValue bitAnd:16rFF. |
1969 b6 := absValue bitAnd:16rFF. |
1970 absValue := absValue bitShift:-8. |
1970 absValue := absValue bitShift:-8. |
1971 absValue == 0 ifTrue:[ |
1971 absValue == 0 ifTrue:[ |
1972 digitByteArray := ByteArray new:6. |
1972 digitByteArray := ByteArray new:6. |
1973 digitByteArray at:1 put:b1. |
1973 digitByteArray at:1 put:b1. |
1974 digitByteArray at:2 put:b2. |
1974 digitByteArray at:2 put:b2. |
1975 digitByteArray at:3 put:b3. |
1975 digitByteArray at:3 put:b3. |
1976 digitByteArray at:4 put:b4. |
1976 digitByteArray at:4 put:b4. |
1977 digitByteArray at:5 put:b5. |
1977 digitByteArray at:5 put:b5. |
1978 digitByteArray at:6 put:b6. |
1978 digitByteArray at:6 put:b6. |
1979 ] ifFalse:[ |
1979 ] ifFalse:[ |
1980 b7 := absValue bitAnd:16rFF. |
1980 b7 := absValue bitAnd:16rFF. |
1981 absValue := absValue bitShift:-8. |
1981 absValue := absValue bitShift:-8. |
1982 absValue == 0 ifTrue:[ |
1982 absValue == 0 ifTrue:[ |
1983 digitByteArray := ByteArray new:7. |
1983 digitByteArray := ByteArray new:7. |
1984 digitByteArray at:1 put:b1. |
1984 digitByteArray at:1 put:b1. |
1985 digitByteArray at:2 put:b2. |
1985 digitByteArray at:2 put:b2. |
1986 digitByteArray at:3 put:b3. |
1986 digitByteArray at:3 put:b3. |
1987 digitByteArray at:4 put:b4. |
1987 digitByteArray at:4 put:b4. |
1988 digitByteArray at:5 put:b5. |
1988 digitByteArray at:5 put:b5. |
1989 digitByteArray at:6 put:b6. |
1989 digitByteArray at:6 put:b6. |
1990 digitByteArray at:7 put:b7. |
1990 digitByteArray at:7 put:b7. |
1991 ] ifFalse:[ |
1991 ] ifFalse:[ |
1992 digitByteArray := ByteArray new:8. |
1992 digitByteArray := ByteArray new:8. |
1993 digitByteArray at:1 put:b1. |
1993 digitByteArray at:1 put:b1. |
1994 digitByteArray at:2 put:b2. |
1994 digitByteArray at:2 put:b2. |
1995 digitByteArray at:3 put:b3. |
1995 digitByteArray at:3 put:b3. |
1996 digitByteArray at:4 put:b4. |
1996 digitByteArray at:4 put:b4. |
1997 digitByteArray at:5 put:b5. |
1997 digitByteArray at:5 put:b5. |
1998 digitByteArray at:6 put:b6. |
1998 digitByteArray at:6 put:b6. |
1999 digitByteArray at:7 put:b7. |
1999 digitByteArray at:7 put:b7. |
2000 digitByteArray at:8 put:absValue. |
2000 digitByteArray at:8 put:absValue. |
2001 ] |
2001 ] |
2002 ] |
2002 ] |
2003 ] |
2003 ] |
2004 ] |
2004 ] |
2005 ] |
2005 ] |
2006 ] |
2006 ] |
2007 ]. |
2007 ]. |
2008 |
2008 |
2009 ^ digitByteArray |
2009 ^ digitByteArray |
2010 |
2010 |
2011 " |
2011 " |
3512 #if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 2) |
3512 #if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 2) |
3513 # define USE_LONGLONG_FOR_MUL |
3513 # define USE_LONGLONG_FOR_MUL |
3514 #endif |
3514 #endif |
3515 |
3515 |
3516 if (__isSmallInteger(aNumber)) { |
3516 if (__isSmallInteger(aNumber)) { |
3517 myValue = __intVal(self); |
3517 myValue = __intVal(self); |
3518 otherValue = __intVal(aNumber); |
3518 otherValue = __intVal(aNumber); |
3519 |
3519 |
3520 #if defined(USE_LONGLONG_FOR_MUL) |
3520 #if defined(USE_LONGLONG_FOR_MUL) |
3521 { |
3521 { |
3522 # if defined(__alpha__) && !defined(__alpha64__) |
3522 # if defined(__alpha__) && !defined(__alpha64__) |
3523 # define LONGLONG INT64 |
3523 # define LONGLONG INT64 |
3524 # else |
3524 # else |
3525 # define LONGLONG long long |
3525 # define LONGLONG long long |
3526 # endif |
3526 # endif |
3527 LONGLONG product; |
3527 LONGLONG product; |
3528 |
3528 |
3529 product = (LONGLONG)myValue * (LONGLONG)otherValue; |
3529 product = (LONGLONG)myValue * (LONGLONG)otherValue; |
3530 if (product < 0) { |
3530 if (product < 0) { |
3531 RETURN ( __mkSmallInteger(-(INT)(-product & _MAX_INT))); |
3531 RETURN ( __mkSmallInteger(-(INT)(-product & _MAX_INT))); |
3532 } |
3532 } |
3533 RETURN ( __mkSmallInteger((INT)(product & _MAX_INT))); |
3533 RETURN ( __mkSmallInteger((INT)(product & _MAX_INT))); |
3534 } |
3534 } |
3535 #else /* no long-long */ |
3535 #else /* no long-long */ |
3536 negative = 1; |
3536 negative = 1; |
3537 if (myValue < 0) { |
3537 if (myValue < 0) { |
3538 negative = -1; |
3538 negative = -1; |
3539 myValue = -myValue; |
3539 myValue = -myValue; |
3540 } |
3540 } |
3541 if (otherValue < 0) { |
3541 if (otherValue < 0) { |
3542 negative = -negative; |
3542 negative = -negative; |
3543 otherValue = -otherValue; |
3543 otherValue = -otherValue; |
3544 } |
3544 } |
3545 |
3545 |
3546 # if defined(__GNUC__) && defined(__mc68k__) |
3546 # if defined(__GNUC__) && defined(__mc68k__) |
3547 asm ("mulu%.l %3,%1:%0" |
3547 asm ("mulu%.l %3,%1:%0" |
3548 : "=d" ((unsigned long)(productLow)), |
3548 : "=d" ((unsigned long)(productLow)), |
3549 "=d" ((unsigned long)(productHi)) |
3549 "=d" ((unsigned long)(productHi)) |
3550 : "%0" ((unsigned long)(myValue)), |
3550 : "%0" ((unsigned long)(myValue)), |
3551 "dmi" ((unsigned long)(otherValue))); |
3551 "dmi" ((unsigned long)(otherValue))); |
3552 # else |
3552 # else |
3553 # if defined (__GNUC__) && defined(__i386__) |
3553 # if defined (__GNUC__) && defined(__i386__) |
3554 asm ("mull %3" |
3554 asm ("mull %3" |
3555 : "=a" ((unsigned long)(productLow)), |
3555 : "=a" ((unsigned long)(productLow)), |
3556 "=d" ((unsigned long)(productHi)) |
3556 "=d" ((unsigned long)(productHi)) |
3557 : "%0" ((unsigned long)(myValue)), |
3557 : "%0" ((unsigned long)(myValue)), |
3558 "rm" ((unsigned long)(otherValue))); |
3558 "rm" ((unsigned long)(otherValue))); |
3559 # else |
3559 # else |
3560 # if defined(WIN32) && defined(__BORLANDC__) |
3560 # if defined(WIN32) && defined(__BORLANDC__) |
3561 asm { |
3561 asm { |
3562 mov eax, myValue |
3562 mov eax, myValue |
3563 mov edx, otherValue |
3563 mov edx, otherValue |
3564 mul edx |
3564 mul edx |
3565 mov productLow, eax |
3565 mov productLow, eax |
3566 mov productHi, edx |
3566 mov productHi, edx |
3567 } |
3567 } |
3568 # else /* generic */ |
3568 # else /* generic */ |
3569 { |
3569 { |
3570 unsigned INT pHH, pHL, pLH, pLL; |
3570 unsigned INT pHH, pHL, pLH, pLL; |
3571 unsigned INT low1, low2, hi1, hi2; |
3571 unsigned INT low1, low2, hi1, hi2; |
3572 unsigned INT t; |
3572 unsigned INT t; |
3573 |
3573 |
3574 /* unsigned multiply myValue * otherValue -> productHi, productLow |
3574 /* unsigned multiply myValue * otherValue -> productHi, productLow |
3575 * |
3575 * |
3576 * this is too slow: |
3576 * this is too slow: |
3577 * since most machines can do 32*32 to 64 bit multiply, |
3577 * since most machines can do 32*32 to 64 bit multiply, |
3578 * (or at least 32*32 with Overflow check) |
3578 * (or at least 32*32 with Overflow check) |
3579 * - need more assembler (inline) functions here |
3579 * - need more assembler (inline) functions here |
3580 */ |
3580 */ |
3581 # if __POINTER_SIZE__ == 8 |
3581 # if __POINTER_SIZE__ == 8 |
3582 low1 = low32Bits((unsigned INT)myValue); |
3582 low1 = low32Bits((unsigned INT)myValue); |
3583 hi1 = hi32Bits((unsigned INT)myValue); |
3583 hi1 = hi32Bits((unsigned INT)myValue); |
3584 low2 = low32Bits((unsigned INT)otherValue); |
3584 low2 = low32Bits((unsigned INT)otherValue); |
3585 hi2 = hi32Bits((unsigned INT)otherValue); |
3585 hi2 = hi32Bits((unsigned INT)otherValue); |
3586 # define LLMASK 0xC000000000000000L |
3586 # define LLMASK 0xC000000000000000L |
3587 # else |
3587 # else |
3588 low1 = low16Bits((unsigned INT)myValue); |
3588 low1 = low16Bits((unsigned INT)myValue); |
3589 hi1 = hi16Bits((unsigned INT)myValue); |
3589 hi1 = hi16Bits((unsigned INT)myValue); |
3590 low2 = low16Bits((unsigned INT)otherValue); |
3590 low2 = low16Bits((unsigned INT)otherValue); |
3591 hi2 = hi16Bits((unsigned INT)otherValue); |
3591 hi2 = hi16Bits((unsigned INT)otherValue); |
3592 # define LLMASK 0xC0000000 |
3592 # define LLMASK 0xC0000000 |
3593 # endif |
3593 # endif |
3594 |
3594 |
3595 pLH = low1 * hi2; |
3595 pLH = low1 * hi2; |
3596 pHL = hi1 * low2; |
3596 pHL = hi1 * low2; |
3597 pLL = low1 * low2; |
3597 pLL = low1 * low2; |
3598 pHH = hi1 * hi2; |
3598 pHH = hi1 * hi2; |
3599 |
3599 |
3600 /* |
3600 /* |
3601 * the common case ... |
3601 * the common case ... |
3602 */ |
3602 */ |
3603 if ((pHL == 0) |
3603 if ((pHL == 0) |
3604 && (pLH == 0) |
3604 && (pLH == 0) |
3605 && (pHH == 0) |
3605 && (pHH == 0) |
3606 && ((pLL & LLMASK) == 0)) { |
3606 && ((pLL & LLMASK) == 0)) { |
3607 if (negative < 0) { |
3607 if (negative < 0) { |
3608 RETURN ( __mkSmallInteger(- ((INT)pLL)) ); |
3608 RETURN ( __mkSmallInteger(- ((INT)pLL)) ); |
3609 } |
3609 } |
3610 RETURN ( __mkSmallInteger((INT)pLL) ); |
3610 RETURN ( __mkSmallInteger((INT)pLL) ); |
3611 } |
3611 } |
3612 |
3612 |
3613 /* |
3613 /* |
3614 * pHH |--------|--------| |
3614 * pHH |--------|--------| |
3615 * pLH |--------|--------| |
3615 * pLH |--------|--------| |
3616 * pHL |--------|--------| |
3616 * pHL |--------|--------| |
3617 * pLL |--------|--------| |
3617 * pLL |--------|--------| |
3618 */ |
3618 */ |
3619 |
3619 |
3620 # if __POINTER_SIZE__ == 8 |
3620 # if __POINTER_SIZE__ == 8 |
3621 t = low32Bits(pLH) + low32Bits(pHL) + hi32Bits(pLL); |
3621 t = low32Bits(pLH) + low32Bits(pHL) + hi32Bits(pLL); |
3622 productLow = (t << 32) + low32Bits(pLL); |
3622 productLow = (t << 32) + low32Bits(pLL); |
3623 productHi = pHH + hi32Bits(t) + hi32Bits(pHL) + hi32Bits(pLH); |
3623 productHi = pHH + hi32Bits(t) + hi32Bits(pHL) + hi32Bits(pLH); |
3624 # else |
3624 # else |
3625 t = low16Bits(pLH) + low16Bits(pHL) + hi16Bits(pLL); |
3625 t = low16Bits(pLH) + low16Bits(pHL) + hi16Bits(pLL); |
3626 productLow = (t << 16) + low16Bits(pLL); |
3626 productLow = (t << 16) + low16Bits(pLL); |
3627 productHi = pHH + hi16Bits(t) + hi16Bits(pHL) + hi16Bits(pLH); |
3627 productHi = pHH + hi16Bits(t) + hi16Bits(pHL) + hi16Bits(pLH); |
3628 # endif |
3628 # endif |
3629 } |
3629 } |
3630 # endif /* ! WIN32 */ |
3630 # endif /* ! WIN32 */ |
3631 # endif /* ! (__GNUC__ && __i386__) */ |
3631 # endif /* ! (__GNUC__ && __i386__) */ |
3632 # endif /* ! (__GNUC__ && __mc68k__) */ |
3632 # endif /* ! (__GNUC__ && __mc68k__) */ |
3633 |
3633 |
3634 if (negative < 0) { |
3634 if (negative < 0) { |
3635 RETURN ( __mkSmallInteger(-(INT)(productLow & _MAX_INT))); |
3635 RETURN ( __mkSmallInteger(-(INT)(productLow & _MAX_INT))); |
3636 } |
3636 } |
3637 RETURN ( __mkSmallInteger((INT)(productLow & _MAX_INT))); |
3637 RETURN ( __mkSmallInteger((INT)(productLow & _MAX_INT))); |
3638 #endif /* ! USE_LONGLONG */ |
3638 #endif /* ! USE_LONGLONG */ |
3639 } |
3639 } |
3640 %}. |
3640 %}. |
3641 |
3641 |
3642 self primitiveFailed |
3642 self primitiveFailed |
3643 |
3643 |
3644 " |
3644 " |
3645 5 times:-1 |
3645 5 times:-1 |
3646 5 times:1 |
3646 5 times:1 |
3647 self maxVal-1 times:2 |
3647 self maxVal-1 times:2 |
3648 self maxVal-1 times:-2 |
3648 self maxVal-1 times:-2 |
3649 self maxVal-1 * 2 bitAnd:16r3fffffff |
3649 self maxVal-1 * 2 bitAnd:16r3fffffff |
3650 " |
3650 " |
3651 ! ! |
3651 ! ! |
3652 |
3652 |
3653 !SmallInteger methodsFor:'printing & storing'! |
3653 !SmallInteger methodsFor:'printing & storing'! |
3654 |
3654 |
3708 * actually only needed on sparc: since thisContext is |
3708 * actually only needed on sparc: since thisContext is |
3709 * in a global register, which gets destroyed by printf, |
3709 * in a global register, which gets destroyed by printf, |
3710 * manually save it here - very stupid ... |
3710 * manually save it here - very stupid ... |
3711 */ |
3711 */ |
3712 __BEGIN_PROTECT_REGISTERS__ |
3712 __BEGIN_PROTECT_REGISTERS__ |
3713 len = snprintf(buffer, sizeof(buffer), "%ld", (long)myValue); |
3713 len = snprintf(buffer, sizeof(buffer), "%"_ld_"", (long)myValue); |
3714 __END_PROTECT_REGISTERS__ |
3714 __END_PROTECT_REGISTERS__ |
3715 |
3715 |
3716 if (len >= 0 && len <= sizeof(buffer)) { |
3716 if (len >= 0 && len <= sizeof(buffer)) { |
3717 newString = __MKSTRING_L(buffer, len); |
3717 newString = __MKSTRING_L(buffer, len); |
3718 } |
3718 } |
3719 |
3719 |
3720 #else |
3720 #else |
3721 if (myValue < 0) { |
3721 if (myValue < 0) { |
3722 negative = 1; |
3722 negative = 1; |
3723 myValue = -myValue; |
3723 myValue = -myValue; |
3724 } |
3724 } |
3725 cp = buffer + sizeof(buffer) - 1; |
3725 cp = buffer + sizeof(buffer) - 1; |
3726 *cp-- = '\0'; |
3726 *cp-- = '\0'; |
3727 while (myValue != 0) { |
3727 while (myValue != 0) { |
3728 *cp = '0' + (myValue % 10); |
3728 *cp = '0' + (myValue % 10); |
3729 myValue = myValue / 10; |
3729 myValue = myValue / 10; |
3730 cp--; |
3730 cp--; |
3731 } |
3731 } |
3732 if (negative) { |
3732 if (negative) { |
3733 *cp-- = '-'; |
3733 *cp-- = '-'; |
3734 } |
3734 } |
3735 newString = __MKSTRING_L(cp+1, (buffer + sizeof(buffer) - 2 - cp)); |
3735 newString = __MKSTRING_L(cp+1, (buffer + sizeof(buffer) - 2 - cp)); |
3736 #endif |
3736 #endif |
3737 if (newString != nil) { |
3737 if (newString != nil) { |
3738 RETURN (newString); |
3738 RETURN (newString); |
3739 } |
3739 } |
3740 %}. |
3740 %}. |
3741 "/ only arrive here, |
3741 "/ only arrive here, |
3742 "/ when having memory problems (i.e. no space for string) ... |
3742 "/ when having memory problems (i.e. no space for string) ... |
3743 ^ super printString |
3743 ^ super printString |
3761 INT myValue; |
3761 INT myValue; |
3762 int negative = 0; |
3762 int negative = 0; |
3763 INT __base; |
3763 INT __base; |
3764 |
3764 |
3765 if (__isSmallInteger(base)) { |
3765 if (__isSmallInteger(base)) { |
3766 myValue = __intVal(self); |
3766 myValue = __intVal(self); |
3767 if (myValue == 0) { |
3767 if (myValue == 0) { |
3768 RETURN (__MKSTRING_L("0", 1)); |
3768 RETURN (__MKSTRING_L("0", 1)); |
3769 } |
3769 } |
3770 __base = __intVal(base); |
3770 __base = __intVal(base); |
3771 |
3771 |
3772 #ifdef SLOW_CODE |
3772 #ifdef SLOW_CODE |
3773 switch (__base) { |
3773 switch (__base) { |
3774 case 10: |
3774 case 10: |
3775 format = "%ld"; |
3775 format = "%"_ld_""; |
3776 break; |
3776 break; |
3777 case 16: |
3777 case 16: |
3778 format = "%lx"; |
3778 format = "%"_lx_""; |
3779 break; |
3779 break; |
3780 case 8: |
3780 case 8: |
3781 format = "%lo"; |
3781 format = "%"_lo_""; |
3782 break; |
3782 break; |
3783 } |
3783 } |
3784 |
3784 |
3785 if (format) { |
3785 if (format) { |
3786 /* |
3786 /* |
3787 * actually only needed on sparc: since thisContext is |
3787 * actually only needed on sparc: since thisContext is |
3788 * in a global register, which gets destroyed by printf, |
3788 * in a global register, which gets destroyed by printf, |
3789 * manually save it here - very stupid ... |
3789 * manually save it here - very stupid ... |
3790 */ |
3790 */ |
3791 __BEGIN_PROTECT_REGISTERS__ |
3791 __BEGIN_PROTECT_REGISTERS__ |
3792 |
3792 |
3793 len = snprintf(buffer, sizeof(buffer), format, (long)myValue); |
3793 len = snprintf(buffer, sizeof(buffer), format, (long)myValue); |
3794 |
3794 |
3795 __END_PROTECT_REGISTERS__ |
3795 __END_PROTECT_REGISTERS__ |
3796 |
3796 |
3797 if (len > 0 && len <= sizeof(buffer)) { |
3797 if (len > 0 && len <= sizeof(buffer)) { |
3798 newString = __MKSTRING_L(buffer, len); |
3798 newString = __MKSTRING_L(buffer, len); |
3799 if (newString != nil) { |
3799 if (newString != nil) { |
3800 RETURN (newString); |
3800 RETURN (newString); |
3801 } |
3801 } |
3802 } |
3802 } |
3803 } |
3803 } |
3804 #else |
3804 #else |
3805 if ((__base <= 36) && (__base > 1)) { |
3805 if ((__base <= 36) && (__base > 1)) { |
3806 if (myValue < 0) { |
3806 if (myValue < 0) { |
3807 negative = 1; |
3807 negative = 1; |
3808 myValue = -myValue; |
3808 myValue = -myValue; |
3809 } |
3809 } |
3810 cp = buffer + sizeof(buffer) - 1; |
3810 cp = buffer + sizeof(buffer) - 1; |
3811 *cp-- = '\0'; |
3811 *cp-- = '\0'; |
3812 while (myValue != 0) { |
3812 while (myValue != 0) { |
3813 int digit; |
3813 int digit; |
3814 |
3814 |
3815 digit = myValue % __base; |
3815 digit = myValue % __base; |
3816 if (digit <= 9) { |
3816 if (digit <= 9) { |
3817 *cp = '0' + digit; |
3817 *cp = '0' + digit; |
3818 } else { |
3818 } else { |
3819 *cp = 'A' + digit - 10; |
3819 *cp = 'A' + digit - 10; |
3820 } |
3820 } |
3821 myValue = myValue / __base; |
3821 myValue = myValue / __base; |
3822 cp--; |
3822 cp--; |
3823 } |
3823 } |
3824 if (negative) { |
3824 if (negative) { |
3825 *cp-- = '-'; |
3825 *cp-- = '-'; |
3826 } |
3826 } |
3827 newString = __MKSTRING_L(cp+1, (buffer + sizeof(buffer) - 2 - cp)); |
3827 newString = __MKSTRING_L(cp+1, (buffer + sizeof(buffer) - 2 - cp)); |
3828 if (newString != nil) { |
3828 if (newString != nil) { |
3829 RETURN (newString); |
3829 RETURN (newString); |
3830 } |
3830 } |
3831 } |
3831 } |
3832 #endif |
3832 #endif |
3833 } |
3833 } |
3834 %}. |
3834 %}. |
3835 "/ arrive here, for bad base, |
3835 "/ arrive here, for bad base, |
3836 "/ or when having memory problems (i.e. no space for string) ... |
3836 "/ or when having memory problems (i.e. no space for string) ... |
3873 This method is NONSTANDARD and may be removed without notice; |
3873 This method is NONSTANDARD and may be removed without notice; |
3874 it is provided to allow special conversions in very special |
3874 it is provided to allow special conversions in very special |
3875 situaltions. |
3875 situaltions. |
3876 Notice that a conversion may not be portable; for example, |
3876 Notice that a conversion may not be portable; for example, |
3877 to correctly convert an int on a 64-bit alpha, a %ld is required, |
3877 to correctly convert an int on a 64-bit alpha, a %ld is required, |
3878 while other systems may be happy with a %d ... |
3878 on 64bit mingw or visualc, %lld is required, |
|
3879 while other systems may be happy with a %d. |
|
3880 (We cannot use lld unconditionally, because some (old) c compilers do not support it!!) |
3879 Use at your own risk (if at all). |
3881 Use at your own risk (if at all). |
3880 WARNNG: this goes directly to the C-printf function and may therefore me inherently unsafe. |
3882 WARNNG: this goes directly to the C-printf function and may therefore me inherently unsafe. |
3881 Please use the printf: method, which is safe as it is completely implemented in Smalltalk." |
3883 Please use the printf: method, which is safe as it is completely implemented in Smalltalk." |
3882 |
3884 |
3883 %{ /* STACK: 400 */ |
3885 %{ /* STACK: 400 */ |
3884 char buffer[256]; |
3886 char buffer[256]; |
3885 OBJ s; |
3887 OBJ s; |
3886 int len; |
3888 int len; |
3887 |
3889 |
3888 if (__isStringLike(formatString)) { |
3890 if (__isStringLike(formatString)) { |
3889 /* |
3891 /* |
3890 * actually only needed on sparc: since thisContext is |
3892 * actually only needed on sparc: since thisContext is |
3891 * in a global register, which gets destroyed by printf, |
3893 * in a global register, which gets destroyed by printf, |
3892 * manually save it here - very stupid ... |
3894 * manually save it here - very stupid ... |
3893 */ |
3895 */ |
3894 __BEGIN_PROTECT_REGISTERS__ |
3896 __BEGIN_PROTECT_REGISTERS__ |
3895 |
3897 |
3896 len = snprintf(buffer, sizeof(buffer), __stringVal(formatString), __intVal(self)); |
3898 len = snprintf(buffer, sizeof(buffer), __stringVal(formatString), __intVal(self)); |
3897 |
3899 |
3898 __END_PROTECT_REGISTERS__ |
3900 __END_PROTECT_REGISTERS__ |
3899 |
3901 |
3900 if (len < 0) goto fail; |
3902 if (len < 0) goto fail; |
3901 |
3903 |
3902 s = __MKSTRING_L(buffer, len); |
3904 s = __MKSTRING_L(buffer, len); |
3903 if (s != nil) { |
3905 if (s != nil) { |
3904 RETURN (s); |
3906 RETURN (s); |
3905 } |
3907 } |
3906 } |
3908 } |
3907 fail: ; |
3909 fail: ; |
3908 %}. |
3910 %}. |
3909 self primitiveFailed |
3911 self primitiveFailed |
3910 |
3912 |
3911 " |
3913 " |
3912 123 printfPrintString:'%%d -> %d' |
3914 123 printfPrintString:'%%d -> %d' |
3913 123 printfPrintString:'%%6d -> %6d' |
3915 123 printfPrintString:'%%6d -> %6d' |
3914 123 printfPrintString:'%%x -> %x' |
3916 123 printfPrintString:'%%x -> %x' |
3915 123 printfPrintString:'%%4x -> %4x' |
3917 123 printfPrintString:'%%4x -> %4x' |
3916 123 printfPrintString:'%%04x -> %04x' |
3918 123 printfPrintString:'%%04x -> %04x' |
3917 " |
3919 " |
3918 ! ! |
3920 ! ! |
3919 |
3921 |
3920 !SmallInteger methodsFor:'private'! |
3922 !SmallInteger methodsFor:'private'! |
3921 |
3923 |