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
This commit is contained in:
parent
f985dceb39
commit
9077d5dc25
@ -385,19 +385,6 @@
|
||||
# define UCONFIG_NO_SERVICE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def UCONFIG_INTERNAL_DIGITLIST
|
||||
* This switch turns on the fast but binary-incompatible Formattable class with an internal DigitList
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
#ifndef UCONFIG_INTERNAL_DIGITLIST
|
||||
# define UCONFIG_INTERNAL_DIGITLIST 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \def UCONFIG_HAVE_PARSEALLINPUT
|
||||
* This switch turns on the "parse all input" attribute. Binary incompatible.
|
||||
@ -405,7 +392,7 @@
|
||||
* @internal
|
||||
*/
|
||||
#ifndef UCONFIG_HAVE_PARSEALLINPUT
|
||||
# define UCONFIG_HAVE_PARSEALLINPUT 0
|
||||
# define UCONFIG_HAVE_PARSEALLINPUT 1
|
||||
#endif
|
||||
|
||||
|
||||
@ -416,7 +403,7 @@
|
||||
* @internal
|
||||
*/
|
||||
#ifndef UCONFIG_FORMAT_FASTPATHS_49
|
||||
# define UCONFIG_FORMAT_FASTPATHS_49 0
|
||||
# define UCONFIG_FORMAT_FASTPATHS_49 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -187,9 +187,6 @@ U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) {
|
||||
|
||||
U_CDECL_END
|
||||
|
||||
|
||||
//#define FMT_DEBUG
|
||||
|
||||
#ifdef FMT_DEBUG
|
||||
#include <stdio.h>
|
||||
static void _debugout(const char *f, int l, const UnicodeString& s) {
|
||||
@ -1011,9 +1008,12 @@ void DecimalFormat::handleChanged() {
|
||||
|
||||
data.fFastpathStatus = kFastpathNO;
|
||||
|
||||
if (fGroupingSize!=0) {
|
||||
debug("No fastpath: fGroupingSize!=0"); // TODO: revisit, should handle ex. up to 999 if groupingsize is 3.
|
||||
} else if(fGroupingSize2!=0) {
|
||||
if (fGroupingSize!=0 && isGroupingUsed()) {
|
||||
debug("No fastpath: fGroupingSize!=0 and grouping is used");
|
||||
#ifdef FMT_DEBUG
|
||||
printf("groupingsize=%d\n", fGroupingSize);
|
||||
#endif
|
||||
} else if(fGroupingSize2!=0 && isGroupingUsed()) {
|
||||
debug("No fastpath: fGroupingSize2!=0");
|
||||
} else if(fUseExponentialNotation) {
|
||||
debug("No fastpath: fUseExponentialNotation");
|
||||
@ -1109,7 +1109,7 @@ DecimalFormat::_format(int64_t number,
|
||||
// Slide the number to the start of the output str
|
||||
U_ASSERT(destIdx >= 0);
|
||||
int32_t length = MAX_IDX - destIdx -1;
|
||||
int32_t prefixLen = appendAffix(appendTo, number, handler, number<0, TRUE);
|
||||
/*int32_t prefixLen = */ appendAffix(appendTo, number, handler, number<0, TRUE);
|
||||
int32_t maxIntDig = getMaximumIntegerDigits();
|
||||
int32_t destlength = length<=maxIntDig?length:maxIntDig; // dest length pinned to max int digits
|
||||
|
||||
@ -1129,7 +1129,7 @@ DecimalFormat::_format(int64_t number,
|
||||
destlength);
|
||||
handler.addAttribute(kIntegerField, intBegin, appendTo.length());
|
||||
|
||||
int32_t suffixLen = appendAffix(appendTo, number, handler, number<0, FALSE);
|
||||
/*int32_t suffixLen =*/ appendAffix(appendTo, number, handler, number<0, FALSE);
|
||||
|
||||
//outputStr[length]=0;
|
||||
|
||||
@ -1869,11 +1869,7 @@ void DecimalFormat::parse(const UnicodeString& text,
|
||||
// status is used to record whether a number is infinite.
|
||||
UBool status[fgStatusLength];
|
||||
|
||||
#if UCONFIG_INTERNAL_DIGITLIST
|
||||
DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer
|
||||
#else
|
||||
DigitList *digits = new DigitList;
|
||||
#endif
|
||||
if (digits == NULL) {
|
||||
return; // no way to report error from here.
|
||||
}
|
||||
@ -1881,9 +1877,6 @@ void DecimalFormat::parse(const UnicodeString& text,
|
||||
if (fCurrencySignCount > fgCurrencySignCountZero) {
|
||||
if (!parseForCurrency(text, parsePosition, *digits,
|
||||
status, currency)) {
|
||||
#if !UCONFIG_INTERNAL_DIGITLIST
|
||||
delete digits;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -1894,9 +1887,6 @@ void DecimalFormat::parse(const UnicodeString& text,
|
||||
parsePosition, *digits, status, currency)) {
|
||||
debug("!subparse(...) - rewind");
|
||||
parsePosition.setIndex(startIdx);
|
||||
#if !UCONFIG_INTERNAL_DIGITLIST
|
||||
delete digits;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1905,9 +1895,6 @@ void DecimalFormat::parse(const UnicodeString& text,
|
||||
if (status[fgStatusInfinite]) {
|
||||
double inf = uprv_getInfinity();
|
||||
result.setDouble(digits->isPositive() ? inf : -inf);
|
||||
#if !UCONFIG_INTERNAL_DIGITLIST
|
||||
delete digits;
|
||||
#endif
|
||||
// TODO: set the dl to infinity, and let it fall into the code below.
|
||||
}
|
||||
|
||||
@ -2100,7 +2087,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
||||
DBGAPPD(posPrefix);
|
||||
DBGAPPD(posSuffix);
|
||||
debugout(s);
|
||||
printf("currencyParsing=%d, fFormatWidth=%d, text.length=%d negPrefLen=%d\n", currencyParsing, fFormatWidth, text.length(), negPrefix!=NULL?negPrefix->length():-1);
|
||||
printf("currencyParsing=%d, fFormatWidth=%d, isParseIntegerOnly=%c text.length=%d negPrefLen=%d\n", currencyParsing, fFormatWidth, (isParseIntegerOnly())?'Y':'N', text.length(), negPrefix!=NULL?negPrefix->length():-1);
|
||||
#endif
|
||||
|
||||
UBool fastParseOk = false; /* TRUE iff fast parse is OK */
|
||||
@ -2117,7 +2104,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
||||
fFormatWidth==0 &&
|
||||
// (negPrefix!=NULL&&negPrefix->isEmpty()) ||
|
||||
text.length()>0 &&
|
||||
text.length()<20 &&
|
||||
text.length()<32 &&
|
||||
(posPrefix==NULL||posPrefix->isEmpty()) &&
|
||||
(posSuffix==NULL||posSuffix->isEmpty()) &&
|
||||
// (negPrefix==NULL||negPrefix->isEmpty()) &&
|
||||
@ -2131,9 +2118,11 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
||||
UChar32 ch = text.char32At(j);
|
||||
const UnicodeString *decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
|
||||
UChar32 decimalChar = 0;
|
||||
UBool intOnly = FALSE;
|
||||
int32_t decimalCount = decimalString->countChar32(0,3);
|
||||
if(isParseIntegerOnly()) {
|
||||
decimalChar = 0; // not allowed
|
||||
intOnly = TRUE;
|
||||
} else if(decimalCount==1) {
|
||||
decimalChar = decimalString->char32At(0);
|
||||
} else if(decimalCount==0) {
|
||||
@ -2165,6 +2154,8 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
||||
parsedNum.append((char)('.'), err);
|
||||
decimalChar=0; // no more decimals.
|
||||
fastParseHadDecimal=TRUE;
|
||||
} else if(intOnly && !u_isdigit(ch)) {
|
||||
break; // hit a non-integer. (fall through if integer, to slow parse)
|
||||
} else {
|
||||
digitCount=-1; // fail
|
||||
break;
|
||||
@ -2172,7 +2163,9 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
||||
j+=U16_LENGTH(ch);
|
||||
ch = text.char32At(j); // for next
|
||||
}
|
||||
if(j==l && (digitCount>0)) {
|
||||
if(
|
||||
((j==l)||intOnly)
|
||||
&& (digitCount>0)) {
|
||||
#ifdef FMT_DEBUG
|
||||
printf("PP -> %d, good = [%s] digitcount=%d, fGroupingSize=%d fGroupingSize2=%d!\n", j, parsedNum.data(), digitCount, fGroupingSize, fGroupingSize2);
|
||||
#endif
|
||||
@ -2194,6 +2187,15 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
||||
#endif
|
||||
parsedNum.clear();
|
||||
}
|
||||
} else {
|
||||
#ifdef FMT_DEBUG
|
||||
printf("Could not fastpath parse. ");
|
||||
printf("fFormatWidth=%d ", fFormatWidth);
|
||||
printf("text.length()=%d ", text.length());
|
||||
printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix);
|
||||
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if(!fastParseOk
|
||||
@ -2587,7 +2589,13 @@ printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.d
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
digits.set(parsedNum.toStringPiece(), err);
|
||||
// uint32_t bits = (fastParseOk?kFastpathOk:0) |
|
||||
// (fastParseHadDecimal?0:kNoDecimal);
|
||||
//printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits);
|
||||
digits.set(parsedNum.toStringPiece(),
|
||||
err,
|
||||
0//bits
|
||||
);
|
||||
|
||||
if (U_FAILURE(err)) {
|
||||
#ifdef FMT_DEBUG
|
||||
|
@ -732,29 +732,56 @@ DigitList::setInteger(int64_t source)
|
||||
* be acceptable for a public API.
|
||||
*/
|
||||
void
|
||||
DigitList::set(const StringPiece &source, UErrorCode &status) {
|
||||
DigitList::set(const StringPiece &source, UErrorCode &status, uint32_t /*fastpathBits*/) {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Figure out a max number of digits to use during the conversion, and
|
||||
// resize the number up if necessary.
|
||||
int32_t numDigits = source.length();
|
||||
if (numDigits > fContext.digits) {
|
||||
#if 0
|
||||
if(fastpathBits==(kFastpathOk|kNoDecimal)) {
|
||||
int32_t size = source.size();
|
||||
const char *data = source.data();
|
||||
int64_t r = 0;
|
||||
int64_t m = 1;
|
||||
// fast parse
|
||||
while(size>0) {
|
||||
char ch = data[--size];
|
||||
if(ch=='+') {
|
||||
break;
|
||||
} else if(ch=='-') {
|
||||
r = -r;
|
||||
break;
|
||||
} else {
|
||||
int64_t d = ch-'0';
|
||||
//printf("CH[%d]=%c, %d, *=%d\n", size,ch, (int)d, (int)m);
|
||||
r+=(d)*m;
|
||||
m *= 10;
|
||||
}
|
||||
}
|
||||
//printf("R=%d\n", r);
|
||||
set(r);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// Figure out a max number of digits to use during the conversion, and
|
||||
// resize the number up if necessary.
|
||||
int32_t numDigits = source.length();
|
||||
if (numDigits > fContext.digits) {
|
||||
// fContext.digits == fStorage.getCapacity()
|
||||
decNumber *t = fStorage.resize(numDigits, fStorage.getCapacity());
|
||||
if (t == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
fDecNumber = t;
|
||||
fContext.digits = numDigits;
|
||||
}
|
||||
}
|
||||
|
||||
fContext.status = 0;
|
||||
uprv_decNumberFromString(fDecNumber, source.data(), &fContext);
|
||||
if ((fContext.status & DEC_Conversion_syntax) != 0) {
|
||||
fContext.status = 0;
|
||||
uprv_decNumberFromString(fDecNumber, source.data(), &fContext);
|
||||
if ((fContext.status & DEC_Conversion_syntax) != 0) {
|
||||
status = U_DECIMAL_NUMBER_SYNTAX_ERROR;
|
||||
}
|
||||
}
|
||||
internalClear();
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ template class U_I18N_API MaybeStackHeaderAndArray<decNumber, char, DEFAULT_DIGI
|
||||
|
||||
enum EStackMode { kOnStack };
|
||||
|
||||
enum EFastpathBits { kFastpathOk = 1, kNoDecimal = 2 };
|
||||
|
||||
/**
|
||||
* Digit List is actually a Decimal Floating Point number.
|
||||
* The original implementation has been replaced by a thin wrapper onto a
|
||||
@ -262,8 +264,9 @@ public:
|
||||
* Utility routine to set the value of the digit list from a decimal number
|
||||
* string.
|
||||
* @param source The value to be set. The string must be nul-terminated.
|
||||
* @param fastpathBits special flags for fast parsing
|
||||
*/
|
||||
void set(const StringPiece &source, UErrorCode &status);
|
||||
void set(const StringPiece &source, UErrorCode &status, uint32_t fastpathBits = 0);
|
||||
|
||||
/**
|
||||
* Multiply this = this * arg
|
||||
|
@ -360,16 +360,12 @@ void Formattable::dispose()
|
||||
delete fDecimalStr;
|
||||
fDecimalStr = NULL;
|
||||
|
||||
#if UCONFIG_INTERNAL_DIGITLIST
|
||||
FmtStackData *stackData = (FmtStackData*)fStackData;
|
||||
if(fDecimalNum != &(stackData->stackDecimalNum)) {
|
||||
delete fDecimalNum;
|
||||
} else {
|
||||
fDecimalNum->~DigitList(); // destruct, don't deallocate
|
||||
}
|
||||
#else
|
||||
delete fDecimalNum;
|
||||
#endif
|
||||
fDecimalNum = NULL;
|
||||
}
|
||||
|
||||
@ -748,7 +744,6 @@ StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
|
||||
}
|
||||
|
||||
|
||||
#if UCONFIG_INTERNAL_DIGITLIST
|
||||
DigitList *
|
||||
Formattable::getInternalDigitList() {
|
||||
FmtStackData *stackData = (FmtStackData*)fStackData;
|
||||
@ -760,7 +755,6 @@ Formattable::getInternalDigitList() {
|
||||
}
|
||||
return fDecimalNum;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ---------------------------------------
|
||||
void
|
||||
|
@ -605,13 +605,10 @@ public:
|
||||
*/
|
||||
DigitList *getDigitList() const { return fDecimalNum;}
|
||||
|
||||
#if UCONFIG_INTERNAL_DIGITLIST
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
DigitList *getInternalDigitList();
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Adopt, and set value from, a DigitList
|
||||
@ -652,9 +649,7 @@ private:
|
||||
|
||||
DigitList *fDecimalNum;
|
||||
|
||||
#if UCONFIG_INTERNAL_DIGITLIST
|
||||
char fStackData[128]; // must be big enough for DigitList
|
||||
#endif
|
||||
|
||||
Type fType;
|
||||
UnicodeString fBogus; // Bogus string when it's needed.
|
||||
|
@ -1,5 +1,5 @@
|
||||
## Makefile.in for ICU - samples/date
|
||||
## Copyright (c) 1999-2011, International Business Machines Corporation and
|
||||
## Copyright (c) 1999-2012, International Business Machines Corporation and
|
||||
## others. All Rights Reserved.
|
||||
|
||||
## Source directory information
|
||||
@ -56,7 +56,7 @@ distclean-local: clean-local
|
||||
$(RMV) Makefile
|
||||
|
||||
check-local:
|
||||
-$(INVOKE) ./$(TARGET)
|
||||
-$(INVOKE) ./$(TARGET) $(ICUDATE_OPTS)
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
|
@ -1,5 +1,5 @@
|
||||
## Makefile.in for ICU - test/perf/howExpensiveIs
|
||||
## Copyright (c) 2001-2011, International Business Machines Corporation and
|
||||
## Copyright (c) 2001-2012, International Business Machines Corporation and
|
||||
## others. All Rights Reserved.
|
||||
|
||||
## Source directory information
|
||||
|
@ -5,11 +5,23 @@
|
||||
**********************************************************************
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sieve.h"
|
||||
#include "unicode/utimer.h"
|
||||
#include "udbgutil.h"
|
||||
#include "unicode/ustring.h"
|
||||
#include "unicode/decimfmt.h"
|
||||
#include "unicode/udat.h"
|
||||
|
||||
#if U_PLATFORM_IMPLEMENTS_POSIX
|
||||
#include <unistd.h>
|
||||
|
||||
static void usage(const char *prog) {
|
||||
fprintf(stderr, "Usage: %s [ -f outfile.xml ] [ -t 'TestName' ]\n", prog);
|
||||
}
|
||||
#endif
|
||||
|
||||
void runTests(void);
|
||||
|
||||
#ifndef ITERATIONS
|
||||
@ -19,8 +31,24 @@ void runTests(void);
|
||||
|
||||
FILE *out = NULL;
|
||||
UErrorCode setupStatus = U_ZERO_ERROR;
|
||||
const char *outName = NULL;
|
||||
int listmode = 0;
|
||||
const char *testName = NULL;
|
||||
const char *progname = NULL;
|
||||
int errflg = 0;
|
||||
int testhit = 0;
|
||||
|
||||
int main(int argc, const char* argv[]){
|
||||
int testMatch(const char *aName) {
|
||||
if(testName==NULL) return 1;
|
||||
int len = strlen(testName);
|
||||
if(testName[len-1]=='*') {
|
||||
return strncmp(testName,aName,len-1);
|
||||
} else {
|
||||
return strcmp(testName,aName);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char * const * argv){
|
||||
#if U_DEBUG
|
||||
fprintf(stderr,"%s: warning: U_DEBUG is on.\n", argv[0]);
|
||||
#endif
|
||||
@ -32,20 +60,67 @@ int main(int argc, const char* argv[]){
|
||||
}
|
||||
#endif
|
||||
|
||||
#if U_PLATFORM_IMPLEMENTS_POSIX
|
||||
int c;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
while((c=getopt(argc,argv,"lf:t:")) != EOF) {
|
||||
switch(c) {
|
||||
case 'f':
|
||||
outName = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
listmode++;
|
||||
break;
|
||||
case 't':
|
||||
testName = optarg;
|
||||
break;
|
||||
case '?':
|
||||
errflg++;
|
||||
}
|
||||
if(errflg) {
|
||||
usage(progname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* for ( ; optind < argc; optind++) { ... argv[optind] } */
|
||||
#else
|
||||
if(argc==2) {
|
||||
out=fopen(argv[1],"w");
|
||||
outName = argv[1];
|
||||
} else if(argc>2) {
|
||||
fprintf(stderr, "Err: usage: %s [ output-file.xml ]\n", argv[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(listmode && outName != NULL ) {
|
||||
fprintf(stderr, "Warning: no output when list mode\n");
|
||||
outName=NULL;
|
||||
}
|
||||
|
||||
if(outName != NULL) {
|
||||
|
||||
|
||||
out=fopen(outName,"w");
|
||||
if(out==NULL) {
|
||||
fprintf(stderr,"Err: can't open %s for writing.\n", argv[1]);
|
||||
fprintf(stderr,"Err: can't open %s for writing.\n", outName);
|
||||
return 1;
|
||||
} else {
|
||||
fprintf(stderr, "# writing results to %s\n", outName);
|
||||
}
|
||||
fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
|
||||
fprintf(out, "<tests icu=\"%s\">\n", U_ICU_VERSION);
|
||||
fprintf(out, "<!-- %s -->\n", U_COPYRIGHT_STRING);
|
||||
} else if(argc>2) {
|
||||
fprintf(stderr, "Err: usage: %s [ output-file.xml ]\n", argv[0]);
|
||||
} else {
|
||||
fprintf(stderr, "# (no output)\n");
|
||||
}
|
||||
|
||||
if(listmode && testName!=NULL) {
|
||||
fprintf(stderr, "ERR: no -l mode when specific test with -t\n");
|
||||
usage(progname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
runTests();
|
||||
|
||||
|
||||
@ -99,7 +174,8 @@ public:
|
||||
fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
*subTime = uprv_getMeanTime(times,ITERATIONS,marginOfError);
|
||||
uint32_t iterations = ITERATIONS;
|
||||
*subTime = uprv_getMeanTime(times,&iterations,marginOfError);
|
||||
return subIterations;
|
||||
}
|
||||
public:
|
||||
@ -111,7 +187,16 @@ public:
|
||||
|
||||
void runTestOn(HowExpensiveTest &t) {
|
||||
if(U_FAILURE(setupStatus)) return; // silently
|
||||
fprintf(stderr, "%s:%d: Running: %s\n", t.fFile, t.fLine, t.getName());
|
||||
const char *tn = t.getName();
|
||||
if(testName!=NULL && testMatch(tn)) return; // skipped.
|
||||
if(listmode) {
|
||||
fprintf(stderr, "%s:%d:\t%s\n", t.fFile, t.fLine, t.getName());
|
||||
testhit++;
|
||||
return;
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d: Running: %s\n", t.fFile, t.fLine, t.getName());
|
||||
testhit++;
|
||||
}
|
||||
double sieveTime = uprv_getSieveTime(NULL);
|
||||
double st;
|
||||
double me;
|
||||
@ -132,7 +217,7 @@ void runTestOn(HowExpensiveTest &t) {
|
||||
|
||||
if(out!=NULL) {
|
||||
fprintf(out, " <test name=\"%s\" standardizedTime=\"%f\" realDuration=\"%f\" marginOfError=\"%f\" iterations=\"%d\" />\n",
|
||||
t.getName(),stn,st,me,iter);
|
||||
tn,stn,st,me,iter);
|
||||
fflush(out);
|
||||
}
|
||||
}
|
||||
@ -260,6 +345,34 @@ public:
|
||||
|
||||
#define DO_AttrNumTest(p,n,x,a,v) { AttrNumTest t(p,n,x,__FILE__,__LINE__,a,v); runTestOn(t); }
|
||||
|
||||
|
||||
class NOXNumTest : public NumTest
|
||||
{
|
||||
private:
|
||||
UNumberFormatAttribute fAttr;
|
||||
int32_t fAttrValue;
|
||||
char name2[100];
|
||||
protected:
|
||||
virtual const char *getClassName() {
|
||||
sprintf(name2,"NOXNumTest:%d=%d", fAttr,fAttrValue);
|
||||
return name2;
|
||||
}
|
||||
public:
|
||||
NOXNumTest(const char *pat, const char *num, double expect, const char *FILE, int LINE /*, UNumberFormatAttribute attr, int32_t newValue */)
|
||||
: NumTest(pat,num,expect,FILE,LINE) /* ,
|
||||
fAttr(attr),
|
||||
fAttrValue(newValue) */
|
||||
{
|
||||
}
|
||||
virtual UNumberFormat* initFmt() {
|
||||
UNumberFormat *fmt = NumTest::initFmt();
|
||||
//unum_setAttribute(fmt, fAttr,fAttrValue);
|
||||
return fmt;
|
||||
}
|
||||
};
|
||||
|
||||
#define DO_NOXNumTest(p,n,x) { NOXNumTest t(p,n,x,__FILE__,__LINE__); runTestOn(t); }
|
||||
|
||||
#define DO_TripleNumTest(p,n,x) DO_AttrNumTest(p,n,x,UNUM_PARSE_ALL_INPUT,UNUM_YES) \
|
||||
DO_AttrNumTest(p,n,x,UNUM_PARSE_ALL_INPUT,UNUM_NO) \
|
||||
DO_AttrNumTest(p,n,x,UNUM_PARSE_ALL_INPUT,UNUM_MAYBE)
|
||||
@ -485,7 +598,7 @@ public:
|
||||
|
||||
int32_t run() {
|
||||
int32_t trial;
|
||||
int i;
|
||||
int i=0;
|
||||
UnicodeString buf;
|
||||
if(U_SUCCESS(setupStatus)) {
|
||||
for(i=0;i<U_LOTS_OF_TIMES;i++){
|
||||
@ -515,10 +628,41 @@ QuickTest(NumParseTest,{ static UChar pattern[] = { 0x23 }; NumParseTest_f
|
||||
QuickTest(NumParseTestdot,{ static UChar pattern[] = { 0x23 }; NumParseTest_fmt = unum_open(UNUM_PATTERN_DECIMAL, pattern, 1, "en_US", 0, &setupStatus); },{ int32_t i; double val; for(i=0;i<U_LOTS_OF_TIMES;i++) { val=unum_parse(NumParseTest_fmt,strdot,1,NULL,&setupStatus); } return i; },{unum_close(NumParseTest_fmt);})
|
||||
QuickTest(NumParseTestspc,{ static UChar pattern[] = { 0x23 }; NumParseTest_fmt = unum_open(UNUM_PATTERN_DECIMAL, pattern, 1, "en_US", 0, &setupStatus); },{ int32_t i; double val; for(i=0;i<U_LOTS_OF_TIMES;i++) { val=unum_parse(NumParseTest_fmt,strspc,1,NULL,&setupStatus); } return i; },{unum_close(NumParseTest_fmt);})
|
||||
QuickTest(NumParseTestgrp,{ static UChar pattern[] = { 0x23 }; NumParseTest_fmt = unum_open(UNUM_PATTERN_DECIMAL, pattern, 1, "en_US", 0, &setupStatus); },{ int32_t i; double val; for(i=0;i<U_LOTS_OF_TIMES;i++) { val=unum_parse(NumParseTest_fmt,strgrp,-1,NULL,&setupStatus); } return i; },{unum_close(NumParseTest_fmt);})
|
||||
|
||||
QuickTest(NumParseTestbeng,{ static UChar pattern[] = { 0x23 }; NumParseTest_fmt = unum_open(UNUM_PATTERN_DECIMAL, pattern, 1, "en_US", 0, &setupStatus); },{ int32_t i; double val; for(i=0;i<U_LOTS_OF_TIMES;i++) { val=unum_parse(NumParseTest_fmt,strbeng,-1,NULL,&setupStatus); } return i; },{unum_close(NumParseTest_fmt);})
|
||||
|
||||
UDateFormat *DateFormatTest_fmt = NULL;
|
||||
UDate sometime = 100000000.0;
|
||||
UChar onekbuf[1024];
|
||||
const int32_t onekbuf_len = sizeof(onekbuf)/sizeof(onekbuf[0]);
|
||||
|
||||
|
||||
QuickTest(DateFormatTestBasic, \
|
||||
{ \
|
||||
DateFormatTest_fmt = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, NULL, NULL, -1, NULL, -1, &setupStatus); \
|
||||
}, \
|
||||
{ \
|
||||
int i; \
|
||||
for(i=0;i<U_LOTS_OF_TIMES;i++) \
|
||||
{ \
|
||||
udat_format(DateFormatTest_fmt, sometime, onekbuf, onekbuf_len, NULL, &setupStatus); \
|
||||
} \
|
||||
return i; \
|
||||
}, \
|
||||
{ \
|
||||
udat_close(DateFormatTest_fmt); \
|
||||
} \
|
||||
)
|
||||
|
||||
|
||||
QuickTest(NullTest,{},{int j=U_LOTS_OF_TIMES;while(--j);return U_LOTS_OF_TIMES;},{})
|
||||
|
||||
#if 0
|
||||
#include <time.h>
|
||||
|
||||
QuickTest(RandomTest,{},{timespec ts; ts.tv_sec=rand()%4; int j=U_LOTS_OF_TIMES;while(--j) { ts.tv_nsec=100000+(rand()%10000)*1000000; nanosleep(&ts,NULL); return j;} return U_LOTS_OF_TIMES;},{})
|
||||
#endif
|
||||
|
||||
OpenCloseTest(pattern,unum,open,{},(UNUM_PATTERN_DECIMAL,pattern,1,"en_US",0,&setupStatus),{})
|
||||
OpenCloseTest(default,unum,open,{},(UNUM_DEFAULT,NULL,-1,"en_US",0,&setupStatus),{})
|
||||
#if !UCONFIG_NO_CONVERSION
|
||||
@ -533,11 +677,24 @@ void runTests() {
|
||||
SieveTest t;
|
||||
runTestOn(t);
|
||||
}
|
||||
#if 0
|
||||
{
|
||||
RandomTest t;
|
||||
runTestOn(t);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
NullTest t;
|
||||
runTestOn(t);
|
||||
}
|
||||
|
||||
#ifndef SKIP_DATEFMT_TESTS
|
||||
{
|
||||
DateFormatTestBasic t;
|
||||
runTestOn(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SKIP_NUMPARSE_TESTS
|
||||
{
|
||||
// parse tests
|
||||
@ -548,8 +705,8 @@ void runTests() {
|
||||
DO_NumTest("#","-2 ",-2);
|
||||
DO_NumTest("+#","+2",2);
|
||||
DO_NumTest("#,###.0","2222.0",2222.0);
|
||||
|
||||
DO_NumTest("#.0","1.000000000000000000000000000000000000000000000000000000000000000000000000000000",1.0);
|
||||
DO_NumTest("#","123456",123456);
|
||||
|
||||
// attr
|
||||
#ifdef HAVE_UNUM_MAYBE
|
||||
@ -567,7 +724,6 @@ void runTests() {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SKIP_NUMFORMAT_TESTS
|
||||
// format tests
|
||||
{
|
||||
@ -587,7 +743,6 @@ void runTests() {
|
||||
DO_NumFmtStringPieceTest("#.0000","123.4560",spPI);
|
||||
DO_NumFmtStringPieceTest("#.00","123.46",spPI);
|
||||
|
||||
#if 1
|
||||
DO_NumFmtTest("#","0",0.0);
|
||||
DO_NumFmtTest("#","12345",12345);
|
||||
DO_NumFmtTest("#","-2",-2);
|
||||
@ -600,24 +755,31 @@ void runTests() {
|
||||
DO_NumFmtInt64Test("#","-2",-2);
|
||||
DO_NumFmtInt64Test("+#","+2",2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SKIP_NUM_OPEN_TEST
|
||||
{
|
||||
Test_unum_opendefault t;
|
||||
runTestOn(t);
|
||||
}
|
||||
{
|
||||
Test_unum_openpattern t;
|
||||
runTestOn(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* skip numformat tests */
|
||||
#if !UCONFIG_NO_CONVERSION
|
||||
{
|
||||
Test_ucnv_opengb18030 t;
|
||||
runTestOn(t);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
Test_unum_openpattern t;
|
||||
runTestOn(t);
|
||||
}
|
||||
{
|
||||
Test_ures_openroot t;
|
||||
runTestOn(t);
|
||||
}
|
||||
|
||||
if(testhit==0) {
|
||||
fprintf(stderr, "ERROR: no tests matched.\n");
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
**********************************************************************
|
||||
* Copyright (c) 2011,International Business Machines
|
||||
* Copyright (c) 2011-2012,International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
*/
|
||||
@ -108,9 +108,9 @@ double qs(double *times, int n, double *q1, double *q2, double *q3) {
|
||||
return *q3-*q1;
|
||||
}
|
||||
|
||||
U_CAPI double uprv_getMeanTime(double *times, uint32_t timeCount, double *marginOfError) {
|
||||
U_CAPI double uprv_getMeanTime(double *times, uint32_t *timeCount, double *marginOfError) {
|
||||
double q1,q2,q3;
|
||||
int n = timeCount;
|
||||
int n = *timeCount;
|
||||
|
||||
/* calculate medians */
|
||||
qsort(times,n,sizeof(times[0]),comdoub);
|
||||
@ -126,18 +126,23 @@ U_CAPI double uprv_getMeanTime(double *times, uint32_t timeCount, double *margin
|
||||
for(int i=0;i<newN;i++) {
|
||||
if(times[i]<rangeMin || times[i]>rangeMax) {
|
||||
#if U_DEBUG
|
||||
printf("Knocking out: %.9f from [%.9f:%.9f]\n", times[i], rangeMin, rangeMax);
|
||||
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
|
||||
printf("Kicked out %d, retrying..\n", n-newN);
|
||||
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);
|
||||
@ -160,11 +165,13 @@ U_CAPI double uprv_getMeanTime(double *times, uint32_t timeCount, double *margin
|
||||
double sd = 0;
|
||||
for(int i=0;i<n;i++) {
|
||||
#if U_DEBUG
|
||||
printf(" %d: %.9f\n", i, times[i]);
|
||||
if(didRemove) {
|
||||
printf("recalc %d/%d: %.9f\n", i, n, times[i]);
|
||||
}
|
||||
#endif
|
||||
sd += (times[i]-meanTime)*(times[i]-meanTime);
|
||||
}
|
||||
sd = sqrt(sd/(n-1));
|
||||
sd = sqrt(sd/((double)n-1.0));
|
||||
|
||||
#if U_DEBUG
|
||||
printf("sd: %.9f, mean: %.9f\n", sd, meanTime);
|
||||
@ -173,7 +180,7 @@ U_CAPI double uprv_getMeanTime(double *times, uint32_t timeCount, double *margin
|
||||
#endif
|
||||
|
||||
/* 1.960 = z sub 0.025 */
|
||||
*marginOfError = 1.960 * (sd/sqrt(n));
|
||||
*marginOfError = 1.960 * (sd/sqrt((double)n));
|
||||
/*printf("Margin of Error = %.4f (95%% confidence)\n", me);*/
|
||||
|
||||
return meanTime;
|
||||
@ -186,16 +193,17 @@ 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("#%d/%d: %.9f\n", i,SAMPLES, times[i]);
|
||||
printf("sieve: %d/%d: %.9f\n", i,SAMPLES, times[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
meanSieveTime = uprv_getMeanTime(times, SAMPLES,&meanSieveME);
|
||||
meanSieveTime = uprv_getMeanTime(times, &samples,&meanSieveME);
|
||||
calcSieveTime=TRUE;
|
||||
}
|
||||
if(marginOfError!=NULL) {
|
||||
|
@ -21,11 +21,11 @@ U_INTERNAL double uprv_calcSieveTime(void);
|
||||
/**
|
||||
* Calculate the mean time, with margin of error
|
||||
* @param times array of times (modified/sorted)
|
||||
* @param timeCount length of array
|
||||
* @param timeCount length of array - on return, how many remain after throwing out outliers
|
||||
* @param marginOfError out parameter: gives +/- margin of err at 95% confidence
|
||||
* @return the mean time, or negative if error/imprecision.
|
||||
*/
|
||||
U_INTERNAL double uprv_getMeanTime(double *times, uint32_t timeCount, double *marginOfError);
|
||||
U_INTERNAL double uprv_getMeanTime(double *times, uint32_t *timeCount, double *marginOfError);
|
||||
|
||||
/**
|
||||
* Get the standardized sieve time. (Doesn't recalculate if already computed.
|
||||
|
@ -524,7 +524,7 @@ static const USystemParams systemParams[] = {
|
||||
#if defined (CYGWINMSVC)
|
||||
{ "build.cygwinmsvc", paramInteger, "b", 1},
|
||||
#endif
|
||||
{ "uconfig.internal_digitlist", paramInteger, "b", UCONFIG_INTERNAL_DIGITLIST},
|
||||
{ "uconfig.internal_digitlist", paramInteger, "b", 1}, /* always 1 */
|
||||
{ "uconfig.have_parseallinput", paramInteger, "b", UCONFIG_HAVE_PARSEALLINPUT},
|
||||
{ "uconfig.format_fastpaths_49",paramInteger, "b", UCONFIG_FORMAT_FASTPATHS_49},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user