Código PHP:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
__inline int fsqrt(__int16 numero)
{
float x = (float)(numero);
float xhalf = 0.5f * x;
register int i = *(int*)&x;
i = 0x5f3759d5 - (i >> 1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
return (__int8)(1/x);
}
__inline int esprimo(__int16 numero)
{
register __int8 resultado;
register __int8 raiz = fsqrt(numero);
__asm
{
mov ax, numero
mov bl, 2
mov cx, ax
mov dl, raiz
cmp ax, 1
je noprimo
cmp ax, 2
je primo
div bl
cmp ah, 0
je noprimo
mov bl, 3
mov ax, cx
ciclo:
div bl
cmp ah, 0
je noprimo
add bl, 2
mov ax, cx
cmp bl, dl
jb ciclo
jmp primo
primo:
mov resultado, 1
jmp fin
noprimo:
mov resultado, 0
fin:
}
return resultado;
}
int main(){
register __int16 numero = 1;
register __int16 cont = 0;
clock_t t_ini, t_fin;
double diff;
t_ini = clock();
while(numero < 500)
{
if(esprimo(numero) == 1)
{
cont++;
}
if(numero > 2) numero+=2;
else numero++;
}
printf("Hay %d primos entre 1 y 500\n",cont);
t_fin = clock();
diff = (double)(t_fin - t_ini);
printf("%.16g ciclo(s) de reloj\n", diff);
system("pause");
return 0;
}
Me gustaria saber si valió la pena y si es mas rapido o solo fue perder tiempo en assembler xD
Lo compile con Visual C++ 2005, y me da 0.001 en mi maquina PERO solo calcula la cantidad de primos entre 1 y 500 (es assembler de 16bits, el maximo numero que se almacena en un registro de 8bits es 511)
Modifique el de cesrlg para que haga lo mismo que el mio (del 1 al 500 y que muestre solo cantidad), asi quedo:
Código PHP:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
struct nodo{
unsigned long int val;
nodo *sgte;
};
int cont = 1;
void calcular_primos(nodo *Raiz, nodo **Final, unsigned long int val);
void main(){
unsigned long int val = 2;
nodo *Lista, *Final;
clock_t t_ini, t_fin;
double diff;
Lista = new nodo;
Lista->val = val;
Lista->sgte = NULL;
Final = Lista;
t_ini = clock();
while( 1 ){
calcular_primos(Lista, &Final, ++val);
if(val == 500){break;} //* Numero limite 100*//
}
cout<<"Hay "<<cont<<" numeros primos entre 1 y 500\n";
t_fin = clock();
diff = (double)(t_fin - t_ini);
printf("%.16g ciclos de reloj\n", diff);
system("pause>nul");
}
void calcular_primos(nodo *Raiz, nodo **Final, unsigned long int val){
bool es_primo = true;
nodo *p = Raiz;
while(p != NULL){
if(val%(p->val) == 0){
es_primo = false;
break;
}
if((p->sgte) != NULL){
if(((p->sgte)->val)*((p->sgte)->val) > val){
break;
}
}
p = p->sgte;
}
if(es_primo){
(*Final)->sgte = new nodo;
((*Final)->sgte)->val = val;
((*Final)->sgte)->sgte = NULL;
*Final = (*Final)->sgte;
cont++;
}
}
cesrlg: 6 ciclos de reloj minimo, 11 ciclos de reloj maximo
mio: 0 ciclos de reloj minimo, 1 ciclo de reloj maximo.