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