]> granicus.if.org Git - icu/commitdiff
ICU-9449 Merge in decimal format performance improvements from branch.
authorSteven R. Loomis <srl@icu-project.org>
Mon, 17 Sep 2012 19:03:01 +0000 (19:03 +0000)
committerSteven R. Loomis <srl@icu-project.org>
Mon, 17 Sep 2012 19:03:01 +0000 (19:03 +0000)
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

12 files changed:
icu4c/source/common/unicode/uconfig.h
icu4c/source/i18n/decimfmt.cpp
icu4c/source/i18n/digitlst.cpp
icu4c/source/i18n/digitlst.h
icu4c/source/i18n/fmtable.cpp
icu4c/source/i18n/unicode/fmtable.h
icu4c/source/samples/date/Makefile.in
icu4c/source/test/perf/howExpensiveIs/Makefile.in
icu4c/source/test/perf/howExpensiveIs/howExpensiveIs.cpp
icu4c/source/test/perf/howExpensiveIs/sieve.cpp
icu4c/source/test/perf/howExpensiveIs/sieve.h
icu4c/source/tools/toolutil/udbgutil.cpp

index 878e346bb9e03de900ef9f2ca344132965da75c1..8d222614add762721053c2d2a90deab5075fc794 100644 (file)
 #   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.
  * @internal
  */
 #ifndef UCONFIG_HAVE_PARSEALLINPUT
-#   define UCONFIG_HAVE_PARSEALLINPUT 0
+#   define UCONFIG_HAVE_PARSEALLINPUT 1
 #endif
 
 
  * @internal
  */
 #ifndef UCONFIG_FORMAT_FASTPATHS_49
-#   define UCONFIG_FORMAT_FASTPATHS_49 0
+#   define UCONFIG_FORMAT_FASTPATHS_49 1
 #endif
 
 #endif
index d3b1becc371c1efa1091630b3fbe310ab5b59bef..bd156918eba3600ee83cc4e5a0eafecf130c8dab 100644 (file)
@@ -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
index 39a30cf937879e26d9e426450597a7af4098c447..592b228259f16630cbdfc2038e2d1f2f30afbbde 100644 (file)
@@ -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();
 }   
index 7234afed05e4e7315b22c3514b4147f6e5106c6e..aa29a14593cc51a65ef0326590e8fd45d38251ae 100644 (file)
@@ -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
index 947649b348f70c0cec82a62e8a5050f0c94fcdac..bdb0b6de9dfb43ea666e3e0dd14c46aff8da37c4 100644 (file)
@@ -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
index 694e2793256669d980dc9398a041ea9707698ed3..845122ed2db2d014e774071e241433201a33bc3b 100644 (file)
@@ -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.
index de16093589e3c34fa6ab846b81253d3b0371d870..fd2d6282e98bc0dc976409946d273bef1af0aaf5 100644 (file)
@@ -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) \
index 190a0c2fdee4901ca81cc9e6d5a369eff2656397..2daea675c249e1c55981fc474cb12b6ce6895cbd 100644 (file)
@@ -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
index fcfd27b3f64857801abaa3d8131f8f4c7a05c689..1d15e04a383b4f137e7db14dc6a576eafe06cb03 100644 (file)
@@ -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 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, const char* argv[]){
+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);
   }
-#if !UCONFIG_NO_CONVERSION
   {
-    Test_ucnv_opengb18030 t;
+    Test_unum_openpattern t;
     runTestOn(t);
   }
 #endif
+
+#endif /* skip numformat tests */
+#if !UCONFIG_NO_CONVERSION
   {
-    Test_unum_openpattern t;
+    Test_ucnv_opengb18030 t;
     runTestOn(t);
   }
+#endif
   {
     Test_ures_openroot t;
     runTestOn(t);
   }
+
+  if(testhit==0) {
+    fprintf(stderr, "ERROR: no tests matched.\n");
+  }
 }
index ce626d7e7e4395b42359e58809845958ea621be3..0db512181bafc0872d43374dc46c1cb979cfa316 100644 (file)
@@ -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) {
index cd89f52e985c8f82b31869c3e67b7385be1f8072..74a394da766b9865aa71b4080631326450e57a4e 100644 (file)
@@ -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.
index a40e8b05f7bd430661372760c44731109ec6c34e..f642f290b91d2fd0971ff6292b0d255f81fa285c 100644 (file)
@@ -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},