[Pharo-project] Two complement smallInteger question
Hi I'm doing a pass on the two complement chapter and small integer implementation and I wanted to check the SmallInteger>>primitiveAdd see below: stackIntegerValue extracts from a smalltalk integer the 31 encoding number bit. I imagine that this is correct. sqInt stackIntegerValue(sqInt offset) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt integerPointer; integerPointer = longAt(GIV(stackPointer) + (offset * BytesPerWord)); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { return (integerPointer >> 1); } else { /* begin primitiveFail */ if (GIV(primFailCode) == 0) { GIV(primFailCode) = 1; } return 0; } } Now I have three questions: - is two complement used to manage small integers at VM level? I saw digitAdd on Integer and it deals with large integer. - integerResult = (stackIntegerValue(1)) + (stackIntegerValue(0)); performs the real add. I imagine that it comes from plain C. Now does anybody has an idea where I could find the definition of such + procedure? In ANSI C - from the books, performing 54 - 5 is equivalent to adding the two complement i.e. 54 + 5' (two complement) this work well for 54 - 5 correct results and we can follow it looking at binary operations: (2r110110 - 2r101) bitString --> '0000000000000000000000000110001' (2r110110 bitString) --> '0000000000000000000000000110110' 2r101 bitString --> '0000000000000000000000000000101' 2r101 negated bitString --> '1111111111111111111111111111011' Now doing 5 - 15 does not (or I miss something ilke always subtracting the smaller one and taking the two complement of the smallerâ¦) so does anybody has the answer on how to perform 5 - 15 ? static void primitiveAdd(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt integerResult; char *sp; /* begin pop2AndPushIntegerIfOK: */ integerResult = (stackIntegerValue(1)) + (stackIntegerValue(0)); if (GIV(primFailCode) == 0) { if ((integerResult ^ (integerResult << 1)) >= 0) { /* begin pop:thenPush: */ longAtput(sp = GIV(stackPointer) + ((2 - 1) * BytesPerWord), ((integerResult << 1) | 1)); GIV(stackPointer) = sp; } else { /* begin success: */ if (!(0)) { if (GIV(primFailCode) == 0) { /* Don't overwrite an error code that has already been set. */ GIV(primFailCode) = 1; } } } } } Stef
I read somewhere that in C short int range value are -32767 to +32767 http://www.ericgiguere.com/articles/ansi-c-summary.html And I was wondering why it does not follow the $-1 * 2^{N-1}\ to\ 2^{N-1}-1$ range encoding Stef On Dec 23, 2011, at 11:35 AM, Stéphane Ducasse wrote:
Hi
I'm doing a pass on the two complement chapter and small integer implementation and I wanted to check the SmallInteger>>primitiveAdd see below:
stackIntegerValue extracts from a smalltalk integer the 31 encoding number bit. I imagine that this is correct.
sqInt stackIntegerValue(sqInt offset) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt integerPointer; integerPointer = longAt(GIV(stackPointer) + (offset * BytesPerWord)); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { return (integerPointer >> 1); } else { /* begin primitiveFail */ if (GIV(primFailCode) == 0) { GIV(primFailCode) = 1; } return 0; } }
Now I have three questions: - is two complement used to manage small integers at VM level? I saw digitAdd on Integer and it deals with large integer.
- integerResult = (stackIntegerValue(1)) + (stackIntegerValue(0)); performs the real add. I imagine that it comes from plain C. Now does anybody has an idea where I could find the definition of such + procedure? In ANSI C
- from the books, performing 54 - 5 is equivalent to adding the two complement i.e. 54 + 5' (two complement) this work well for 54 - 5 correct results and we can follow it looking at binary operations:
(2r110110 - 2r101) bitString --> '0000000000000000000000000110001' (2r110110 bitString) --> '0000000000000000000000000110110' 2r101 bitString --> '0000000000000000000000000000101' 2r101 negated bitString --> '1111111111111111111111111111011'
Now doing 5 - 15 does not (or I miss something ilke always subtracting the smaller one and taking the two complement of the smallerâ¦) so does anybody has the answer on how to perform 5 - 15 ?
static void primitiveAdd(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt integerResult; char *sp;
/* begin pop2AndPushIntegerIfOK: */ integerResult = (stackIntegerValue(1)) + (stackIntegerValue(0)); if (GIV(primFailCode) == 0) { if ((integerResult ^ (integerResult << 1)) >= 0) { /* begin pop:thenPush: */ longAtput(sp = GIV(stackPointer) + ((2 - 1) * BytesPerWord), ((integerResult << 1) | 1)); GIV(stackPointer) = sp; } else { /* begin success: */ if (!(0)) { if (GIV(primFailCode) == 0) {
/* Don't overwrite an error code that has already been set. */
GIV(primFailCode) = 1; } } } } }
Stef
Hi: On 23 Dec 2011, at 12:49, Stéphane Ducasse wrote:
I read somewhere that in C short int range value are -32767 to +32767
http://www.ericgiguere.com/articles/ansi-c-summary.html
And I was wondering why it does not follow the $-1 * 2^{N-1}\ to\ 2^{N-1}-1$ range encoding
Because your source has a typo? Have a look into /usr/include/stdint.h that is what runs on your system... #define INT16_MAX 32767 #define INT16_MIN -32768
Now I have three questions: - is two complement used to manage small integers at VM level?
It is done at the hardware level.
Since C does not specify many things including signed overflows, I would assume they just map directly onto what the hardware provides. And for all practical purposes, two's complement is the standard. I am not aware of anything mainstream using one's complement.
Now doing 5 - 15 does not (or I miss something ilke always subtracting the smaller one and taking the two complement of the smallerâ¦) so does anybody has the answer on how to perform 5 - 15 ?
http://en.wikipedia.org/wiki/Two%27s_complement#Subtraction Regards Stefan -- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525
Hi stefan
Because your source has a typo?
Yes this is what I thought. or that people do not understand it :)
Now doing 5 - 15 does not (or I miss something ilke always subtracting the smaller one and taking the two complement of the smallerâ¦) so does anybody has the answer on how to perform 5 - 15 ?
I already read it in the past but may be I'm blind normally a -b = a + b'two complement So they say it but do not really show it example: 15 â 35 = â20: they do the negation and I want to see how the two complement actually works for real on negative number results. 11100 0000 (borrow) 0000 1111 (15) â 0010 0011 (35) =========== 1110 1100 (â20) ok but this example does not show use of two' complement. so we have 15 0000 1111 (15) and 0010 0011 (35) 1101 1100 (35 bitInvert) 1101 1101 (35 bitInvert+ 1) =35 two complement 0011111 (carry) 0000 1111 (15) + 1101 1101 35two complement ----------------- 1111111101100 ok it works. I did a mistake probably yesterday evening when I was playing with another example. So thanks redoing another example removed my bug.
Regards Stefan
-- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525
participants (3)
-
Stefan Marr -
Stéphane Ducasse -
Stéphane Ducasse