1 /*---------------------------------------------------------------------------*
2   Project:  NitroSDK - FX - demos - test
3   File:     fx_append_vec.c
4 
5   Copyright 2003-2007 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: fx_append_vec.c,v $
14   Revision 1.9  2007/05/22 02:05:01  okubata_ryoma
15   Indicated that warnings will occur in places.
16 
17   Revision 1.8  2006/01/18 02:11:21  kitase_hirotake
18   do-indent.
19 
20   Revision 1.7  2005/02/28 05:26:13  yosizaki
21   do-indent.
22 
23   Revision 1.6  2004/11/02 08:32:54  takano_makoto
24   Fixed comments.
25 
26   Revision 1.5  2004/04/12 10:05:26  takano_makoto
27   Fixed a bug in BasicOperator_test_.
28 
29   Revision 1.4  2004/04/07 01:27:57  yada
30   Fixed header comment.
31 
32   Revision 1.3  2004/02/05 07:09:02  yasu
33   Changed SDK prefix from iris to nitro.
34 
35   Revision 1.2  2004/01/29 01:35:09  kitani_toshikazu
36   Fixed some bugs for debug build, restored appended test cases.
37 
38   $NoKeywords: $
39 
40  *---------------------------------------------------------------------------*/
41 
42 #ifndef  FX_APPEND_VEC_H_
43 #include "fx_append_vec.h"
44 #endif //  FX_APPEND_VEC_H_
45 
46 
47 
48 #define FX2D( fx ) (double)FX_FX32_TO_F32( fx )
49 #define FX64C2D( fx ) (double)( (double)( fx ) / (double)( 0x1LL << FX64C_SHIFT ) )
50 #define FX_FX32_TO_FX64C(x) ( (fx64)(x) << ( FX64C_SHIFT - FX32_SHIFT ))
51 
52 
53 
54 
55 #define fxIntMax        ( FX32_MAX & FX32_INT_MASK )
56 #define fxLSD           0x1
57 
58 
59 // Input data
60 static const VecFx32 vInputData[] = {
61     {fxLSD, 0x0, 0x0},
62     {fxLSD << 1, 0x0, 0x0},
63     {FX32_ONE, 0x0, 0x0},
64     {fxIntMax >> 6, 0x0, 0x0},
65     {fxIntMax >> 5, 0x0, 0x0},
66     {fxIntMax >> 4, 0x0, 0x0},
67     {fxIntMax >> 3, 0x0, 0x0},
68     {fxIntMax >> 2, 0x0, 0x0},
69     {fxIntMax >> 1, 0x0, 0x0},
70     {fxIntMax, 0x0, 0x0},
71 
72     // Case that addition happens internally
73     {fxLSD, fxLSD, 0x0},
74     {fxLSD << 1, fxLSD << 1, 0x0},
75     {fxIntMax >> 5, fxIntMax >> 5, 0x0},
76     {fxIntMax >> 4, fxIntMax >> 4, 0x0},
77     {fxIntMax >> 3, fxIntMax >> 3, 0x0},
78     {fxIntMax >> 2, fxIntMax >> 2, 0x0},
79     {fxIntMax >> 1, fxIntMax >> 1, 0x0},
80     {fxIntMax, fxIntMax, 0x0}
81 };
82 
83 
84 
85 
86 
87 
88 // Util
89 static void VecFx32ToVecD_(const VecFx32 *src, VecD * dst);
90 static void VecSubVecD_(const VecD * a, const VecD * b, VecD * ab);
91 static void GetErrorVecD_(const VecD * a, const VecD * b, VecD * ab);
92 static void CalcErrorBtweenVecFxAndVecD_(const VecFx32 *a, const VecD * b, VecD * vError);
93 static double FindMaxElement_(const VecD * v);
94 
95 
96 
97 // Implementation of double version
98 static double FX_Mul_d_(const fx32 a, const fx32 b);
99 static double VEC_DotProduct_d_(const VecFx32 *a, const VecFx32 *b);
100 static void VEC_CrossProduct_d_(const VecFx32 *a, const VecFx32 *b, VecD * axb);
101 static double VEC_Mag_d_(const VecFx32 *pSrc);
102 static void VEC_Normalize_d_(const VecFx32 *pSrc, VecD * pDst);
103 
104 // Error calculation
105 static double GetDotProductError_(const VecFx32 *a, const VecFx32 *b);
106 static double GetCrossProductError_(const VecFx32 *a, const VecFx32 *b);
107 static double GetMagError_(const VecFx32 *a);
108 static void GetNormalizeError_(const VecFx32 *a, VecD * vError);
109 
110 // Tests
111 static void VEC_Mag_test_();
112 static void VEC_Normalize_test_();
113 static void VEC_DotCrossProduct_test_();
114 static void BasicOperator_test_();
115 static void Unary_operator_test_(fx32 vf1);
116 static void Binary_operator_test_(fx32 vf1, fx32 vf2);
117 
118 
119 //------------------------------------------------------------------------------
120 // Test additional items entry
VECTest_Appended()121 void VECTest_Appended()
122 {
123     OS_Printf("**================== VECTest_Appended start ====================\n");
124     BasicOperator_test_();
125     VEC_DotCrossProduct_test_();
126     VEC_Mag_test_();
127     VEC_Normalize_test_();
128     OS_Printf("**================== VECTest_Appended done ====================\n");
129 }
130 
131 //==============================================================================
132 // Display related
133 
134 //------------------------------------------------------------------------------
printVecFx32Msg(const char * msg,const VecFx32 * v)135 static void printVecFx32Msg(const char *msg, const VecFx32 *v)
136 {
137     SDK_NULL_ASSERT(msg);
138     SDK_NULL_ASSERT(v);
139 
140     OutDetail(msg);
141     OutDetail("( %.5f, %.5f, %.5f )", FX_FX32_TO_F32(v->x), FX_FX32_TO_F32(v->y),
142               FX_FX32_TO_F32(v->z));
143     OutDetail("\n");
144 }
145 
146 //------------------------------------------------------------------------------
printVecDMsg(const char * msg,const VecD * v)147 static void printVecDMsg(const char *msg, const VecD * v)
148 {
149     SDK_NULL_ASSERT(msg);
150     SDK_NULL_ASSERT(v);
151 
152     OutDetail(msg);
153     OutDetail("( %.5f, %.5f, %.5f )", v->x, v->y, v->z);
154     OutDetail("\n");
155 }
156 
157 
158 
159 //==============================================================================
160 // Misc.
161 //------------------------------------------------------------------------------
VecFx32ToVecD_(const VecFx32 * src,VecD * dst)162 static void VecFx32ToVecD_(const VecFx32 *src, VecD * dst)
163 {
164     SDK_NULL_ASSERT(src);
165     SDK_NULL_ASSERT(dst);
166 
167     dst->x = (double)FX_FX32_TO_F32(src->x);
168     dst->y = (double)FX_FX32_TO_F32(src->y);
169     dst->z = (double)FX_FX32_TO_F32(src->z);
170 }
171 
172 //------------------------------------------------------------------------------
VecSubVecD_(const VecD * a,const VecD * b,VecD * ab)173 static void VecSubVecD_(const VecD * a, const VecD * b, VecD * ab)
174 {
175     SDK_NULL_ASSERT(a);
176     SDK_NULL_ASSERT(b);
177     SDK_NULL_ASSERT(ab);
178 
179     ab->x = a->x - b->x;
180     ab->y = a->y - b->y;
181     ab->z = a->z - b->z;
182 }
183 
184 //------------------------------------------------------------------------------
GetErrorVecD_(const VecD * a,const VecD * b,VecD * ab)185 static void GetErrorVecD_(const VecD * a, const VecD * b, VecD * ab)
186 {
187     SDK_NULL_ASSERT(a);
188     SDK_NULL_ASSERT(b);
189     SDK_NULL_ASSERT(ab);
190 
191     VecSubVecD_(a, b, ab);
192 
193     ab->x = fabs(ab->x);
194     ab->y = fabs(ab->y);
195     ab->z = fabs(ab->z);
196 }
197 
198 //------------------------------------------------------------------------------
CalcErrorBtweenVecFxAndVecD_(const VecFx32 * a,const VecD * b,VecD * vError)199 static void CalcErrorBtweenVecFxAndVecD_(const VecFx32 *a, const VecD * b, VecD * vError)
200 {
201     VecD    aD;
202 
203     SDK_NULL_ASSERT(a);
204     SDK_NULL_ASSERT(b);
205     SDK_NULL_ASSERT(vError);
206 
207     // fx => double
208     VecFx32ToVecD_(a, &aD);
209 
210     // error = a - b
211     GetErrorVecD_(&aD, b, vError);
212 }
213 
214 //------------------------------------------------------------------------------
215 // Get the element with the highest absolute value
FindMaxElement_(const VecD * v)216 static double FindMaxElement_(const VecD * v)
217 {
218 
219     double  max = 0.0;
220 
221     SDK_NULL_ASSERT(v);
222 
223     if (fabs(v->x) > fabs(v->y))
224     {
225         max = fabs(v->x);
226     }
227     else
228     {
229         max = fabs(v->y);
230     }
231 
232     if (fabs(v->z) > max)
233         max = fabs(v->z);
234 
235     return max;
236 }
237 
238 
239 
240 
241 
242 //------------------------------------------------------------------------------
243 // double version
244 //------------------------------------------------------------------------------
245 //
246 //------------------------------------------------------------------------------
FX_Mul_d_(const fx32 a,const fx32 b)247 static double FX_Mul_d_(const fx32 a, const fx32 b)
248 {
249     return (double)(FX_FX32_TO_F32(a)) * (double)(FX_FX32_TO_F32(b));
250 }
251 
252 //------------------------------------------------------------------------------
VEC_DotProduct_d_(const VecFx32 * a,const VecFx32 * b)253 static double VEC_DotProduct_d_(const VecFx32 *a, const VecFx32 *b)
254 {
255     VecD    da, db;
256 
257     SDK_NULL_ASSERT(a);
258     SDK_NULL_ASSERT(b);
259 
260 
261     VecFx32ToVecD_(a, &da);
262     VecFx32ToVecD_(b, &db);
263 
264     return da.x * db.x + da.y * db.y + da.z * db.z;
265 }
266 
267 //------------------------------------------------------------------------------
VEC_CrossProduct_d_(const VecFx32 * a,const VecFx32 * b,VecD * axb)268 static void VEC_CrossProduct_d_(const VecFx32 *a, const VecFx32 *b, VecD * axb)
269 {
270     VecD    da, db;
271 
272     SDK_NULL_ASSERT(a);
273     SDK_NULL_ASSERT(b);
274     SDK_NULL_ASSERT(axb);
275 
276     VecFx32ToVecD_(a, &da);
277     VecFx32ToVecD_(b, &db);
278 
279     axb->x = da.y * db.z - da.z * db.y;
280     axb->y = da.z * db.x - da.x * db.z;
281     axb->z = da.x * db.y - da.y * db.x;
282 }
283 
284 //------------------------------------------------------------------------------
VEC_Mag_d_(const VecFx32 * pSrc)285 static double VEC_Mag_d_(const VecFx32 *pSrc)
286 {
287     VecD    pSrcD;
288 
289     SDK_NULL_ASSERT(pSrc);
290 
291 
292     VecFx32ToVecD_(pSrc, &pSrcD);
293 
294     return sqrt(pSrcD.x * pSrcD.x + pSrcD.y * pSrcD.y + pSrcD.z * pSrcD.z);
295 }
296 
297 //------------------------------------------------------------------------------
VEC_Normalize_d_(const VecFx32 * pSrc,VecD * pDst)298 static void VEC_Normalize_d_(const VecFx32 *pSrc, VecD * pDst)
299 {
300     double  t = 0.0;
301     VecD    pSrcD;
302 
303     SDK_NULL_ASSERT(pSrc);
304     SDK_NULL_ASSERT(pDst);
305 
306 
307     VecFx32ToVecD_(pSrc, &pSrcD);
308 
309     t = VEC_Mag_d_(pSrc);
310     SDK_ASSERTMSG(t > 0, "*pSrc is (0, 0, 0)");
311 
312     t = 1.0 / t;
313 
314     pDst->x = t * pSrcD.x;
315     pDst->y = t * pSrcD.y;
316     pDst->z = t * pSrcD.z;
317 }
318 
319 
320 //==============================================================================
321 // Error calculation
322 //
323 //------------------------------------------------------------------------------
GetDotProductError_(const VecFx32 * a,const VecFx32 * b)324 static double GetDotProductError_(const VecFx32 *a, const VecFx32 *b)
325 {
326     double  resD = 0.0;
327     double  resFX = 0.0;
328 
329     SDK_NULL_ASSERT(a);
330     SDK_NULL_ASSERT(b);
331 
332     resD = VEC_DotProduct_d_(a, b);
333     resFX = (double)(FX_FX32_TO_F32(VEC_DotProduct(a, b)));
334 
335     return fabs(resFX - resD);
336 }
337 
338 //------------------------------------------------------------------------------
GetCrossProductError_(const VecFx32 * a,const VecFx32 * b)339 static double GetCrossProductError_(const VecFx32 *a, const VecFx32 *b)
340 {
341     VecFx32 resFX;
342     VecD    vError;
343 
344     SDK_NULL_ASSERT(a);
345     SDK_NULL_ASSERT(b);
346 
347 
348     VEC_CrossProduct_d_(a, b, &vError);
349     VEC_CrossProduct(a, b, &resFX);
350 
351     CalcErrorBtweenVecFxAndVecD_(&resFX, &vError, &vError);
352 
353     return FindMaxElement_(&vError);
354 }
355 
356 //------------------------------------------------------------------------------
GetMagError_(const VecFx32 * a)357 static double GetMagError_(const VecFx32 *a)
358 {
359     double  resD = 0.0;
360     double  resFX = 0.0;
361 
362     SDK_NULL_ASSERT(a);
363 
364     resD = VEC_Mag_d_(a);
365     resFX = (double)(FX_FX32_TO_F32(VEC_Mag(a)));
366 
367 
368     OutDetail("**** VEC_Mag ::: FX     Result => %.10f\n");
369     OutDetail("**** VEC_Mag ::: double Result => %.10f\n");
370 
371 
372     return fabs(resFX - resD);
373 }
374 
375 //------------------------------------------------------------------------------
GetNormalizeError_(const VecFx32 * a,VecD * vError)376 static void GetNormalizeError_(const VecFx32 *a, VecD * vError)
377 {
378     VecFx32 resFX;
379 
380     SDK_NULL_ASSERT(a);
381     SDK_NULL_ASSERT(vError);
382 
383     VEC_Normalize(a, &resFX);
384     VEC_Normalize_d_(a, vError);
385 
386 
387     OutDetail
388         ("===================================================================================\n");
389     printVecFx32Msg("**** VEC_Mag :::        Input  => ", a);
390     printVecFx32Msg("                 FX     Result => ", &resFX);
391     printVecDMsg("                 double Result => ", vError);
392 
393 
394     CalcErrorBtweenVecFxAndVecD_(&resFX, vError, vError);
395 
396 
397     OutDetail
398         ("-----------------------------------------------------------------------------------\n");
399     printVecDMsg("                 | FX-double | => ", vError);
400     OutDetail("\n");
401 
402 }
403 
404 //------------------------------------------------------------------------------
IsResultVecValid(const VecD * result)405 static BOOL IsResultVecValid(const VecD * result)
406 {
407     SDK_NULL_ASSERT(result);
408     return (FindMaxElement_(result) < CRITICAL_ERROR_THRESHOLD) ? TRUE : FALSE;
409 }
410 
411 //==============================================================================
412 // Test Method
413 //==============================================================================
414 // Apply VEC_Mag_test_for different size of vector
415 // If an unexpected error is found, output message and quit the application.
VEC_Mag_test_()416 static void VEC_Mag_test_()
417 {
418     int     i = 0;
419     double  err = 0.0;
420     VecFx32 *v = NULL;
421 
422     OS_Printf("==================== VEC_Mag_test_ begin ====================\n");
423 
424     // OK Cases
425     OS_Printf("------------ Must be OK case \n");
426     for (i = 0; i < 9; i++)
427         MUST_SUCCEED_ASSERT(GetMagError_(&vInputData[i]) < CRITICAL_ERROR_THRESHOLD, 1);
428 
429     // NG Case
430     OS_Printf("------------ Must be NG case \n");
431     MUST_FAIL_ASSERT(GetMagError_(&vInputData[9]) < CRITICAL_ERROR_THRESHOLD, 2);
432 
433     // Case that addition happens internally
434     // OK Cases
435     OS_Printf("------------ Must be OK case \n");
436     for (i = 10; i < 16; i++)
437         MUST_SUCCEED_ASSERT(GetMagError_(&vInputData[i]) < CRITICAL_ERROR_THRESHOLD, 3);
438 
439 
440     // NG Case
441     OS_Printf("------------ Must be NG case \n");
442     MUST_FAIL_ASSERT(GetMagError_(&vInputData[16]) < CRITICAL_ERROR_THRESHOLD, 4);
443     MUST_FAIL_ASSERT(GetMagError_(&vInputData[17]) < CRITICAL_ERROR_THRESHOLD, 5);
444 
445     OS_Printf("==================== VEC_Mag_test_ done ====================\n");
446 }
447 
448 
449 //------------------------------------------------------------------------------
450 // Compares the output errors of the vector's normalization function to the double version.
451 // Output message when an unexpected error is found.
452 //
VEC_Normalize_test_()453 static void VEC_Normalize_test_()
454 {
455     int     i = 0;
456     VecD    testResult;
457 
458     OS_Printf("==================== VEC_Normalize_test_ begin ====================\n");
459     OS_Printf("------------ Must SUCCEED case \n");
460     for (i = 0; i < 7; i++)
461     {
462         GetNormalizeError_(&vInputData[i], &testResult);
463         MUST_SUCCEED_ASSERT(IsResultVecValid(&testResult), 1);
464     }
465 
466 
467     for (i = 11; i < 14; i++)
468     {
469         GetNormalizeError_(&vInputData[i], &testResult);
470         MUST_SUCCEED_ASSERT(IsResultVecValid(&testResult), 2);
471     }
472 
473     OS_Printf("------------ Must FAIL case \n");
474     // NG Case          very large
475     for (i = 7; i < 10; i++)
476     {
477         GetNormalizeError_(&vInputData[i], &testResult);
478         MUST_FAIL_ASSERT(IsResultVecValid(&testResult), 3);
479     }
480 
481     // NG Case          very small
482     GetNormalizeError_(&vInputData[10], &testResult);
483     MUST_FAIL_ASSERT(IsResultVecValid(&testResult), 4);
484 
485     // NG Case          very large
486     for (i = 14; i < 18; i++)
487     {
488         GetNormalizeError_(&vInputData[i], &testResult);
489         MUST_FAIL_ASSERT(IsResultVecValid(&testResult), 5);
490     }
491 
492     OS_Printf("==================== VEC_Normalize_test_ done ====================\n");
493 }
494 
495 //------------------------------------------------------------------------------
496 // Calculates the cross product and dot product values and checks errors with double calculation for parallel and orthogonal vectors.
497 // If an unexpected error is found, output message and quit the application.
498 // When defining FX_TEST__SHOW_DETAIL, output the detail information to debug console.
VEC_DotCrossProduct_test_()499 static void VEC_DotCrossProduct_test_()
500 {
501     VecFx32 v1;
502     VecFx32 v2;
503     VecFx32 v3;
504 
505     int     i = 0, j = 0;
506     const int angD = 182;              // minute angle change (about 1 degree)
507     const int ang45 = 8192;
508     double  errDot = 0.0;
509     double  errCross = 0.0;
510 
511     OS_Printf("==================== VEC_DotCrossProduct_test_ begin ====================\n");
512     OS_Printf("-------- Some Warning is displayed \n");
513     // Changing the angle slightly
514     // (because of an ideal orthogonal and parallel vector at i = 0, there is no error)
515     for (i = 1; i < 5; i++)
516     {
517         v1.x = FX_CosIdx(ang45);
518         v1.y = FX_SinIdx(ang45);
519         v1.z = 0x0;
520         v2.x = FX_CosIdx(ang45 + angD * i);
521         v2.y = -FX_SinIdx(ang45 + angD * i);
522         v2.z = 0x0;                    // Orthogonal
523         v3.x = FX_CosIdx(ang45 + angD * i);
524         v3.y = FX_SinIdx(ang45 + angD * i);
525         v3.z = 0x0;                    // Parallel
526 
527         // Lengthen out
528         for (j = 0; j < 7; j++)
529         {
530             v1.x = FX_Mul(v1.x, FX32_ONE << j);
531             v1.y = FX_Mul(v1.y, FX32_ONE << j);
532             v2.x = FX_Mul(v2.x, FX32_ONE << j);
533             v2.y = FX_Mul(v2.y, FX32_ONE << j);
534             v3.x = FX_Mul(v3.x, FX32_ONE << j);
535             v3.y = FX_Mul(v3.y, FX32_ONE << j);
536 
537             // Calculates the maximum error value with double implementation
538             errDot = GetDotProductError_(&v1, &v2);
539             errCross = GetCrossProductError_(&v1, &v3);
540 
541 
542             // Confirm success and failure
543             if (j < 5)
544             {
545                 MUST_SUCCEED_ASSERT((errDot < CRITICAL_ERROR_THRESHOLD) &&
546                                     (errCross < CRITICAL_ERROR_THRESHOLD), 1);
547             }
548             else
549             {
550                 // A large amount of errors will occur in the CrossProduct result when the length is FX32_ONE << 5 or greater.
551                 // Therefore, this trial is supposed to fail.
552                 // Moreover, for parallel vectors of the same length facing the opposite direction, it is possible to calculate even bigger values.
553                 // A further check of the inside of CrossProduct is expected.
554                 MUST_FAIL_ASSERT((errDot < CRITICAL_ERROR_THRESHOLD) &&
555                                  (errCross < CRITICAL_ERROR_THRESHOLD), 2);
556             }
557 
558             // Output the detail information
559             {
560                 OutDetail("------------ input ---------------------\n");
561                 printVecFx32Msg("v1                      = ", &v1);
562                 printVecFx32Msg("v2(perpendicular to v1) = ", &v2);
563                 printVecFx32Msg("v3(parallel To v1)      = ", &v3);
564 
565                 OutDetail("v1 . v2 Error   = %.10f \n", errDot);
566                 OutDetail("v1 X v3 Error   = %.10f \n", errCross);
567             }
568         }
569     }
570 
571     OS_Printf("==================== VEC_DotCrossProduct_test_ done ====================\n");
572 }
573 
574 
575 //------------------------------------------------------------------------------
576 // Basic operation function test
577 // The error between the fixed decimal calculation function and the calculation performed in double is displayed on the debug console
578 //
BasicOperator_test_()579 static void BasicOperator_test_()
580 {
581     int     i = 0, j = 0;
582     fx32    vf1 = 0x0, vf2 = 0x0;
583 
584     OS_Printf("==================== BasicOperator_test_ begin ====================\n");
585 
586     // unary_operators
587     OS_Printf("------------ unary_operators begin ---------------------\n");
588     for (i = 0; i < 32; i += 4)
589     {
590         vf1 += 0x1 << i;
591         Unary_operator_test_(vf1);
592     }
593     OS_Printf("------------ unary_operators done ---------------------\n");
594     // binary_operators
595     OS_Printf("------------ binary_operators begin ---------------------\n");
596     OS_Printf("-------- Some Warning is displayed \n");
597     vf1 = 0x0;
598     for (i = 0; i < 32; i += 4)
599     {
600         vf1 += 0x1 << i;
601         vf2 = 0;
602         for (j = 0; j < 32; j++)
603         {
604             vf2 += 0x1 << j;
605             Binary_operator_test_(vf1, vf2);
606         }
607     }
608     OS_Printf("------------ binary_operators done ---------------------\n");
609 
610     OS_Printf("==================== BasicOperator_test_ done ====================\n");
611 }
612 
613 
614 
615 //------------------------------------------------------------------------------
616 // Test of functions that perform fixed-point unary operations
617 // Runs calculations with an input value as a parameter and shows the difference between these calculations and ones performed using a double in the debug console.
618 //
619 //
Unary_operator_test_(fx32 vf1)620 static void Unary_operator_test_(fx32 vf1)
621 {
622     double  vd1 = (double)FX_FX32_TO_F32(vf1);
623 
624     double  diff = 0.0;
625 
626     // Input fixed-point value
627     OutDetail("                 v = %.10f \n", vd1);
628 
629     // FX_Sqrt
630     diff = fabs(FX2D(FX_Sqrt(vf1)) - sqrt(vd1));
631     OutDetail("sqrt( v1 )   Error = %.10f \n", diff);
632 
633     // FX_InvSqrt
634     diff = fabs(FX2D(FX_InvSqrt(vf1)) - 1.0 / sqrt(vd1));
635     OutDetail("InvSqrt( v1 )Error = %.10f \n", diff);
636 
637     // FX_Inv
638     diff = fabs(FX2D(FX_Inv(vf1)) - 1.0 / vd1);
639     OutDetail("1.0 / v1     Error = %.10f \n", diff);
640 
641     // FX_InvFx64c
642     diff = fabs(FX64C2D(FX_InvFx64c(vf1)) - 1.0 / vd1);
643     OutDetail("1.0 / v1 _64 Error = %.10f \n", diff);
644 
645 }
646 
647 //------------------------------------------------------------------------------
648 // Fixed decimal binary operation function test
649 // Runs calculations with an input value as a parameter and shows the difference between these calculations and ones performed using a double in the debug console.
650 //
651 //
Binary_operator_test_(fx32 vf1,fx32 vf2)652 static void Binary_operator_test_(fx32 vf1, fx32 vf2)
653 {
654     double  vd1 = (double)FX_FX32_TO_F32(vf1);
655     double  vd2 = (double)FX_FX32_TO_F32(vf2);
656     double  diff = 0.0;
657 
658     // Input fixed-point value
659     OutDetail("v1 = %.10f, v2 = %.10f\n", vd1, vd2);
660 
661     // FX_Mul
662     diff = fabs(FX2D(FX_Mul(vf1, vf2)) - vd1 * vd2);
663     OutDetail("v1 * v2     Error = %.10f \n", diff);
664 
665     // FX_Div
666     diff = fabs(FX2D(FX_Div(vf1, vf2)) - vd1 / vd2);
667     OutDetail("v1 / v2     Error = %.10f \n", diff);
668 
669     // FX_Mul32x64c
670     diff = fabs(FX2D(FX_Mul32x64c(vf1, FX_FX32_TO_FX64C(vf2))) - vd1 * vd2);
671     OutDetail("v1 * v2 _64 Error = %.10f \n", diff);
672 
673     // FX_DivFx64c
674     diff = fabs(FX64C2D(FX_DivFx64c(vf1, vf2)) - vd1 / vd2);
675     OutDetail("v1 / v2 _64 Error = %.10f \n", diff);
676 
677 }
678