# The Wiert Corner – irregular stream of stuff

• ## Email Subscription

Join 2,351 other followers

## QualityCentral 56524: tanh function from Delphi 7 till Delphi XE was buggy; XE2 fixed it

Posted by jpluimers on 2019/08/13

In case you maintain code in older versions of Delphi, be aware that the `function tanh` was broken starting in Delphi 7 and only got fixed in Delphi XE2: QualityCentral QualityCentral 56524: tanh function from Delphi 7 till Delphi XE was buggy; XE2 fixed it.

For big inputs, it would just fail, instead of returning 1.

The reason is that in the buggy versions, `tanh` got replaced from an old working version into a simple `sinh/cosh`, which mathematically is correct, but if your numeric data type has limited accuracy, you need to account for the boundaries where the result fits, but intermediates do not.

the [WayBack] `Math.Tanh` Function implements the hyperbolic tangent, for which you can find the definition at Hyperbolic function – Wikipedia: Definitions.

By now it is implemented for all floating point types the same way (only the parameter type changes in each implementation)

```function Tanh(const X: Extended): Extended; overload;
const
MaxTanhDomain = 23;
C1of3 = 1/3;
CBorder = 1.8145860519450699870567321328132e-5; // 2 ^(-63 / 4)
CLn2Div2 = 0.34657359027997265470861606072909; // Ln2 / 2
var
y, z: Extended;
begin
FClearExcept;
case TExtendedRec(X).SpecialType of
fsPositive,
fsNegative:
begin
z := X;
if X < 0 then z := -z;
if (z > MaxTanhDomain) then
Result := 1.0
else if (z < CBorder) then
Result := z  - z * z * z * c1of3
else if (z < CLn2Div2) then
begin
y := ExpMinus1(2*z);
Result := y / (2 + y);
end
else
begin
y := Exp(2*z);
Result := 1 - (2/(y + 1));
end;
if X < 0 then Result := -Result;
end;
else
Result := X;
end;
FCheckExcept;
end;```

–jeroen

This site uses Akismet to reduce spam. Learn how your comment data is processed.