long int multiplcation bug on Arduino 0016

Hello,

I have come across what appears to be a bug with long integer multiplication on my Arduino Duemilanove. I am using Arduino 0016 on Ubuntu Linux. I have written a test driver to reproduce my issue and am posting it here so other users can verify that they have the same issue and/or see if it is resolved on their systems.

I have heard that avr-gcc version 4.3.0 (which is the version I have) had problems with some long int multiplications. I will upgrade that on my system and see if that resolves the issue with multiplication that I have seen. If that works I will report back with my success or failure issues with the new avr-gcc version. Maybe upgrading to 0017 of the IDE will help; I'll check that too.

Has anyone else seen this or something similar to it out there?

Here is the output from my test driver:

Testing multiplcation of longs

testRoutine(): Got byte argument 13
testRoutine(): Multiplicaton Result a = 13000
testRoutine(): Value of b After assignment from byte b = 13
testRoutine(): Multiplicaton Result b = b * 1000 was: 65
ERROR: Expected Result of 13000, got this instead: 65
testRoutine(): Multiplicaton Result b = byteArg * 1000 13000

And here is the source code to reproduce it:

// ///////////////////////////////////////////////////////////////////////////
//
// Arduino code for testing multiplication of long numbers.
// 20090903, Adam E. Hampton.  This code is released to the public domain.
//
// ///////////////////////////////////////////////////////////////////////////
//
// The purpose of this code is to illustrate some odd behavior I see with 
// "unsigned long int" variables being cast in from a byte.  It appears that
// tyring to multiply an "unsignled long int" after assigning it a value from
// a byte variable produces unexpected results.  
//
// Seen on: Arduino Duemilanove with an ATMega 186 @ 20MHz,
//          using Arduino 0016 on Ubuntu Linux 8.10.
//
// ///////////////////////////////////////////////////////////////////////////

// ///////////////////////////////////////////////////////////////////////////
void setup () {

  Serial.begin(9600); // Serial output to the computer on pin 1.
  delay(50);

}

// ///////////////////////////////////////////////////////////////////////////
void loop () {

  Serial.println("");
  Serial.println("Testing multiplcation of longs");
  Serial.println("");

  // Test Case: multiply some stuff by powers of 10.
  byte myByte = 13;
  testRoutine(myByte);

  delay(1000);

}

unsigned long int testRoutine (byte byteArg) {

  Serial.print("testRoutine(): Got byte argument ");
  Serial.println(byteArg, DEC);

  unsigned long int a = 0;
  a = byteArg * 1000;

  // This works correctly.  
  Serial.print("testRoutine(): Multiplicaton Result a = ");
  Serial.println(a);
  if (a != 13000) {
    Serial.println("   ERROR: Expected Result of 13000 for a, got something else."); 
  } 

  // Next lets try a direct assignment from the byte argument.  The assignment works.
  unsigned long int b = 0;  
  b = (unsigned long int) byteArg;
  Serial.print("testRoutine(): Value of b After assignment from byte b = ");
  Serial.println(b);

  // Next try multiplying the long integer by 10^3.  This is where things break.
  b = b * 1000;

  Serial.print("testRoutine(): Multiplicaton Result b = b * 1000 was: ");
  Serial.println(b);
  if (b != 13000) {
    Serial.print("   ERROR: Expected Result of 13000, got this instead: "); 
    Serial.println(b);
  } 
  else {
    Serial.println("   Got correct response from b = b * 1000."); 
  }

  // Just for the purpose of a sanity check we test the original case again, 
  // just like it was done with the "a" variable: direct product of the byte arg
  // and an integer.
  b = 0;
  b = byteArg * 1000;

  Serial.print("testRoutine(): Multiplicaton Result b = byteArg * 1000 ");
  Serial.println(b);
  if (b != 13000) {
    Serial.print("   ERROR: Expected Result of 13000, got this instead: "); 
    Serial.println(b);    
  } 
  else {
    Serial.println("   Got correct response from b = byteArg * 1000."); 
  }
  
  // Next check to see if multiplying b but 1 (identity) fixes the issue.
  b = 0;  
  b = (unsigned long int) byteArg;
  Serial.print("testRoutine(): Value of b after assignment from byte = ");
  Serial.println(b);

  // Next try multiplying the long integer by 1
  
  // *** WHEN Un-Commented this block crashes my arduino.  It never comes
  // back from the b = b * 1 operation correctly.  The next time b is touched
  // the micro freezes.
  // b = b * 1;
  // Serial.print("testRoutine(): Multiplicaton Result b = b * 1 is : ");
  // Serial.println(b);  
  // if (b != 13) {
  //   Serial.print("   ERROR: Expected Result of 13, got this instead: "); 
  //   Serial.println(b);
  // } else {
  //   Serial.println("   Got correct response from b = b * 1."); 
  // }// *** WHEN Un-Commented this line crashes my arduino: 

  // 1234 * 1234 = 1522756.  This routine checks to see if the Arduino agrees.
  unsigned long int c = 0;
  c = 1234;
  c = c * c;
  Serial.print("testRoutine(): 1234 * 1234 in c = ");
  Serial.println(c);
  if (c != 1522756) {
    Serial.print("   ERROR: Expected Result of 1522756, got this instead: "); 
    Serial.println(c);
  } 
  else {
    Serial.println("   Got correct response from c = 1234 * 1234."); 
  }

  // 12345 * 67890 = 838102050.
  // This routine checks to see if the Arduino agrees.
  Serial.println("testRoutine(): Check sanity of 12345 * 67890 = ? ");

  unsigned long int x = 12345;
  unsigned long int y = 67890;
  unsigned long int z = 838102050;

  unsigned long p = x * y;
  if (p != z) {
    Serial.print("   ERROR: Did not get the expected 838102050.  Got this:  ");
    Serial.println(p); 
  } 
  else {
    Serial.print("   Got correct repsonse, 838102050, in variable:  ");
    Serial.println(p); 
  }

}

Aha..

I just got around to reading the playground main page:

"""
Version 4.3.0 has a major bug which affects multiplication of long int's. This is the default version in Ubuntu Intrepid (8.10). Check using "avr-gcc --version" and upgrade if necessary.
"""

I'll be upgrading now. An apparently we all shoud!

Cheers,
--Adam ::slight_smile:

if use long int after counter more 3FFF , result minus :cry:

apparently we all should!

In the Windows and Mac versions of Arduino, the compiler is bundled with the IDE. Only Arduino 12 and 13 included the buggy 4.3.0 compiler...