You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by jk...@apache.org on 2001/10/15 17:31:11 UTC

cvs commit: xml-xalan/java/src/org/apache/xpath/objects XStringForFSB.java

jkesselm    01/10/15 08:31:11

  Modified:    java/src/org/apache/xpath/objects XStringForFSB.java
  Log:
  Bugzilla 3384. See comments in the toDouble method; I suspect this may be wasted micro-optimization.
  
  Revision  Changes    Path
  1.4       +61 -64    xml-xalan/java/src/org/apache/xpath/objects/XStringForFSB.java
  
  Index: XStringForFSB.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XStringForFSB.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XStringForFSB.java	2001/06/18 02:16:14	1.3
  +++ XStringForFSB.java	2001/10/15 15:31:11	1.4
  @@ -961,94 +961,91 @@
      * Convert a string to a double -- Allowed input is in fixed
      * notation ddd.fff.
      *
  +   * %OPT% CHECK PERFORMANCE against generating a Java String and
  +   * converting it to double. The advantage of running in native
  +   * machine code -- perhaps even microcode, on some systems -- may
  +   * more than make up for the cost of allocating and discarding the
  +   * additional object. We need to benchmark this. 
  +   *
  +   * %OPT% More importantly, we need to decide whether we _care_ about
  +   * the performance of this operation. Does XString.toDouble constitute
  +   * any measurable percentage of our typical runtime? I suspect not!
  +   *
      * @return A double value representation of the string, or return Double.NaN 
  -   * if the string can not be converted.
  -   */
  +   * if the string can not be converted.  */
     public double toDouble()
     {
  -
  -    int start = m_start;
  -    int end = m_length+start;
  -    
  +    int end = m_length+m_start;
       if(0 == end)
         return Double.NaN;
  -      
  -    double result = 0.0;
  -    int punctPos = end-1;
  +
  +    int start = m_start;
       FastStringBuffer fsb = fsb();
  +      
  +    long longResult=0;
  +    boolean isNegative=false;
  +    int[] digitsFound={0,0}; // intpart,fracpart
  +    int digitType=0;    // Index to which kind of digit we're accumulating
  +    double doubleResult;
       
  -    // Scan to first whitespace character.
  -    for (int i = start; i < end; i++) 
  -    {
  -      char c = fsb.charAt(i);
  -      if( !XMLCharacterRecognizer.isWhiteSpace( c ) )
  -      {
  -        break;
  -      }
  -      else
  -        start++;
  -    }
  -
  -    double sign = 1.0;
  +    // Scan past whitespace characters
  +    while(start< end &&
  +          XMLCharacterRecognizer.isWhiteSpace( fsb.charAt(start) )
  +          )
  +      ++start;
  +    
       if (start < end && fsb.charAt(start) == '-')
       {
  -      sign = -1.0;
  -
  +      isNegative=true;
         start++;
       }
       
  -    int digitsFound = 0;
  -    for (int i = start; i < end; i++)  // parse the string from left to right converting the integer part
  +    // parse the string from left to right converting as an integer.
  +    for (int i = start; i < end; i++)
       {
         char c = fsb.charAt(i);
  -      if (c != '.')
  +
  +      if (c == '.')
         {
  -        if(XMLCharacterRecognizer.isWhiteSpace(c))
  -          break;
  -        else if (Character.isDigit(c))
  -        {
  -          result = result * 10.0 + (c - 0x30);
  -          digitsFound++;
  -        }
  +        if(digitType==0)
  +          digitType=1;
           else
  -        {
  -          return Double.NaN;
  -        }
  +          return Double.NaN;    // Second period is error
         }
  -      else
  -      {
  -        punctPos = i;
  +      
  +      else if(XMLCharacterRecognizer.isWhiteSpace(c))
  +        break;                  // Whitespace is ignored
   
  -        break;
  -      }
  -    }
  -    
  -    if (fsb.charAt(punctPos) == '.')  // parse the string from the end to the '.' converting the fractional part
  -    {
  -      double fractPart = 0.0;
  -      for (int i = end - 1; i > punctPos; i--)
  +      else if (Character.isDigit(c))
         {
  -        char c = fsb.charAt(i);
  -        if(XMLCharacterRecognizer.isWhiteSpace(c))
  -          continue;
  -        else if (Character.isDigit(c))
  -        {
  -          fractPart = fractPart / 10.0 + (c - 0x30);
  -          digitsFound++;
  -        }
  -        else
  -        {
  -          return Double.NaN;
  -        }
  +        longResult = longResult * 10 + (c - '0'); // Accumulate as int
  +        ++digitsFound[digitType]; // Remember scaling
         }
   
  -      result += fractPart / 10.0;
  +      else
  +      {
  +        return Double.NaN;      // Nonnumeric is error
  +      }
       }
  -    
  -    if(0 == digitsFound)
  +
  +    if(0 ==digitsFound[0]&& 0==digitsFound[1])
         return Double.NaN;
   
  -    return result * sign;
  +    // Convert from scaled integer to floating point. This will come close. 
  +    // There's an alternative solution involving Double.longBitsToDouble
  +    // followed by a combined renormalize/scale operation... but I honestly
  +    // think the more straightforward solution comes out to just about
  +    // the same thing.
  +                
  +    long scale=1;               // AFAIK, java doesn't have an easier 10^n operation
  +    for(int i=digitsFound[1];i>0;--i) 
  +      scale*=10;
  +                
  +    doubleResult=((double)longResult)/scale;
  +                
  +    if(isNegative)
  +      doubleResult *= -1;
  +    return doubleResult;
     }
   
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org