diff --git a/doc/src/sgml/ref/drop_operator.sgml b/doc/src/sgml/ref/drop_operator.sgml
index 4c14954c48238eef8550552e79729e77d12d7f28..5b17ebec1b5bd508718199a2ea6c5ca7d77afe2f 100644
--- a/doc/src/sgml/ref/drop_operator.sgml
+++ b/doc/src/sgml/ref/drop_operator.sgml
@@ -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
 -->
 
@@ -108,9 +108,9 @@ DROP OPERATOR ~ (none, bit);
 
   <para>
    Remove the right unary factorial operator <literal>x!</literal>
-   for type <type>integer</type>:
+   for type <type>bigint</type>:
 <programlisting>
-DROP OPERATOR ! (integer, none);
+DROP OPERATOR ! (bigint, none);
 </programlisting>
   </para>
  </refsect1>
diff --git a/doc/src/sgml/typeconv.sgml b/doc/src/sgml/typeconv.sgml
index bd68c242b3cdf7e777d9299d0134421570acc168..64a1a5c98574dc8b60e75c194d2eef718fc0659e 100644
--- a/doc/src/sgml/typeconv.sgml
+++ b/doc/src/sgml/typeconv.sgml
@@ -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">
@@ -412,7 +412,7 @@ type to resolve the unknown literals to.
 </example>
 
 <example>
-<title>Absolute-Value and Factorial Operator Type Resolution</title>
+<title>Absolute-Value and Negation Operator Type Resolution</title>
 
 <para>
 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
 </screen>
 </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>
 
 </sect1>
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 7f16ee37a247910126cb99ab0654080c8cda548b..e825b101a1656070629673f6edba6aace194ae9a 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -14,7 +14,7 @@
  * Copyright (c) 1998-2003, PostgreSQL Global Development Group
  *
  * 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()
- * Computer factorial
+ *
+ * Compute factorial
  */
-
 Datum
 numeric_fac(PG_FUNCTION_ARGS)
 {
-
 	int64		num = PG_GETARG_INT64(0);
-	NumericVar	count;
+	Numeric		res;
 	NumericVar	fact;
-	NumericVar	zerovar;
 	NumericVar	result;
-	Numeric		res;
 
-	if(num < 1) {
+	if (num <= 1)
+	{
 		res = make_result(&const_one);
 		PG_RETURN_NUMERIC(res);
 	}
 
-
 	init_var(&fact);
-	init_var(&count);
 	init_var(&result);
-	init_var(&zerovar);
-	zero_var(&zerovar);
-
-	int8_to_numericvar((int64)num, &result);
-	set_var_from_var(&const_one, &count);
 
-	for(num = num - 1; num > 0; num--) {
-		set_var_from_var(&result,&count);
+	int8_to_numericvar(num, &result);
 
-		int8_to_numericvar((int64)num,&fact);
+	for (num = num - 1; num > 1; num--)
+	{
+		int8_to_numericvar(num, &fact);
 
-		mul_var(&count, &fact, &result, count.dscale + fact.dscale);
+		mul_var(&result, &fact, &result, 0);
 	}
 
-	res = make_result(&count);
+	res = make_result(&result);
 
-	free_var(&count);
 	free_var(&fact);
 	free_var(&result);
-	free_var(&zerovar);
 
 	PG_RETURN_NUMERIC(res);
 }