Ticket #3815: Length_approx.patch

File Length_approx.patch, 1.6 KB (added by fsincos, 8 years ago)
  • source/maths/FixedVector2D.h

    diff --git a/source/maths/FixedVector2D.h b/source/maths/FixedVector2D.h
    index d2728f4..7b9957b 100644
    a b public:  
    116116        return r;
    117117    }
    118118
     119    // Rough approximation of the length.
     120    fixed Length_approx() const
     121    {
     122        // CORDIC algorithm: Rotate (x,y) onto the x-axis and use the new x as an approximation of the length.
     123
     124        // TODO: Choose an appropriate value of max_loop_var.
     125        // Error: N := max_loop_var - 1, emax_rel = 1 - cos(arctan(1/2^N)) = 1 - 1/sqrt(1+4^(-N))
     126        // In this case: Rel. error <= emax_rel (N=7) ~ 3*10^-5
     127
     128        const i32 max_loop_var = 8;
     129        // Because we use multiples of rotation matrices, we need to scale the result.
     130        // Factor = Product of (1+4^(-n))^(-1/2) from 0 to max_loop_var - 1.
     131        // The factor below is (obviously) only right for max_loop_var = 8.
     132        CFixed_15_16 corr_factor = CFixed_15_16::FromDouble(0.60725911229889273006029454182250359069);
     133
     134        i32 x = X.GetInternalValue();
     135        i32 y = Y.GetInternalValue();
     136        // We want x >= 0.
     137        // TODO: Further optimizations.
     138        if (x < 0)
     139            x *= -1;
     140
     141        i32 tmp;
     142        for (u8 loop_var = 0; loop_var < max_loop_var; ++loop_var)
     143        {
     144            tmp = x >> loop_var;
     145            if(y < 0)
     146            {
     147                // (x,y) -> (x,y) + 1/2^n * (-y,x)
     148                x -= y >> loop_var;
     149                y += tmp;
     150            }
     151            else
     152            {
     153                // (x,y) -> (x,y) + 1/2^n * (y,-x)
     154                x += y >> loop_var;
     155                y -= tmp;
     156            }
     157        }
     158        CFixed_15_16 result;
     159        result.SetInternalValue(x);
     160        return result.Multiply(corr_factor);
     161    }
     162
    119163    /**
    120164     * Returns -1, 0, +1 depending on whether length is less/equal/greater
    121165     * than the argument.