(svn r9060) [gamebalance] -Add: Added the two basic trigonometric functions (sine / cosine) for variables of types FixedT, so that we can compute periodic fluctuations.
--- a/src/fixedt.h Wed Mar 07 14:36:57 2007 +0000
+++ b/src/fixedt.h Thu Mar 08 09:41:06 2007 +0000
@@ -305,4 +305,80 @@
};
+/** The value of \f$\pi\f$ with ample precision for our computations */
+static const FixedT<int64, 16> PI(3141592, 1000000);
+/** The number of elements used in Taylor approximations */
+static const int PRECISION = 5;
+/**
+ * Computes a single element of the Taylor series for the approximation of the cosine.
+ * A single element of the Taylor series computes as:
+ * \f[
+ * \frac{(-1)^nx^{2n}}{(2n)!}
+ * \f]
+ * In order to prevent overflows, underflows and other nasty stuff, we do not compute
+ * the numerator and denominator separately in the formula but build a product of
+ * fractions:
+ * \f[
+ * \frac{x}{2n} * \frac{x}{2n-1} * \frac{x}{2n-2} ...
+ * \f]
+ * @param arg The value of "x" in above formula
+ * @param pow The value of "2n" in above formula
+ * @return The value of the element of the Taylor series
+ */
+template <typename Tstorage, int Tdec_bits>
+FixedT<Tstorage, Tdec_bits> trigbase(const FixedT<Tstorage, Tdec_bits> &arg, int pow)
+{
+ /* Shortcut for the very first element */
+ if (pow == 0) return (FixedT<Tstorage, Tdec_bits>)1;
+
+ /* find out the (-1)^n part, element should be negative if n is non-even
+ * but "pow" already holds 2n, account for that
+ */
+ bool neg = ( (pow / 2) % 2 > 0);
+
+ FixedT<Tstorage, Tdec_bits> element = arg / pow;
+ for (--pow; pow > 0; pow --) element *= arg / pow;
+
+ return (neg) ? -element : element;
+}
+
+/**
+ * Computes the cosine of an argument using a Taylor series.
+ * @param arg The number to compute the cosine from, assumes arg to be in radians.
+ * @returns The cosine
+ * @todo Optimize the two while loops.
+ * @note It is possible to factor out the series to optimize even further, but is it
+ * worth the effort? It could reduce the opcount a little.
+ * @see trigbase, PRECISION
+ */
+template <typename Tstorage, int Tdec_bits>
+FixedT<Tstorage, Tdec_bits> cos(const FixedT<Tstorage, Tdec_bits> &arg)
+{
+ FixedT<Tstorage, Tdec_bits> l_arg = arg;
+ FixedT<Tstorage, Tdec_bits> cosine = 0;
+
+ /* We've got to adjust the argument around zero, otherwise we will need
+ * (literally) hundreds of elements
+ */
+ while (l_arg < -PI) l_arg += PI * 2;
+ while (l_arg > PI) l_arg -= PI * 2;
+
+ /* sum up the Taylor elements */
+ for(int i = 0; i < PRECISION; i++) cosine += trigbase(l_arg, 2 * i);
+
+ return cosine;
+}
+
+/**
+ * Computes the sine of an argument using a Taylor series, uses the cosine
+ * computation in fact, as \f$sin(x) = cos(x - \frac{\pi}{2}))\f$
+ * @param arg The number to compute the cosine from, assumes arg to be in radians.
+ * @returns The sine
+ */
+template <typename Tstorage, int Tdec_bits>
+FixedT<Tstorage, Tdec_bits> sin(const FixedT<Tstorage, Tdec_bits> &arg)
+{
+ return cos(arg - PI / 2);
+}
+