Code and docs review for numeric-factorial patch.

This commit is contained in:
Tom Lane 2003-12-02 00:26:59 +00:00
parent ea4b9f14f3
commit 145d9fa46c
3 changed files with 42 additions and 28 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/drop_operator.sgml,v 1.23 2003/11/29 19:51:38 pgsql Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/drop_operator.sgml,v 1.24 2003/12/02 00:26:59 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -108,9 +108,9 @@ DROP OPERATOR ~ (none, bit);
<para> <para>
Remove the right unary factorial operator <literal>x!</literal> Remove the right unary factorial operator <literal>x!</literal>
for type <type>integer</type>: for type <type>bigint</type>:
<programlisting> <programlisting>
DROP OPERATOR ! (integer, none); DROP OPERATOR ! (bigint, none);
</programlisting> </programlisting>
</para> </para>
</refsect1> </refsect1>

View File

@ -1,5 +1,5 @@
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/typeconv.sgml,v 1.40 2003/12/01 21:53:15 momjian Exp $ $PostgreSQL: pgsql/doc/src/sgml/typeconv.sgml,v 1.41 2003/12/02 00:26:59 tgl Exp $
--> -->
<chapter Id="typeconv"> <chapter Id="typeconv">
@ -412,7 +412,7 @@ type to resolve the unknown literals to.
</example> </example>
<example> <example>
<title>Absolute-Value and Factorial Operator Type Resolution</title> <title>Absolute-Value and Negation Operator Type Resolution</title>
<para> <para>
The <productname>PostgreSQL</productname> operator catalog has several The <productname>PostgreSQL</productname> operator catalog has several
@ -437,6 +437,30 @@ SELECT @ '-4.5e500' AS "abs";
ERROR: "-4.5e500" is out of range for type double precision ERROR: "-4.5e500" is out of range for type double precision
</screen> </screen>
</para> </para>
<para>
On the other hand, the prefix operator <literal>~</> (bitwise negation)
is defined only for integer data types, not for <type>float8</type>. So, if we
try a similar case with <literal>~</>, we get:
<screen>
SELECT ~ '20' AS "negation";
ERROR: operator is not unique: ~ "unknown"
HINT: Could not choose a best candidate operator. You may need to add explicit
type casts.
</screen>
This happens because the system can't decide which of the several
possible <literal>~</> operators should be preferred. We can help
it out with an explicit cast:
<screen>
SELECT ~ CAST('20' AS int8) AS "negation";
negation
----------
-21
(1 row)
</screen>
</para>
</example> </example>
</sect1> </sect1>

View File

@ -14,7 +14,7 @@
* Copyright (c) 1998-2003, PostgreSQL Global Development Group * Copyright (c) 1998-2003, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.69 2003/12/01 21:52:37 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.70 2003/12/02 00:26:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1290,49 +1290,39 @@ numeric_larger(PG_FUNCTION_ARGS)
/* /*
* numeric_fac() * numeric_fac()
* Computer factorial *
* Compute factorial
*/ */
Datum Datum
numeric_fac(PG_FUNCTION_ARGS) numeric_fac(PG_FUNCTION_ARGS)
{ {
int64 num = PG_GETARG_INT64(0); int64 num = PG_GETARG_INT64(0);
NumericVar count;
NumericVar fact;
NumericVar zerovar;
NumericVar result;
Numeric res; Numeric res;
NumericVar fact;
NumericVar result;
if(num < 1) { if (num <= 1)
{
res = make_result(&const_one); res = make_result(&const_one);
PG_RETURN_NUMERIC(res); PG_RETURN_NUMERIC(res);
} }
init_var(&fact); init_var(&fact);
init_var(&count);
init_var(&result); init_var(&result);
init_var(&zerovar);
zero_var(&zerovar);
int8_to_numericvar((int64)num, &result); int8_to_numericvar(num, &result);
set_var_from_var(&const_one, &count);
for(num = num - 1; num > 0; num--) { for (num = num - 1; num > 1; num--)
set_var_from_var(&result,&count); {
int8_to_numericvar(num, &fact);
int8_to_numericvar((int64)num,&fact); mul_var(&result, &fact, &result, 0);
mul_var(&count, &fact, &result, count.dscale + fact.dscale);
} }
res = make_result(&count); res = make_result(&result);
free_var(&count);
free_var(&fact); free_var(&fact);
free_var(&result); free_var(&result);
free_var(&zerovar);
PG_RETURN_NUMERIC(res); PG_RETURN_NUMERIC(res);
} }