Home | History | Annotate | Download | only in howExpensiveIs
      1 /*
      2  **********************************************************************
      3  * Copyright (c) 2011-2012,International Business Machines
      4  * Corporation and others.  All Rights Reserved.
      5  **********************************************************************
      6  */
      7 
      8 #include "unicode/utimer.h"
      9 #include <stdio.h>
     10 #include <math.h>
     11 #include <stdlib.h>
     12 
     13 #include "sieve.h"
     14 
     15 /* prime number sieve */
     16 
     17 U_CAPI double uprv_calcSieveTime() {
     18 #if 1
     19 #define SIEVE_SIZE U_LOTS_OF_TIMES /* standardized size */
     20 #else
     21 #define SIEVE_SIZE  <something_smaller>
     22 #endif
     23 
     24 #define SIEVE_PRINT 0
     25 
     26   char sieve[SIEVE_SIZE];
     27   UTimer a,b;
     28   int i,k;
     29 
     30   utimer_getTime(&a);
     31   for(int j=0;j<SIEVE_SIZE;j++) {
     32     sieve[j]=1;
     33   }
     34   sieve[0]=0;
     35   utimer_getTime(&b);
     36 
     37 
     38 #if SIEVE_PRINT
     39   printf("init %d: %.9f\n", SIEVE_SIZE,utimer_getDeltaSeconds(&a,&b));
     40 #endif
     41 
     42   utimer_getTime(&a);
     43   for(i=2;i<SIEVE_SIZE/2;i++) {
     44     for(k=i*2;k<SIEVE_SIZE;k+=i) {
     45       sieve[k]=0;
     46     }
     47   }
     48   utimer_getTime(&b);
     49 #if SIEVE_PRINT
     50   printf("sieve %d: %.9f\n", SIEVE_SIZE,utimer_getDeltaSeconds(&a,&b));
     51 
     52   if(SIEVE_PRINT>0) {
     53     k=0;
     54     for(i=2;i<SIEVE_SIZE && k<SIEVE_PRINT;i++) {
     55       if(sieve[i]) {
     56         printf("%d ", i);
     57         k++;
     58       }
     59     }
     60     puts("");
     61   }
     62   {
     63     k=0;
     64     for(i=0;i<SIEVE_SIZE;i++) {
     65       if(sieve[i]) k++;
     66     }
     67     printf("Primes: %d\n", k);
     68   }
     69 #endif
     70 
     71   return utimer_getDeltaSeconds(&a,&b);
     72 }
     73 static int comdoub(const void *aa, const void *bb)
     74 {
     75   const double *a = (const double*)aa;
     76   const double *b = (const double*)bb;
     77 
     78   return (*a==*b)?0:((*a<*b)?-1:1);
     79 }
     80 
     81 double midpoint(double *times, double i, int n) {
     82   double fl = floor(i);
     83   double ce = ceil(i);
     84   if(ce>=n) ce=n;
     85   if(fl==ce) {
     86     return times[(int)fl];
     87   } else {
     88     return (times[(int)fl]+times[(int)ce])/2;
     89   }
     90 }
     91 
     92 double medianof(double *times, int n, int type) {
     93   switch(type) {
     94   case 1:
     95     return midpoint(times,n/4,n);
     96   case 2:
     97     return midpoint(times,n/2,n);
     98   case 3:
     99     return midpoint(times,(n/2)+(n/4),n);
    100   }
    101   return -1;
    102 }
    103 
    104 double qs(double *times, int n, double *q1, double *q2, double *q3) {
    105   *q1 = medianof(times,n,1);
    106   *q2 = medianof(times,n,2);
    107   *q3 = medianof(times,n,3);
    108   return *q3-*q1;
    109 }
    110 
    111 U_CAPI double uprv_getMeanTime(double *times, uint32_t *timeCount, double *marginOfError) {
    112   double q1,q2,q3;
    113   int n = *timeCount;
    114 
    115   /* calculate medians */
    116   qsort(times,n,sizeof(times[0]),comdoub);
    117   double iqr = qs(times,n,&q1,&q2,&q3);
    118   double rangeMin=  (q1-(1.5*iqr));
    119   double rangeMax =  (q3+(1.5*iqr));
    120 
    121   /* Throw out outliers */
    122   int newN = n;
    123 #if U_DEBUG
    124   printf("iqr: %.9f, q1=%.9f, q2=%.9f, q3=%.9f, max=%.9f, n=%d\n", iqr,q1,q2,q3,(double)-1, n);
    125 #endif
    126   for(int i=0;i<newN;i++) {
    127     if(times[i]<rangeMin || times[i]>rangeMax) {
    128 #if U_DEBUG
    129       printf("Removing outlier: %.9f outside [%.9f:%.9f]\n", times[i], rangeMin, rangeMax);
    130 #endif
    131       times[i--] = times[--newN]; // bring down a new value
    132     }
    133   }
    134 
    135 #if U_DEBUG
    136   UBool didRemove = false;
    137 #endif
    138   /* if we removed any outliers, recalculate iqr */
    139   if(newN<n) {
    140 #if U_DEBUG
    141     didRemove = true;
    142     printf("removed %d outlier(s), recalculating IQR..\n", n-newN);
    143 #endif
    144     n = newN;
    145     *timeCount = n;
    146 
    147     qsort(times,n,sizeof(times[0]),comdoub);
    148     double iqr = qs(times,n,&q1,&q2,&q3);
    149     rangeMin=  (q1-(1.5*iqr));
    150     rangeMax =  (q3+(1.5*iqr));
    151   }
    152 
    153   /* calculate min/max and mean */
    154   double minTime = times[0];
    155   double maxTime = times[0];
    156   double meanTime = times[0];
    157   for(int i=1;i<n;i++) {
    158     if(minTime>times[i]) minTime=times[i];
    159     if(maxTime<times[i]) maxTime=times[i];
    160     meanTime+=times[i];
    161   }
    162   meanTime /= n;
    163 
    164   /* caculate standard deviation */
    165   double sd = 0;
    166   for(int i=0;i<n;i++) {
    167 #if U_DEBUG
    168     if(didRemove) {
    169       printf("recalc %d/%d: %.9f\n", i, n, times[i]);
    170     }
    171 #endif
    172     sd += (times[i]-meanTime)*(times[i]-meanTime);
    173   }
    174   sd = sqrt(sd/((double)n-1.0));
    175 
    176 #if U_DEBUG
    177   printf("sd: %.9f, mean: %.9f\n", sd, meanTime);
    178   printf("min: %.9f, q1=%.9f, q2=%.9f, q3=%.9f, max=%.9f, n=%d\n", minTime,q1,q2,q3,maxTime, n);
    179   printf("iqr/sd = %.9f\n", iqr/sd);
    180 #endif
    181 
    182   /* 1.960 = z sub 0.025 */
    183   *marginOfError = 1.960 * (sd/sqrt((double)n));
    184   /*printf("Margin of Error = %.4f (95%% confidence)\n", me);*/
    185 
    186   return meanTime;
    187 }
    188 
    189 UBool calcSieveTime = FALSE;
    190 double meanSieveTime = 0.0;
    191 double meanSieveME = 0.0;
    192 
    193 U_CAPI double uprv_getSieveTime(double *marginOfError) {
    194   if(calcSieveTime==FALSE) {
    195 #define SAMPLES 50
    196     uint32_t samples = SAMPLES;
    197     double times[SAMPLES];
    198 
    199     for(int i=0;i<SAMPLES;i++) {
    200       times[i] = uprv_calcSieveTime();
    201 #if U_DEBUG
    202       printf("sieve: %d/%d: %.9f\n", i,SAMPLES, times[i]);
    203 #endif
    204     }
    205 
    206     meanSieveTime = uprv_getMeanTime(times, &samples,&meanSieveME);
    207     calcSieveTime=TRUE;
    208   }
    209   if(marginOfError!=NULL) {
    210     *marginOfError = meanSieveME;
    211   }
    212   return meanSieveTime;
    213 }
    214