AKI-H8/3052で遊ぶ ~ 簡易数値計算ライブラリ

gccのライブラリはやっぱり大きくて入りません.どこかに小さいライブラリが無いか探したのですが….っていうか,FPUの無い環境でfloatなんか使いたくありません.

ロボットの座標を計算するために,三角関数が必要だったので作ってみました.

sin,cos,tan,atan,sqrt

// sin(x)  x:0~511  sin(x):-128~128
// sqrt(x)  x:0~65535^2

#define sin __sin
#define cos(x) sin((x)+128)
#define tan(x) ((sin(x)<<7)/sin((x)+128))
#define atan __atan
#define sqrt __sqrt

#if defined(SIN) || defined(ATAN)
//#define MAX_THETA 512
// 360deg=512
static const unsigned char sin_table[]={
0,1,3,4,6,7,9,10,12,14,15,17,18,20,21,23,
24,26,28,29,31,32,34,35,37,38,40,41,43,44,46,47,
48,50,51,53,54,56,57,58,60,61,63,64,65,67,68,69,
71,72,73,74,76,77,78,79,81,82,83,84,85,87,88,89,
90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,
106,107,108,108,109,110,111,112,112,113,114,115,115,116,117,117,
118,118,119,119,120,121,121,122,122,122,123,123,124,124,124,125,
125,125,126,126,126,126,127,127,127,127,127,127,127,127,127,127,
128,
};

int __sin(int x)
{
    int s=x&0x100; // sign
    if (x&0x80) {
        x=0x80-(x&0x7f);
    } else {
        x&=0x7f;
    }

    return s?-sin_table[x]:sin_table[x];
}

#endif

#ifdef ATAN

unsigned int __atan(int x,int y)
{
    int c=0,atan=0,s=1;
    long xx,yy;

    // +-45度に
    if (x+y>0) {
        if (x>y) {
            xx=x;
            yy=y;
        } else {
            xx=y;
            yy=x;
            atan=128;
            s=-1;
        }
    } else {
        if (x<y) {
            xx=-x;
            yy=-y;
            atan=256;
        } else {
            xx=-y;
            yy=-x;
            atan=384;
            s=-1;
        }
    }

    if (xx) {
        int i=7;
        int a=64,b=-64;
        int n;
        while (i--) {
            n=(a+b)>>1;
            //    tan(n) >= ((yy<<7)/xx)
            // (sin(n)<<7)/cos(n) >= ((yy<<7)/xx)
            if ( xx*sin(n) >= yy*cos(n) ) {
                a=n;
            } else {
                b=n;
            }
        }
        atan+=s*a;
    }
    return atan;
}

#endif

#ifdef SQRT

unsigned int __sqrt(unsigned long d)
{
    unsigned long a=0,t=32768;
    int i;
    for(i=0;i<16;i++) {
        if ((a|t)*(a|t)<=d) {
            a|=t;
        }
        t>>=1;
    }
    return a;
}

#endif

使い方

必用な機能をdefineして有効にしてください.

sinの周期は512,振幅は128です.sinはテーブルから作ってます.cos,tanは単なるマクロです.atanはatan2です.

終わりに

sinテーブルはPerlで作りましたが,こういうのが自動で出来る強力なプリプロセッサが欲しいと思うのは私だけですか?むしろ,C言語で書けるプリプロセッサ…というか,コンパイル時に計算するべき処理を指定できるプログラミング言語が欲しいような….

この文書の履歴

Copyright © 瓶詰堂 all rights reserved.