Skip to main content
Stack Overflow
  1. About
  2. For Teams

You are not logged in. Your edit will be placed in a queue until it is peer reviewed.

We welcome edits that make the post easier to understand and more valuable for readers. Because community members review edits, please try to make the post substantially better than how you found it, for example, by fixing grammar or adding additional resources and hyperlinks.

Required fields*

Required fields*

floating-point implementation of a function with removable singularity

Consider the following function:

  • ƒ(x) = sin(sqrt(x)) / sqrt(x) if x > 0
  • ƒ(x) = 1 if x = 0
  • ƒ(x) = sinh(sqrt(-x)) / sqrt(-x) if x < 0

This is an entire function with a Taylor series at 0 of: 1/1!, -1/3!, 1/5!, -1/7!, ... that I want to implement in floating point (think IEEE-754 single, IEEE-754 double or arbitrary precision like with MPFR.

My current C-ish implementation with a floating-point type F looks something like:

F func (F x)
{
 F q = sqrt (fabs (x));
 if (x * x == 0)
 return 1 - x / 6;
 else
 return x > 0
 ? sin (q) / q
 : sinh (q) / q;
}

From what I can tell the implementation works reasonably well in an environment of 0, but I am wondering if there are loophole values where it does not work (well).

Answer*

Draft saved
Draft discarded
Cancel
6
  • 1
    (+1) For "very negative" x, why not simply compute 1 / (2 * sqrt (-x) * exp (-sqrt (-x))), taking advantage of subnormals? This should produce results with smaller error than going through logarithmic space and exponentiating at the end, which incurs a substantial amount of error magnification at the extreme end of the range. Commented May 10, 2025 at 21:26
  • @njuffa Interesting idea. Answer updated. Just went through a similar issue here with best approach. Will ponder some more. Commented May 10, 2025 at 21:36
  • I decided to be less lazy and actually tried my idea and your proposed fix, and the results of a quick experiment seem clear. For a double implementation, the maximum error with my approach is about 6050 ulp, while it is about 1500 ulp with yours (i.e., when going through logarithmic space). My initial thought was that both approaches would lose on the order of 12 bits due to error magnification, but mine would reduce the error being magnified a bit for overall better accuracy. Clearly that is not the case. Commented May 10, 2025 at 22:35
  • @njuffa The trick bring the computation into the fat FP zone near 0.0 to 1.0, forms the pre-answer and then scale exactly by 2^n. I'll look more into it later - real life calls. Commented May 11, 2025 at 1:14
  • 1
    You latest proposal results in a maximum error of 513 ulps. I am sampling double arguments in [-514165, -504776], BTW. Commented May 11, 2025 at 3:16

AltStyle によって変換されたページ (->オリジナル) /