00001
00025
00026
00027 #ifndef __ETL__FASTANGLE_H
00028 #define __ETL__FASTANGLE_H
00029
00030
00031
00032 #include <cmath>
00033 #include <ETL/fixed>
00034
00035 #include "_fastangle_tables.h"
00036
00037
00038
00039 #ifndef PI
00040 # define PI (3.1415926535897932384626433832795029L)
00041 #endif
00042
00043 #define ETL_FASTANGLE_INIT()
00044
00045
00046
00047
00048
00049 _ETL_BEGIN_NAMESPACE
00050
00057 class fastangle
00058 {
00059 public:
00060 typedef double value_type;
00061
00062 protected:
00063 typedef fixed_base<ETL_FIXED_TYPE,ETL_FASTANGLE_LOOKUP_RES> unit;
00064
00065 unit v;
00066
00067 public:
00068
00069
00070
00071
00072
00074 fastangle
00075 operator+(const fastangle &rhs)const
00076 {
00077 fastangle ret;
00078 ret.v=v+rhs.v;
00079 return ret;
00080 }
00081
00083
00084 fastangle
00085 operator-(const fastangle &rhs)const
00086 {
00087 fastangle ret;
00088 ret.v=v-rhs.v;
00089 return ret;
00090 }
00091
00093
00095 fastangle
00096 operator*(const unit &rhs)const
00097 {
00098 fastangle ret;
00099 ret.v=v*rhs;
00100 return ret;
00101 }
00102
00103 fastangle
00104 operator/(const unit &rhs)const
00105 {
00106 fastangle ret;
00107 ret.v=v/rhs;
00108 return ret;
00109 }
00110
00111 const fastangle &
00112 operator+=(const fastangle &rhs)
00113 {
00114 v+=rhs.v;
00115 return *this;
00116 }
00117
00118 const fastangle &
00119 operator-=(const fastangle &rhs)
00120 {
00121 v-=rhs.v;
00122 return *this;
00123 }
00124
00125 const fastangle &
00126 operator*=(const unit &rhs)
00127 {
00128 v*=rhs;
00129 return *this;
00130 }
00131
00132 const fastangle &
00133 operator/=(const unit &rhs)
00134 {
00135 v/=rhs;
00136 return *this;
00137 }
00138
00140 fastangle
00141 operator-()const
00142 {
00143 fastangle ret;
00144 ret.v=-v;
00145 return ret;
00146 }
00147
00149
00152 fastangle
00153 operator~()const
00154 {
00155 fastangle ret;
00156 ret.v=(unit)std::floor(v+0.5f);
00157 return ret;
00158 }
00159
00163 bool
00164 operator<(const fastangle &rhs)const
00165 { return v<rhs.v; }
00166
00167
00171 bool
00172 operator>(const fastangle &rhs)const
00173 { return v>rhs.v; }
00174
00175
00181 bool
00182 operator<=(const fastangle &rhs)const
00183 { return v<=rhs.v; }
00184
00185
00191 bool
00192 operator>=(const fastangle &rhs)const
00193 { return v>=rhs.v; }
00194
00195
00199 bool
00200 operator==(const fastangle &rhs)const
00201 { return v==rhs.v; }
00202
00203
00207 bool
00208 operator!=(const fastangle &rhs)const
00209 { return v!=rhs.v; }
00210
00211
00213
00218 fastangle
00219 dist(const fastangle &rhs)const
00220 {
00221 fastangle ret;
00222 ret.v=v-rhs.v;
00223 ret.v-=(unit)std::floor(ret.v+0.5f);
00224 return ret;
00225 }
00226
00228
00230 fastangle
00231 mod()const
00232 {
00233 fastangle ret(*this);
00234 ret.v-=(unit)std::floor(ret.v);
00235 return ret;
00236 }
00237
00238 static fastangle
00239 zero()
00240 {
00241 fastangle ret;
00242 ret.v=0;
00243 return ret;
00244 }
00245
00246 bool operator!()const { return v==unit(0); }
00247
00248
00249
00250
00251
00252 class radians;
00253 class degrees;
00254 class rotations;
00255
00256
00257
00258
00259
00260 class sin;
00261 class cos;
00262 class tan;
00263
00264
00265
00266
00267
00268 friend class radians;
00269 friend class degrees;
00270 friend class rotations;
00271 friend class sin;
00272 friend class cos;
00273 friend class tan;
00274
00275
00276
00277
00278
00279 typedef radians rad;
00280 typedef degrees deg;
00281 typedef rotations rot;
00282
00283 };
00284
00291 class fastangle::radians : public fastangle
00292 {
00293 public:
00294 radians(const value_type &x) { v=x/((value_type)PI*2.0f); }
00295 radians(const fastangle &a):fastangle(a) { }
00296 radians mod()const { return fastangle::mod(); }
00297 radians dist(const fastangle &rhs)const { return fastangle::dist(rhs); }
00298 operator value_type()const { return get(); }
00299 value_type get()const { return (value_type)v*(value_type)PI*2.0f; }
00300 };
00301
00308 class fastangle::degrees : public fastangle
00309 {
00310 public:
00311 degrees(const value_type &x) { v=x/360; }
00312 degrees(const fastangle &a):fastangle(a) { }
00313 degrees mod()const { return fastangle::mod(); }
00314 degrees dist(const fastangle &rhs)const { return fastangle::dist(rhs); }
00315 operator value_type()const { return get(); }
00316 value_type get()const { return v*360; }
00317 };
00318
00325 class fastangle::rotations : public fastangle
00326 {
00327 public:
00328 rotations(const value_type &x) { v=x; }
00329 rotations(const fastangle &a):fastangle(a) { }
00330 rotations mod()const { return fastangle::mod(); }
00331 rotations dist(const fastangle &rhs)const { return fastangle::dist(rhs); }
00332 operator value_type()const { return get(); }
00333 value_type get()const { return v; }
00334 };
00335
00342 class fastangle::sin : public fastangle
00343 {
00344 public:
00345 sin(const value_type &x) { v.data()=_fastangle_asin_table[(int)((x+1)*(value_type)(1<<(ETL_FASTANGLE_LOOKUP_RES-1)))]; }
00346 sin(const fastangle &a):fastangle(a) { }
00347 sin mod()const { return fastangle::mod(); }
00348 sin dist(const fastangle &rhs)const { return fastangle::dist(rhs); }
00349 operator value_type()const { return get(); }
00350 value_type get()const { return (value_type)_fastangle_sin_table[v.data()&( (1<<ETL_FASTANGLE_LOOKUP_RES)-1)]; }
00351 };
00352
00359 class fastangle::cos : public fastangle
00360 {
00361 public:
00362 cos(const value_type &x) { v.data()=(1<<(ETL_FASTANGLE_LOOKUP_RES-2))-_fastangle_asin_table[(int)((x+1)*(value_type)(1<<(ETL_FASTANGLE_LOOKUP_RES-1)))]; }
00363 cos(const fastangle &a):fastangle(a) { }
00364 cos mod()const { return fastangle::mod(); }
00365 cos dist(const fastangle &rhs)const { return fastangle::dist(rhs); }
00366 operator value_type()const { return get(); }
00367 value_type get()const { return (value_type)_fastangle_sin_table[(v.data()+(1<<(ETL_FASTANGLE_LOOKUP_RES-2)))&( (1<<ETL_FASTANGLE_LOOKUP_RES)-1)]; }
00368 };
00369
00376 class fastangle::tan : public fastangle
00377 {
00378 public:
00379 tan(const value_type &x)
00380 {
00381 if(x>1)
00382 v.data()=(1<<(ETL_FASTANGLE_LOOKUP_RES-2))-_fastangle_atan_table[(int)(((1.0/x)+1)*(value_type)((1<<(ETL_FASTANGLE_LOOKUP_RES-1))-1))];
00383 else if(x<-1)
00384 v.data()=-(1<<(ETL_FASTANGLE_LOOKUP_RES-1)) + (1<<(ETL_FASTANGLE_LOOKUP_RES-2)) - _fastangle_atan_table[(int)(((1.0/x)+1)*(value_type)((1<<(ETL_FASTANGLE_LOOKUP_RES-1))-1))];
00385 else
00386 v.data()=_fastangle_atan_table[(int)((x+1)*(value_type)((1<<(ETL_FASTANGLE_LOOKUP_RES-1))-1))];
00387 }
00388
00389 tan(const value_type &y,const value_type &x)
00390 {
00391 if(x>=0 && y>=0)
00392 {
00393 if(y>x)
00394 v.data()=(1<<(ETL_FASTANGLE_LOOKUP_RES-2))-_fastangle_atan_table[(int)(((x/y)+1)*(value_type)((1<<(ETL_FASTANGLE_LOOKUP_RES-1))-1))];
00395 else
00396 v.data()=_fastangle_atan_table[(int)(((y/x)+1)*(value_type)((1<<(ETL_FASTANGLE_LOOKUP_RES-1))-1))];
00397 }
00398 else if(x>=0 && y<0)
00399 {
00400 if(-y>x)
00401 v.data()=-(1<<(ETL_FASTANGLE_LOOKUP_RES-1)) + (1<<(ETL_FASTANGLE_LOOKUP_RES-2))-_fastangle_atan_table[(int)(((x/y)+1.0)*(value_type)((1<<(ETL_FASTANGLE_LOOKUP_RES-1))-1))];
00402 else
00403 v.data()=_fastangle_atan_table[(int)(((y/x)+1.0)*(value_type)((1<<(ETL_FASTANGLE_LOOKUP_RES-1))-1))];
00404 }
00405 else if(x<0 && y>=0)
00406 {
00407 if(y>-x)
00408 v.data()=(1<<(ETL_FASTANGLE_LOOKUP_RES-2))-_fastangle_atan_table[(int)(((x/y)+1.0)*(value_type)((1<<(ETL_FASTANGLE_LOOKUP_RES-1))-1))];
00409 else
00410 v.data()=_fastangle_atan_table[(int)(((y/x)+1.0)*(value_type)((1<<(ETL_FASTANGLE_LOOKUP_RES-1))-1))]+(1<<(ETL_FASTANGLE_LOOKUP_RES-1));
00411 }
00412 else if(x<0 && y<0)
00413 {
00414 if(-y>-x)
00415 v.data()=(1<<(ETL_FASTANGLE_LOOKUP_RES-2))-_fastangle_atan_table[(int)(((x/y)+1.0)*(value_type)((1<<(ETL_FASTANGLE_LOOKUP_RES-1))-1))] - (1<<(ETL_FASTANGLE_LOOKUP_RES-1));
00416 else
00417 v.data()=_fastangle_atan_table[(int)(((y/x)+1.0)*(value_type)((1<<(ETL_FASTANGLE_LOOKUP_RES-1))-1))]-(1<<(ETL_FASTANGLE_LOOKUP_RES-1));
00418 }
00419 else v.data()=0;
00420 }
00421 tan(const fastangle &a):fastangle(a) { }
00422 tan mod()const { return fastangle::mod(); }
00423 tan dist(const fastangle &rhs)const { return fastangle::dist(rhs); }
00424 operator value_type()const { return get(); }
00425 value_type get()const { return (value_type)_fastangle_tan_table[v.data()&( (1<<ETL_FASTANGLE_LOOKUP_RES)-1)]; }
00426 };
00427
00428 _ETL_END_NAMESPACE
00429
00430 template <>
00431 struct affine_combo<etl::fastangle,float>
00432 {
00433 etl::fastangle operator()(const etl::fastangle &a,const etl::fastangle &b,const float &t)const
00434 {
00435 return b.dist(a)*t+a;
00436 }
00437
00438 etl::fastangle reverse(const etl::fastangle &x, const etl::fastangle &b, const float &t)const
00439 {
00440 return x.dist(b*t)*((float)1/((float)1-t));
00441 }
00442 };
00443
00444 template <>
00445 struct distance_func<etl::fastangle> : public std::binary_function<etl::fastangle, etl::fastangle, etl::fastangle>
00446 {
00447 etl::fastangle operator()(const etl::fastangle &a,const etl::fastangle &b)const
00448 {
00449 etl::fastangle delta=b.dist(a);
00450 if(delta<etl::fastangle::zero())
00451 return -delta;
00452 return delta;
00453 }
00454
00455 etl::fastangle cook(const etl::fastangle &x) { return x; }
00456 etl::fastangle uncook(const etl::fastangle &x) { return x; }
00457 };
00458
00459
00460
00461 #endif