How run FP64lib on Arduino ZERO?

My project involves differences between large numbers, and 32 bit floating point ain't enough. There's a library for 64 bit math called FP64lib. I used the library manager to load it and want to try things out with the "NoDouble" example demo sketch.

The documentation provided with the FP64 library says it DOES work with the Arduino Zero. But I get a compile time error message. It APPEARS to be a warning that maybe the library won't work with the Zero. I get that a warning is nice.

How do I turn off the error message? Is there some compiler directive to ignore errors from, say, an include file? I tried to go in to edit the include file (yes, always a dangerous idea) but I cannot see a way to do the edit safely.

Perhaps I should use a normal text editor and edit the header file directly?

Thanks,
--jim

WARNING: library fp64lib claims to run on avr, atmelavr architecture(s) and may be incompatible with your current board which runs on samd architecture(s).
In file included from /Users/jimhahn/Documents/Arduino/libraries/fp64lib/fp64lib.h:205:0,
from /Users/jimhahn/Downloads/fp64lib-1.1.20/examples/NoDouble/NoDouble.ino:1:
/Users/jimhahn/Documents/Arduino/libraries/fp64lib/fp64def.h:34:2: error: #error fp64lib is created and tested only for Atmel AVR 328p microprocessors like Arduino UNO or Nano

According to this post, the Arduino Zero and other SAMD21 M0 boards support type double "out of the box".

I tested this code on the Adafruit Feather M0, which has the same processor, and got the expected result.

// Test: set the double to the smallest number greater than 1
union
{
  double d;                   // double
  struct 
  {
    uint64_t mantissa : 52;   // 52 bit mantissa
    uint64_t exponent : 11;   // 11 bit exponent
    uint64_t sign : 1;        // 1 bit sign
  } part;
} doubleFloat;

void setup() 
{
  Serial.begin(115200);
  while(!Serial) delay(1);
  
  doubleFloat.part.mantissa = 0x1;      // Load mantissa
  doubleFloat.part.exponent = 0x3FF;    // Load exponent
  doubleFloat.part.sign = 0x0;          // Load sign
  Serial.print(F("Double: "));
  Serial.println(doubleFloat.d, 16);    // Should output: 1.0000000000000002
}

void loop() {}

Where did you see that? A direct quote from their page:

fp64lib is a library for implementing 64-bit floating point arithmetic on the AVR MegaAVR architecure microprocessors, like the popular Arduino series.

Ask and ye shall receive:
https://docs.arduino.cc/libraries/fp64lib/#Compatibility

Those compatibility claims are hard to believe, given the warning, and the more obvious red flag that the library is written in AVR assembly code.

I would take that warning seriously, especially since you don't need that library for double precision float calculations on the Arduino Zero.

I am certain you know lots more than me about double precision and the Zero etc. I looked at your code and it's clear one can define double precision numbers as you did. That does not imply (?) you can do double precision arithmetic with the Zero as is. (Remember: I said you know more than me!) Nowhere in reading about the Zero does, at least what I have done, does it say/imply anything about 64 bit floating point. I'd be happy to be wrong.

I freely admit I don't understand the #define's from the snip below:

#if (!defined(AVR_ATmega328P) || defined(AVR_TINY) || !defined(AVR_ENHANCED)) && !defined(ARDUINO_AVR_MEGA2560) &&!defined(AVR_MEGA)
#error fp64lib is created and tested only for Atmel AVR 328p microprocessors like Arduino UNO or Nano
#endif

Yes, it does. Try it.

I freely admit I don't understand the #define's from the snip below:

#if (!defined(**AVR_ATmega328P**) || defined(**AVR_TINY**) || !defined(**AVR_ENHANCED**)) && !defined(ARDUINO_AVR_MEGA2560) &&!defined(**AVR_MEGA**)
#error fp64lib is created and tested only for Atmel AVR 328p microprocessors like Arduino UNO or Nano
#endif

Those preprocessor commands test whether the processor is among the ones specifically listed, and if not, the error message "fp64lib is created and tested only for Atmel AVR 328p microprocessors like Arduino UNO or Nano" is printed.

Good luck with your project.

The compatibility list is plainly wrong.

To repeat what @blh64 said in an earlier reply, and quoting from https://fp64lib.org

fp64lib is a library for implementing 64-bit floating point arithmetic on the AVR MegaAVR architecure microprocessors

The M0 is not a MegaAVR chip.

The compatibility list is plainly wrong.

To repeat what @jremington said in an earlier post, the library uses AVR assembly code. That will neither assemble nor run on an M0.

The compatibility list is plainly wrong.

And to repeat what @jremington also said in an earlier reply, the M0 supports double out of the box.

Prove it to yourself.

Run this sketch on an R3, and on your Zero.

void setup() {
   Serial.begin(115200);
   while( !Serial );
   delay(1000);
   
   Serial.print("float is ");
   Serial.print(sizeof(float));
   Serial.println(" bytes");

   Serial.print("double is ");
   Serial.print(sizeof(double));
   Serial.println(" bytes");
}

void loop() {
}

Look at the results.

Think about the difference.

Come to your own conclusions.

Thank you both. Looks like you guys are right. Back to my drawing board to see why the heck I THOUGHT I needed better floating point math for my application.

51 bits of mantissa yields 15 decimal digits.
--jim

You might indeed need some or all of those extra decimal digits. Why not tell us about the project and/or the problem?

There are ways to get around some of the limitations of floating point math, if that actually is causing a problem.

One of them is simply rearranging a calculation such that you don't subtract two nearly equal numbers.

My project computes speed of sound times on a 100x100 inch grid. From the corners to an arbitrary point in the grid. I originally (and stupidly) used INTs for the type. Later I got "too clever by half" and switched to DOUBLE so I could do fractional inches. Deep in one nested function, I pulled a value out as an INT and the compiler happily cast a double to an int. My Mistake.

I'll look into the tricks of rearranging calculations. Thank you.
--jim

The speed of sound depends on temperature and humidity.
Does the grid have a large temperature or humidity gradient?

Or do you want to determine the point of impact?
E.g. by calculating the time it takes the sound to reach the corners?

Point of Impact. There are now several commercial electronic devices which shooters use to display their target and shots thereon. See the device named "ShotMarker" ($800). 8 mikes (microphones) are positioned at the corners of the 6x6 foot target. These feed a small box on the target. It's a set of time measurement circuits. These time measurement are fed back to another box which computes point of impact and generates a web page which the shooter "logs into" to see his target.

I worked on a hobby project once I retired to try to build one. We had 4 retired EE's and we worked for ten years. (Yes, ten!) One key software/physics/math problem is how do you turn a set of time measurements into a point of impact x,y.

There are 3 or 4 methods to do this - probably. One which failed for us was Newton Raphson and we never really understood why. It had a lot to do with not being math majors!

The project ended 5 years ago but it's always bugged me that NR failed in our real world. A few weeks ago I stumbled on a linear minimization technique and decided to see if it, or something like it, would have worked better than our implementation of NR. So that's what I am coding up now.

Yes, you need a temperature sensor to allow you to calculate SOS. Humidity does not matter in these calculations.

I solved the same problem a dozen years ago on the old part of the forum, cannot find the code (probably on one of my previous PC's).

When you try to do that mathematically you need a lot of formulas (tried that but stopped)

The working idea was simple, I try to recall the details.

There is an square area with 4 mikes at the corners (A B C D).

A-------------------B
|         |         |
|  a      |      b  |
|      x  |         |
| - - - - - - - - - |
|         |         |
|  c      |      d  |
|         |         |
C-------------------D

There are a number of scenarios:

  1. four mikes receive the sound at the same time: ==> point is the middle.
  2. three mikes receive the sound at the same time ==> impossible (ok 1 broken mike).
  3. two mikes receive the sound at the same time => point is on the middle line between the two mikes.
  4. one mike receives the sound as first.

The interesting cases are 3 and 4, I continue with the last one.

Suppose mike A hears the sound as first you know the impact point is in quadrant a.
So either B or C should get the sound as second, the other as third and D as last.

So we have 4 impact times T0, T1, T2, T3 and the quadrant the shot was in.
T0 was the first timestamp, so we can calculate all delta timestamps Tn -T0
So we get t0 t1 t2 and t3, and t0 == 0.

The idea is now:
We now search through all the points in quadrant a and ask the following question.

If x was the point of impact, what would be the delta in timestamps for t0 .. t3?
These delta timestamps can be calculated by the distance functions (sqrt(x^2 + y^2)) divided by SOS.
The point that has the smallest error is the point of impact.

The search can be done brute force, going through all points or more intelligent.

Assume you have 1000 x 1000 points area to search, you could go through all million.
Or you could it in a few iterations, first roughly in a 10x10 grid.
Take the best 4 points and search in there for a 10x10 grid,
take the best 4 points and search in there for a 10x10 grid,
in just 3 iterations (300 points checked) you would find the point.

Another way would be to split the area in 4 and choose the quadrant with the least error.
split again in 4 and choose the quadrant with the least error.
split again in 4 and choose the quadrant with the least error.
split again in 4 and choose the quadrant with the least error.
split again in 4 and choose the quadrant with the least error.

you need about 10 iterations to find the point (2^10 ~~1000) 10 iterations would mean you need to calculate and check about 40 points.

Long story short, the point can be found by "simulation" instead of calculation.

If time permits I will try to find the original thread or code.

Google was helpful

No need to solve for circle intersections, etc.

The trilateration problem was solved explictly a number of years ago, by a simple algebraic trick that linearizes the problem. Given N+1 distances or times of flight, the point of origin in 2D or 3D can be solved by linear least squares, e.g. inverting an NxN matrix.

For the method, see this short technical paper:

This was proposed earlier by other authors -- variations of this technique are reviewed in an open access publication:

Thanks for sharing!

mmm....

from the TR-2-2015-least-sqaures-with-ToA.pdf

In this paper it is assumed that distances between an anchor (or reference node) and a tag is available. The situation is depicted in Figure 1. In this figure several anchors (denoted as Ai) are shown and further a tag is present. Between those anchors and tags distance measurements are available. This is paper does not describe how to obtain such distances but focuses to solve the localization problem

In fact if only two distances are known (and the location of the 4 anchors) it is simply solving the 3rd point of a triangle.

Note the OP does not have the distances from the point of impact to the anchors.
One only knows the arrival times of the sound at the four corners (and their deltas).
So one still has to determine the distances, which might still need circle intersection.

That is why I said, "given N+1 distances or times of flight" ...

There's two different problems here. One is called TOA which stands for time of arrival. It assumes you know the time t0 of when the signal originated. And each mike has a time measured from that t0. Subtractions of a mike time and t0 gets you time delay for the signal to reach you. Div by SOS and you got distance. GPS sort of works this way: The satellite "knows" the time of day when it sends the signal out and the receiver know when it gets it. Using speed of light, you got distance.

The bullet on target problem is TDOA. Time DELAY of arrival. You don't know when the bullet hits; you don't know t0. Each mike has a timer upcounter circuit, all starting at zero time. When any mike hears the signal, all timers start counting. And any given mike's timer is stopped when that mike itself hears the signal. The first mike gets a time of zero reported for it.

The math works out that two mikes produce a hyperbola arm and you know the formula for that arm. x=f1(x). Another two mikes gets you x=f2(x). Knowing those two formulas gives you a prayer of solving for x0,y0 the point of impact. Where the hyperbolas cross.

There are several methods to attack the TDOA problem. A couple use those formulas f1 and f2. (And of course if you have lots more mikes, you get lots more functions to play with.)

As I think I mentioned, we tried and failed with NR. Turns out there's a lot more to it. x0,y0 are obviously critical. But three other variables play in and need solution. Velocity of the bullet, incoming angle of the bullet in the x dimension, and angle in the y dimension. Alas, the sound wave does not spread out at SOS but another velocity (we called it vSignal) based on SOS and vBullet.

So a few weeks ago when I ran into another minimization technique (I think it was "simplex" or something like that) I decided to play around again with software to find the impact hole. I do all my development on the Arduino. I think I must have some more bugs!
--jim