[prev in list] [next in list] [prev in thread] [next in thread] 

List:       koffice-devel
Subject:    Re: bug in waiting with bessel functions (kspread)
From:       Andrew <andrew.dorrell () gmail ! com>
Date:       2008-11-17 3:24:41
Message-ID: 200811171424.41923.andrew.dorrell () gmail ! com
[Download RAW message or body]

On Mon, 17 Nov 2008 12:45:28 am Tomas Mecir wrote:
> Hi Andrew !
>
> 2008/11/16 Andrew <andrew.dorrell@gmail.com>:
> > The problem is that no range checking is performed on the parameters in
> > the wrappers.  The ccmath functions will produce garbage for v>=29 due to
> > the ccmath_gaml function:
>
> The bessel* functions are called in kspread/functions/engineering.cpp,
> in functions func_besseli and similar. Error handling is basically
> something like
> if (x >= 30) return Value::errorVALUE();
> these would likely best be placed in ValueCalc, after the toFloat
> calls, as that's where the double-precision value is pulled out of the
> Value class, including conversion if needed.

OK... I'd do it as per the attached patch (which I have built and minimally 
checked).  Looking at the numbers it generates though I'm concerned there 
might be a more fundamental issue... compare 
http://en.wikipedia.org/wiki/Bessel_function.

In a quick test spreadsheet I can get some huge numbers back from the 1st 
order bessel function (which should be bounded in [-1,1] at least).  Not sure 
what's up there...


["ValueCalc.patch" (text/x-patch)]

Index: ValueCalc.cpp
===================================================================
--- ValueCalc.cpp	(revision 885321)
+++ ValueCalc.cpp	(working copy)
@@ -1551,7 +1551,7 @@
  */
 
 static double ccmath_gaml(double x)
-{ double g,h;
+{ double g,h=0; /* NB must be called with 0<=x<29 */
   for(g=1.; x<30. ;g*=x,x+=1.) h=x*x;
   g=(x-.5)*log(x)-x+.918938533204672-log(g);
   g+=(1.-(1./6.-(1./3.-1./(4.*h))/(7.*h))/(5.*h))/(12.*x);
@@ -1679,35 +1679,42 @@
 
 /* ---------- end of CCMATH code ---------- */
 
+template <typename func_ptr>
+Value CalcBessel(
+  func_ptr       *func,
+  ValueConverter *converter, 
+  Value v, Value x)
+{
+  double vv = numToDouble (converter->toFloat (v));
+  double xx = numToDouble (converter->toFloat (x));
+  // vv must be a non-negative integer and <29 for implementation reasons
+  // xx must be non-negative
+  if(xx>=0 && vv>=0 && vv<29 && vv == floor(vv))
+    return Value (func (vv, xx));
+  return Value::errorVALUE();
+}
 
 Value ValueCalc::besseli (Value v, Value x)
 {
-  Number vv = converter->toFloat (v);
-  Number xx = converter->toFloat (x);
-  return Value (ccmath_ibes (numToDouble (vv), numToDouble (xx)));
+  return CalcBessel(ccmath_ibes, converter, v, x);
 }
 
 Value ValueCalc::besselj (Value v, Value x)
 {
-  Number vv = converter->toFloat (v);
-  Number xx = converter->toFloat (x);
-  return Value (ccmath_jbes (numToDouble (vv), numToDouble (xx)));
+  return CalcBessel(ccmath_jbes, converter, v, x);
 }
 
 Value ValueCalc::besselk (Value v, Value x)
 {
-  Number vv = converter->toFloat (v);
-  Number xx = converter->toFloat (x);
-  return Value (ccmath_kbes (numToDouble (vv), numToDouble (xx)));
+  return CalcBessel(ccmath_kbes, converter, v, x);
 }
 
 Value ValueCalc::besseln (Value v, Value x)
 {
-  Number vv = converter->toFloat (v);
-  Number xx = converter->toFloat (x);
-  return Value (ccmath_nbes (numToDouble (vv), numToDouble (xx)));
+  return CalcBessel(ccmath_nbes, converter, v, x);
 }
 
+
 // ------------------------------------------------------
 
 Value ValueCalc::erf (Value x)


_______________________________________________
koffice-devel mailing list
koffice-devel@kde.org
https://mail.kde.org/mailman/listinfo/koffice-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic