xref: /aosp_15_r20/external/OpenCL-CTS/test_conformance/printf/util_printf.cpp (revision 6467f958c7de8070b317fc65bcb0f6472e388d82)
1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //    http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #include "harness/rounding_mode.h"
17 #include "harness/kernelHelpers.h"
18 
19 #include "test_printf.h"
20 #include <assert.h>
21 #include <CL/cl_half.h>
22 
23 
24 // Helpers for generating runtime reference results
25 static void intRefBuilder(printDataGenParameters&, char*, const size_t);
26 static void halfRefBuilder(printDataGenParameters&, char* rResult,
27                            const size_t);
28 static void floatRefBuilder(printDataGenParameters&, char* rResult, const size_t);
29 static void octalRefBuilder(printDataGenParameters&, char*, const size_t);
30 static void unsignedRefBuilder(printDataGenParameters&, char*, const size_t);
31 static void hexRefBuilder(printDataGenParameters&, char*, const size_t);
32 
33 //==================================
34 
35 // int
36 
37 //==================================
38 
39 //------------------------------------------------------
40 
41 // [string] format  | [string] int-data representation |
42 
43 //------------------------------------------------------
44 
45 std::vector<printDataGenParameters> printIntGenParameters = {
46 
47     //(Minimum)Five-wide,default(right)-justified
48 
49     {"%5d","10"},
50 
51         //(Minimum)Five-wide,left-justified
52 
53     {"%-5d","10"},
54 
55         //(Minimum)Five-wide,default(right)-justified,zero-filled
56 
57     {"%05d","10"},
58 
59         //(Minimum)Five-wide,default(right)-justified,with sign
60 
61     {"%+5d","10"},
62 
63          //(Minimum)Five-wide ,left-justified,with sign
64 
65     {"%-+5d","10"},
66 
67         //(Minimum)Five-digit(zero-filled in absent digits),default(right)-justified
68 
69     {"%.5i","100"},
70 
71         //(Minimum)Six-wide,Five-digit(zero-filled in absent digits),default(right)-justified
72 
73     {"%6.5i","100"},
74 
75         //0 and - flag both apper ==>0 is ignored,left-justified,capital I
76 
77     {"%-06i","100"},
78 
79         //(Minimum)Six-wide,Five-digit(zero-filled in absent digits),default(right)-justified
80 
81     {"%06.5i","100"}
82 
83 };
84 
85 //-----------------------------------------------
86 
87 //test case for int                             |
88 
89 //-----------------------------------------------
90 
91 testCase testCaseInt = {
92 
93     TYPE_INT,
94 
95     correctBufferInt,
96 
97     printIntGenParameters,
98 
99     intRefBuilder,
100 
101     kint
102 
103 };
104 
105 
106 //==============================================
107 
108 // half
109 
110 //==============================================
111 
112 //--------------------------------------------------------
113 
114 // [string] format |  [string] float-data representation |
115 
116 //--------------------------------------------------------
117 
118 std::vector<printDataGenParameters> printHalfGenParameters = {
119 
120     // Default(right)-justified
121 
122     { "%f", "1.234h" },
123 
124     // One position after the decimal,default(right)-justified
125 
126     { "%4.2f", "1.2345h" },
127 
128     // Zero positions after the
129     // decimal([floor]rounding),default(right)-justified
130 
131     { "%.0f", "0.1h" },
132 
133     // Zero positions after the decimal([ceil]rounding),default(right)-justified
134 
135     { "%.0f", "0.6h" },
136 
137     // Zero-filled,default positions number after the
138     // decimal,default(right)-justified
139 
140     { "%0f", "0.6h" },
141 
142     // Double argument representing floating-point,used by f
143     // style,default(right)-justified
144 
145     { "%4g", "5.678h" },
146 
147     // Double argument representing floating-point,used by e
148     // style,default(right)-justified
149 
150     { "%4.2g", "5.678h" },
151 
152     // Double argument representing floating-point,used by e
153     // style,default(right)-justified
154 
155     { "%4G", "0.000062h" },
156 
157     // Double argument representing floating-point,with
158     // exponent,left-justified,default(right)-justified
159 
160     { "%-#20.15e", "65504.0h" },
161 
162     // Double argument representing floating-point,with
163     // exponent,left-justified,with sign,capital E,default(right)-justified
164 
165     { "%+#21.15E", "-65504.0h" },
166 };
167 
168 //---------------------------------------------------------
169 
170 // Test case for float                                     |
171 
172 //---------------------------------------------------------
173 
174 testCase testCaseHalf = {
175 
176     TYPE_HALF,
177 
178     correctBufferHalf,
179 
180     printHalfGenParameters,
181 
182     halfRefBuilder,
183 
184     kfloat
185 
186 };
187 
188 
189 //==============================================
190 
191 // half limits
192 
193 //==============================================
194 
195 
196 //--------------------------------------------------------
197 
198 // [string] format |  [string] float-data representation |
199 
200 //--------------------------------------------------------
201 
202 
203 std::vector<printDataGenParameters> printHalfLimitsGenParameters = {
204 
205     // Infinity (1.0/0.0)
206 
207     { "%f", "1.0h/0.0h" },
208 
209     // NaN
210 
211     { "%f", "sqrt(-1.0h)" },
212 
213     // NaN
214     { "%f", "acospi(2.0h)" }
215 
216 };
217 //--------------------------------------------------------
218 
219 //  Lookup table - [string]float-correct buffer             |
220 
221 //--------------------------------------------------------
222 
223 std::vector<std::string> correctBufferHalfLimits = {
224 
225     "inf",
226 
227     "-nan",
228 
229     "nan"
230 
231 };
232 
233 //---------------------------------------------------------
234 
235 // Test case for float                                     |
236 
237 //---------------------------------------------------------
238 
239 testCase testCaseHalfLimits = {
240 
241     TYPE_HALF_LIMITS,
242 
243     correctBufferHalfLimits,
244 
245     printHalfLimitsGenParameters,
246 
247     NULL
248 
249 };
250 
251 
252 //==============================================
253 
254 // float
255 
256 //==============================================
257 
258 
259 
260 //--------------------------------------------------------
261 
262 // [string] format |  [string] float-data representation |
263 
264 //--------------------------------------------------------
265 
266 std::vector<printDataGenParameters> printFloatGenParameters = {
267 
268     //Default(right)-justified
269 
270     {"%f","10.3456"},
271 
272     //One position after the decimal,default(right)-justified
273 
274     {"%.1f","10.3456"},
275 
276     //Two positions after the decimal,default(right)-justified
277 
278     {"%.2f","10.3456"},
279 
280     //(Minimum)Eight-wide,three positions after the decimal,default(right)-justified
281 
282     {"%8.3f","10.3456"},
283 
284     //(Minimum)Eight-wide,two positions after the decimal,zero-filled,default(right)-justified
285 
286     {"%08.2f","10.3456"},
287 
288     //(Minimum)Eight-wide,two positions after the decimal,left-justified
289 
290     {"%-8.2f","10.3456"},
291 
292     //(Minimum)Eight-wide,two positions after the decimal,with sign,default(right)-justified
293 
294     {"%+8.2f","-10.3456"},
295 
296     //Zero positions after the decimal([floor]rounding),default(right)-justified
297 
298     {"%.0f","0.1"},
299 
300     //Zero positions after the decimal([ceil]rounding),default(right)-justified
301 
302     {"%.0f","0.6"},
303 
304     //Zero-filled,default positions number after the decimal,default(right)-justified
305 
306     {"%0f","0.6"},
307 
308     //Double argument representing floating-point,used by f style,default(right)-justified
309 
310     {"%4g","12345.6789"},
311 
312     //Double argument representing floating-point,used by e style,default(right)-justified
313 
314     {"%4.2g","12345.6789"},
315 
316     //Double argument representing floating-point,used by f style,default(right)-justified
317 
318     {"%4G","0.0000023"},
319 
320     //Double argument representing floating-point,used by e style,default(right)-justified
321 
322     {"%4G","0.023"},
323 
324     //Double argument representing floating-point,with exponent,left-justified,default(right)-justified
325 
326     {"%-#20.15e","789456123.0"},
327 
328     //Double argument representing floating-point,with exponent,left-justified,with sign,capital E,default(right)-justified
329 
330     {"%+#21.15E","789456123.0"},
331 
332     //Double argument representing floating-point,in [-]xh.hhhhpAd style
333 
334     {"%.6a","0.1"},
335 
336     //(Minimum)Ten-wide,Double argument representing floating-point,in xh.hhhhpAd style,default(right)-justified
337 
338     {"%10.2a","9990.235"},
339 };
340 
341 //---------------------------------------------------------
342 
343 //Test case for float                                     |
344 
345 //---------------------------------------------------------
346 
347 testCase testCaseFloat = {
348 
349     TYPE_FLOAT,
350 
351     correctBufferFloat,
352 
353     printFloatGenParameters,
354 
355     floatRefBuilder,
356 
357     kfloat
358 
359 };
360 
361 //==============================================
362 
363 // float limits
364 
365 //==============================================
366 
367 
368 
369 //--------------------------------------------------------
370 
371 // [string] format |  [string] float-data representation |
372 
373 //--------------------------------------------------------
374 
375 
376 std::vector<printDataGenParameters> printFloatLimitsGenParameters = {
377 
378     // Infinity (1.0/0.0)
379 
380     { "%f", "1.0f/0.0f" },
381 
382     // NaN
383 
384     { "%f", "sqrt(-1.0f)" },
385 
386     // NaN
387     { "%f", "acospi(2.0f)" }
388 
389 };
390 //--------------------------------------------------------
391 
392 //  Lookup table - [string]float-correct buffer             |
393 
394 //--------------------------------------------------------
395 
396 std::vector<std::string> correctBufferFloatLimits = {
397 
398     "inf",
399 
400     "-nan",
401 
402     "nan"
403 
404 };
405 
406 //---------------------------------------------------------
407 
408 //Test case for float                                     |
409 
410 //---------------------------------------------------------
411 
412 testCase testCaseFloatLimits = {
413 
414     TYPE_FLOAT_LIMITS,
415 
416     correctBufferFloatLimits,
417 
418     printFloatLimitsGenParameters,
419 
420     NULL
421 
422 };
423 
424 //=========================================================
425 
426 // octal
427 
428 //=========================================================
429 
430 
431 
432 //---------------------------------------------------------
433 
434 // [string] format  | [string] octal-data representation  |
435 
436 //---------------------------------------------------------
437 
438 std::vector<printDataGenParameters> printOctalGenParameters = {
439 
440     //Default(right)-justified
441 
442     {"%o","10"},
443 
444     //Five-digit,default(right)-justified
445 
446     {"%.5o","10"},
447 
448     //Default(right)-justified,increase precision
449 
450     {"%#o","100000000"},
451 
452     //(Minimum)Four-wide,Five-digit,0-flag ignored(because of precision),default(right)-justified
453 
454     {"%04.5o","10"}
455 
456 };
457 
458 //-------------------------------------------------------
459 
460 //Test case for octal                                   |
461 
462 //-------------------------------------------------------
463 
464 testCase testCaseOctal = {
465 
466     TYPE_OCTAL,
467 
468     correctBufferOctal,
469 
470     printOctalGenParameters,
471 
472     octalRefBuilder,
473 
474     kulong
475 
476 };
477 
478 
479 
480 //=========================================================
481 
482 // unsigned
483 
484 //=========================================================
485 
486 
487 
488 //---------------------------------------------------------
489 
490 // [string] format  | [string] unsined-data representation  |
491 
492 //---------------------------------------------------------
493 
494 std::vector<printDataGenParameters> printUnsignedGenParameters = {
495 
496     //Default(right)-justified
497 
498     {"%u","10"},
499 
500     //Zero precision for zero,default(right)-justified
501 
502     {"%.0u","0"},
503 
504 };
505 
506 //-------------------------------------------------------
507 
508 //Test case for octal                                   |
509 
510 //-------------------------------------------------------
511 
512 testCase testCaseUnsigned = {
513 
514     TYPE_UNSIGNED,
515 
516     correctBufferUnsigned,
517 
518     printUnsignedGenParameters,
519 
520     unsignedRefBuilder,
521 
522     kulong
523 
524 };
525 
526 
527 
528 //=======================================================
529 
530 // hexadecimal
531 
532 //=======================================================
533 
534 
535 
536 //--------------------------------------------------------------
537 
538 // [string] format  | [string] hexadecimal-data representation |
539 
540 //--------------------------------------------------------------
541 
542 std::vector<printDataGenParameters> printHexadecimalGenParameters = {
543 
544     //Add 0x,low x,default(right)-justified
545 
546     {"%#x","0xABCDEF"},
547 
548     //Add 0x,capital X,default(right)-justified
549 
550     {"%#X","0xABCDEF"},
551 
552     //Not add 0x,if zero,default(right)-justified
553 
554     {"%#X","0"},
555 
556     //(Minimum)Eight-wide,default(right)-justified
557 
558     {"%8x","399"},
559 
560     //(Minimum)Four-wide,zero-filled,default(right)-justified
561 
562     {"%04x","399"}
563 
564 };
565 
566 //--------------------------------------------------------------
567 
568 //Test case for hexadecimal                                    |
569 
570 //--------------------------------------------------------------
571 
572 testCase testCaseHexadecimal = {
573 
574     TYPE_HEXADEC,
575 
576     correctBufferHexadecimal,
577 
578     printHexadecimalGenParameters,
579 
580     hexRefBuilder,
581 
582     kulong
583 
584 };
585 
586 
587 
588 //=============================================================
589 
590 // char
591 
592 //=============================================================
593 
594 
595 
596 //-----------------------------------------------------------
597 
598 // [string] format  | [string] string-data representation   |
599 
600 //-----------------------------------------------------------
601 
602 std::vector<printDataGenParameters> printCharGenParameters = {
603 
604     //Four-wide,zero-filled,default(right)-justified
605 
606     {"%4c","\'1\'"},
607 
608         //Four-wide,left-justified
609 
610     {"%-4c","\'1\'"},
611 
612         //(unsigned) int argument,default(right)-justified
613 
614     {"%c","66"}
615 
616 };
617 
618 //---------------------------------------------------------
619 
620 // Lookup table -[string] char-correct buffer             |
621 
622 //---------------------------------------------------------
623 
624 std::vector<std::string> correctBufferChar = {
625 
626     "   1",
627 
628     "1   ",
629 
630     "B",
631 
632 };
633 
634 
635 
636 
637 //----------------------------------------------------------
638 
639 //Test case for char                                       |
640 
641 //----------------------------------------------------------
642 
643 testCase testCaseChar = {
644 
645     TYPE_CHAR,
646 
647     correctBufferChar,
648 
649     printCharGenParameters,
650 
651     NULL,
652 
653     kchar
654 
655 };
656 
657 
658 
659 //==========================================================
660 
661 // string
662 
663 //==========================================================
664 
665 
666 
667 //--------------------------------------------------------
668 
669 // [string]format | [string] string-data representation  |
670 
671 //--------------------------------------------------------
672 
673 std::vector<printDataGenParameters> printStringGenParameters = {
674 
675     //(Minimum)Four-wide,zero-filled,default(right)-justified
676 
677     {"%4s","\"foo\""},
678 
679     //One-digit(precision ignored),left-justified
680 
681     {"%.1s","\"foo\""},
682 
683     //%% specification
684 
685     {"%s","\"%%\""},
686 };
687 
688 //---------------------------------------------------------
689 
690 // Lookup table -[string] string-correct buffer           |
691 
692 //---------------------------------------------------------
693 
694 std::vector<std::string> correctBufferString = {
695 
696     " foo",
697 
698     "f",
699 
700     "%%",
701 };
702 
703 
704 //---------------------------------------------------------
705 
706 //Test case for string                                    |
707 
708 //---------------------------------------------------------
709 
710 testCase testCaseString = {
711 
712     TYPE_STRING,
713 
714     correctBufferString,
715 
716     printStringGenParameters,
717 
718     NULL,
719 
720     kchar
721 
722 };
723 
724 
725 
726 //=========================================================
727 
728 // vector
729 
730 //=========================================================
731 
732 
733 
734 //-------------------------------------------------------------------------------------------------------------------
735 
736 //[string] flag | [string] specifier | [string] type | [string] vector-data representation | [string] vector size   |
737 
738 //-------------------------------------------------------------------------------------------------------------------
739 
740 std::vector<printDataGenParameters> printVectorGenParameters = {
741 
742     //(Minimum)Two-wide,two positions after decimal
743 
744     { NULL, "(1.0f,2.0f,3.0f,4.0f)", "%2.2", "hlf", "float", "4" },
745 
746     // Alternative form,uchar argument
747 
748     { NULL, "(0xFA,0xFB)", "%#", "hhx", "uchar", "2" },
749 
750     // Alternative form,ushort argument
751 
752     { NULL, "(0x1234,0x8765)", "%#", "hx", "ushort", "2" },
753 
754     // Alternative form,uint argument
755 
756     { NULL, "(0x12345678,0x87654321)", "%#", "hlx", "uint", "2" },
757 
758     // Alternative form,long argument
759 
760     { NULL, "(12345678,98765432)", "%", "ld", "long", "2" },
761 
762     //(Minimum)Two-wide,two positions after decimal
763 
764     { NULL, "(1.0h,2.0h,3.0h,4.0h)", "%2.2", "hf", "half", "4" }
765 };
766 
767 //------------------------------------------------------------
768 
769 // Lookup table -[string] vector-correct buffer              |
770 
771 //------------------------------------------------------------
772 
773 std::vector<std::string> correctBufferVector = {
774 
775     "1.00,2.00,3.00,4.00",
776 
777     "0xfa,0xfb",
778 
779     "0x1234,0x8765",
780 
781     "0x12345678,0x87654321",
782 
783     "12345678,98765432",
784 
785     "1.00,2.00,3.00,4.00"
786 
787 };
788 
789 //-----------------------------------------------------------
790 
791 //Test case for vector                                      |
792 
793 //-----------------------------------------------------------
794 
795 testCase testCaseVector = {
796 
797     TYPE_VECTOR,
798 
799     correctBufferVector,
800 
801     printVectorGenParameters,
802 
803     NULL
804 
805 };
806 
807 
808 
809 //==================================================================
810 
811 // address space
812 
813 //==================================================================
814 
815 
816 
817 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------
818 
819 // [string] argument type qualifier |[string] variable type qualifier + initialization | [string] format | [string] parameter |[string]%p indicator/additional code |
820 
821 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------
822 
823 
824 
825 std::vector<printDataGenParameters> printAddrSpaceGenParameters = {
826 
827     //Global memory region
828 
829     {"\"%d\\n\"",NULL,NULL,NULL,NULL,NULL,"__global int* x","","*x",""},
830 
831     //Global,constant, memory region
832 
833     {"\"%d\\n\"",NULL,NULL,NULL,NULL,NULL,"constant int* x","","*x",""},
834 
835     //Local memory region
836 
837     {"\"%+d\\n\"",NULL,NULL,NULL,NULL,NULL,"","local int x;\n x= (int)3;\n","x",""},
838 
839     //Private memory region
840 
841     {"\"%i\\n\"",NULL,NULL,NULL,NULL,NULL,"","private int x;\n x = (int)-1;\n","x",""},
842 
843     //Address of void * from global memory region
844 
845     {"\"%p\\n\"",NULL,NULL,NULL,NULL,NULL,"__global void* x,__global intptr_t*  xAddr","","x","*xAddr = (intptr_t)x;\n"}
846 
847 };
848 
849 //-------------------------------------------------------------------------------
850 
851 //  Lookup table -[string] address space -correct buffer                        |
852 
853 //-------------------------------------------------------------------------------
854 
855 std::vector<std::string> correctAddrSpace = {
856 
857     "2","2","+3","-1",""
858 
859 };
860 
861 //-------------------------------------------------------------------------------
862 
863 //Test case for address space                                                   |
864 
865 //-------------------------------------------------------------------------------
866 
867 testCase testCaseAddrSpace = {
868 
869     TYPE_ADDRESS_SPACE,
870 
871     correctAddrSpace,
872 
873     printAddrSpaceGenParameters,
874 
875     NULL
876 
877 };
878 
879 
880 
881 //-------------------------------------------------------------------------------
882 
883 //All Test cases                                                                |
884 
885 //-------------------------------------------------------------------------------
886 
887 std::vector<testCase*> allTestCase = {
888     &testCaseInt,      &testCaseHalf,        &testCaseHalfLimits,
889     &testCaseFloat,    &testCaseFloatLimits, &testCaseOctal,
890     &testCaseUnsigned, &testCaseHexadecimal, &testCaseChar,
891     &testCaseString,   &testCaseVector,      &testCaseAddrSpace
892 };
893 
894 //-----------------------------------------
895 
896 cl_half_rounding_mode half_rounding_mode = CL_HALF_RTE;
897 
898 //-----------------------------------------
899 
900 // Check functions
901 
902 //-----------------------------------------
903 
verifyOutputBuffer(char * analysisBuffer,testCase * pTestCase,size_t testId,cl_ulong pAddr)904 size_t verifyOutputBuffer(char *analysisBuffer,testCase* pTestCase,size_t testId,cl_ulong pAddr)
905 {
906     int terminatePos = strlen(analysisBuffer);
907         if(terminatePos > 0)
908     {
909         analysisBuffer[terminatePos - 1] = '\0';
910     }
911 
912     //Convert analysis buffer to long for address space
913     if(pTestCase->_type == TYPE_ADDRESS_SPACE && strcmp(pTestCase->_genParameters[testId].addrSpacePAdd,""))
914 
915     {
916         char analysisBufferTmp[ANALYSIS_BUFFER_SIZE];
917 
918         if(strstr(analysisBuffer,"0x") == NULL)
919         // Need to prepend 0x to ASCII number before calling strtol.
920         strcpy(analysisBufferTmp,"0x");
921 
922         else analysisBufferTmp[0]='\0';
923         strcat(analysisBufferTmp,analysisBuffer);
924         if (sizeof(long) == 8) {
925             if(strtoul(analysisBufferTmp,NULL,0) == pAddr) return 0;
926         }
927         else {
928             if(strtoull(analysisBufferTmp,NULL,0) == pAddr) return 0;
929         }
930         return 1;
931 
932     }
933 
934     char* exp;
935     //Exponenent representation
936     if((exp = strstr(analysisBuffer,"E+")) != NULL || (exp = strstr(analysisBuffer,"e+")) != NULL || (exp = strstr(analysisBuffer,"E-")) != NULL || (exp = strstr(analysisBuffer,"e-")) != NULL)
937     {
938         char correctExp[3]={0};
939         strncpy(correctExp,exp,2);
940 
941         char* eCorrectBuffer = strstr((char*)pTestCase->_correctBuffer[testId].c_str(),correctExp);
942         if(eCorrectBuffer == NULL)
943             return 1;
944 
945         eCorrectBuffer+=2;
946         exp += 2;
947 
948         //Exponent always contains at least two digits
949         if(strlen(exp) < 2)
950             return 1;
951         //Skip leading zeros in the exponent
952         while(*exp == '0')
953             ++exp;
954         while(*eCorrectBuffer == '0')
955             ++eCorrectBuffer;
956         return strcmp(eCorrectBuffer,exp);
957     }
958     if(!strcmp(pTestCase->_correctBuffer[testId].c_str(),"inf"))
959     return strcmp(analysisBuffer,"inf")&&strcmp(analysisBuffer,"infinity")&&strcmp(analysisBuffer,"1.#INF00")&&strcmp(analysisBuffer,"Inf");
960     if(!strcmp(pTestCase->_correctBuffer[testId].c_str(),"nan") || !strcmp(pTestCase->_correctBuffer[testId].c_str(),"-nan")) {
961        return strcmp(analysisBuffer,"nan")&&strcmp(analysisBuffer,"-nan")&&strcmp(analysisBuffer,"1.#IND00")&&strcmp(analysisBuffer,"-1.#IND00")&&strcmp(analysisBuffer,"NaN")&&strcmp(analysisBuffer,"nan(ind)")&&strcmp(analysisBuffer,"nan(snan)")&&strcmp(analysisBuffer,"-nan(ind)");
962     }
963     return strcmp(analysisBuffer,pTestCase->_correctBuffer[testId].c_str());
964 }
965 
intRefBuilder(printDataGenParameters & params,char * refResult,const size_t refSize)966 static void intRefBuilder(printDataGenParameters& params, char* refResult, const size_t refSize)
967 {
968     snprintf(refResult, refSize, params.genericFormat, atoi(params.dataRepresentation));
969 }
970 
halfRefBuilder(printDataGenParameters & params,char * refResult,const size_t refSize)971 static void halfRefBuilder(printDataGenParameters& params, char* refResult,
972                            const size_t refSize)
973 {
974     cl_half val = cl_half_from_float(strtof(params.dataRepresentation, NULL),
975                                      half_rounding_mode);
976     snprintf(refResult, refSize, params.genericFormat, cl_half_to_float(val));
977 }
978 
floatRefBuilder(printDataGenParameters & params,char * refResult,const size_t refSize)979 static void floatRefBuilder(printDataGenParameters& params, char* refResult, const size_t refSize)
980 {
981     snprintf(refResult, refSize, params.genericFormat, strtof(params.dataRepresentation, NULL));
982 }
983 
octalRefBuilder(printDataGenParameters & params,char * refResult,const size_t refSize)984 static void octalRefBuilder(printDataGenParameters& params, char* refResult, const size_t refSize)
985 {
986     const unsigned long int data = strtoul(params.dataRepresentation, NULL, 10);
987     snprintf(refResult, refSize, params.genericFormat, data);
988 }
989 
unsignedRefBuilder(printDataGenParameters & params,char * refResult,const size_t refSize)990 static void unsignedRefBuilder(printDataGenParameters& params, char* refResult, const size_t refSize)
991 {
992     const unsigned long int data = strtoul(params.dataRepresentation, NULL, 10);
993     snprintf(refResult, refSize, params.genericFormat, data);
994 }
995 
hexRefBuilder(printDataGenParameters & params,char * refResult,const size_t refSize)996 static void hexRefBuilder(printDataGenParameters& params, char* refResult, const size_t refSize)
997 {
998     const unsigned long int data = strtoul(params.dataRepresentation, NULL, 0);
999     snprintf(refResult, refSize, params.genericFormat, data);
1000 }
1001 
1002 /*
1003     Generate reference results.
1004 
1005     Results are only generated for test cases
1006     that can easily be generated by using CPU
1007     printf.
1008 
1009     If that is not the case, results are constants
1010     that have been hard-coded.
1011 */
generateRef(const cl_device_id device)1012 void generateRef(const cl_device_id device)
1013 {
1014     const cl_device_fp_config fpConfigSingle =
1015         get_default_rounding_mode(device);
1016     const cl_device_fp_config fpConfigHalf = (half_rounding_mode == CL_HALF_RTE)
1017         ? CL_FP_ROUND_TO_NEAREST
1018         : CL_FP_ROUND_TO_ZERO;
1019     const RoundingMode hostRound = get_round();
1020 
1021     // Map device rounding to CTS rounding type
1022     // get_default_rounding_mode supports RNE and RTZ
1023     auto get_rounding = [](const cl_device_fp_config& fpConfig) {
1024         if (fpConfig == CL_FP_ROUND_TO_NEAREST)
1025         {
1026             return kRoundToNearestEven;
1027         }
1028         else if (fpConfig == CL_FP_ROUND_TO_ZERO)
1029         {
1030             return kRoundTowardZero;
1031         }
1032         else
1033         {
1034             assert(false && "Unreachable");
1035         }
1036         return kDefaultRoundingMode;
1037     };
1038 
1039     // Loop through all test cases
1040     for (auto &caseToTest: allTestCase)
1041     {
1042         /*
1043             Cases that have a NULL function pointer
1044             already have their reference results
1045             as they're constant and hard-coded
1046         */
1047         if (caseToTest->printFN == NULL)
1048             continue;
1049 
1050         // Make sure the reference result is empty
1051         assert(caseToTest->_correctBuffer.size() == 0);
1052 
1053         const cl_device_fp_config* fpConfig = &fpConfigSingle;
1054         if (caseToTest->_type == TYPE_HALF
1055             || caseToTest->_type == TYPE_HALF_LIMITS)
1056             fpConfig = &fpConfigHalf;
1057         RoundingMode deviceRound = get_rounding(*fpConfig);
1058 
1059         // Loop through each input
1060         for (auto &params: caseToTest->_genParameters)
1061         {
1062             char refResult[ANALYSIS_BUFFER_SIZE];
1063             // Set CPU rounding mode to match that of the device
1064             set_round(deviceRound, caseToTest->dataType);
1065             // Generate the result
1066             caseToTest->printFN(params, refResult, ARRAY_SIZE(refResult));
1067             // Restore the original CPU rounding mode
1068             set_round(hostRound, kfloat);
1069             // Save the reference result
1070             caseToTest->_correctBuffer.push_back(refResult);
1071         }
1072     }
1073 }
1074