]> Creatis software - gdcm.git/blob - Testing/TestInline.cxx
Small exe, for unaware users
[gdcm.git] / Testing / TestInline.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: TestInline.cxx,v $
5   Language:  C++
6   Date:      $Date: 2008/09/19 09:33:17 $
7   Version:   $Revision: 1.21 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18 // This test is expected to 'show' the actual effect on an 'inline' function.
19 // We exchange 2 numbers
20 // - with a macro : this is the quicker (any doubt ?)
21 // - with a function, passing the params by pointer
22 // - with a function, passing the params by reference (exactly same time)
23 // - with an inline function described in the .cxx
24 //                                                   absolutely NO effect ?!?
25 // - with a function, described in the .h
26 //                                                   absolutely NO effect ?!?
27 // - with an inline function, described in the .h
28 //                                                   absolutely NO effect ?!?
29 //
30 // Which CXX_FLAGS, LINKER_FLAGS, ...,  must we set to see the difference?
31
32 #include "gdcmUtil.h"
33 #include <string.h>  // Needed under Suse?!? 
34 #include <stdlib.h> // atoi
35 #if defined(__BORLANDC__)  || defined (_MSC_VER)
36 #include <time.h>
37    #if defined(__BORLANDC__)
38    #include <stdio.h>
39    #endif
40 #define GET_TIME(a) a=clock()
41 #define HOW_LONG(b,a)                             \
42    std::cout  << (double) (b-a)  << std::endl 
43
44 #else
45 #include <sys/times.h>
46 #define GET_TIME(a)  times(&a)
47 #define HOW_LONG(b,a)                             \
48    std::cout                                      \
49         << (long) ((b.tms_utime) - (a.tms_utime)) \
50         << std::endl  
51 #endif
52
53 #include <iostream>
54
55 void        frswap (double &a, double &b);
56 void        fpswap (double *a, double *b);
57 inline void ifrswap(double &a, double &b);
58 inline void ifpswap(double *a, double *b);
59
60 uint8_t     passDirect8(uint8_t a,  uint8_t b);
61 uint8_t     passRef8(uint8_t &a, uint8_t &b);
62 uint8_t     passPtr8(uint8_t *a, uint8_t *b);
63
64 uint16_t     passDirect16(uint16_t a,  uint16_t b);
65 uint16_t     passRef16(uint16_t &a, uint16_t &b);
66 uint16_t     passPtr16(uint16_t *a, uint16_t *b);
67
68 uint32_t     passDirect32(uint32_t a,  uint32_t b);
69 uint32_t     passRef32(uint32_t &a, uint32_t &b);
70 uint32_t     passPtr32(uint32_t *a, uint32_t *b);
71
72 double     passDirect(double a,  double b);
73 double     passRef(double &a, double &b);
74 double     passPtr(double *a, double *b);
75
76 #define           \
77 mswap(a, b)       \
78 {                 \
79    double tmp = a;\
80    a   = b;       \
81    b   = tmp;     \
82 }
83
84 //  ============= no inline
85
86 void frswap(double &a, double &b)
87 {
88    double tmp;
89    tmp = a;
90    a   = b;
91    b   = tmp;
92 }
93
94 void fpswap(double *a, double *b)
95 {
96    double tmp;
97    tmp = *a;
98    *a  = *b;
99    *b  = tmp;
100 }
101
102 //  ============= inline
103
104 inline void ifpswap(double *a, double *b)
105 {
106    double tmp;
107    tmp = *a;
108    *a  = *b;
109    *b  = tmp;
110 }
111
112 inline void ifrswap(double &a, double &b)
113 {
114    double tmp;
115    tmp = a;
116    a   = b;
117    b   = tmp;
118 }
119
120
121 uint32_t passRef32(uint32_t &a, uint32_t &b)
122 {
123    return a + b;
124
125 uint32_t passPtr32(uint32_t *a, uint32_t *b)
126 {
127    return *a + *b;
128
129 uint32_t passDirect32(uint32_t a, uint32_t b)
130 {
131    return a + b;
132
133
134
135 uint16_t passRef16(uint16_t &a, uint16_t &b)
136 {
137    return a + b;
138
139 uint16_t passPtr16(uint16_t *a, uint16_t *b)
140 {
141    return *a + *b;
142
143 uint16_t passDirect16(uint16_t a, uint16_t b)
144 {
145    return a + b;
146
147
148 uint8_t passRef8(uint8_t &a, uint8_t &b)
149 {
150    return a + b;
151
152 uint8_t passPtr8(uint8_t *a, uint8_t *b)
153 {
154    return *a + *b;
155
156 uint8_t passDirect8(uint8_t a, uint8_t b)
157 {
158    return a + b;
159
160
161 float passRefFloat(float &a, float &b)
162 {
163    return a + b;
164
165 float passPtrFloat(float *a, float *b)
166 {
167    return *a + *b;
168
169 float passDirectFloat(float a, float b)
170 {
171    return a + b;
172
173
174 double passRefDouble(double &a, double &b)
175 {
176    return a + b;
177
178 double passPtrDouble(double *a, double *b)
179 {
180    return *a + *b;
181
182 double passDirectDouble(double a, double b)
183 {
184    return a + b;
185
186
187 int TestInline(int argc, char *argv[])
188 {
189
190 #if defined(__BORLANDC__) || defined (_MSC_VER)
191    clock_t tms1, tms2;
192 #else
193    struct tms tms1, tms2;
194 #endif
195
196 // ====================================================================
197
198    std::cout << std::endl << std::endl
199              << "Just to be sure : sizes of native types" << std::endl
200              << "======================================="      
201              << std::endl << std::endl;
202    // just to know, on every proc
203    std::cout << "Size of char      " << sizeof(char)      << std::endl;   
204    std::cout << "Size of short int " << sizeof(short int) << std::endl;
205    std::cout << "Size of int       " << sizeof(int)       << std::endl;
206    std::cout << "Size of long      " << sizeof(long)      << std::endl;
207    std::cout << "Size of float     " << sizeof(float)     << std::endl;
208    std::cout << "Size of double    " << sizeof(double)    << std::endl;
209    std::cout << "Size of bool      " << sizeof(bool)    << std::endl;   
210    std::cout << std::endl;
211    std::cout << "Size of char*     " << sizeof(char*)     << std::endl;
212    std::cout << "Size of short int*" << sizeof(short int*)<< std::endl;
213    std::cout << "Size of int*      " << sizeof(int*)      << std::endl;
214    std::cout << "Size of double*   " << sizeof(double*)   << std::endl;
215    std::cout <<  "-----------------" << std::endl;   
216    
217  // ====================================================================
218     
219    unsigned int nbLoop; 
220    unsigned int i;
221       
222    if (argc > 1)
223       nbLoop = atoi(argv[1]);
224    else
225       nbLoop = 100000000;
226
227    uint8_t  x8 =1, y8 =2;    
228    uint16_t x16=1, y16=2;    
229    uint32_t x32=1, y32=2;    
230    float  fx =1.0f, fy=1.0f;
231    double dx =1.0 , dy=1.0;
232    double a = 1, b = 2;
233    
234  // ====================================================================
235  
236    std::cout << std::endl << std::endl
237              << "Check different ways of passing scalars to a function "<< nbLoop << " times"  << std::endl
238              << "=====================================================" 
239              << std::endl << std::endl; 
240     
241    std::cout << "Pass uint_8 param directly"
242              << std::endl;
243
244    GET_TIME(tms1);    
245    for(i = 0 ; i< nbLoop ; i++)
246    {
247       passDirect8 (x8, y8);  
248    }
249    GET_TIME(tms2);   
250    HOW_LONG(tms2,tms1);
251
252  // ----------------------------------------
253  
254    std::cout << "Pass uint_8 param as ref"
255              << std::endl;
256
257    GET_TIME(tms1);  
258    for(i = 0 ; i< nbLoop ; i++)
259    {
260       passRef8 (x8, y8);  
261    }
262    GET_TIME(tms2);   
263    HOW_LONG(tms2,tms1);
264
265  // ----------------------------------------
266  
267    std::cout << "Pass uint_8 param as ptr"
268              << std::endl;
269
270    GET_TIME(tms1);  
271    for(i = 0 ; i< nbLoop ; i++)
272    {
273       passPtr8 (&x8, &y8);  
274    }
275    GET_TIME(tms2);   
276    HOW_LONG(tms2,tms1);
277
278  // ----------------------------------------
279    std::cout << std::endl;
280    std::cout << "Pass uint_16 param directly"
281              << std::endl;
282
283    GET_TIME(tms1);   
284    for(i = 0 ; i< nbLoop ; i++)
285    {
286       passDirect16 (x16, y16);  
287    }
288    GET_TIME(tms2);   
289    HOW_LONG(tms2,tms1);
290
291  // ----------------------------------------
292  
293    std::cout << "Pass uint_16 param as ref"
294              << std::endl;
295
296    GET_TIME(tms1);   
297    for(i = 0 ; i< nbLoop ; i++)
298    {
299       passRef16 (x16, y16);  
300    }
301    GET_TIME(tms2);   
302    HOW_LONG(tms2,tms1);
303
304  // ----------------------------------------
305  
306    std::cout << "Pass uint_16 param as ptr"
307              << std::endl;
308
309    GET_TIME(tms1);   
310    for(i = 0 ; i< nbLoop ; i++)
311    {
312       passPtr16 (&x16, &y16);  
313    }
314    GET_TIME(tms2);   
315    HOW_LONG(tms2,tms1);
316
317  // ----------------------------------------
318    std::cout << std::endl;
319    std::cout << "Pass uint_32 param directly"
320              << std::endl;
321
322    GET_TIME(tms1);  
323    for(i = 0 ; i< nbLoop ; i++)
324    {
325       passDirect32 (x32, y32);  
326    }
327    GET_TIME(tms2);   
328    HOW_LONG(tms2,tms1);
329
330  // ----------------------------------------
331  
332    std::cout << "Pass uint32_t param as ref"
333              << std::endl;
334
335    GET_TIME(tms1);    
336    for(i = 0 ; i< nbLoop ; i++)
337    {
338       passRef32 (x32, y32 );  
339    }
340    GET_TIME(tms2);   
341    HOW_LONG(tms2,tms1);
342
343  // ----------------------------------------
344  
345    std::cout << "Pass uint_32 param as ptr"
346              << std::endl;
347
348    GET_TIME(tms1);    
349    for(i = 0 ; i< nbLoop ; i++)
350    {
351       passPtr32 (&x32, &y32);  
352    }
353    GET_TIME(tms2);   
354    HOW_LONG(tms2,tms1);
355
356  // ----------------------------------------
357    std::cout << std::endl; 
358    std::cout << "Pass float param directly"
359              << std::endl;
360
361    GET_TIME(tms1);   
362    for(i = 0 ; i< nbLoop ; i++)
363    {
364       passDirectFloat (fx, fy);  
365    }
366    GET_TIME(tms2);   
367    HOW_LONG(tms2,tms1);
368
369  // ----------------------------------------
370  
371    std::cout << "Pass float param as ref"
372              << std::endl;
373
374    GET_TIME(tms1);    
375    for(i = 0 ; i< nbLoop ; i++)
376    {
377       passRefFloat (fx, fy);  
378    }
379    GET_TIME(tms2);   
380    HOW_LONG(tms2,tms1);
381
382  // ----------------------------------------
383  
384    std::cout << "Pass float param as ptr"
385              << std::endl;
386
387    GET_TIME(tms1);   
388    for(i = 0 ; i< nbLoop ; i++)
389    {
390       passPtrFloat (&fx, &fy);  
391    }
392    GET_TIME(tms2);   
393    HOW_LONG(tms2,tms1);
394
395  // ----------------------------------------
396    std::cout << std::endl; 
397    std::cout << "Pass double param directly"
398              << std::endl;
399
400    GET_TIME(tms1);   
401    for(i = 0 ; i< nbLoop ; i++)
402    {
403       passDirectDouble (dx, dy);  
404    }
405    GET_TIME(tms2);   
406    HOW_LONG(tms2,tms1);
407
408  // ----------------------------------------
409  
410    std::cout << "Pass double param as ref"
411              << std::endl;
412
413    GET_TIME(tms1);  
414    for(i = 0 ; i< nbLoop ; i++)
415    {
416       passRefDouble (dx, dy);  
417    }
418    GET_TIME(tms2);   
419    HOW_LONG(tms2,tms1);
420  // ----------------------------------------
421  
422    std::cout << "Pass double param as ptr"
423              << std::endl;
424
425    GET_TIME(tms1);  
426    for(i = 0 ; i< nbLoop ; i++)
427    {
428       passPtrDouble (&dx, &dy);  
429    }
430    GET_TIME(tms2);   
431    HOW_LONG(tms2,tms1);
432
433  
434 // ====================================================================
435   
436    std::cout << std::endl;
437    std::cout << "Exchange 2 scalars " << nbLoop << " times" << std::endl
438              << "==================="
439              << std::endl << std::endl;
440     
441  // ----------------------------------------
442  
443    std::cout << "Direct "<< std::endl;
444
445    GET_TIME(tms1);   
446    for(i = 0 ; i< nbLoop ; i++)
447    {
448       double tmp;
449       tmp=a;
450       a=b;
451       b=tmp;
452    }
453    GET_TIME(tms2);
454    HOW_LONG(tms2,tms1);  
455
456    
457  // ----------------------------------------
458  
459    std::cout << "Use a macro "<< std::endl;
460
461    GET_TIME(tms1);   
462    for(i = 0 ; i< nbLoop ; i++)
463    {
464       mswap (a,b);  
465    }
466    GET_TIME(tms2);   
467    HOW_LONG(tms2,tms1);  
468    
469  // ----------------------------------------
470  
471    std::cout << std::endl;  
472    std::cout << "Use a function, param passed by reference" << std::endl;
473
474    GET_TIME(tms1);    
475    for(i = 0 ; i< nbLoop ; i++)
476    {
477       frswap (a,b);  
478    }
479    GET_TIME(tms2);   
480    HOW_LONG(tms2,tms1); 
481    
482  // ----------------------------------------
483   
484    std::cout << "Use a function, param passed by pointer" << std::endl;
485
486    GET_TIME(tms1);  ;   
487    for(i = 0 ; i< nbLoop ; i++)
488    {
489       fpswap (&a, &b);  
490    }
491    GET_TIME(tms2);   
492    HOW_LONG(tms2,tms1); 
493    
494  // ----------------------------------------
495  
496    std::cout << std::endl;
497  
498    std::cout << "Use inline, .cxx-defined function, param passed by reference" << std::endl;
499
500    GET_TIME(tms1);  
501    for(i = 0 ; i< nbLoop ; i++)
502    {
503       ifrswap (a, b);  
504    }
505    GET_TIME(tms2);   
506    HOW_LONG(tms2,tms1);
507    
508  // ----------------------------------------
509  
510    std::cout << "Use inline, .cxx-defined function, param passed by pointer" << std::endl;
511
512    GET_TIME(tms1);     
513    for(i = 0 ; i< nbLoop ; i++)
514    {
515       ifpswap (&a, &b);  
516    }
517    GET_TIME(tms2);
518    HOW_LONG(tms2,tms1);
519
520  // ----------------------------------------
521
522    std::cout << std::endl;
523      
524 //To check the 2 following cases, we just put the two 'static' functions
525 //hifpswap and  hNoifpswap in gdcmUtil.h
526     
527    std::cout << "Use inline, .h defined, WITH inline keyword, param passed by pointer"
528              << std::endl;
529
530    GDCM_NAME_SPACE::Util util;
531
532    GET_TIME(tms1);    
533    for(i = 0 ; i< nbLoop ; i++)
534    {
535       util.hifpswap (&a, &b);
536    }
537    GET_TIME(tms2);   
538    HOW_LONG(tms2,tms1);
539
540    
541  // ----------------------------------------
542
543    std::cout << "Use inline, .h defined, NO inline keyword, param passed by pointer"
544              << std::endl;
545
546    GET_TIME(tms1);     
547    for(i = 0 ; i< nbLoop ; i++)
548    {
549       util.hNoifpswap (&a, &b);
550    }
551    GET_TIME(tms2);   
552    HOW_LONG(tms2,tms1);
553
554  // ----------------------------------------
555    std::cout << std::endl;
556    
557    std::cout << "Use inline, .h defined, WITH inline keyword, param passed by pointer STATIC function"
558              << std::endl;
559
560    GET_TIME(tms1);   
561    for(i = 0 ; i< nbLoop ; i++)
562    {
563       GDCM_NAME_SPACE::Util::sthifpswap (&a, &b);
564    }
565    GET_TIME(tms2);   
566    HOW_LONG(tms2,tms1);
567    
568  // ----------------------------------------
569
570    std::cout << "Use inline, .h defined, NO inline keyword, param passed by pointer STATIC function"
571              << std::endl;
572
573    GET_TIME(tms1);    
574    for(i = 0 ; i< nbLoop ; i++)
575    {
576       GDCM_NAME_SPACE::Util::sthNoifpswap (&a, &b);
577    }
578    GET_TIME(tms2);   
579    HOW_LONG(tms2,tms1);
580  
581  // ----------------------------------------
582  
583  // Just to point out that playing with pointers doesn't save so much time ...
584  
585   std::cout << "Play with arrays\n================" << std::endl; 
586  
587    nbLoop=1000;
588
589    std::cout << "Copy 2 arrays [i][j]"
590              << std::endl; 
591
592      
593    unsigned short int  z1[128][3118], z2[128][3118];       
594    GET_TIME(tms1);  
595    for(i = 0 ; i< nbLoop ; i++)
596    {
597    unsigned short int *pv1=&z1[0][0], *pv2=&z2[0][0];     
598    for (int j=0;j<3118;j++)
599       for(int i=0; i<128;i++)
600          z2[i][j] = z1[i][j];
601    }      
602    GET_TIME(tms2);   
603    HOW_LONG(tms2,tms1);
604
605    std::cout << "Copy 2 arrays ([i][j], pointer)"
606              << std::endl;
607        
608    GET_TIME(tms1); 
609    for(i = 0 ; i< nbLoop ; i++)
610    {
611    unsigned short int *pv1=&z1[0][0], *pv2=&z2[0][0];
612    for (int j=0;j<3118;j++)
613       for(int i=0; i<128;i++)
614          z2[i][j] = *pv1++;
615    }      
616    GET_TIME(tms2);   
617    HOW_LONG(tms2,tms1);
618    
619    std::cout << "Copy 2 arrays (2 pointers)"    << std::endl;      
620    GET_TIME(tms1);     
621   // unsigned short int  w1[3118*128], w2[3118][128];
622    for(i = 0 ; i< nbLoop ; i++)
623    {
624    unsigned short int *pw1=&z1[0][0], *pw2=&z2[0][0];  
625    for (int j=0;j<3118;j++)
626       for(int i=0; i<128;i++)
627          *pw2++ = *pw1++;
628    }      
629    GET_TIME(tms2);   
630    HOW_LONG(tms2,tms1);  
631
632
633    std::cout << "Copy 2 arrays (memcpy)"    << std::endl;   
634    GET_TIME(tms1);    
635    for(i = 0 ; i< nbLoop ; i++)
636    {
637     unsigned short int *pw1=&z1[0][0], *pw2=&z2[0][0];  
638     memcpy(pw2,pw1,3118*128*sizeof(unsigned short int));
639    }      
640    GET_TIME(tms2);   
641    HOW_LONG(tms2,tms1);   
642    
643    
644          
645    std::cout << "Transpose 2 arrays [i][j]"
646              << std::endl; 
647      
648    unsigned short int  t1[3118][128], t2[128][3118];       
649    GET_TIME(tms1);  
650    for(i = 0 ; i< nbLoop ; i++)
651    {
652    unsigned short int *pv1=&t1[0][0], *pv2=&t2[0][0];     
653    for (int j=0;j<3118;j++)
654       for(int i=0; i<128;i++)
655          t2[i][j] = t1[j][i];
656    }      
657    GET_TIME(tms2);   
658    HOW_LONG(tms2,tms1);
659
660
661    std::cout << "Transpose 2 arrays ([i][j], pointer)"
662              << std::endl;
663      
664    unsigned short int  w1[3118*128], w2[3118][128];      
665    GET_TIME(tms1); 
666    for(i = 0 ; i< nbLoop ; i++)
667    {
668    unsigned short int *pw1=w1, *pw2=&w2[0][0];  
669    for (int j=0;j<3118;j++)
670       for(int i=0; i<128;i++)
671          w2[i][j] = *pw1++;
672    }      
673    GET_TIME(tms2);   
674    HOW_LONG(tms2,tms1);
675    
676       
677    std::cout << "Transpose 2 arrays (2 pointers)"
678              << std::endl; 
679      
680    unsigned short int  v1[3118*128], v2[128*3118];       
681    GET_TIME(tms1);  
682    for(i = 0 ; i< nbLoop ; i++)
683    {
684    unsigned short int *pv1=v1, *pv2=v2;  
685    for (int j=0;j<3118;j++)
686       for(int i=0; i<128;i++)
687          *(pv2+i*128+j) = *pv1++;
688    }      
689    GET_TIME(tms2);   
690    HOW_LONG(tms2,tms1);
691
692
693    
694    //return 1; // will generate an error, 
695              // just to allow us to see the full log in the dashboard
696    return 0;
697 }