SmallInteger.st
changeset 11728 0c197f1c3cd0
parent 11718 1128a869a77a
child 11792 6782c723834a
child 17711 39faaaf888b4
equal deleted inserted replaced
11727:e0ffd06e50fd 11728:0c197f1c3cd0
   172 ! !
   172 ! !
   173 
   173 
   174 !SmallInteger methodsFor:'arithmetic'!
   174 !SmallInteger methodsFor:'arithmetic'!
   175 
   175 
   176 * aNumber
   176 * aNumber
   177     "return the product of the receivers value and the arguments value"
   177     "return the product of the receiver and the argument"
   178 
   178 
   179 %{  /* NOCONTEXT */
   179 %{  /* NOCONTEXT */
   180 
   180 
   181     /*
   181     /*
   182      * notice:
   182      * notice:
   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 
  3786 ! !
  3786 ! !
  3787 
  3787 
  3788 !SmallInteger class methodsFor:'documentation'!
  3788 !SmallInteger class methodsFor:'documentation'!
  3789 
  3789 
  3790 version
  3790 version
  3791     ^ '$Header: /cvs/stx/stx/libbasic/SmallInteger.st,v 1.177 2009-05-26 06:30:43 cg Exp $'
  3791     ^ '$Header: /cvs/stx/stx/libbasic/SmallInteger.st,v 1.178 2009-05-26 06:37:45 cg Exp $'
  3792 ! !
  3792 ! !