Hi Alvaro,

Thank you so much for taking the time to review the patch and for taking
the time again to sort things
out with me this evening.



> I see that in dtanh() you set errno to 0 before calling tanh(), but 1)
> you don't check for it afterwards (seems like you should be checking for
> ERANGE, as well as checking the return value for isinf()), and 2) you
> don't do that in dsinh() and dcosh() and I'm not quite sure I see why.
> What's up with that?
>
>
At the time I wrote that patch, I tried to include errno testing.Then, I
think again and
came back with the wrong idea everything would be fine.

By re-reading math.h documentation, it is now clear that the three
functions can raise a
ERANGE error.

There are two cases :
- range error due to overflow occurs.
- range error occurs due to underflow. In that case, the correct result
(after rounding) is returned. So I assume we can ignore that case.

For sinh and cosh, we can have both cases and we added support for overflow.

For tanh, the only possible case is underflow and then, the result is
correct.

We included comments to explain errno handling in those functions.

Cheers,

Lætitia
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 4930ec17f6..30ecf496ca 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -896,6 +896,19 @@
        <entry><literal>2</literal></entry>
       </row>
 
+      <row>
+       <entry>
+        <indexterm>
+         <primary>log10</primary>
+        </indexterm>
+        <literal><function>log10(<type>dp</type> or <type>numeric</type>)</function></literal>
+       </entry>
+       <entry>(same as input)</entry>
+       <entry>base 10 logarithm</entry>
+       <entry><literal>log10(100.0)</literal></entry>
+       <entry><literal>2</literal></entry>
+      </row>
+
       <row>
        <entry><literal><function>log(<parameter>b</parameter> <type>numeric</type>,
         <parameter>x</parameter> <type>numeric</type>)</function></literal></entry>
@@ -1147,7 +1160,7 @@
   </para>
 
   <para>
-   Finally, <xref linkend="functions-math-trig-table"/> shows the
+   <xref linkend="functions-math-trig-table"/> shows the
    available trigonometric functions.  All trigonometric functions
    take arguments and return values of type <type>double
    precision</type>.  Each of the trigonometric functions comes in
@@ -1311,8 +1324,66 @@
    </para>
   </note>
 
-  </sect1>
+  <para>
+   Finally, <xref linkend="functions-math-hyp-table"/> shows the
+   available hyperbolic functions. All hyperbolic functions apply to
+   hyperbolic angles expressed in hyperbolic radians.
+  </para>
 
+  <table id="functions-math-hyp-table">
+    <title>Hyperbolic Functions</title>
+
+    <tgroup cols="5">
+     <thead>
+      <row>
+       <entry>Function</entry>
+       <entry>Return Type</entry>
+       <entry>Description</entry>
+       <entry>Example</entry>
+       <entry>Result</entry>
+      </row>
+     </thead>
+     <tbody>
+      <row>
+       <entry>
+        <indexterm>
+         <primary>sinh</primary>
+        </indexterm>
+        <literal><function>sinh(dp)</function></literal>
+       </entry>
+       <entry><type>dp</type></entry>
+       <entry>hyperbolic sine</entry>
+       <entry><literal>sinh(0)</literal></entry>
+       <entry><literal>0</literal></entry>
+      </row>
+      <row>
+       <entry>
+        <indexterm>
+         <primary>cosh</primary>
+        </indexterm>
+        <literal><function>cosh(dp)</function></literal>
+       </entry>
+       <entry><type>dp</type></entry>
+       <entry>hyperbolic cosine</entry>
+       <entry><literal>cosh(0)</literal></entry>
+       <entry><literal>1</literal></entry>
+      </row>
+      <row>
+       <entry>
+        <indexterm>
+         <primary>tanh</primary>
+        </indexterm>
+        <literal><function>tanh(dp)</function></literal>
+       </entry>
+       <entry><type>dp</type></entry>
+       <entry>hyperbolic tangent</entry>
+       <entry><literal>tanh(0)</literal></entry>
+       <entry><literal>0</literal></entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
+  </sect1>
 
   <sect1 id="functions-string">
    <title>String Functions and Operators</title>
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 117ded8d1d..29a6ba0859 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -2375,6 +2375,77 @@ radians(PG_FUNCTION_ARGS)
 	PG_RETURN_FLOAT8(float8_mul(arg1, RADIANS_PER_DEGREE));
 }
 
+/* ========== HYPERBOLIC FUNCTIONS ========== */
+
+/*
+ *		dsinh			- returns the hyperbolic sine of arg1
+ */
+Datum
+dsinh(PG_FUNCTION_ARGS)
+{
+	float8		arg1 = PG_GETARG_FLOAT8(0);
+	float8		result;
+
+	errno = 0;
+	result = sinh(arg1);
+
+	/*
+	 * if an ERANGE error occurs, it means there is an overflow. For sinh, it 
+	 * can be either -infinite or infinite, depending on the sign of arg1.
+	*/
+	if (errno == ERANGE)
+	{
+		if (arg1 < 0)
+			result = -get_float8_infinity();
+		else
+			result = get_float8_infinity();
+	}
+
+	check_float8_val(result, isinf(arg1), true);
+	PG_RETURN_FLOAT8(result);
+}
+
+
+/*
+ *		dcosh			- returns the hyperbolic cosine of arg1
+ */
+Datum
+dcosh(PG_FUNCTION_ARGS)
+{
+	float8		arg1 = PG_GETARG_FLOAT8(0);
+	float8		result;
+
+	errno = 0;
+	result = cosh(arg1);
+
+	/*
+	 * if an ERANGE error occurs, it means there is an overflow. As cosh is
+	 * always positive, it always means the result is positive infinite.
+	*/
+	if (errno == ERANGE)
+		result = get_float8_infinity();
+
+	check_float8_val(result, isinf(arg1), false);
+	PG_RETURN_FLOAT8(result);
+}
+
+/*
+ *		dtanh			- returns the hyperbolic tangent of arg1
+ */
+Datum
+dtanh(PG_FUNCTION_ARGS)
+{
+	float8		arg1 = PG_GETARG_FLOAT8(0);
+	float8		result;
+
+	/*
+	 * For tanh, we don't have errno check because it nevers overflows.
+	*/
+	result = tanh(arg1);
+
+	check_float8_val(result, false, true);
+	PG_RETURN_FLOAT8(result);
+}
 
 /*
  *		drandom		- returns a random number
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b8de13f03b..ecd05949a2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -2617,6 +2617,9 @@
 { oid => '1340', descr => 'base 10 logarithm',
   proname => 'log', prorettype => 'float8', proargtypes => 'float8',
   prosrc => 'dlog10' },
+{ oid => '1364', descr => 'base 10 logarithm',
+  proname => 'log10', prorettype => 'float8', proargtypes => 'float8',
+  prosrc => 'dlog10' },
 { oid => '1341', descr => 'natural logarithm',
   proname => 'ln', prorettype => 'float8', proargtypes => 'float8',
   prosrc => 'dlog1' },
@@ -3283,6 +3286,17 @@
 { oid => '1610', descr => 'PI',
   proname => 'pi', prorettype => 'float8', proargtypes => '', prosrc => 'dpi' },
 
+{ oid => '2462', descr => 'hyperbolic sine',
+  proname => 'sinh', prorettype => 'float8', proargtypes => 'float8',
+  prosrc => 'dsinh' },
+{ oid => '2463', descr => 'hyperbolic cosine',
+  proname => 'cosh', prorettype => 'float8', proargtypes => 'float8',
+  prosrc => 'dcosh' },
+{ oid => '2464', descr => 'hyperbolic tangent',
+  proname => 'tanh', prorettype => 'float8', proargtypes => 'float8',
+  prosrc => 'dtanh' },
+
+
 { oid => '1618',
   proname => 'interval_mul', prorettype => 'interval',
   proargtypes => 'interval float8', prosrc => 'interval_mul' },
@@ -4195,6 +4209,9 @@
 { oid => '1741', descr => 'base 10 logarithm',
   proname => 'log', prolang => 'sql', prorettype => 'numeric',
   proargtypes => 'numeric', prosrc => 'select pg_catalog.log(10, $1)' },
+{ oid => '2023', descr => 'base 10 logarithm',
+  proname => 'log10', prolang => '14', prorettype => 'numeric',
+  proargtypes => 'numeric', prosrc => 'select pg_catalog.log(10, $1)' },
 { oid => '1742', descr => 'convert float4 to numeric',
   proname => 'numeric', prorettype => 'numeric', proargtypes => 'float4',
   prosrc => 'float4_numeric' },
diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out
index 75c0bf389b..3f76929591 100644
--- a/src/test/regress/expected/float8.out
+++ b/src/test/regress/expected/float8.out
@@ -632,4 +632,23 @@ FROM (SELECT 10*cosd(a), 10*sind(a)
   10 |   0 |      0 | t
 (5 rows)
 
+-- hyperbolic functions
+SELECT sinh(float8 '0');
+ sinh 
+------
+    0
+(1 row)
+
+SELECT cosh(float8 '0');
+ cosh 
+------
+    1
+(1 row)
+
+SELECT tanh(float8 '0');
+ tanh 
+------
+    0
+(1 row)
+
 RESET extra_float_digits;
diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8.sql
index 6595fd2b95..b099ae6321 100644
--- a/src/test/regress/sql/float8.sql
+++ b/src/test/regress/sql/float8.sql
@@ -232,4 +232,9 @@ SELECT x, y,
 FROM (SELECT 10*cosd(a), 10*sind(a)
       FROM generate_series(0, 360, 90) AS t(a)) AS t(x,y);
 
+-- hyperbolic functions
+SELECT sinh(float8 '0');
+SELECT cosh(float8 '0');
+SELECT tanh(float8 '0');
+
 RESET extra_float_digits;

Reply via email to