(svn r9060) [gamebalance] -Add: Added the two basic trigonometric functions (sine / cosine) for variables of types FixedT, so that we can compute periodic fluctuations. gamebalance
authorcelestar
Thu, 08 Mar 2007 09:41:06 +0000
branchgamebalance
changeset 9878 98be05df31ef
parent 9877 29bb0e8924b7
child 9879 c552b8cedd3d
(svn r9060) [gamebalance] -Add: Added the two basic trigonometric functions (sine / cosine) for variables of types FixedT, so that we can compute periodic fluctuations.
src/fixedt.h
--- 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);
+}
+