Hello hackers, In his blog post (What's new in SQL 2016)[ https://modern-sql.com/blog/2017-06/whats-new-in-sql-2016], Markus Winand explained some of the changes added to SQL:2016. I spotted that Postgres was behind other RDBMS on hyperbolic functions and log10 function. The log10 function existed but under the name log(<value>).
The new functions can be called in a simple select statement : select log10(100); select sinh(0); select cosh(0); select tanh(0); Even if Markus Winand had added hyperbolic functions in the paragraph "Trigonometric and Logarithmic Functions", I didn't add hyperbolic function with the trigonometric functions in the documentation, because hyperbolic functions are not trigonometric functions. I added regression tests for the new functions, but I didn't for log10 function, assuming that if log function worked, log10 will work too. You'll find enclosed the first version of the patch that can build successfully on my laptop against master. I'm open to any improvement. Cheers, Lætitia -- *Think! Do you really need to print this email ? * *There is no Planet B.*
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 4930ec17f6..94e3fcd4b9 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,65 @@ </para> </note> - </sect1> + <para> + Finally, <xref linkend="functions-math-hyp-table"/> shows the + available hyperbolic functions. + </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..c83eed99c6 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -2375,6 +2375,54 @@ 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; + + result = sinhf(arg1); + + 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; + + result = coshf(arg1); + + 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; + + errno = 0; + result = tanhf(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 3ecc2e12c3..ca6b09a13d 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..4a9e0fb203 100644 --- a/src/test/regress/expected/float8.out +++ b/src/test/regress/expected/float8.out @@ -632,4 +632,77 @@ 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 sinh(float8 'Infinity'); + sinh +---------- + Infinity +(1 row) + +SELECT sinh(float8 '-Infinity'); + sinh +----------- + -Infinity +(1 row) + +SELECT sinh(float8 'NaN'); + sinh +------ + NaN +(1 row) + +SELECT cosh(float8 '0'); + cosh +------ + 1 +(1 row) + +SELECT cosh(float8 'Infinity'); + cosh +---------- + Infinity +(1 row) + +SELECT cosh(float8 '-Infinity'); + cosh +---------- + Infinity +(1 row) + +SELECT cosh(float8 'NaN'); + cosh +------ + NaN +(1 row) + +SELECT tanh(float8 '0'); + tanh +------ + 0 +(1 row) + +SELECT tanh(float8 'Infinity'); + tanh +------ + 1 +(1 row) + +SELECT tanh(float8 '-Infinity'); + tanh +------ + -1 +(1 row) + +SELECT tanh(float8 'NaN'); + tanh +------ + NaN +(1 row) + RESET extra_float_digits; diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8.sql index 6595fd2b95..56053d530d 100644 --- a/src/test/regress/sql/float8.sql +++ b/src/test/regress/sql/float8.sql @@ -232,4 +232,18 @@ 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 sinh(float8 'Infinity'); +SELECT sinh(float8 '-Infinity'); +SELECT sinh(float8 'NaN'); +SELECT cosh(float8 '0'); +SELECT cosh(float8 'Infinity'); +SELECT cosh(float8 '-Infinity'); +SELECT cosh(float8 'NaN'); +SELECT tanh(float8 '0'); +SELECT tanh(float8 'Infinity'); +SELECT tanh(float8 '-Infinity'); +SELECT tanh(float8 'NaN'); + RESET extra_float_digits;