00001 #ifndef CCTBX_MATH_COS_SIN_TABLE_H
00002 #define CCTBX_MATH_COS_SIN_TABLE_H
00003
00004 #include <cctbx/error.h>
00005 #include <scitbx/constants.h>
00006 #include <boost/shared_array.hpp>
00007 #include <complex>
00008
00009 namespace cctbx { namespace math {
00010
00011 template <typename FloatType=double>
00012 class cos_sin_exact
00013 {
00014 public:
00015 typedef FloatType float_type;
00016 typedef std::complex<float_type> complex_type;
00017
00018 static
00019 complex_type
00020 get(float_type unary_angle)
00021 {
00022 float_type x = scitbx::constants::two_pi * unary_angle;
00023 return complex_type(std::cos(x), std::sin(x));
00024 }
00025
00026 complex_type operator()(float_type unary_angle) const {
00027 return get(unary_angle);
00028 }
00029 };
00030
00031 template <typename FloatType=double>
00032 class cos_sin_table
00033 {
00034 public:
00035 typedef FloatType float_type;
00036 typedef std::complex<float_type> complex_type;
00037
00038 cos_sin_table() {}
00039
00040 cos_sin_table(int n_points)
00041 :
00042 n_points_(n_points),
00043 n_points_4_(n_points/4),
00044 values_memory_(new float_type[n_points_+n_points_4_]),
00045 values_(values_memory_.get())
00046 {
00047 CCTBX_ASSERT(n_points % 4 == 0);
00048 using scitbx::constants::two_pi;
00049 for(int i=0;i<n_points_+n_points_4_;i++) {
00050 values_[i] = std::sin(i*two_pi/n_points_);
00051 }
00052 }
00053
00054 int
00055 n_points() const { return n_points_; }
00056
00057 complex_type
00058 get(float_type unary_angle) const
00059 {
00060 int i = static_cast<int>(unary_angle*n_points_) % n_points_;
00061 if (i < 0) i += n_points_;
00062 return complex_type(values_[i+n_points_4_], values_[i]);
00063 }
00064
00065 complex_type operator()(float_type unary_angle) const {
00066 return get(unary_angle);
00067 }
00068
00069 private:
00070 int n_points_;
00071 int n_points_4_;
00072 boost::shared_array<float_type> values_memory_;
00073 float_type* values_;
00074 };
00075
00076 template <typename FloatType=double>
00077 class cos_sin_lin_interp_table
00078 {
00079 public:
00080 typedef FloatType float_type;
00081 typedef std::complex<float_type> complex_type;
00082
00083 cos_sin_lin_interp_table() {}
00084
00085 cos_sin_lin_interp_table(int n_points)
00086 :
00087 n_points_(n_points),
00088 n_points_4_(n_points/4),
00089 values_memory_(new float_type[n_points_+n_points_4_+1]),
00090 values_(values_memory_.get()),
00091 diffvalues_memory_(new float_type[n_points_+n_points_4_+1]),
00092 diffvalues_(diffvalues_memory_.get())
00093 {
00094 CCTBX_ASSERT(n_points % 4 == 0);
00095 using scitbx::constants::two_pi;
00096 for(int i=0;i<=n_points_+n_points_4_;i++)
00097 {
00098 values_[i] = std::sin(i*two_pi/n_points_);
00099 diffvalues_[i] = std::sin((i+1)*two_pi/n_points_)
00100 - std::sin(i*two_pi/n_points_);
00101 }
00102 }
00103
00104 int
00105 n_points() const { return n_points_; }
00106
00107 complex_type
00108 get(float_type unary_angle) const
00109 {
00110 float_type dec = unary_angle*n_points_;
00111 if (dec<0.0)
00112 {
00113 dec = -dec;
00114 int i = static_cast<int>(dec);
00115
00116 float_type frac = dec - i;
00117
00118 i = i % n_points_;
00119
00120 return complex_type(
00121 values_[i+n_points_4_] + frac*diffvalues_[i+n_points_4_],
00122 - values_[i] -frac*diffvalues_[i]);
00123 }
00124 else
00125 {
00126 int i = static_cast<int>(dec);
00127 float_type frac = dec - i;
00128
00129 i = i % n_points_;
00130
00131 return complex_type(
00132 values_[i+n_points_4_] + frac*diffvalues_[i+n_points_4_],
00133 values_[i] + frac*diffvalues_[i]);
00134 }
00135 }
00136
00137 complex_type operator()(float_type unary_angle) const {
00138 return get(unary_angle);
00139 }
00140
00141 private:
00142 int n_points_;
00143 int n_points_4_;
00144 boost::shared_array<float_type> values_memory_;
00145 float_type* values_;
00146 boost::shared_array<float_type> diffvalues_memory_;
00147 float_type* diffvalues_;
00148 };
00149
00150
00151 #if defined(__sgi) && !defined(__GNUC__)
00152 namespace work_around_edg_typename_handling {
00153 typedef cos_sin_exact<double> cos_sin_exact_double;
00154 typedef cos_sin_table<double> cos_sin_table_double;
00155 typedef cos_sin_lin_interp_table<double> cos_sin_lin_interp_table_double;
00156 }
00157 #endif
00158
00159 }}
00160
00161 #endif // CCTBX_MATH_COS_SIN_TABLE_H