[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [xml] XPath fix



On Fri, Mar 22, 2002 at 12:23:39PM -0000, Cyberthymia wrote:
> >  Section 3.5 of the XPath spec states:
> >    "This is the same as the % operator in Java and ECMAScript."
> >    "This is not the same as the IEEE 754 remainder operation,
> >     which returns the remainder from a rounding division."
> >
> > So they may be right, I hate those parts where XPath/XSLT relies on Java
> >for the semantic of operations, it is usually a mess.
> 
> That bit confused the heck out of me - so does that imply that Java doesn't
> do IEEE 754 floating point numbers properly?
 
  seems to imply it, yes. You're surprized ?
  
> I've found another couple of problems with float, round and ceil.
> floor(-5.2) returns -5 instead of -6
> ceiling(-5.2) returns -4 instead of -5
> round(-5.6) returns -5 instead of -6
> I've had a look at the code in xpath.c that does this maths
> (xmlXPathFloorFunction(), etc) and what I thought would have been the
> correct fix (by using the real C functions) in all 3 cases has been "#if
> 0"'d out and replaced by approximations doing wierd things with casts.
> This is probably a silly question, but was there a specific issue caused by
> using the C functions that stopped them from working?

  Looked at it, I wonder if I didn't do this to avoid using the
functions from the math library when avoidable. Weird casts are 
a sign of ownership ... it seems I forgot about negative values though :-)

  Apparently I got burned by a problem with floor() as a comment
indicates : "floor(0.999999999999) => 1.0 !!!!!!!!!!!"
and decided to bypass it using direct cast to implement the right
semantic.

The enclosed patch tries to fix this, could you build a test file
like the others in test/XPath/expr/ testings those 3 functions and
raise errors if there is still some to fix,

  thanks,

Daniel

-- 
Daniel Veillard      | Red Hat Network https://rhn.redhat.com/
veillard redhat com  | libxml GNOME XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/
Index: xpath.c
===================================================================
RCS file: /cvs/gnome/gnome-xml/xpath.c,v
retrieving revision 1.173
diff -c -r1.173 xpath.c
*** xpath.c	22 Mar 2002 12:23:14 -0000	1.173
--- xpath.c	22 Mar 2002 13:39:34 -0000
***************
*** 6483,6497 ****
   */
  void
  xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) {
      CHECK_ARITY(1);
      CAST_TO_NUMBER;
      CHECK_TYPE(XPATH_NUMBER);
! #if 0
!     ctxt->value->floatval = floor(ctxt->value->floatval);
! #else
!     /* floor(0.999999999999) => 1.0 !!!!!!!!!!! */
!     ctxt->value->floatval = (double)((int) ctxt->value->floatval);
! #endif
  }
  
  /**
--- 6483,6501 ----
   */
  void
  xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+     double f;
+ 
      CHECK_ARITY(1);
      CAST_TO_NUMBER;
      CHECK_TYPE(XPATH_NUMBER);
! 
!     f = (double)((int) ctxt->value->floatval);
!     if (f != ctxt->value->floatval) {
! 	if (ctxt->value->floatval > 0)
! 	    ctxt->value->floatval = f;
! 	else
! 	    ctxt->value->floatval = f - 1;
!     }
  }
  
  /**
***************
*** 6516,6523 ****
      ctxt->value->floatval = ceil(ctxt->value->floatval);
  #else
      f = (double)((int) ctxt->value->floatval);
!     if (f != ctxt->value->floatval)
! 	ctxt->value->floatval = f + 1;
  #endif
  }
  
--- 6520,6531 ----
      ctxt->value->floatval = ceil(ctxt->value->floatval);
  #else
      f = (double)((int) ctxt->value->floatval);
!     if (f != ctxt->value->floatval) {
! 	if (ctxt->value->floatval > 0)
! 	    ctxt->value->floatval = f + 1;
! 	else
! 	    ctxt->value->floatval = f;
!     }
  #endif
  }
  
***************
*** 6546,6560 ****
  	(ctxt->value->floatval == 0.0))
  	return;
  
- #if 0
-     f = floor(ctxt->value->floatval);
- #else
      f = (double)((int) ctxt->value->floatval);
! #endif
!     if (ctxt->value->floatval < f + 0.5)
!         ctxt->value->floatval = f;
!     else 
!         ctxt->value->floatval = f + 1;
  }
  
  /************************************************************************
--- 6554,6571 ----
  	(ctxt->value->floatval == 0.0))
  	return;
  
      f = (double)((int) ctxt->value->floatval);
!     if (ctxt->value->floatval < 0) {
! 	if (ctxt->value->floatval < f - 0.5)
! 	    ctxt->value->floatval = f - 1;
! 	else 
! 	    ctxt->value->floatval = f;
!     } else {
! 	if (ctxt->value->floatval < f + 0.5)
! 	    ctxt->value->floatval = f;
! 	else 
! 	    ctxt->value->floatval = f + 1;
!     }
  }
  
  /************************************************************************


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]