2013年12月15日日曜日

32bit整数レジスタを自己流実数レジスタとして扱いsin,cosを求める

akira@dynabookAZ:~/arm1312$ ./c010
Number: 45   45度をラジアンで計算
l=2d00000   45(10)=2d(16)
sin(dd*pi/180)=0.7071067812   cos(dd*pi/180)=0.7071067812  通常演算(元の参考値)
@@@  sin1(do)=  @@@   l=   b504f   +0.7071065902  自己流で計算した値
@@@  cos1(do)=  @@@   l=   b504f   +0.7071065902
Number: 30
l=1e00000
sin(dd*pi/180)=0.5000000000   cos(dd*pi/180)=0.8660254038  
@@@  sin1(do)=  @@@   l=   7fffe   +0.4999980926
@@@  cos1(do)=  @@@   l=   ddb40   +0.8660278320
Number: 60
l=3c00000
sin(dd*pi/180)=0.8660254038   cos(dd*pi/180)=0.5000000000  
@@@  sin1(do)=  @@@   l=   ddb3d   +0.8660249710
@@@  cos1(do)=  @@@   l=   80001   +0.5000009536
Number: 0
l=0
sin(dd*pi/180)=0.0000000000   cos(dd*pi/180)=1.0000000000  
@@@  sin1(do)=  @@@   l=       0   +0.0000000000
@@@  cos1(do)=  @@@   l=  100000   +1.0000000000
Number: 180
l=b400000
sin(dd*pi/180)=0.0000000000   cos(dd*pi/180)=-1.0000000000  
@@@  sin1(do)=  @@@   l=       0   +0.0000000000
@@@  cos1(do)=  @@@   l=80100000   -1.0000000000
Number: -12.4
l=80c66666
sin(dd*pi/180)=-0.2147353272   cos(dd*pi/180)=0.9766722783  
@@@  sin1(do)=  @@@   l=80036f8d   -0.2147340774
@@@  cos1(do)=  @@@   l=   fa073   +0.9766721725
Number: -33.3
l=8214cccc
sin(dd*pi/180)=-0.5490228180   cos(dd*pi/180)=0.8358073614  
@@@  sin1(do)=  @@@   l=8008c8ca   -0.5490207672
@@@  cos1(do)=  @@@   l=   d5f79   +0.8358087539
Number: ^C
akira@dynabookAZ:~/arm1312$ cat c010.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define  x8  0x80000000
#define  x7f 0x7fffffff
#define  xpi 0x3243f6

long main1a();
long add0(long l1,long l2);
long sub0(long l1,long l2);
long add1(long l1,long l2);
long sub1(long l1,long l2);
long mul1(long l1,long l2);
long div1(long l1,long l2);
long mod1(long l1,long l2);
void printl(char *txt,long l);
long sin0(long l1);
long cos0(long l1);
long sin1(long l1);
long cos1(long l1);
long atan1(long l1);

main(){
   long l,l1,l2,l3,l4;

 while(1){
   l=main1a();
   l=div1(l,180<<20);
   l=mul1(l,xpi);
   l1=sin1(l);
   printl("sin1(do)=",l1);
   l1=cos1(l);
   printl("cos1(do)=",l1);
 }
}

long sin1(long l1){

   l1=add1(l1,0x3f9e0358);
   l1=mod1(l1,0x6487ec);

   if(0<=l1&&l1<=0x1921fb) return sin0(l1);
   else if(0x1921fb<l1&&l1<=0x3243f6){
      l1=sub1(0x3243f6,l1);
      return sin0(l1);
   }
   else if(0x3243f6<l1&&l1<=0x4b65f1){
      l1=sub1(l1,0x3243f6);
      return sin0(l1)^x8;
   }
   else if(0x4b65f1<l1&&l1<=0x6487ec){
      l1=sub1(0x6487ec,l1);
      return sin0(l1)^x8;
   }

}

long cos1(long l1){

   l1=add1(l1,0x3f9e0358);
   l1=mod1(l1,0x6487ec);

  /*printf("171 l1=%lx   ",l1);*/

   if(0<=l1&&l1<=0x1921fb) return cos0(l1);
   else if(0x1921fb<l1&&l1<=0x3243f6){
      l1=sub1(0x3243f6,l1);
      return cos0(l1)^x8;
   }
   else if(0x3243f6<l1&&l1<=0x4b65f1){
      l1=sub1(l1,0x3243f6);
      return cos0(l1)^x8;
   }
   else if(0x4b65f1<l1&&l1<=0x6487ec){
      l1=sub1(0x6487ec,l1);
      return cos0(l1);
   }

}


long sin0(long l1){
   long l,a1,a2,a3,a4,a5;
 
   a1=div1(l1,6<<20);
   a1=mul1(a1,l1);
   a1=mul1(a1,l1);

   a2=div1(a1,20<<20);
   a2=mul1(a2,l1);
   a2=mul1(a2,l1);

   a3=div1(a2,42<<20);
   a3=mul1(a3,l1);
   a3=mul1(a3,l1);

   a4=div1(a3,72<<20);
   a4=mul1(a4,l1);
   a4=mul1(a4,l1);

   a5=div1(a4,110<<20);
   a5=mul1(a5,l1);
   a5=mul1(a5,l1);

   l=sub1(l1,a1);
   l=add1(l,a2);
   l=sub1(l,a3);
   l=add1(l,a4);
   l=sub1(l,a5);
   return l;
}

long cos0(long l1){
   long l,a1,a2,a3,a4,a5,a6;
 
   a1=div1(l1,2<<20);
   a1=mul1(a1,l1);

   a2=div1(a1,12<<20);
   a2=mul1(a2,l1);
   a2=mul1(a2,l1);

   a3=div1(a2,30<<20);
   a3=mul1(a3,l1);
   a3=mul1(a3,l1);

   a4=div1(a3,56<<20);
   a4=mul1(a4,l1);
   a4=mul1(a4,l1);

   a5=div1(a4,90<<20);
   a5=mul1(a5,l1);
   a5=mul1(a5,l1);
/*
   a6=div1(a5,132<<20);
   a6=mul1(a6,l1);
   a6=mul1(a6,l1);
*/
   l=1<<20;
   l=sub1(l,a1);
   l=add1(l,a2);
   l=sub1(l,a3);
   l=add1(l,a4);
   l=sub1(l,a5);
   /*l=add1(l,a6);*/

   return l;
}

long atan1(long l1){
   long l,b,a1,a2,a3,a4,a5;
 
   b=mul1(l1,l1);
   b=mul1(b,l1);
   a1=div1(b,3<<20);

   b=mul1(b,l1);
   b=mul1(b,l1);
   a2=div1(b,5<<20);

   b=mul1(b,l1);
   b=mul1(b,l1);
   a3=div1(b,7<<20);

   b=mul1(b,l1);
   b=mul1(b,l1);
   a4=div1(b,9<<20);

   b=mul1(b,l1);
   b=mul1(b,l1);
   a5=div1(b,11<<20);

   l=sub1(l1,a1);
   l=add1(l,a2);
   l=sub1(l,a3);
   l=add1(l,a4);
   l=sub1(l,a5);
   return l;
}



long add0(long l1,long l2){
   return (l1+l2);
}

long sub0(long l1,long l2){
   if(l1>=l2) return (l1-l2);
   else       return ((l2-l1)^x8);
}

long add1(long l1,long l2){
   long s1,s2;

   s1=l1&x8;
   s2=l2&x8;
   l1&=x7f;
   l2&=x7f;
   if(s1!=x8&&s2!=x8) return add0(l1,l2);
   if(s1!=x8&&s2==x8) return sub0(l1,l2);
   if(s1==x8&&s2!=x8) return sub0(l1,l2)^x8;
   if(s1==x8&&s2==x8) return add0(l1,l2)^x8;
}


long sub1(long l1,long l2){
   long s1,s2;

   s1=l1&x8;
   s2=l2&x8;
   l1&=x7f;
   l2&=x7f;
   if(s1!=x8&&s2!=x8) return sub0(l1,l2);
   if(s1!=x8&&s2==x8) return add0(l1,l2);
   if(s1==x8&&s2!=x8) return add0(l1,l2)^x8;
   if(s1==x8&&s2==x8) return sub0(l1,l2)^x8;
}


long mul1(long l1,long l2){
   long long int ll;
   long s1,s2;

   s1=l1&x8;
   s2=l2&x8;
   l1&=x7f;
   l2&=x7f;
   ll=((long long int)l1*l2)>>20;
   return ((long)ll)^(s1^s2);
}

long div1(long l1,long l2){
   long long int ll;
   long s1,s2;

   s1=l1&x8;
   s2=l2&x8;
   l1&=x7f;
   l2&=x7f;
   ll=(((long long int)l1)<<20)/l2;
   return ((long)ll)^(s1^s2);
}


long mod1(long l1,long l2){
   l1&=x7f;
   l2&=x7f;

   l1%=l2;
   return l1;
}



long main1a(){
   char ss[100]="                            ";
   long l,l2;
   int  i,kd=0,ke=0,js=0,dotf=0;
   double kf=0.0,kg=0.1,l1,dd;

   printf("Number: ");
   scanf("%s",ss);

   i=0;
   while(ss[i]!='\0'){
      if(ss[i]=='-') js=1;
      if(ss[i]=='.') dotf=1;
      if('0'<=ss[i]&&ss[i]<='9'){
         if(dotf==0){
            kd=ke*10+(ss[i]-48);
            ke=kd;
         }
         else{
            kf+=kg*(ss[i]-48);
            kg*=0.1;
         }
      }
      i++;
   }
   if(kd>=2048){
      printf("2048 OVER !\n");
      exit(0);
   }
   dd=kd+kf;
   l=kd<<20;
   l1=kf*16.0;
   l2=(int)l1;
   l+=l2<<16;
   l1=(l1-l2)*16.0;
   l2=(int)l1;
   l+=l2<<12;
   l1=(l1-l2)*16.0;
   l2=(int)l1;
   l+=l2<<8;
   l1=(l1-l2)*16.0;
   l2=(int)l1;
   l+=l2<<4;
   l1=(l1-l2)*16.0;
   l2=(int)l1;
   l+=l2;
   if(js==1) l^=x8;
   if(js==1) dd*=-1.0;
   printf("l=%lx\n",l);
   printf("sin(dd*pi/180)=%3.10f   cos(dd*pi/180)=%3.10f   \n",sin(dd*M_PI/180.),cos(dd*M_PI/180.));
   return l;
}

void printl(char *txt,long l){
   long i,j;
   int  a,dotf=0;

   printf("@@@  %s  @@@   ",txt);
   printf("l=%8lx   ",l);
   if(l<0){ dotf=1; l^=x8; }
   /*printf("%+5ld.",l);*/
   i=l>>20;
   if(dotf==1) printf("-");
   else        printf("+");
   printf("%ld.",i);
   a=0;
   while(a<10){
      i=l&0x000fffff;
      j=((i<<2)+i)<<1;
      l=j;
      j>>=20;
      printf("%lx",j);
      a++;
   }
   printf("\n");
}


akira@dynabookAZ:~/arm1312$

0 件のコメント:

コメントを投稿