Floating Point Mathematics

From Nutwiki
Revision as of 16:17, 2 August 2010 by AdrianPyka (Talk) (Test Environments)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Test Environments

Hardware Comments Nut/OS
4.8.7
Ethernut 1.3 H OK
Binaries
Compiler: AVR-GCC 4.3.2
Ethernut 2.1 B OK
Binaries
Compiler: AVR-GCC 4.3.2
Ethernut 3.0 E NO

Overview

This example demonstrates Floating Point Math using Nut/OS and the math lib corresponding to your platform (avr-libc for AVR, newlib for ARM).

For this example it is also assumed that you have a working knowledge of how Nut/OS handles floatint point values. If you did not read the Floating Point Input and Ouput example yet, that should be your first stop before continuing with this part.

Before you begin, please enable floating point support for your project. In order to do this, open the configurator, load the appropriate config file for your project and then activate the following option:

Floatactivation.png

Now rebuild Nut/OS to apply the changed configuration.

Source Code

<source lang="c">

  1. include <dev/board.h>
  2. include <stdio.h>
  3. include <io.h>
  4. include <math.h>

int main(void) {

   unsigned long baud = 115200;
   double val = 0.0;
   double val2 = 0.0;
   NutRegisterDevice(&DEV_UART, 0, 0);
   freopen(DEV_UART_NAME, "w", stdout);
   freopen(DEV_UART_NAME, "r", stdin);
   _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
   puts("\nNut/OS Floating Point Math Demo");
   puts("Please enter a first floating point value:");
   scanf("%lf", &val);
   puts("Please enter a second floating point value:");
   scanf("%lf", &val2);
   printf("We will now perform some advanced math operations using the numbers %lf and %lf:\n\n", val, val2);
   printf("Sine: sin(%lf) -> %lf\n", val, sin(val));
   printf("Tangens: tan(%lf) -> %lf\n", val, tan(val));
   printf("Arc Tangens: atan(%lf) -> %lf\n\n", val, atan(val));
   printf("Exponential: exp(%lf) -> %lf\n", val, exp(val));
   printf("Power: pow(%lf, %lf) -> %lf\n", val, val2, pow(val, val2));
   printf("Square Root: sqrt(%lf) -> %lf\n", val, sqrt(val));
   printf("Logarithm: log(%lf) -> %lf\n", val, log(val));
   printf("Base 10 Logarithm: log10(%lf) -> %lf\n\n", val, log10(val));
   printf("Floating Point Absolute: fabs(%lf) -> %lf\n", val, fabs(val));
   printf("Floor: floor(%lf) -> %lf\n", val, floor(val));
  1. if defined(__arm__)
   /* This only exists in newlib so we'll not use it when compiling vor AVR */
   printf("Remainder: remainder(%lf%, %lf) -> %lf\n", val, val2, remainder(val, val2));
  1. endif
   printf("Round: round(%lf) -> %lf\n", val, round(val));
   printf("Truncate to Integer: trunc(%lf) -> %lf\n", val, trunc(val));
   for (;;);
   return 0;

} </source>

Details

<source lang="c"> unsigned long baud = 115200; double val = 0.0; double val2 = 0.0;

NutRegisterDevice(&DEV_UART, 0, 0); freopen(DEV_UART_NAME, "w", stdout); freopen(DEV_UART_NAME, "r", stdin); _ioctl(_fileno(stdout), UART_SETSPEED, &baud);

puts("\nNut/OS Floating Point Math Demo"); </source>

Up to this point, this example looks exactly the same as the first example on floating point values. The only difference is the name of the application so far.

<source lang="c"> puts("Please enter a first floating point value:"); scanf("%lf", &val);

puts("Please enter a second floating point value:"); scanf("%lf", &val2); </source>

Since we want to do calculations with floating point values, we first ask for 2 of them. Most of the functions demonstrated hereafter will only need 1 but some need 2.

That's it, we're ready to calculate some things.

<source lang="c"> printf("Sine: sin(%lf) -> %lf\n", val, sin(val)); </source> Since the example uses the same line over and over again for each function, it is pretty easy to understand how it works:

First the normal, english name of the mathematical operation is printed, then the function name with the values inserted. After that, we print the return value of the function.

Since the functions themselves are pretty much self-explaining, you should be easily able to understand what each function does. If you still get stuck, take a look at the corresponding documentation for your platform:

AVR: avr-libc

ARM & AVR32: newlib

<source lang="c">

  1. if defined(__arm__)
   /* This only exists in newlib so we'll not use it when compiling vor AVR */
   printf("Remainder: remainder(%lf%, %lf) -> %lf\n", val, val2, remainder(val, val2));
  1. endif

</source>

By the way: The remainder function only exists in newlib. If you try to use it on AVR, the compiler will throw an error.

A homebrew remainder function for the AVR could look something like this:

<source lang="c"> float remainder(float num1, float num2) {

   while(num1 >= num2) {
       num1 -= num2;
   }
   return num1;

} </source>

Keep in mind that floating point math is very slow on AVR and ARM CPUs. Use it only when absolutely needed.

Output

<source lang="text"> Nut/OS Floating Point Math Demo Please enter a first floating point value: Please enter a second floating point value: We will now perform some advanced math operations using the numbers 4.600000 and

3.100000:

Sine: sin(4.600000) -> -0.993691 Tangens: tan(4.600000) -> 8.860168 Arc Tangens: atan(4.600000) -> 1.356736

Exponential: exp(4.600000) -> 99.484299 Power: pow(4.600000, 3.100000) -> 113.383360 Square Root: sqrt(4.600000) -> 2.144761 Logarithm: log(4.600000) -> 1.526056 Base 10 Logarithm: log10(4.600000) -> 0.662758

Floating Point Absolute: fabs(4.600000) -> 4.600000 Floor: floor(4.600000) -> 4.000000 Round: round(4.600000) -> 5.000000 Truncate to Integer: trunc(4.600000) -> 4.000000 </source>

See also