Hop, cadeau :
Code:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
// p in Pascal
// result in meters
// Approximates the function
// f = (((101325 / x) ^ 0.190223) - 1) * 44330.08;
// in the domain [40960;106496]
int16_t pressure_to_altitude(int32_t p)
{
// Split the domain into 8 intervals from 40960 to 105728
// Approximate the function by a degree-2 polynomial in each interval
struct { int64_t p0; int32_t p1; int16_t p2; }
static const coeffs[] = {
{ 35795727448128, -1042448034, 12462 }, // in [40960;49152], error = 0.80951611993493776711245609581499619714315753029553
{ 28086794889324, -840897244, 8629 }, // in [49152;57344], error = 0.474799929040441506427073063081948032935080914747029
{ 21773918533619, -700885309, 6300 }, // in [57344;65536], error = 0.30018159785032809444115203457430196706491908525297
{ 16452901730270, -598438494, 4786 }, // in [65536;73728], error = 0.20120032429450890214321783461333055282725558564658
{ 11870206341953, -520491130, 3749 }, // in [73728;81920], error = 0.14170511581801910239701078064260695685954381904145
{ 7856891565555, -459363604, 3010 }, // in [81920;90112], error = 0.102858579232502722242344676757379695070697753320511
{ 4295019137961, -410249303, 2466 }, // in [90112;98304], error = 7.6857608182274683964630313720095645400848430388807e-2
{ 1099167366159, -369990149, 2054 }, // in [98304;106496], error = 5.9026577330911215789619856390339475180979511534459e-2
};
// Get index from high bits
int32_t i = (p >> 13) - 5;
// Get offset from low bits
int16_t x = p & ((1 << 13) - 1);
// Perform bound checks
if(i < 0) {
return 8336; // Too high -> saturate
}
else if(i >= 8) {
return -418; // Too low -> saturate
}
// Get polynomial coefficients
int64_t P0 = coeffs[i].p0;
int32_t P1 = coeffs[i].p1;
int16_t P2 = coeffs[i].p2;
// Evaluate polynomial
int64_t r = P0 + (int64_t)x * (P1 + (int32_t)x * P2);
return r >> 32; // Truncate to whole meters.
}
int main(int argc, char * argv[])
{
int p = atoi(argv[1]);
int a = pressure_to_altitude(p);
printf("%d\n", a);
return 0;
}
Pour l'utiliser, dégage tous les float et double qui trainent, enlève la division à la fin de la fonction pressure et fais-lui renvoyer la pression en Pascal sous forme d'entier (on utilise le système SI merde).
Waring: ne pas utiliser pour le saut en scaphandre à plus de 8335m ou pour la plongée à moins de -417m. Aucune garantie expresse ou implicite sur la non-buggabilité du code. Néanmoins, le calcul des coefficients est prouvé en Coq et la précision est totalement overkill par rapport à celle des mesures et des constantes physiques, donc ça devrait le faire. J'ai laissé le nombre de chiffres significatifs par défaut sur les erreurs, ça donne l'impression qu'on est super précis.