home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 January / macformat-033.iso / mac / Shareware City / Developers / VideoToolbox / Demos / TimeCPU.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-13  |  25.2 KB  |  1,022 lines  |  [TEXT/CWIE]

  1. /*
  2. TimeCPU.c
  3. Denis G. Pelli, 1991-1995
  4. This routine uses Timer.c to measure the timing of basic CPU
  5. operations and several random number generators. The Fixed data type is
  6. predefined by Apple as a long (i.e. 32 bits) with an assumed decimal point in
  7. the middle.
  8.  
  9. The access to video memory overwrites a small part of your main screen, the
  10. first 40 bytes. This will be in the upper left hand corner of your display, and
  11. will usually be barely noticeable. I like seeing that, as it confirms that the
  12. program really is accessing the video memory.
  13.  
  14. This program requests a memory partition of 900K. It will run in less, but will
  15. then do fewer iterations.
  16.  
  17. The timing seems to be very accurate. It ought to be as accurate as the
  18. frequency of the oscillator in the VIA chip. However, I haven't checked the
  19. timing against a known standard.
  20.  
  21. HISTORY:
  22. 1/91    dgp    wrote it
  23. 2/16/91    dgp    added fpu test, to fail gracefully if compiled with FPU support, but FPU
  24.             is not present.
  25. 3/4/91    dgp    added timing of random number generators
  26. 8/6/91    dgp    added timing of RandFill.
  27. 8/24/91    dgp    Made compatible with THINK C 5.0.
  28. 1/25/92    dgp    Calibrate and correct for the slowness of TimeIt(). 
  29.             Measure and subtract off the small loop overhead.
  30.             Identify machine and compiler.
  31.             Automatically append results to TimeCPU.data file.
  32. 1/29/92    dgp    Time move from memory to video memory, for showing movies.
  33.             Added transcendental functions since Radius 8881 init and System 7.01
  34.             speed them up dramatically and the Quadra is reputed to
  35.             do them very slowly.
  36. 1/30/92    dgp    Access video memory only in 32-bit mode, to avoid crashes.
  37. 8/19/92    dgp    time the 68881 instructions _sin, _sqrt, _exp, _log
  38.             Use new Timer.c instead of old TimeIt.c
  39. 8/28/92    dgp    updated to use new reentrant Timer.c
  40. 11/18/92 dgp renamed output file to “TimeCPU results”
  41. 1/11/93    dgp    check for presence of 68020. Put Gestalt tests in main, without
  42.             any fpu usage, since program was crashing when fpu was absent
  43.             before getting to the fpu test. (Supposedly that was fixed
  44.             in THINK C 5. Oh well.)
  45. 2/7/93    dgp    added timing of SetPixelsQuickly().
  46. 7/9/93    dgp check for 32-bit addressing capability.
  47. 3/13/94    dgp    added timing of short arithmetic, and put conditionals around each section.
  48. 6/1/94    dgp    added timing of BlockMoveData().
  49. 6/14/94    dgp    can32 is now computed by calling TrapAvailable(_SwapMMUMode), which 
  50.             returns the correct answer even on Macs with dirty ROMs.
  51. 7/31/94    dgp made compatible with new SANE.h in Universal Headers.
  52. 9/5/94 dgp removed assumption in printf's that int==short.
  53. 10/2/94    dgp deleted RandomX() since it's part of SANE, which doesn't exist on PowerPC,
  54.             and, in any event, was uselessly slow on 68k machines. Tidied up the
  55.             printout for readability even for computers as fast as the PowerPC.
  56. 4/9/95 dgp added a few tests relevant to nrand(). Increased n. Polished the printout a bit.
  57. 4/11/95 dgp changed declaration of bufferHandle from void ** to Handle, for compatibility with
  58. old pre-universal apple headers.
  59. 5/23/95 dgp Apple changed the prototype in the header file from SwapMMUMode(char *) to 
  60.             SwapMMUMode(signed char *). To retain compatibility with both old and new
  61.             headers, I cast the argument (void *).
  62. */
  63. #include "VideoToolbox.h"
  64. #ifndef __TRAPS__
  65.     #include <Traps.h>        // _SwapMMUMode
  66. #endif
  67. //#include <Menus.h>    // DrawMenuBar
  68. void ShrinkRect(Rect *r,int hDivisor,int vDivisor);
  69. void ExpandRect(Rect *r,double hMag,double vMag);
  70. void ExpandAndOffsetRect(Rect *r,double hMag,double vMag,double hOffset,double vOffset);
  71.  
  72. void TimeCPU(void);
  73.  
  74. void main(void)
  75. {
  76.     long value;
  77.  
  78.     Require(gestaltOriginalQD);
  79.     Gestalt(gestaltTimeMgrVersion,&value);
  80.     if(value<gestaltRevisedTimeMgr)
  81.         PrintfExit("Sorry, your System is too old; I need at least \n"
  82.             "the Revised Time Manager.\n");
  83.     TimeCPU();
  84. }
  85.  
  86. void TimeCPU(void)
  87. {
  88.     long n,quickDraw;
  89.     short i;
  90.     register long *paL,*pbL,iL,jL,kL,mL;
  91.     double x,y,z;
  92.     Fixed xF,yF,zF;
  93.     Handle bufferHandle;
  94.     void *buffer,*buffer2;
  95.     char Buffer[32];
  96.     FILE *o[2],*dataFile;
  97.     GDHandle device;
  98.     long startTicks,finalTicks;
  99.     double s,s0,overhead;
  100.     Timer *timer;
  101.     Boolean can32;
  102.     OSErr osErr;
  103.  
  104.     MaximizeConsoleHeight();
  105.     /* INITIALIZE QuickDraw */
  106.     #if (THINK_C || THINK_CPLUS || SYMANTEC_C)
  107.         console_options.ncols = 90;
  108.     #elif __MWERKS__
  109.         SIOUXSettings.columns=90;
  110.     #elif
  111.         InitGraf(&qd.thePort);
  112.         InitFonts();
  113.         InitWindows();
  114.         InitCursor();
  115.     #endif
  116.     printf("Welcome to TimeCPU.\n");
  117.     assert(StackSpace()>4000);
  118.     can32=TrapAvailable(_SwapMMUMode);
  119.     timer=NewTimer();
  120.     Delay(1,&startTicks);
  121.     StartTimer(timer);
  122.     Delay(60,&finalTicks);
  123.     s=StopTimerSecs(timer);
  124.     printf("The VBL tick frequency is %.2f Hz.\n",(finalTicks-startTicks)/s);
  125.     o[0]=stdout;
  126.     o[1]=dataFile=fopen("TimeCPU results","a");    /* Append to data file */
  127.     if(dataFile!=NULL){
  128.         printf("Key results will be appended to “TimeCPU results” file.\n\n");
  129.         SetFileInfo("TimeCPU results",'TEXT','ttxt');
  130.     }
  131.     else printf("Could not open “TimeCPU results” file\n\n");
  132.     ffprintf(o,"\n%s\n",BreakLines(IdentifyMachine(),80));
  133.     ffprintf(o,"%s\n\n",BreakLines(IdentifyCompiler(),80));
  134.     ffprintf(o,"      Time    Operation\n");
  135.     srand(clock());
  136.     y=sqrt(2.0);
  137.     z=sqrt(3.0);
  138.     kL=y*1000.;
  139.     mL=z*10.;
  140.     RandFill(Buffer,sizeof(Buffer));
  141.         
  142.     n=100000;    // REDUCE THIS NUMBER TO SPEED UP THE TESTING, BUT REDUCE PRECISION.
  143.     overhead=0.0;
  144.     StartTimer(timer);
  145.     for(iL=n/10;iL>0;iL--) ;
  146.     overhead=StopTimerSecs(timer)/n-overhead;    // the loop overhead per operation
  147.  
  148.     Gestalt(gestaltQuickdrawVersion,&quickDraw);
  149.     if(quickDraw>=gestalt8BitQD){
  150.         unsigned long row[256],row2[256];
  151.         int rowLength=256,clutSize;
  152.         
  153.         assert(StackSpace()>4000);
  154.         n/=100;
  155.         device=GetMainDevice();
  156.         clutSize=GDClutSize(device);
  157.         for(i=0;i<rowLength;i++)row[i]=nrand(clutSize);
  158.         StartTimer(timer);
  159.         for(iL=n;iL>0;iL--){
  160.             SetDevicePixelsQuickly(device,0,0,row,rowLength);
  161.         }
  162.         // NOTE: if you single step through this in the Debugger
  163.         // you'll get an apparent read-back error if the Debugger
  164.         // redraws the Menu bar between writing and reading the pixels.
  165.         s=StopTimerSecs(timer)/n-overhead;
  166.         GetDevicePixelsQuickly(device,0,0,row2,rowLength);
  167.         ffprintf(o,"%11.3f ms    SetPixelsQuickly(,,,,%d);// %d-bit pixels, %.3f MB/s\n",s*1e3
  168.             ,(int)rowLength,(int)(**(**device).gdPMap).pixelSize
  169.             ,(double)rowLength*(**(**device).gdPMap).pixelSize/8/1024/1024/s);
  170.  
  171.         StartTimer(timer);
  172.         for(iL=n;iL>0;iL--){
  173.             GetDevicePixelsQuickly(device,0,0,row,rowLength);
  174.         }
  175.         s=StopTimerSecs(timer)/n-overhead;
  176.         ffprintf(o,"%11.3f ms    GetPixelsQuickly(,,,,%d);// %d-bit pixels, %.3f MB/s\n",s*1e3
  177.             ,(int)rowLength,(int)(**(**device).gdPMap).pixelSize
  178.             ,(double)rowLength*(**(**device).gdPMap).pixelSize/8/1024/1024/s);
  179.         n*=100;
  180.  
  181.         for(i=0;i<1;i++)if(row2[i]!=row[i])printf("Pixel %d: wrote %ld != read %ld\n"
  182.             ,(int)i,row[i],row2[i]);
  183.  
  184.     }
  185.  
  186.     if(quickDraw>=gestalt32BitQD){
  187.         GWorldPtr aWorld,bWorld;
  188.         Rect r;
  189.         int error,pixelSize;
  190.         double pixels;
  191.  
  192.         n=2;
  193.         SetRect(&r,0,0,100,100);
  194.         pixels=(double)(r.right-r.left)*(r.bottom-r.top);
  195.         error=NewGWorld(&aWorld,8,&r,NULL,NULL,0);
  196.         if(!error)error=NewGWorld(&bWorld,8,&r,NULL,NULL,0);
  197.         if(!error){
  198.             LockPixels(GetGWorldPixMap(aWorld));
  199.             LockPixels(GetGWorldPixMap(bWorld));
  200.             StartTimer(timer);
  201.             for(iL=n;iL>0;iL--){
  202.                 CopyWindows(aWorld,bWorld,&aWorld->portRect,&aWorld->portRect,srcCopy,NULL);
  203.             }
  204.             s=StopTimerSecs(timer)/n-overhead;
  205.             pixelSize=(**GetGWorldPixMap(aWorld)).pixelSize;
  206.             ffprintf(o,"%11.3f ms    CopyWindows(,,,,srcCopy,);// %dx%dx%d, %.3f MB/s\n"
  207.                 ,s*1e3,(int)r.right,(int)r.bottom
  208.                 ,pixelSize,pixels*pixelSize/8/1024/1024/s);
  209.         }
  210.         DisposeGWorld(aWorld);
  211.         DisposeGWorld(bWorld);
  212.         SetRect(&r,0,0,100,100);
  213.         pixels=(double)(r.right-r.left)*(r.bottom-r.top);
  214.         error=NewGWorld(&bWorld,8,&r,NULL,NULL,0);
  215.         ShrinkRect(&r,20,1);
  216.         if(!error)error=NewGWorld(&aWorld,8,&r,NULL,NULL,0);
  217.         if(!error){
  218.             LockPixels(GetGWorldPixMap(aWorld));
  219.             LockPixels(GetGWorldPixMap(bWorld));
  220.             StartTimer(timer);
  221.             for(iL=n;iL>0;iL--){
  222.                 CopyWindows(aWorld,bWorld,&aWorld->portRect,&bWorld->portRect,srcCopy,NULL);
  223.             }
  224.             s=StopTimerSecs(timer)/n-overhead;
  225.             pixelSize=(**GetGWorldPixMap(aWorld)).pixelSize;
  226.             ffprintf(o,"%11.3f ms    CopyWindows(,,,,srcCopy,);// %dx%d to %dx%dx%d, %.3f MB/s\n"
  227.                 ,s*1e3
  228.                 ,(int)aWorld->portRect.right,(int)aWorld->portRect.bottom
  229.                 ,(int)bWorld->portRect.right,(int)bWorld->portRect.bottom
  230.                 ,pixelSize,pixels*pixelSize/8/1024/1024/s);
  231.         }
  232.         DisposeGWorld(aWorld);
  233.         DisposeGWorld(bWorld);
  234.         SetRect(&r,0,0,100,100);
  235.         pixels=(double)(r.right-r.left)*(r.bottom-r.top);
  236.         error=NewGWorld(&bWorld,8,&r,NULL,NULL,0);
  237.         ShrinkRect(&r,1,20);
  238.         if(!error)error=NewGWorld(&aWorld,8,&r,NULL,NULL,0);
  239.         if(!error){
  240.             LockPixels(GetGWorldPixMap(aWorld));
  241.             LockPixels(GetGWorldPixMap(bWorld));
  242.             StartTimer(timer);
  243.             for(iL=n;iL>0;iL--){
  244.                 CopyWindows(aWorld,bWorld,&aWorld->portRect,&bWorld->portRect,srcCopy,NULL);
  245.             }
  246.             s=StopTimerSecs(timer)/n-overhead;
  247.             pixelSize=(**GetGWorldPixMap(aWorld)).pixelSize;
  248.             r=aWorld->portRect;
  249.             ffprintf(o,"%11.3f ms    CopyWindows(,,,,srcCopy,);// %dx%d to %dx%dx%d, %.3f MB/s\n"
  250.                 ,s*1e3
  251.                 ,(int)aWorld->portRect.right,(int)aWorld->portRect.bottom
  252.                 ,(int)bWorld->portRect.right,(int)bWorld->portRect.bottom
  253.                 ,pixelSize,pixels*pixelSize/8/1024/1024/s);
  254.         }
  255.         DisposeGWorld(aWorld);
  256.         DisposeGWorld(bWorld);
  257.         n=100000;
  258.     }
  259.     if(quickDraw>=gestalt32BitQD){
  260.         GWorldPtr aWorld,bWorld;
  261.         Rect r;
  262.         int error,pixelSize;
  263.         double pixels;
  264.  
  265.         n=2;
  266.         SetRect(&r,0,0,100,100);
  267.         pixels=(double)(r.right-r.left)*(r.bottom-r.top);
  268.         error=NewGWorld(&aWorld,8,&r,NULL,NULL,0);
  269.         if(!error)error=NewGWorld(&bWorld,8,&r,NULL,NULL,0);
  270.         if(!error){
  271.             LockPixels(GetGWorldPixMap(aWorld));
  272.             LockPixels(GetGWorldPixMap(bWorld));
  273.             StartTimer(timer);
  274.             for(iL=n;iL>0;iL--){
  275.                 CopyWindows(aWorld,bWorld,&aWorld->portRect,&aWorld->portRect,srcCopyLiterally,NULL);
  276.             }
  277.             s=StopTimerSecs(timer)/n-overhead;
  278.             pixelSize=(**GetGWorldPixMap(aWorld)).pixelSize;
  279.             ffprintf(o,"%11.3f ms    CopyWindows(,,,,srcCopyLiterally,);// %dx%dx%d, %.3f MB/s\n"
  280.                 ,s*1e3,(int)r.right,(int)r.bottom
  281.                 ,pixelSize,pixels*pixelSize/8/1024/1024/s);
  282.         }
  283.         DisposeGWorld(aWorld);
  284.         DisposeGWorld(bWorld);
  285.         SetRect(&r,0,0,100,100);
  286.         pixels=(double)(r.right-r.left)*(r.bottom-r.top);
  287.         error=NewGWorld(&bWorld,8,&r,NULL,NULL,0);
  288.         ShrinkRect(&r,20,1);
  289.         if(!error)error=NewGWorld(&aWorld,8,&r,NULL,NULL,0);
  290.         if(!error){
  291.             LockPixels(GetGWorldPixMap(aWorld));
  292.             LockPixels(GetGWorldPixMap(bWorld));
  293.             StartTimer(timer);
  294.             for(iL=n;iL>0;iL--){
  295.                 CopyWindows(aWorld,bWorld,&aWorld->portRect,&bWorld->portRect,srcCopyLiterally,NULL);
  296.             }
  297.             s=StopTimerSecs(timer)/n-overhead;
  298.             pixelSize=(**GetGWorldPixMap(aWorld)).pixelSize;
  299.             ffprintf(o,"%11.3f ms    CopyWindows(,,,,srcCopyLiterally,);// %dx%d to %dx%dx%d, %.3f MB/s\n"
  300.                 ,s*1e3
  301.                 ,(int)aWorld->portRect.right,(int)aWorld->portRect.bottom
  302.                 ,(int)bWorld->portRect.right,(int)bWorld->portRect.bottom
  303.                 ,pixelSize,pixels*pixelSize/8/1024/1024/s);
  304.         }
  305.         DisposeGWorld(aWorld);
  306.         DisposeGWorld(bWorld);
  307.         SetRect(&r,0,0,100,100);
  308.         pixels=(double)(r.right-r.left)*(r.bottom-r.top);
  309.         error=NewGWorld(&bWorld,8,&r,NULL,NULL,0);
  310.         ShrinkRect(&r,1,20);
  311.         if(!error)error=NewGWorld(&aWorld,8,&r,NULL,NULL,0);
  312.         if(!error){
  313.             LockPixels(GetGWorldPixMap(aWorld));
  314.             LockPixels(GetGWorldPixMap(bWorld));
  315.             StartTimer(timer);
  316.             for(iL=n;iL>0;iL--){
  317.                 CopyWindows(aWorld,bWorld,&aWorld->portRect,&bWorld->portRect,srcCopyLiterally,NULL);
  318.             }
  319.             s=StopTimerSecs(timer)/n-overhead;
  320.             pixelSize=(**GetGWorldPixMap(aWorld)).pixelSize;
  321.             r=aWorld->portRect;
  322.             ffprintf(o,"%11.3f ms    CopyWindows(,,,,srcCopyLiterally,);// %dx%d to %dx%dx%d, %.3f MB/s\n"
  323.                 ,s*1e3
  324.                 ,(int)aWorld->portRect.right,(int)aWorld->portRect.bottom
  325.                 ,(int)bWorld->portRect.right,(int)bWorld->portRect.bottom
  326.                 ,pixelSize,pixels*pixelSize/8/1024/1024/s);
  327.         }
  328.         DisposeGWorld(aWorld);
  329.         DisposeGWorld(bWorld);
  330.         n=100000;
  331.     }
  332.     
  333.     for(;n>0;){
  334.         bufferHandle=NewHandle(2*sizeof(long)*n);
  335.         if(bufferHandle==NULL)bufferHandle=TempNewHandle(2*sizeof(long)*n,&osErr);
  336.         if(bufferHandle!=NULL)break;
  337.         n/=2;
  338.         printf("Reducing iterations to %ld to fit in available memory.\n",n);
  339.     }
  340.     assert(bufferHandle!=NULL);
  341.     HLockHi(bufferHandle);
  342.     buffer=*bufferHandle;
  343.     buffer2=(long *)buffer+n;
  344.     StartTimer(timer);
  345.     BlockMove(buffer2,buffer,4*n);
  346.     s=StopTimerSecs(timer);
  347.     ffprintf(o,"%11.3f ms    BlockMove(,,%ld);    // %.3f µs/byte or %.1f MB/s\n"
  348.         ,s*1e3,n*4,s*1e6/(n*4),n*4/1024./1024./s);
  349.     StartTimer(timer);
  350.     BlockMoveData(buffer2,buffer,4*n);
  351.     s=StopTimerSecs(timer);
  352.     ffprintf(o,"%11.3f ms    BlockMoveData(,,%ld);    // %.3f µs/byte or %.1f MB/s\n"
  353.         ,s*1e3,n*4,s*1e6/(n*4),n*4/1024./1024./s);
  354.     paL=(long *)buffer;
  355.     pbL=(long *)buffer2;
  356.     StartTimer(timer);
  357.     for(iL=n/10;iL>0;iL--){
  358.         *paL++=*pbL++;
  359.         *paL++=*pbL++;
  360.         *paL++=*pbL++;
  361.         *paL++=*pbL++;
  362.         *paL++=*pbL++;
  363.         *paL++=*pbL++;
  364.         *paL++=*pbL++;
  365.         *paL++=*pbL++;
  366.         *paL++=*pbL++;
  367.         *paL++=*pbL++;
  368.     }
  369.     s=StopTimerSecs(timer)/n-overhead;
  370.     ffprintf(o,"%11.3f µs    *paL++=*pbL++;        // long, memory to memory, %.1f MB/s\n",s*1e6,4e-6/s);
  371.  
  372.     Gestalt(gestaltQuickdrawVersion,&quickDraw);
  373.     if(quickDraw>=gestalt8BitQD){
  374.         device=GetMainDevice();
  375.         if(device!=NULL){
  376.             paL=(long *)(**(**device).gdPMap).baseAddr;
  377.             if(paL!=NULL){
  378.                 signed char mode=true32b;
  379.                 long *pSave=paL;
  380.                 
  381.                 StartTimer(timer);
  382.                 if(can32)SwapMMUMode((void *)&mode);
  383.                 for(iL=n/10;iL>0;iL--) paL-=10;
  384.                 if(can32)SwapMMUMode((void *)&mode);
  385.                 s0=StopTimerSecs(timer)/n-overhead;
  386.                 paL=pSave;
  387.                 pbL=(long *)buffer2;
  388.                 StartTimer(timer);
  389.                 if(can32)SwapMMUMode((void *)&mode);
  390.                 for(iL=n/10;iL>0;iL--){
  391.                     *paL++=*pbL++;
  392.                     *paL++=*pbL++;
  393.                     *paL++=*pbL++;
  394.                     *paL++=*pbL++;
  395.                     *paL++=*pbL++;
  396.                     *paL++=*pbL++;
  397.                     *paL++=*pbL++;
  398.                     *paL++=*pbL++;
  399.                     *paL++=*pbL++;
  400.                     *paL++=*pbL++;
  401.                     paL-=10;
  402.                 }
  403.                 if(can32)SwapMMUMode((void *)&mode);
  404.                 s=StopTimerSecs(timer)/n-overhead;
  405.                 s-=s0;                                    // remove time for the paL-=10;
  406.                 ffprintf(o,"%11.3f µs    *paL++=*pbL++;        // long, memory to video mem. %.1f MB/s\n",s*1e6,4e-6/s);
  407.  
  408.                 if(0){
  409.                     // doesn't always work, alas
  410.                     paL=pSave;
  411.                     pbL=(long *)buffer2;
  412.                     StartTimer(timer);
  413.                     BlockMoveData(pbL,paL,4*n);
  414.                     s=StopTimerSecs(timer)-overhead;
  415.                     ffprintf(o,"%11.3f ms    BlockMoveData(,,%ld);    // i.e. %.3f µs/byte\n"
  416.                         ,s*1e3,n*4,s*1e6/(n*4));
  417.                 }
  418.             }
  419.         }
  420.     }
  421.     DisposeHandle(bufferHandle);
  422.     buffer=buffer2=NULL;
  423.  
  424.     if(1){            // time long arithmetic
  425.         StartTimer(timer);
  426.         for(iL=n/10;iL>0;iL--){
  427.             jL=kL;
  428.             jL=kL;
  429.             jL=kL;
  430.             jL=kL;
  431.             jL=kL;
  432.             jL=kL;
  433.             jL=kL;
  434.             jL=kL;
  435.             jL=kL;
  436.             jL=kL;
  437.         }
  438.         s=StopTimerSecs(timer)/n-overhead;
  439.         ffprintf(o,"%11.3f µs    jL=kL;            // long, register to register\n",s*1e6);
  440.     
  441.         StartTimer(timer);
  442.         for(iL=n/10;iL>0;iL--){
  443.             jL=kL>>1;
  444.             jL=kL>>1;
  445.             jL=kL>>1;
  446.             jL=kL>>1;
  447.             jL=kL>>1;
  448.             jL=kL>>1;
  449.             jL=kL>>1;
  450.             jL=kL>>1;
  451.             jL=kL>>1;
  452.             jL=kL>>1;
  453.         }
  454.         s=StopTimerSecs(timer)/n-overhead;
  455.         ffprintf(o,"%11.3f µs    jL=kL>>1;\n",s*1e6);
  456.     
  457.         StartTimer(timer);
  458.         for(iL=n/10;iL>0;iL--){
  459.             jL=kL+mL;
  460.             jL=kL+mL;
  461.             jL=kL+mL;
  462.             jL=kL+mL;
  463.             jL=kL+mL;
  464.             jL=kL+mL;
  465.             jL=kL+mL;
  466.             jL=kL+mL;
  467.             jL=kL+mL;
  468.             jL=kL+mL;
  469.         }
  470.         s=StopTimerSecs(timer)/n-overhead;
  471.         ffprintf(o,"%11.3f µs    jL=kL+mL;\n",s*1e6);
  472.     
  473.         StartTimer(timer);
  474.         for(iL=n/10;iL>0;iL--){
  475.             jL=kL-mL;
  476.             jL=kL-mL;
  477.             jL=kL-mL;
  478.             jL=kL-mL;
  479.             jL=kL-mL;
  480.             jL=kL-mL;
  481.             jL=kL-mL;
  482.             jL=kL-mL;
  483.             jL=kL-mL;
  484.             jL=kL-mL;
  485.         }
  486.         s=StopTimerSecs(timer)/n-overhead;
  487.         ffprintf(o,"%11.3f µs    jL=kL-mL;\n",s*1e6);
  488.     
  489.         n/=10;            /* all other operations take at least several microseconds */
  490.         StartTimer(timer);
  491.         for(iL=n/10;iL>0;iL--){
  492.             jL=kL*mL;
  493.             jL=kL*mL;
  494.             jL=kL*mL;
  495.             jL=kL*mL;
  496.             jL=kL*mL;
  497.             jL=kL*mL;
  498.             jL=kL*mL;
  499.             jL=kL*mL;
  500.             jL=kL*mL;
  501.             jL=kL*mL;
  502.         }
  503.         s=StopTimerSecs(timer)/n-overhead;
  504.         ffprintf(o,"%11.3f µs    jL=kL*mL;\n",s*1e6);
  505.     
  506.         StartTimer(timer);
  507.         for(iL=n/10;iL>0;iL--){
  508.             jL=kL/mL;
  509.             jL=kL/mL;
  510.             jL=kL/mL;
  511.             jL=kL/mL;
  512.             jL=kL/mL;
  513.             jL=kL/mL;
  514.             jL=kL/mL;
  515.             jL=kL/mL;
  516.             jL=kL/mL;
  517.             jL=kL/mL;
  518.         }
  519.         s=StopTimerSecs(timer)/n-overhead;
  520.         ffprintf(o,"%11.3f µs    jL=kL/mL;\n",s*1e6);
  521.         n*=10;
  522.     }
  523.     if(1){                // time short arithmetic
  524.         register short jH,kH=1234,mH=5678;
  525.         
  526.         StartTimer(timer);
  527.         for(iL=n/10;iL>0;iL--){
  528.             jH=kH;
  529.             jH=kH;
  530.             jH=kH;
  531.             jH=kH;
  532.             jH=kH;
  533.             jH=kH;
  534.             jH=kH;
  535.             jH=kH;
  536.             jH=kH;
  537.             jH=kH;
  538.         }
  539.         s=StopTimerSecs(timer)/n-overhead;
  540.         ffprintf(o,"%11.3f µs    jH=kH;            // short, register to register\n",s*1e6);
  541.     
  542.         StartTimer(timer);
  543.         for(iL=n/10;iL>0;iL--){
  544.             jH=kH>>1;
  545.             jH=kH>>1;
  546.             jH=kH>>1;
  547.             jH=kH>>1;
  548.             jH=kH>>1;
  549.             jH=kH>>1;
  550.             jH=kH>>1;
  551.             jH=kH>>1;
  552.             jH=kH>>1;
  553.             jH=kH>>1;
  554.         }
  555.         s=StopTimerSecs(timer)/n-overhead;
  556.         ffprintf(o,"%11.3f µs    jH=kH>>1;\n",s*1e6);
  557.     
  558.         StartTimer(timer);
  559.         for(iL=n/10;iL>0;iL--){
  560.             jH=kH+mH;
  561.             jH=kH+mH;
  562.             jH=kH+mH;
  563.             jH=kH+mH;
  564.             jH=kH+mH;
  565.             jH=kH+mH;
  566.             jH=kH+mH;
  567.             jH=kH+mH;
  568.             jH=kH+mH;
  569.             jH=kH+mH;
  570.         }
  571.         s=StopTimerSecs(timer)/n-overhead;
  572.         ffprintf(o,"%11.3f µs    jH=kH+mH;\n",s*1e6);
  573.     
  574.         StartTimer(timer);
  575.         for(iL=n/10;iL>0;iL--){
  576.             jH=kH-mH;
  577.             jH=kH-mH;
  578.             jH=kH-mH;
  579.             jH=kH-mH;
  580.             jH=kH-mH;
  581.             jH=kH-mH;
  582.             jH=kH-mH;
  583.             jH=kH-mH;
  584.             jH=kH-mH;
  585.             jH=kH-mH;
  586.         }
  587.         s=StopTimerSecs(timer)/n-overhead;
  588.         ffprintf(o,"%11.3f µs    jH=kH-mH;\n",s*1e6);
  589.     
  590.         n/=10;            /* all other operations take at least several microseconds */
  591.         StartTimer(timer);
  592.         for(iL=n/10;iL>0;iL--){
  593.             jH=kH*mH;
  594.             jH=kH*mH;
  595.             jH=kH*mH;
  596.             jH=kH*mH;
  597.             jH=kH*mH;
  598.             jH=kH*mH;
  599.             jH=kH*mH;
  600.             jH=kH*mH;
  601.             jH=kH*mH;
  602.             jH=kH*mH;
  603.         }
  604.         s=StopTimerSecs(timer)/n-overhead;
  605.         ffprintf(o,"%11.3f µs    jH=kH*mH;\n",s*1e6);
  606.     
  607.         StartTimer(timer);
  608.         for(iL=n/10;iL>0;iL--){
  609.             jH=kH/mH;
  610.             jH=kH/mH;
  611.             jH=kH/mH;
  612.             jH=kH/mH;
  613.             jH=kH/mH;
  614.             jH=kH/mH;
  615.             jH=kH/mH;
  616.             jH=kH/mH;
  617.             jH=kH/mH;
  618.             jH=kH/mH;
  619.         }
  620.         s=StopTimerSecs(timer)/n-overhead;
  621.         ffprintf(o,"%11.3f µs    jH=kH/mH;\n",s*1e6);
  622.         n*=10;
  623.     }
  624.  
  625.     n/=10;            /* all other operations take at least several microseconds */
  626.  
  627.     if(1){        // time double arithmetic
  628.         StartTimer(timer);
  629.         for(iL=n/10;iL>0;iL--){
  630.             x=y;
  631.             x=y;
  632.             x=y;
  633.             x=y;
  634.             x=y;
  635.             x=y;
  636.             x=y;
  637.             x=y;
  638.             x=y;
  639.             x=y;
  640.         }
  641.         s=StopTimerSecs(timer)/n-overhead;
  642.         ffprintf(o,"%11.3f µs    x=y;            // double\n",s*1e6);
  643.     
  644.         StartTimer(timer);
  645.         for(iL=n/10;iL>0;iL--){
  646.             x=y+z;
  647.             x=y+z;
  648.             x=y+z;
  649.             x=y+z;
  650.             x=y+z;
  651.             x=y+z;
  652.             x=y+z;
  653.             x=y+z;
  654.             x=y+z;
  655.             x=y+z;
  656.         }
  657.         s=StopTimerSecs(timer)/n-overhead;
  658.         ffprintf(o,"%11.3f µs    x=y+z;\n",s*1e6);
  659.     
  660.         StartTimer(timer);
  661.         for(iL=n/10;iL>0;iL--){
  662.             x=y-z;
  663.             x=y-z;
  664.             x=y-z;
  665.             x=y-z;
  666.             x=y-z;
  667.             x=y-z;
  668.             x=y-z;
  669.             x=y-z;
  670.             x=y-z;
  671.             x=y-z;
  672.         }
  673.         s=StopTimerSecs(timer)/n-overhead;
  674.         ffprintf(o,"%11.3f µs    x=y-z;\n",s*1e6);
  675.     
  676.         StartTimer(timer);
  677.         for(iL=n/10;iL>0;iL--){
  678.             x=y*z;
  679.             x=y*z;
  680.             x=y*z;
  681.             x=y*z;
  682.             x=y*z;
  683.             x=y*z;
  684.             x=y*z;
  685.             x=y*z;
  686.             x=y*z;
  687.             x=y*z;
  688.         }
  689.         s=StopTimerSecs(timer)/n-overhead;
  690.         ffprintf(o,"%11.3f µs    x=y*z;\n",s*1e6);
  691.     
  692.         StartTimer(timer);
  693.         for(iL=n/10;iL>0;iL--){
  694.             x=y/z;
  695.             x=y/z;
  696.             x=y/z;
  697.             x=y/z;
  698.             x=y/z;
  699.             x=y/z;
  700.             x=y/z;
  701.             x=y/z;
  702.             x=y/z;
  703.             x=y/z;
  704.         }
  705.         s=StopTimerSecs(timer)/n-overhead;
  706.         ffprintf(o,"%11.3f µs    x=y/z;\n",s*1e6);
  707.     }
  708.     
  709.     if(1){                // time transcendental functions
  710.         StartTimer(timer);
  711.         for(iL=n/10;iL>0;iL--){
  712.             x=sin(y);
  713.             x=sin(y);
  714.             x=sin(y);
  715.             x=sin(y);
  716.             x=sin(y);
  717.             x=sin(y);
  718.             x=sin(y);
  719.             x=sin(y);
  720.             x=sin(y);
  721.             x=sin(y);
  722.         }
  723.         s=StopTimerSecs(timer)/n-overhead;
  724.         ffprintf(o,"%11.3f µs    x=sin(y);\n",s*1e6);
  725.     
  726.         StartTimer(timer);
  727.         for(iL=n/10;iL>0;iL--){
  728.             x=sqrt(y);
  729.             x=sqrt(y);
  730.             x=sqrt(y);
  731.             x=sqrt(y);
  732.             x=sqrt(y);
  733.             x=sqrt(y);
  734.             x=sqrt(y);
  735.             x=sqrt(y);
  736.             x=sqrt(y);
  737.             x=sqrt(y);
  738.         }
  739.         s=StopTimerSecs(timer)/n-overhead;
  740.         ffprintf(o,"%11.3f µs    x=sqrt(y);\n",s*1e6);
  741.     
  742.         n/=100;
  743.         StartTimer(timer);
  744.         for(iL=n/10;iL>0;iL--){
  745.             x=log(y);
  746.             x=log(y);
  747.             x=log(y);
  748.             x=log(y);
  749.             x=log(y);
  750.             x=log(y);
  751.             x=log(y);
  752.             x=log(y);
  753.             x=log(y);
  754.             x=log(y);
  755.         }
  756.         s=StopTimerSecs(timer)/n-overhead;
  757.         ffprintf(o,"%11.3f µs    x=log(y);\n",s*1e6);
  758.         StartTimer(timer);
  759.         for(iL=n/10;iL>0;iL--){
  760.             x=exp(y);
  761.             x=exp(y);
  762.             x=exp(y);
  763.             x=exp(y);
  764.             x=exp(y);
  765.             x=exp(y);
  766.             x=exp(y);
  767.             x=exp(y);
  768.             x=exp(y);
  769.             x=exp(y);
  770.         }
  771.         s=StopTimerSecs(timer)/n-overhead;
  772.         ffprintf(o,"%11.3f µs    x=exp(y);\n",s*1e6);
  773.         n*=100;
  774.     
  775.     }
  776.  
  777.     o[1]=NULL;        /* that's all we want to save in “TimeCPU results” */
  778.  
  779.     if(1){                    // time Fixed
  780.         yF=zF=0x12341234;
  781.         StartTimer(timer);
  782.         for(iL=n/10;iL>0;iL--){
  783.             xF=FixMul(yF,zF);
  784.             xF=FixMul(yF,zF);
  785.             xF=FixMul(yF,zF);
  786.             xF=FixMul(yF,zF);
  787.             xF=FixMul(yF,zF);
  788.             xF=FixMul(yF,zF);
  789.             xF=FixMul(yF,zF);
  790.             xF=FixMul(yF,zF);
  791.             xF=FixMul(yF,zF);
  792.             xF=FixMul(yF,zF);
  793.         }
  794.         s=StopTimerSecs(timer)/n-overhead;
  795.         ffprintf(o,"%11.3f µs    xF=FixMul(yF,zF);    // Fixed\n",s*1e6);
  796.     
  797.         yF=(long)(PI*256);
  798.         zF=(long)(1.1*256);
  799.         StartTimer(timer);
  800.         for(iL=n/10;iL>0;iL--){
  801.             xF=FixDiv(yF,zF);
  802.             xF=FixDiv(yF,zF);
  803.             xF=FixDiv(yF,zF);
  804.             xF=FixDiv(yF,zF);
  805.             xF=FixDiv(yF,zF);
  806.             xF=FixDiv(yF,zF);
  807.             xF=FixDiv(yF,zF);
  808.             xF=FixDiv(yF,zF);
  809.             xF=FixDiv(yF,zF);
  810.             xF=FixDiv(yF,zF);
  811.         }
  812.         s=StopTimerSecs(timer)/n-overhead;
  813.         ffprintf(o,"%11.3f µs    xF=FixDiv(yF,zF);\n",s*1e6);
  814.     
  815.         StartTimer(timer);
  816.         for(iL=n/10;iL>0;iL--){
  817.             xF=FixRatio(123,1234);
  818.             xF=FixRatio(123,1234);
  819.             xF=FixRatio(123,1234);
  820.             xF=FixRatio(123,1234);
  821.             xF=FixRatio(123,1234);
  822.             xF=FixRatio(123,1234);
  823.             xF=FixRatio(123,1234);
  824.             xF=FixRatio(123,1234);
  825.             xF=FixRatio(123,1234);
  826.             xF=FixRatio(123,1234);
  827.         }
  828.         s=StopTimerSecs(timer)/n-overhead;
  829.         ffprintf(o,"%11.3f µs    xF=FixRatio(123,1234);\n",s*1e6);
  830.     
  831.         StartTimer(timer);
  832.         for(iL=n/10;iL>0;iL--){
  833.             xF=DoubleToFix(y);
  834.             xF=DoubleToFix(y);
  835.             xF=DoubleToFix(y);
  836.             xF=DoubleToFix(y);
  837.             xF=DoubleToFix(y);
  838.             xF=DoubleToFix(y);
  839.             xF=DoubleToFix(y);
  840.             xF=DoubleToFix(y);
  841.             xF=DoubleToFix(y);
  842.             xF=DoubleToFix(y);
  843.         }
  844.         s=StopTimerSecs(timer)/n-overhead;
  845.         ffprintf(o,"%11.3f µs    xF=DoubleToFix(y);\n",s*1e6);
  846.     
  847.         xF=(long)(PI*256);
  848.         StartTimer(timer);
  849.         for(iL=n/10;iL>0;iL--){
  850.             x=FixToDouble(xF);
  851.             x=FixToDouble(xF);
  852.             x=FixToDouble(xF);
  853.             x=FixToDouble(xF);
  854.             x=FixToDouble(xF);
  855.             x=FixToDouble(xF);
  856.             x=FixToDouble(xF);
  857.             x=FixToDouble(xF);
  858.             x=FixToDouble(xF);
  859.             x=FixToDouble(xF);
  860.             x=FixToDouble(xF);
  861.         }
  862.         s=StopTimerSecs(timer)/n-overhead;
  863.         ffprintf(o,"%11.3f µs    x=FixToDouble(xF);\n",s*1e6);
  864.     }
  865.     
  866.     if(1){                // time rand()
  867.         n*=10;
  868.         for(;n>0;){
  869.             bufferHandle=NewHandle(n);
  870.             if(bufferHandle==NULL)bufferHandle=TempNewHandle(n,&osErr);
  871.             if(bufferHandle!=NULL)break;
  872.             n/=2;
  873.             printf("Reducing iterations to %ld to fit in available memory.\n",n);
  874.         }
  875.         assert(bufferHandle!=NULL);
  876.         HLockHi(bufferHandle);
  877.         buffer=*bufferHandle;
  878.         StartTimer(timer);
  879.         s=StopTimerSecs(timer);
  880.         StartTimer(timer);
  881.         RandFill(buffer,n);
  882.         s=StopTimerSecs(timer) - s;
  883.         DisposeHandle(bufferHandle);
  884.         buffer=NULL;
  885.         ffprintf(o,"%11.3f µs    RandFill(,%ld);    // i.e. %4.1f µs/byte\n"
  886.             ,s*1e6,n,s*1e6/n);
  887.         n/=10;
  888.     
  889.         StartTimer(timer);
  890.         for(iL=n/10;iL>0;iL--){
  891.             i=randU();
  892.             i=randU();
  893.             i=randU();
  894.             i=randU();
  895.             i=randU();
  896.             i=randU();
  897.             i=randU();
  898.             i=randU();
  899.             i=randU();
  900.             i=randU();
  901.         }
  902.         s=StopTimerSecs(timer)/n-overhead;
  903.         ffprintf(o,"%11.3f µs    i=randU();        // i.e. %4.1f µs/byte\n",s*1e6, s*1e6/2.);
  904.     
  905.         StartTimer(timer);
  906.         for(iL=n/10;iL>0;iL--){
  907.             i=rand();
  908.             i=rand();
  909.             i=rand();
  910.             i=rand();
  911.             i=rand();
  912.             i=rand();
  913.             i=rand();
  914.             i=rand();
  915.             i=rand();
  916.             i=rand();
  917.         }
  918.         s=StopTimerSecs(timer)/n-overhead;
  919.         ffprintf(o,"%11.3f µs    i=rand();         // i.e. %4.1f µs/byte\n",s*1e6, s*1e6/1.);
  920.     
  921.         StartTimer(timer);
  922.         for(iL=n/10;iL>0;iL--){
  923.             i=Random();
  924.             i=Random();
  925.             i=Random();
  926.             i=Random();
  927.             i=Random();
  928.             i=Random();
  929.             i=Random();
  930.             i=Random();
  931.             i=Random();
  932.             i=Random();
  933.         }
  934.         s=StopTimerSecs(timer)/n-overhead;
  935.         ffprintf(o,"%11.3f µs    i=Random();\n",s*1e6);
  936.     
  937.         StartTimer(timer);
  938.         for(iL=n/10;iL>0;iL--){
  939.             i=nrand(127);
  940.             i=nrand(127);
  941.             i=nrand(127);
  942.             i=nrand(127);
  943.             i=nrand(127);
  944.             i=nrand(127);
  945.             i=nrand(127);
  946.             i=nrand(127);
  947.             i=nrand(127);
  948.             i=nrand(127);
  949.         }
  950.         s=StopTimerSecs(timer)/n-overhead;
  951.         ffprintf(o,"%11.3f µs    i=nrand(127);\n",s*1e6);
  952.     
  953.         StartTimer(timer);
  954.         for(iL=n/10;iL>0;iL--){
  955.             i=127L*randU()>>16;
  956.             i=127L*randU()>>16;
  957.             i=127L*randU()>>16;
  958.             i=127L*randU()>>16;
  959.             i=127L*randU()>>16;
  960.             i=127L*randU()>>16;
  961.             i=127L*randU()>>16;
  962.             i=127L*randU()>>16;
  963.             i=127L*randU()>>16;
  964.             i=127L*randU()>>16;
  965.         }
  966.         s=StopTimerSecs(timer)/n-overhead;
  967.         ffprintf(o,"%11.3f µs    i=127L*randU()>>16;\n",s*1e6);
  968.     
  969.         StartTimer(timer);
  970.         for(iL=n/10;iL>0;iL--){
  971.             i=127L*rand()>>15;
  972.             i=127L*rand()>>15;
  973.             i=127L*rand()>>15;
  974.             i=127L*rand()>>15;
  975.             i=127L*rand()>>15;
  976.             i=127L*rand()>>15;
  977.             i=127L*rand()>>15;
  978.             i=127L*rand()>>15;
  979.             i=127L*rand()>>15;
  980.             i=127L*rand()>>15;
  981.         }
  982.         s=StopTimerSecs(timer)/n-overhead;
  983.         ffprintf(o,"%11.3f µs    i=127L*rand()>>15;\n",s*1e6);
  984.     
  985.         StartTimer(timer);
  986.         for(iL=n/10;iL>0;iL--){
  987.             i=randU()%(unsigned short)127;
  988.             i=randU()%(unsigned short)127;
  989.             i=randU()%(unsigned short)127;
  990.             i=randU()%(unsigned short)127;
  991.             i=randU()%(unsigned short)127;
  992.             i=randU()%(unsigned short)127;
  993.             i=randU()%(unsigned short)127;
  994.             i=randU()%(unsigned short)127;
  995.             i=randU()%(unsigned short)127;
  996.             i=randU()%(unsigned short)127;
  997.         }
  998.         s=StopTimerSecs(timer)/n-overhead;
  999.         ffprintf(o,"%11.3f µs    i=randU()%%(unsigned short)127;\n",s*1e6);
  1000.     
  1001.         StartTimer(timer);
  1002.         for(iL=n/10;iL>0;iL--){
  1003.             i=rand()%127;
  1004.             i=rand()%127;
  1005.             i=rand()%127;
  1006.             i=rand()%127;
  1007.             i=rand()%127;
  1008.             i=rand()%127;
  1009.             i=rand()%127;
  1010.             i=rand()%127;
  1011.             i=rand()%127;
  1012.             i=rand()%127;
  1013.         }
  1014.         s=StopTimerSecs(timer)/n-overhead;
  1015.         ffprintf(o,"%11.3f µs    i=rand()%%127;\n",s*1e6);
  1016.     }
  1017.     DisposeTimer(timer);
  1018.     fclose(dataFile);    /* close “TimeCPU results” */
  1019.     DrawMenuBar();
  1020. }
  1021.  
  1022.