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