scuffed-code/icu4c/source/test/perf/howExpensiveIs/sieve.cpp
Steven R. Loomis 9077d5dc25 ICU-9449 Merge in decimal format performance improvements from branch.
Improvements to 'howExpensiveIs' benchmark test.
Use internal digitlist in Formattable (save mallocs).
Enable fastpath by default.
Enable internal API "parse all input", returning an error if all input was not consumed.

X-SVN-Rev: 32397
2012-09-17 19:03:01 +00:00

214 lines
4.7 KiB
C++

/*
**********************************************************************
* Copyright (c) 2011-2012,International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
#include "unicode/utimer.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "sieve.h"
/* prime number sieve */
U_CAPI double uprv_calcSieveTime() {
#if 1
#define SIEVE_SIZE U_LOTS_OF_TIMES /* standardized size */
#else
#define SIEVE_SIZE <something_smaller>
#endif
#define SIEVE_PRINT 0
char sieve[SIEVE_SIZE];
UTimer a,b;
int i,k;
utimer_getTime(&a);
for(int j=0;j<SIEVE_SIZE;j++) {
sieve[j]=1;
}
sieve[0]=0;
utimer_getTime(&b);
#if SIEVE_PRINT
printf("init %d: %.9f\n", SIEVE_SIZE,utimer_getDeltaSeconds(&a,&b));
#endif
utimer_getTime(&a);
for(i=2;i<SIEVE_SIZE/2;i++) {
for(k=i*2;k<SIEVE_SIZE;k+=i) {
sieve[k]=0;
}
}
utimer_getTime(&b);
#if SIEVE_PRINT
printf("sieve %d: %.9f\n", SIEVE_SIZE,utimer_getDeltaSeconds(&a,&b));
if(SIEVE_PRINT>0) {
k=0;
for(i=2;i<SIEVE_SIZE && k<SIEVE_PRINT;i++) {
if(sieve[i]) {
printf("%d ", i);
k++;
}
}
puts("");
}
{
k=0;
for(i=0;i<SIEVE_SIZE;i++) {
if(sieve[i]) k++;
}
printf("Primes: %d\n", k);
}
#endif
return utimer_getDeltaSeconds(&a,&b);
}
static int comdoub(const void *aa, const void *bb)
{
const double *a = (const double*)aa;
const double *b = (const double*)bb;
return (*a==*b)?0:((*a<*b)?-1:1);
}
double midpoint(double *times, double i, int n) {
double fl = floor(i);
double ce = ceil(i);
if(ce>=n) ce=n;
if(fl==ce) {
return times[(int)fl];
} else {
return (times[(int)fl]+times[(int)ce])/2;
}
}
double medianof(double *times, int n, int type) {
switch(type) {
case 1:
return midpoint(times,n/4,n);
case 2:
return midpoint(times,n/2,n);
case 3:
return midpoint(times,(n/2)+(n/4),n);
}
return -1;
}
double qs(double *times, int n, double *q1, double *q2, double *q3) {
*q1 = medianof(times,n,1);
*q2 = medianof(times,n,2);
*q3 = medianof(times,n,3);
return *q3-*q1;
}
U_CAPI double uprv_getMeanTime(double *times, uint32_t *timeCount, double *marginOfError) {
double q1,q2,q3;
int n = *timeCount;
/* calculate medians */
qsort(times,n,sizeof(times[0]),comdoub);
double iqr = qs(times,n,&q1,&q2,&q3);
double rangeMin= (q1-(1.5*iqr));
double rangeMax = (q3+(1.5*iqr));
/* Throw out outliers */
int newN = n;
#if U_DEBUG
printf("iqr: %.9f, q1=%.9f, q2=%.9f, q3=%.9f, max=%.9f, n=%d\n", iqr,q1,q2,q3,(double)-1, n);
#endif
for(int i=0;i<newN;i++) {
if(times[i]<rangeMin || times[i]>rangeMax) {
#if U_DEBUG
printf("Removing outlier: %.9f outside [%.9f:%.9f]\n", times[i], rangeMin, rangeMax);
#endif
times[i--] = times[--newN]; // bring down a new value
}
}
#if U_DEBUG
UBool didRemove = false;
#endif
/* if we removed any outliers, recalculate iqr */
if(newN<n) {
#if U_DEBUG
didRemove = true;
printf("removed %d outlier(s), recalculating IQR..\n", n-newN);
#endif
n = newN;
*timeCount = n;
qsort(times,n,sizeof(times[0]),comdoub);
double iqr = qs(times,n,&q1,&q2,&q3);
rangeMin= (q1-(1.5*iqr));
rangeMax = (q3+(1.5*iqr));
}
/* calculate min/max and mean */
double minTime = times[0];
double maxTime = times[0];
double meanTime = times[0];
for(int i=1;i<n;i++) {
if(minTime>times[i]) minTime=times[i];
if(maxTime<times[i]) maxTime=times[i];
meanTime+=times[i];
}
meanTime /= n;
/* caculate standard deviation */
double sd = 0;
for(int i=0;i<n;i++) {
#if U_DEBUG
if(didRemove) {
printf("recalc %d/%d: %.9f\n", i, n, times[i]);
}
#endif
sd += (times[i]-meanTime)*(times[i]-meanTime);
}
sd = sqrt(sd/((double)n-1.0));
#if U_DEBUG
printf("sd: %.9f, mean: %.9f\n", sd, meanTime);
printf("min: %.9f, q1=%.9f, q2=%.9f, q3=%.9f, max=%.9f, n=%d\n", minTime,q1,q2,q3,maxTime, n);
printf("iqr/sd = %.9f\n", iqr/sd);
#endif
/* 1.960 = z sub 0.025 */
*marginOfError = 1.960 * (sd/sqrt((double)n));
/*printf("Margin of Error = %.4f (95%% confidence)\n", me);*/
return meanTime;
}
UBool calcSieveTime = FALSE;
double meanSieveTime = 0.0;
double meanSieveME = 0.0;
U_CAPI double uprv_getSieveTime(double *marginOfError) {
if(calcSieveTime==FALSE) {
#define SAMPLES 50
uint32_t samples = SAMPLES;
double times[SAMPLES];
for(int i=0;i<SAMPLES;i++) {
times[i] = uprv_calcSieveTime();
#if U_DEBUG
printf("sieve: %d/%d: %.9f\n", i,SAMPLES, times[i]);
#endif
}
meanSieveTime = uprv_getMeanTime(times, &samples,&meanSieveME);
calcSieveTime=TRUE;
}
if(marginOfError!=NULL) {
*marginOfError = meanSieveME;
}
return meanSieveTime;
}