Help with int/long signed/unsign math operations

To save processing power (speed is vital, i have about 40 usec per loop) in my program Im using unsigned longs for the things that required that type, longs for numbers that could be both large and +/-, ints for medium sized numbers, and bytes for small numbers. In essence I'm trying to shrink the type to the smallest possible for what its going to store.

However, I need to do an if statement that looks like this:
if (unsignedLong-(int*byte) < long)
with the current setup. This wasn't working so i had to change the int to a long and then it worked...

I'm wondering how the proc (alu?) does the math. For example if I want to add a long and a int, does it buffer the int with 0's? Or does it chop off the long? In this case, does the order I add in matter then?

References to material covering this would be fine... this is totally new ground for me so I didn't even know what to google :slight_smile:

thanks!

flyingsilverfin:
To save processing power (speed is vital, i have about 40 usec per loop)

This will shave a few to several machine instructions off your loop...

void loop( void )
{
  while ( true )
  {
    // your code goes here
  }
}

However, I need to do an if statement that looks like this:
if (unsignedLong-(int*byte) < long)
with the current setup. This wasn't working so i had to change the int to a long and then it worked...

This also would have solved the problem (names changed in an attempt to add clarity)...

if ( MyUnsignedLongVariable - ( (unsigned long) MyIntVariable * (unsigned long) MyByteVariable ) < MyLongVariable )

I'm wondering how the proc (alu?) does the math.

One byte at a time (it's an 8 bit processor).

For example if I want to add a long and a int, does it buffer the int with 0's?

No. The int value is "sign extended" to a long.

Or does it chop off the long?

No.

In this case, does the order I add in matter then?

Possibly. The operands are first extended to the "largest" datatype of each operand. For example, when adding an int to a long the int is first sign extended to a long and then the addition is performed.

References to material covering this would be fine... this is totally new ground for me so I didn't even know what to google :slight_smile:

"type conversion" "sign extension" "type promotion" ...and, of course... "c++"

The compiler already knows everything needed about the ALU. All the programmer needs is to understand how to talk to the compiler. :slight_smile:

Looking at your conditional expression - (int*byte) will produce an int result. If the result doesn't fit into an int, then you can use a (long) cast to tell the compiler to expect a long-sized result.

unsignedLong - int could become dicey if the result is negative because your intention is ambiguous. Perhaps the unsignedLong should just be a long? ... Or should the int be an unsigned?

The missing vocabulary word (not very intuitive!) is "promotion". :grin:

To give you a feel for it. This sketch:

volatile unsigned long foo = 20;
volatile unsigned long bar = 22;
volatile unsigned long fubar;

void setup () { }

void loop ()
{
   fubar = foo + bar;
}

Loop generates this code:

void loop ()
{
   fubar = foo + bar;
  be:	20 91 00 01 	lds	r18, 0x0100
  c2:	30 91 01 01 	lds	r19, 0x0101
  c6:	40 91 02 01 	lds	r20, 0x0102
  ca:	50 91 03 01 	lds	r21, 0x0103
  ce:	80 91 04 01 	lds	r24, 0x0104
  d2:	90 91 05 01 	lds	r25, 0x0105
  d6:	a0 91 06 01 	lds	r26, 0x0106
  da:	b0 91 07 01 	lds	r27, 0x0107
  de:	82 0f       	add	r24, r18
  e0:	93 1f       	adc	r25, r19
  e2:	a4 1f       	adc	r26, r20
  e4:	b5 1f       	adc	r27, r21
  e6:	80 93 1a 01 	sts	0x011A, r24
  ea:	90 93 1b 01 	sts	0x011B, r25
  ee:	a0 93 1c 01 	sts	0x011C, r26
  f2:	b0 93 1d 01 	sts	0x011D, r27
}
  f6:	08 95       	ret

The lds/sts are 2 clock cycles, the adds are 1.
12 x 2 + 4 = 28 cycles.
28 * 62.5 nS = 1.750 uS.

So a single add of two unsigned longs takes 1.750 uS. I made them volatile to force the compiler to generate code, you wouldn't normally do that. Anyway, you can see that you don't want to be doing much more than 20 such things inside loop, or you will exceed 40 uS.

However often enough when people ask very specific questions like this, it helps to know why there is this requirement. Perhaps the problem can be solved other ways (eg. timers, interrupts).

To save processing power (speed is vital, i have about 40 usec per loop) in my program Im using unsigned longs for the things that required that type, longs for numbers that could be both large and +/-, ints for medium sized numbers, and bytes for small numbers. In essence I'm trying to shrink the type to the smallest possible for what its going to store.

Can you post the code you have now?