1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| #include <iostream>
#include <stdarg.h>
#include <windef.h>
#include <winbase.h>
#include <string>
using namespace std;
typedef long long int_64;
//#define D2I_CONVERSION_FACTOR (1.5 * 4503599627370496.0)
#define D2I_CONVERSION_FACTOR 6755399441055744.0
inline int d2i(double val)
{
union {
int i[2];
double d;
} dlong;
dlong.d = val + D2I_CONVERSION_FACTOR;
return dlong.i[0];
}
// la fonction qui fait le test
void tt(void)
{
// nombre de boucles à faire
#define NB 100000000
LARGE_INTEGER t1,t2,t3,t4; // pour stocker les points de QueryPerformanceCounter
// encadrant les boucles
double d = -12345.1234665;
int n1 = 0, n2 = 0;
// boucle utilisant "l'astuce" d2i
QueryPerformanceCounter(&t1);
for (int i=0;i<NB;++i)
{
n1 = d2i(d);
}
QueryPerformanceCounter(&t2);
// boucle utilisant le cast classique, ou l'assembleur
// (commenter/décommenter la version à tester)
QueryPerformanceCounter(&t3);
for (int i=0;i<NB;++i)
{
// pour tester le cast classique
//n2 = (int)d;
// pour tester en assembleur
__asm__ (
"fldl %[orig]\n\t"
"fistpl %[dest]\n\t"
: [dest] "=g" (n2)
: [orig] "m" (d)
:
);
}
QueryPerformanceCounter(&t4);
// calcul des durées et du rapport, et affichage des résultats
int_64 r12 = t2.QuadPart - t1.QuadPart;
int_64 r34 = t4.QuadPart - t3.QuadPart;
double rapport;
if (r34)
{
rapport = (double)r12/(double)r34;
}
else
{
rapport = -1;
}
cout<<"special : "<<r12<<", cast : "<<r34<<", rapport (astuce/cast) = "<<rapport<<endl;
if (n1!=n2)
{
cout<<"error (n1 = "<<n1<<") != (n2 = "<<n2<<")"<<endl;
cout<<"n1 = "<<n1<<", n2 = "<<n2<<endl;
} else
{
cout<<"bravo, n1 == n2 = "<<n1<<endl;
}
}
int main()
{
tt();
return 0;
} |
Partager