src/fixedt.h
branchgamebalance
changeset 9878 98be05df31ef
parent 9877 29bb0e8924b7
child 9879 c552b8cedd3d
equal deleted inserted replaced
9877:29bb0e8924b7 9878:98be05df31ef
   303 	 */
   303 	 */
   304 	friend std::ostream& operator << (std::ostream &os, const FixedT &value) { os << (double)value.m_data / (1ULL << Raw::dec_bits); return os; }
   304 	friend std::ostream& operator << (std::ostream &os, const FixedT &value) { os << (double)value.m_data / (1ULL << Raw::dec_bits); return os; }
   305 
   305 
   306 };
   306 };
   307 
   307 
   308 
   308 /** The value of \f$\pi\f$ with ample precision for our computations */
       
   309 static const FixedT<int64, 16> PI(3141592, 1000000);
       
   310 /** The number of elements used in Taylor approximations */
       
   311 static const int PRECISION = 5;
       
   312 
       
   313 /**
       
   314  * Computes a single element of the Taylor series for the approximation of the cosine.
       
   315  * A single element of the Taylor series computes as:
       
   316  * \f[
       
   317  *    \frac{(-1)^nx^{2n}}{(2n)!}
       
   318  * \f]
       
   319  * In order to prevent overflows, underflows and other nasty stuff, we do not compute
       
   320  * the numerator and denominator separately in the formula but build a product of
       
   321  * fractions:
       
   322  * \f[
       
   323  *    \frac{x}{2n} * \frac{x}{2n-1} * \frac{x}{2n-2} ...
       
   324  * \f]
       
   325  * @param arg The value of "x" in above formula
       
   326  * @param pow The value of "2n" in above formula
       
   327  * @return    The value of the element of the Taylor series
       
   328  */
       
   329 template <typename Tstorage, int Tdec_bits>
       
   330 FixedT<Tstorage, Tdec_bits> trigbase(const FixedT<Tstorage, Tdec_bits> &arg, int pow)
       
   331 {
       
   332 	/* Shortcut for the very first element */
       
   333 	if (pow == 0) return (FixedT<Tstorage, Tdec_bits>)1;
       
   334 
       
   335 	/* find out the (-1)^n part, element should be negative if n is non-even
       
   336 	 * but "pow" already holds 2n, account for that
       
   337 	 */
       
   338 	bool neg = ( (pow / 2) % 2 > 0);
       
   339 
       
   340 	FixedT<Tstorage, Tdec_bits> element = arg / pow;
       
   341 	for (--pow; pow > 0; pow --) element *= arg / pow;
       
   342 
       
   343 	return (neg) ? -element : element;
       
   344 }
       
   345 
       
   346 /**
       
   347  * Computes the cosine of an argument using a Taylor series.
       
   348  * @param arg The number to compute the cosine from, assumes arg to be in radians.
       
   349  * @returns   The cosine
       
   350  * @todo      Optimize the two while loops.
       
   351  * @note      It is possible to factor out the series to optimize even further, but is it
       
   352  *            worth the effort? It could reduce the opcount a little.
       
   353  * @see       trigbase, PRECISION
       
   354  */
       
   355 template <typename Tstorage, int Tdec_bits>
       
   356 FixedT<Tstorage, Tdec_bits> cos(const FixedT<Tstorage, Tdec_bits> &arg)
       
   357 {
       
   358 	FixedT<Tstorage, Tdec_bits> l_arg = arg;
       
   359 	FixedT<Tstorage, Tdec_bits> cosine = 0;
       
   360 
       
   361 	/* We've got to adjust the argument around zero, otherwise we will need
       
   362 	 * (literally) hundreds of elements
       
   363 	 */
       
   364 	while (l_arg < -PI) l_arg += PI * 2;
       
   365 	while (l_arg >  PI) l_arg -= PI * 2;
       
   366 
       
   367 	/* sum up the Taylor elements */
       
   368 	for(int i = 0; i < PRECISION; i++) cosine += trigbase(l_arg, 2 * i);
       
   369 
       
   370 	return cosine;
       
   371 }
       
   372 
       
   373 /**
       
   374  * Computes the sine of an argument using a Taylor series, uses the cosine
       
   375  * computation in fact, as \f$sin(x) = cos(x - \frac{\pi}{2}))\f$
       
   376  * @param arg The number to compute the cosine from, assumes arg to be in radians.
       
   377  * @returns   The sine
       
   378  */
       
   379 template <typename Tstorage, int Tdec_bits>
       
   380 FixedT<Tstorage, Tdec_bits> sin(const FixedT<Tstorage, Tdec_bits> &arg)
       
   381 {
       
   382 	return cos(arg - PI / 2);
       
   383 }
       
   384