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 ¶ms: 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