asik/FixedMath.Net

A bug when use Acos() to 2 normalized vector

SteveCruise opened this issue · 2 comments

It throw out exception "Must between -FP.One and FP.One"

The demo is as follow:

FP x1 = FP.FromRaw(3492999344);
FP y1 = FP.FromRaw(2499139782);
FP x2 = FP.FromRaw(-3492914803);
FP y2 = FP.FromRaw(-2499256617);
Debug.Log("x1: " + x1 + " y1: " + y1 + " x2: " + x2 + " y2: " + y2);  
// x1: 0.8132773 y1: 0.5818763 x2: -0.8132576 y2: -0.5819035

FP x1_normalized = x1 / FP.Sqrt(x1 * x1 + y1 * y1);
FP y1_normalized = y1 / FP.Sqrt(x1 * x1 + y1 * y1);
Debug.Log("normalized vector1 x: " + x1_normalized + " y: " + y1_normalized);
// normalized vector1 x: 0.8132773 y: 0.5818763

FP x2_normalized = x2 / FP.Sqrt(x2 * x2 + y2 * y2);
FP y2_normalized = y2 / FP.Sqrt(x2 * x2 + y2 * y2);
Debug.Log("normalized vector2 x: " + x2_normalized + " y: " + y2_normalized); 
// normalized vector2 x: -0.8132578 y: -0.5819036

FP dot = x1_normalized * x2_normalized + y1_normalized * y2_normalized;
Debug.Log("Dot of vector1 and vector2: " + dot); 
// Dot of vector1 and vector2: -1
            
FP.Acos(dot); 
// ArgumentOutOfRangeException: x 
// Parameter name: Must between -FP.One and FP.One 

The code of Fix64:

        /// <summary>
        /// Returns the arccos of of the specified number, calculated using Atan and Sqrt
        /// This function has at least 7 decimals of accuracy.
        /// </summary>
        public static FP Acos(FP x)
        {
            if (x < -One || x > One)
            {
                throw new ArgumentOutOfRangeException("Must between -FP.One and FP.One", "x");
            }

            if (x.RawValue == 0) return PiOver2;

            var result = Atan(Sqrt(One - x * x) / x);
            return x.RawValue < 0 ? result + Pi : result;
        }

Dot RawValue: -4294967297
FP.One RawValue: 4294967296

May be it's just not so accurate