// // trig.cpp : Basic trigonometry routines. // //! \file trig.cpp //! \author J Vijn //! \date 20080130 - 20080210 // /* === NOTES === Multiple atan2's present. Select the one you want. Best performance tends to be with atan2Lerp or possibly atan2Tonc. If your division really sucks, use atan2Cordic. This module still needs a header for some system-specific basics before you can use it. Specifically, ALIGN and QDIV will needs some extra effort. */ /* dsgmLib adaptations: - Only atan2Lerp was needed, all other trigonometry functions are already present in libnds and were removed from this library - Upgraded the code from C++ to C */ #include "DSGM.h" // -------------------------------------------------------------------- // MACROS / INLINES // -------------------------------------------------------------------- // Get the octant a coordinate pair is in. #define OCTANTIFY(_x, _y, _o) do { \ int _t; _o= 0; \ if(_y< 0) { _x= -_x; _y= -_y; _o += 4; } \ if(_x<= 0) { _t= _x; _x= _y; _y= -_t; _o += 2; } \ if(_x<=_y) { _t= _y-_x; _x= _x+_y; _y= _t; _o += 1; } \ } while(0); // Special-case division because I need a little more control // than divf32 offers static inline int QDIV(int num, int den, const int bits) { while(REG_DIVCNT & DIV_BUSY); REG_DIVCNT = DIV_64_32; REG_DIV_NUMER = ((int64)num)<= 0 ? 0 : BRAD_PI); int phi, fa, fb, h; uint t; OCTANTIFY(x, y, phi); phi *= BRAD_PI/4; t = QDIV(y, x, ATAN_FP); h = t % ATANLUT_STRIDE; fa = atanLUT[t/ATANLUT_STRIDE ]; fb = atanLUT[t/ATANLUT_STRIDE+1]; return phi + ((fa + ((fb-fa)*h >> ATANLUT_STRIDE_SHIFT))>>3); }