Open vtomanov opened 8 years ago
Interesting. I would try to convert the two integer parts to f64 each and add them together afterwards. Are you sure that you absolutely need 64-bit floats? I've done some pretty impressively accurate polar coordinate stuff for astronomy using just 32 bits. See my godob project. mic
On 20 Aug 2016 15:59, "vtomanov" notifications@github.com wrote:
Hi,
The raw GPS data is in the following format :
int16_t deg; // the integer part of the number uint32_t minSec; // exact 9 digits after the decimal point - e.g. 3.123456789, 4.123000000
Do you have any suggestion for the best way to create f64 type from this structure ? atoi seems slow to me ? Also vise-verse from f64 extract the data in the original structure ?
FYI: I'm planing to use your library for some GPS calculations and currently experimenting with it....
Kind Regards Vasko Tomanov
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/mmoller2k/Float64/issues/2, or mute the thread https://github.com/notifications/unsubscribe-auth/ADIetN-fBl2Tb-Qs3FTPA0Zh5Rz2zoqvks5qhwhYgaJpZM4JpFLo .
OK that can do the job - 1.get the fractional integer 2. divide by 1000000000 3. add the integer part...
re: f32 - I need 6 decimal places after the decimal point and in degrees I need max 3 decimals in the integer part - e.g in total 9 decimal places... I miss about 2-3 in f32
hmmm performance wise not good so far ... a distance calculation takes 5 second... result is correct ( 687513.69 meters) but really slow...
point 1 lat : 40.748600000 lng : -73, 986400000
point 2 lat: 45, 748600000 lng: -78, 986400000 // Return distance between two coordinates in meters inline void dist64(f64 & latStart, f64 & lngStart,
f64 & latEnd,
f64 & lngEnd,
f64 & dist)
{
f64 _latStart; dtor64(latStart, _latStart); f64 _lngStart; dtor64(lngStart, _lngStart);
f64 _latEnd; dtor64(latEnd, _latEnd); f64 _lngEnd; dtor64(lngEnd, _lngEnd);
//=ACOS( SIN(lat1)_SIN(lat2) + COS(lat1)_COS(lat2)COS(lon2-lon1) ) * 6371000 dist = acos64( sin64(_latStart) * sin64(_latEnd) + cos64(_latStart) * cos64(_latEnd) * cos64(_lngEnd - _lngStart) ) \ GPS_DATA_6371000;
}
// Convert degree to radians inline void dtor64(const f64 & d, f64 & r) { r = d; r *= GPS_DATA_PI_180; }
Impressive. What cpu are you running it on?
On 21 Aug 2016 3:35 p.m., "vtomanov" notifications@github.com wrote:
define GPS_DATA_90 f64(90L)
define GPS_DATA_PIO2 f64(0x3FF921FB, 0x54442D18)
define GPS_DATA_6371000 f64(6371000L)
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mmoller2k/Float64/issues/2#issuecomment-241257631, or mute the thread https://github.com/notifications/unsubscribe-auth/ADIetAflRB1dl8mRlWnEbtW9EUNUzxq8ks5qiFQHgaJpZM4JpFLo .
https://www.arduino.cc/en/Main/ArduinoBoardMega2560
but the result is not good .... I will measure the functions one by one to find the bottleneck.. - should be about 1/10 sec max...
Test shows that acos64 need SERIOUS improvement about 20x - 4.65 sec cos64 and sin64 are slow but not so tragic....
results :
dtor64 (latStart): 0 dtor64 (lngStart): 0 dtor64 (lngEnd): 0 dtor64 (lngEnd): 1 sin64 (sin64_latStart): 74 sin64 (sin64_latEnd): 76 mul64 (sin_mul): 0 cos64 (cos64_latStart): 77 cos64 (cos64_latEnd): 77 cos64 (cos64_lngEnd_lngStart): 86 mul64 (cos_mul): 0 acos64 (acos64_sin_mul_cos_mul): 4650
-- test code ---- // Return distance between two coordinates in meters inline void dist64(f64 & latStart, f64 & lngStart,
f64 & latEnd,
f64 & lngEnd,
f64 & dist)
{ uint32_t s = millis();
f64 _latStart; dtor64(latStart, _latStart); uint32_t sLatStart = millis(); f64 _lngStart; dtor64(lngStart, _lngStart); uint32_t sLngStart = millis();
f64 _latEnd; dtor64(latEnd, _latEnd); uint32_t sLatEnd = millis(); f64 _lngEnd; dtor64(lngEnd, _lngEnd); uint32_t sLngEnd = millis();
//=ACOS( SIN(lat1)_SIN(lat2) + COS(lat1)_COS(lat2)COS(lon2-lon1) ) \ 6371000
f64 sin64_latStart = sin64(_latStart); uint32_t sSin64_latStart = millis(); f64 sin64_latEnd = sin64(_latEnd); uint32_t sSin64_latEnd = millis(); f64 sin_mul = sin64_latStart * sin64_latEnd; uint32_t sSin_mul = millis();
f64 cos64_latStart = cos64(_latStart); uint32_t sCos64_latStart = millis(); f64 cos64_latEnd = cos64(_latEnd); uint32_t sCos64_latEnd = millis(); f64 cos64_lngEnd_lngStart = cos64(_lngEnd - _lngStart); uint32_t sCos64_lngEnd_lngStart = millis(); f64 cos_mul = cos64_latStart * cos64_latEnd * cos64_lngEnd_lngStart; uint32_t sCos_mul = millis();
f64 acos64_sin_mul_cos_mul = acos64( sin_mul + cos_mul ); uint32_t sAcos64_sin_mul_cos_mul = millis(); dist = acos64_sin_mul_cos_mul * GPS_DATA_6371000;
uint32_t e = millis();
Serial.println("dtor64 (latStart): " + String(sLatStart - s)); Serial.println("dtor64 (lngStart): " + String(sLngStart - sLatStart)); Serial.println("dtor64 (lngEnd): " + String(sLatEnd - sLngStart)); Serial.println("dtor64 (lngEnd): " + String(sLngEnd - sLatEnd));
Serial.println("sin64 (sin64_latStart): " + String(sSin64_latStart - sLngEnd)); Serial.println("sin64 (sin64_latEnd): " + String(sSin64_latEnd - sSin64_latStart)); Serial.println("mul64 (sin_mul): " + String(sSin_mul - sSin64_latEnd));
Serial.println("cos64 (cos64_latStart): " + String(sCos64_latStart - sSin_mul)); Serial.println("cos64 (cos64_latEnd): " + String(sCos64_latEnd - sCos64_latStart)); Serial.println("cos64 (cos64_lngEnd_lngStart): " + String(sCos64_lngEnd_lngStart - sCos64_latEnd)); Serial.println("mul64 (cos_mul): " + String(sCos_mul - sCos64_lngEnd_lngStart));
Serial.println("acos64 (acos64_sin_mul_cos_mul): " + String(sAcos64_sin_mul_cos_mul - sCos_mul));
Serial.println("dist64: " + String(e - s)); }
will be very useful if you can add to your Math64 lib fast trigonometric functions based on the code from here : http://http.developer.nvidia.com/Cg/index_stdlib.html
you can name them little bit different to acknowledge that they actually have some tradeoff in the precision ... but will be still good for most cases
after more tests the things looks actually worse - in case of small distances the acos64 may go more then 10sec ... definitely it needs a faster algorithm implementation
acos64 (acos64_sin_mul_cos_mul): 10224
Wow! Thanks for all the effort. I'll have a look and see what I can do. When I first wrote the math lib, memory was the problem, not speed. But faster trig functions are definitely possible. I'm away most of next week but will look into it when I'm back. If you think the trig functions are slow you should try the logs and exponent functions... mic
On 21 Aug 2016 7:15 p.m., "vtomanov" notifications@github.com wrote:
after mote test the things are actually worse in small distances the
acos64 may go more then 10sec ... definitely in need of a faster algo
acos64 (acos64_sin_mul_cos_mul): 10224
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mmoller2k/Float64/issues/2#issuecomment-241269584, or mute the thread https://github.com/notifications/unsubscribe-auth/ADIetJeH89cG06ie-KjTI_MMDyglQEgDks5qiIeggaJpZM4JpFLo .
The thing definitely need a huge improvement ( btw: sqrt64 seems very slow also)
this is with normal floats on arduino e.g. 32bit floating point: e.g. about 10 millis result compared to 10 seconds with f64 ... e.g. 1000x slower with f64
dtor (latStart): 1 dtor (lngStart): 2 dtor (lngEnd): 1 dtor (lngEnd): 0 sin (sin_latStart): 5 sin (sin_latEnd): 0 mul (sin_mul): 0 cos (cos_latStart): 0 cos (cos_latEnd): 0 cos(cos_lngEnd_lngStart): 0 mul(cos_mul): 0 acos (acos_sin_mul_cos_mul): 1
total dist: 10
this is with f64 :
dtor64 (latStart): 0 dtor64 (lngStart): 1 dtor64 (lngEnd): 1 dtor64 (lngEnd): 0 sin64 (sin64_latStart): 74 sin64 (sin64_latEnd): 75 mul64 (sin_mul): 0 cos64 (cos64_latStart): 77 cos64 (cos64_latEnd): 77 cos64 (cos64_lngEnd_lngStart): 87 mul64 (cos_mul): 0 acos64 (acos64_sin_mul_cos_mul): 10226
total dist64: 10618
Yeah I know. I actually removed the square root function to save memory. It should still be commented out in the code somewhere. The sqrt function in the math library actually used logs - which is nice and memory efficient of you don't mind the wait. I'll try and look into some speed improvements sometime soon. mic
On 23 Aug 2016 11:05, "vtomanov" notifications@github.com wrote:
The thing definitely need a huge improvement ( btw: sqrt64 seems very slow also)
this is with normal floats on arduino e.g. 32bit floating point: e.g. about 10 millis result compared to 10 seconds with f64 ... e.g. 1000x slower with f64
dtor (latStart): 1 dtor (lngStart): 2 dtor (lngEnd): 1 dtor (lngEnd): 0 sin (sin_latStart): 5 sin (sin_latEnd): 0 mul (sin_mul): 0 cos (cos_latStart): 0 cos (cos_latEnd): 0 cos(cos_lngEnd_lngStart): 0 mul(cos_mul): 0 acos (acos_sin_mul_cos_mul): 1
total dist: 10
this is with f64 :
dtor64 (latStart): 0 dtor64 (lngStart): 1 dtor64 (lngEnd): 1 dtor64 (lngEnd): 0 sin64 (sin64_latStart): 74 sin64 (sin64_latEnd): 75 mul64 (sin_mul): 0 cos64 (cos64_latStart): 77 cos64 (cos64_latEnd): 77 cos64 (cos64_lngEnd_lngStart): 87 mul64 (cos_mul): 0 acos64 (acos64_sin_mul_cos_mul): 10226
total dist64: 10618
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mmoller2k/Float64/issues/2#issuecomment-241671267, or mute the thread https://github.com/notifications/unsubscribe-auth/ADIetM4vjff4liqSgyLiCMAhrG5z_gdUks5qirfagaJpZM4JpFLo .
I've try this implementation of acos (..) and the sqrt inside still takes 10sec
inline void acos64o(const f64 & rhs, f64 & ret) { f64 negate = f64(rhs < 0); f64 x(rhs.fabs()); ret = f64(f64(-187293L) / f64(10000000L)); ret = x; ret += f64(f64(742610L) / f64(10000000L)); ret = x; ret -= f64(f64(2121144L) / f64(10000000L)); ret = x; ret += f64(f64(15707288L) / f64(10000000L)); ret = sqrt64(f64(1L) - x); ///// THIS LINE TAKES 10sec ret -= f64(2L) * negate * ret; ret += negate * GPS_DATA_PI; }
you can test the performance using the following lib that I just commited :
Hi,
The raw GPS data is in the following format :
int16_t deg; // the integer part of the number uint32_t minSec; // exact 9 digits after the decimal point - e.g. 3.123456789, 4.123000000
Do you have any suggestion for the best way to create f64 type from this structure ? atoi seems slow to me ? Also vise-verse from f64 extract the data in the original structure ?
FYI: I'm planing to use your library for some GPS calculations and currently experimenting with it....
Kind Regards Vasko Tomanov