Fred wrote:Ok, just explain to me how you will compare signed and unsigned numbers at high speed...
I'm using C and ASM because I need languages that support unsigned types in order to give examples.
First, to quote the IA-32 Intel® Architecture Software Developer's Manual, Volume 2: Instruction Set Reference:
"Jcc - Jump if Condition Is Met (Continued)
The conditions for each Jcc mnemonic are given in the Description column of the table on the preceding page. The terms "less" and "greater" are used for comparisons of signed integers and the terms "above" and "below" are used for unsigned integers."
And, for a particular instruction (I chose ADD):
"The ADD instruction performs integer addition. It evaluates the result for both signed and unsigned integer operands and sets the OF and CF flags to indicate a carry (overflow) in the signed or unsigned result, respectively. The SF flag indicates the sign of the signed result."
Now, from the IA-32 Intel® Architecture Software Developer's Manual Volume 1: Basic Architecture:
"Some integer instructions (such as the ADD, SUB, PADDB, and PSUBB instructions) operate on either unsigned or signed integer operands. Other interger instructions (such as IMUL, MUL, IDIV, DIV, FIADD, and FISUB) operate on only one integer type."
Now, first of all, there is no difference between a signed and unsigned integer except for a few things:
1. How the programmer decides to treat the data.
2. How the language checks comparisons.
3. How the language does multiplication and division (in the case of IA32 architecture.)
So, basically what this comes down to for the byte, word, and long types in PB is what Jcc (conditional jump) PB's compiler chooses, and whether to use MUL or IMUL and DIV or IDIV. Now, since PB maintains the type of each variable, this should be trivial and can be (and should be) done at compile time. Also, since we are talking about using JBE (for unsigned comparisons) or JLE (for signed comparisons) or MUL/IMUL, etc. I don't understand what this performance problem is you keep talking about??? I hope you don't try to tell me that JBE executes slower the JLE, etc.???
Here is an example (see below for the actual code.) Compile these on your favorite Unix box with gcc and look at the ASM output:
gcc -S signed.c
gcc -S unsigned.c
diff signed.s unsigned.s
1c1
< .file "signed.c"
---
> .file "unsigned.c"
20c20
< jle .L6
---
> jbe .L6
If you run these you will notice that they perform as expected, with the only difference being the choice of comparison at compile time.
So, to support unsigned bytes, words, and longs, all you need to do is:
1. Allow the programmer to indicate a type:
a. var1.ub (unsigned byte)
b. var2.uw (unsigned word)
c. var3.ul (unsigned long)
2. For comparisons, make a check of the type and use the appropriate Jcc instruction.
3. For multiply or divide, make a check of the type and use IMUL/MUL or IDIV/DIV accordingly.
4. For SHR/SAR, make a check of the type and use SHR for signed types, and SAR for unsigned types.
5. It would be nice if output functions (like PrintN) would also consider the type and output accordingly.
That's pretty much it. If the programmer tries to compare unsigned to signed types you can either blow and error during compile time, treat both numbers as signed/unsigned based on some rule that you document, or allow the programmer to cast one type to the other for that operation (like in C...)
Matthew
(unsigned.c)
#include <stdio.h>
int
main(void)
{
unsigned int i;
unsigned int j;
unsigned int k;
i = -10; // <-- really 4294967286
j = 10;
if ( i > j )
k = 1;
else
k = 0;
printf("%d, %d, %d\n", i, j, k);
return(0);
}
Output: -10, 10, 1
(signed.c)
#include <stdio.h>
int
main(void)
{
int i;
int j;
int k;
i = -10;
j = 10;
if ( i > j )
k = 1;
else
k = 0;
printf("%d, %d, %d\n", i, j, k);
return(0);
}
Output: -10, 10, 0