• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &params: 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