Pages: [1]   Go Down
Author Topic: long int multiplcation bug on Arduino 0016  (Read 919 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
[size=10]
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[/size]


And here is the source code to reproduce it:

Code:
// ///////////////////////////////////////////////////////////////////////////
//
// 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);
  }

}

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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  :smiley
Logged

indonesia
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

if use long int after counter more 3FFF , result minus  :'(
Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 124
Posts: 6645
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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...
Logged

Pages: [1]   Go Up
Jump to: