diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index 70e9971dd1f64db554be27e878e78121a3b6fb97..e23706582e268a31ed79be5cfff1f9ec55e7120a 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.58 2003/11/29 19:51:58 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.59 2003/12/01 21:52:37 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,7 +26,7 @@
  *		 intpl, intmi, int4mul, intdiv
  *
  *		Arithmetic operators:
- *		 intmod, int4fac
+ *		 intmod
  */
 
 #include "postgres.h"
@@ -849,40 +849,6 @@ int42mod(PG_FUNCTION_ARGS)
 	PG_RETURN_INT32(arg1 % arg2);
 }
 
-/* int[24]fac()
- * Factorial
- */
-Datum
-int4fac(PG_FUNCTION_ARGS)
-{
-	int32		arg1 = PG_GETARG_INT32(0);
-	int32		result;
-
-	if (arg1 == 0)
-		result = 1;
-	else if (arg1 < 0)
-		result = 0;
-	else
-		for (result = 1; arg1 > 0; --arg1)
-			result *= arg1;
-	PG_RETURN_INT32(result);
-}
-
-Datum
-int2fac(PG_FUNCTION_ARGS)
-{
-	int16		arg1 = PG_GETARG_INT16(0);
-	int32		result;
-
-	if (arg1 == 0)
-		result = 1;
-	else if (arg1 < 0)
-		result = 0;
-	else
-		for (result = 1; arg1 > 0; --arg1)
-			result *= arg1;
-	PG_RETURN_INT32(result);
-}
 
 /* int[24]abs()
  * Absolute value
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index 616ceaaf9dbeb8c21c4591f67898fcbfdde4f49d..016330a053395a716d74914b00508437e0362cfb 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.49 2003/11/29 19:51:58 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.50 2003/12/01 21:52:37 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -561,26 +561,6 @@ int8mod(PG_FUNCTION_ARGS)
 	PG_RETURN_INT64(result);
 }
 
-/* int8fac()
- * Factorial
- */
-Datum
-int8fac(PG_FUNCTION_ARGS)
-{
-	int64		arg1 = PG_GETARG_INT64(0);
-	int64		result;
-	int64		i;
-
-	if (arg1 == 0)
-		result = 1;
-	else if (arg1 < 1)
-		result = 0;
-	else
-		for (i = arg1, result = 1; i > 0; --i)
-			result *= i;
-
-	PG_RETURN_INT64(result);
-}
 
 Datum
 int8inc(PG_FUNCTION_ARGS)
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index b2ffefa9da4bfbc6666b39da3ffe6725a3a50341..7f16ee37a247910126cb99ab0654080c8cda548b 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.68 2003/11/29 19:51:59 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.69 2003/12/01 21:52:37 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1288,6 +1288,55 @@ numeric_larger(PG_FUNCTION_ARGS)
  * ----------------------------------------------------------------------
  */
 
+/*
+ * numeric_fac()
+ * Computer factorial
+ */
+
+Datum
+numeric_fac(PG_FUNCTION_ARGS)
+{
+
+	int64		num = PG_GETARG_INT64(0);
+	NumericVar	count;
+	NumericVar	fact;
+	NumericVar	zerovar;
+	NumericVar	result;
+	Numeric		res;
+
+	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((int64)num,&fact);
+
+		mul_var(&count, &fact, &result, count.dscale + fact.dscale);
+	}
+
+	res = make_result(&count);
+
+	free_var(&count);
+	free_var(&fact);
+	free_var(&result);
+	free_var(&zerovar);
+
+	PG_RETURN_NUMERIC(res);
+}
+
 
 /*
  * numeric_sqrt() -
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index 42f19d7687dbad538c79e9fe8ac5fdfc4c30ed33..f9ce05af2a6751658b2647894e55757531df524e 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.122 2003/11/29 22:40:58 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.123 2003/12/01 21:52:37 momjian Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -122,12 +122,12 @@ DATA(insert OID = 375 (  "||"	   PGNSP PGUID b f 2277 2277 2277	0 0 0 0 0 0 arra
 
 DATA(insert OID = 352 (  "="	   PGNSP PGUID b t	28	28	16 352	 0	 0	 0	 0	 0 xideq eqsel eqjoinsel ));
 DATA(insert OID = 353 (  "="	   PGNSP PGUID b f	28	23	16	 0	 0	 0	 0	 0	 0 xideqint4 eqsel eqjoinsel ));
+DATA(insert OID = 388 (  "!"	   PGNSP PGUID r f  20   0  1700   0   0   0   0  0   0 numeric_fac - - ));
+DATA(insert OID = 389 (  "!!"	   PGNSP PGUID l f   0  20  1700   0   0   0   0  0   0 numeric_fac - - ));
 DATA(insert OID = 385 (  "="	   PGNSP PGUID b t	29	29	16 385	 0	 0	 0	 0	 0 cideq eqsel eqjoinsel ));
 DATA(insert OID = 386 (  "="	   PGNSP PGUID b t	22	22	16 386	 0	 0	 0	 0	 0 int2vectoreq eqsel eqjoinsel ));
 DATA(insert OID = 387 (  "="	   PGNSP PGUID b f	27	27	16 387	 0	 0	 0	 0	 0 tideq eqsel eqjoinsel ));
 #define TIDEqualOperator   387
-DATA(insert OID = 388 (  "!"	   PGNSP PGUID r f	20	 0	20	 0	 0	 0	 0	 0	 0 int8fac - - ));
-DATA(insert OID = 389 (  "!!"	   PGNSP PGUID l f	 0	20	20	 0	 0	 0	 0	 0	 0 int8fac - - ));
 
 DATA(insert OID = 410 ( "="		   PGNSP PGUID b t	20	20	16 410 411 412 412 412 413 int8eq eqsel eqjoinsel ));
 DATA(insert OID = 411 ( "<>"	   PGNSP PGUID b f	20	20	16 411 410 0 0 0 0 int8ne neqsel neqjoinsel ));
@@ -176,8 +176,6 @@ DATA(insert OID = 511 (  "@"	   PGNSP PGUID b f 600 603	16	 0	 0	 0	 0	 0	 0 on_
 DATA(insert OID = 512 (  "@"	   PGNSP PGUID b f 600 602	16 755	 0	 0	 0	 0	 0 on_ppath - - ));
 DATA(insert OID = 513 (  "@@"	   PGNSP PGUID l f	 0 603 600	 0	 0	 0	 0	 0	 0 box_center - - ));
 DATA(insert OID = 514 (  "*"	   PGNSP PGUID b f	23	23	23 514	 0	 0	 0	 0	 0 int4mul - - ));
-DATA(insert OID = 515 (  "!"	   PGNSP PGUID r f	23	 0	23	 0	 0	 0	 0	 0	 0 int4fac - - ));
-DATA(insert OID = 516 (  "!!"	   PGNSP PGUID l f	 0	23	23	 0	 0	 0	 0	 0	 0 int4fac - - ));
 DATA(insert OID = 517 (  "<->"	   PGNSP PGUID b f 600 600 701 517	 0	 0	 0	 0	 0 point_distance - - ));
 DATA(insert OID = 518 (  "<>"	   PGNSP PGUID b f	23	23	16 518	96	0  0   0   0 int4ne neqsel neqjoinsel ));
 DATA(insert OID = 519 (  "<>"	   PGNSP PGUID b f	21	21	16 519	94	0  0   0   0 int2ne neqsel neqjoinsel ));
@@ -507,8 +505,6 @@ DATA(insert OID = 1133 (  ">"		PGNSP PGUID b f  701	700  16 1122 1134  0 0 0 0 f
 DATA(insert OID = 1134 (  "<="		PGNSP PGUID b f  701	700  16 1125 1133  0 0 0 0 float84le scalarltsel scalarltjoinsel ));
 DATA(insert OID = 1135 (  ">="		PGNSP PGUID b f  701	700  16 1124 1132  0 0 0 0 float84ge scalargtsel scalargtjoinsel ));
 
-DATA(insert OID = 1158 (  "!"		PGNSP PGUID r f 21	  0   23 0 0 0 0 0 0 int2fac - - ));
-DATA(insert OID = 1175 (  "!!"		PGNSP PGUID l f  0	 21   23 0 0 0 0 0 0 int2fac - - ));
 
 /* LIKE hacks by Keith Parks. */
 DATA(insert OID = 1207 (  "~~"	  PGNSP PGUID b f  19	25	16 0 1208 0 0 0 0 namelike likesel likejoinsel ));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 5515a48d31cf4ba1a2883c75ee3a94d6cba2c9f8..1ed5359ffb9b4ebb130401ea8bdbcb494cc5e516 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.316 2003/11/29 22:40:58 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.317 2003/12/01 21:52:37 momjian Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -208,8 +208,6 @@ DESCR("PostgreSQL version string");
 
 /* OIDS 100 - 199 */
 
-DATA(insert OID = 100 (  int8fac		   PGNSP PGUID 12 f f t f i 1 20 "20"  int8fac - _null_ ));
-DESCR("factorial");
 DATA(insert OID = 101 (  eqsel			   PGNSP PGUID 12 f f t f s 4 701 "2281 26 2281 23"  eqsel - _null_ ));
 DESCR("restriction selectivity of = and related operators");
 DATA(insert OID = 102 (  neqsel			   PGNSP PGUID 12 f f t f s 4 701 "2281 26 2281 23"  neqsel - _null_ ));
@@ -231,7 +229,7 @@ DATA(insert OID =  109 (  unknownin		   PGNSP PGUID 12 f f t f i 1 705 "2275"	un
 DESCR("I/O");
 DATA(insert OID =  110 (  unknownout	   PGNSP PGUID 12 f f t f i 1 2275	"705"	unknownout - _null_ ));
 DESCR("I/O");
-
+DATA(insert OID = 111 (  numeric_fac	   PGNSP PGUID 12 f f t f i 1 1700 "20"  numeric_fac - _null_ ));
 DATA(insert OID = 112 (  text			   PGNSP PGUID 12 f f t f i 1  25 "23"	int4_text - _null_ ));
 DESCR("convert int4 to text");
 DATA(insert OID = 113 (  text			   PGNSP PGUID 12 f f t f i 1  25 "21"	int2_text - _null_ ));
@@ -294,8 +292,6 @@ DATA(insert OID = 140 (  areajoinsel	   PGNSP PGUID 12 f f t f s 4 701 "2281 26
 DESCR("join selectivity for area-comparison operators");
 DATA(insert OID = 141 (  int4mul		   PGNSP PGUID 12 f f t f i 2 23 "23 23"	int4mul - _null_ ));
 DESCR("multiply");
-DATA(insert OID = 142 (  int4fac		   PGNSP PGUID 12 f f t f i 1 23 "23"  int4fac - _null_ ));
-DESCR("factorial");
 DATA(insert OID = 144 (  int4ne			   PGNSP PGUID 12 f f t f i 2 16 "23 23"	int4ne - _null_ ));
 DESCR("not equal");
 DATA(insert OID = 145 (  int2ne			   PGNSP PGUID 12 f f t f i 2 16 "21 21"	int2ne - _null_ ));
@@ -571,9 +567,6 @@ DESCR("Current date and time - increments during transactions");
 DATA(insert OID = 275 (  isfinite		   PGNSP PGUID 12 f f t f i 1 16 "702"	abstime_finite - _null_ ));
 DESCR("finite abstime?");
 
-DATA(insert OID = 276 (  int2fac		   PGNSP PGUID 12 f f t f i 1 23 "21"  int2fac - _null_ ));
-DESCR("factorial");
-
 DATA(insert OID = 277 (  inter_sl		   PGNSP PGUID 12 f f t f i 2 16 "601 628"	inter_sl - _null_ ));
 DESCR("intersect?");
 DATA(insert OID = 278 (  inter_lb		   PGNSP PGUID 12 f f t f i 2 16 "628 603"	inter_lb - _null_ ));
@@ -1758,11 +1751,7 @@ DATA(insert OID = 1390 (  isfinite	   PGNSP PGUID 12 f f t f i 1 16 "1186"  inte
 DESCR("finite interval?");
 
 
-DATA(insert OID = 1391 (  factorial		   PGNSP PGUID 12 f f t f i 1 23 "21"  int2fac - _null_ ));
-DESCR("factorial");
-DATA(insert OID = 1392 (  factorial		   PGNSP PGUID 12 f f t f i 1 23 "23"  int4fac - _null_ ));
-DESCR("factorial");
-DATA(insert OID = 1393 (  factorial		   PGNSP PGUID 12 f f t f i 1 20 "20"  int8fac - _null_ ));
+DATA(insert OID = 1376 (  factorial        PGNSP PGUID 12 f f t f i 1 1700 "20"  numeric_fac - _null_ ));
 DESCR("factorial");
 DATA(insert OID = 1394 (  abs			   PGNSP PGUID 12 f f t f i 1 700 "700"  float4abs - _null_ ));
 DESCR("absolute value");
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 92663c3e5cd1ed1a4f64001ea9823be26c078548..c784f28afdc541558e0f7e109f2372ba382c9d11 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.230 2003/11/29 22:41:15 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.231 2003/12/01 21:52:38 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -159,8 +159,6 @@ extern Datum int4mod(PG_FUNCTION_ARGS);
 extern Datum int2mod(PG_FUNCTION_ARGS);
 extern Datum int24mod(PG_FUNCTION_ARGS);
 extern Datum int42mod(PG_FUNCTION_ARGS);
-extern Datum int4fac(PG_FUNCTION_ARGS);
-extern Datum int2fac(PG_FUNCTION_ARGS);
 extern Datum int2larger(PG_FUNCTION_ARGS);
 extern Datum int2smaller(PG_FUNCTION_ARGS);
 extern Datum int4larger(PG_FUNCTION_ARGS);
@@ -720,6 +718,7 @@ extern Datum numeric_mod(PG_FUNCTION_ARGS);
 extern Datum numeric_inc(PG_FUNCTION_ARGS);
 extern Datum numeric_smaller(PG_FUNCTION_ARGS);
 extern Datum numeric_larger(PG_FUNCTION_ARGS);
+extern Datum numeric_fac(PG_FUNCTION_ARGS);
 extern Datum numeric_sqrt(PG_FUNCTION_ARGS);
 extern Datum numeric_exp(PG_FUNCTION_ARGS);
 extern Datum numeric_ln(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/int8.h b/src/include/utils/int8.h
index aad610eb9eec42fef13a66b650806113b5ced293..7fe9800b2359010ee7f166bcd99a1cb27bffea75 100644
--- a/src/include/utils/int8.h
+++ b/src/include/utils/int8.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.39 2003/11/29 22:41:15 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.40 2003/12/01 21:52:38 momjian Exp $
  *
  * NOTES
  * These data types are supported on all 64-bit architectures, and may
@@ -72,7 +72,6 @@ extern Datum int8mi(PG_FUNCTION_ARGS);
 extern Datum int8mul(PG_FUNCTION_ARGS);
 extern Datum int8div(PG_FUNCTION_ARGS);
 extern Datum int8abs(PG_FUNCTION_ARGS);
-extern Datum int8fac(PG_FUNCTION_ARGS);
 extern Datum int8mod(PG_FUNCTION_ARGS);
 extern Datum int8inc(PG_FUNCTION_ARGS);
 extern Datum int8larger(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/create_operator.out b/src/test/regress/expected/create_operator.out
index 7685dbe802c74e7134bca5ac00aabe2aacce37ba..df25f35ae77cbea5302b4752c7b70f24aebe28ab 100644
--- a/src/test/regress/expected/create_operator.out
+++ b/src/test/regress/expected/create_operator.out
@@ -15,19 +15,17 @@ CREATE OPERATOR <% (
    negator = >=% 
 );
 CREATE OPERATOR @#@ (
-   rightarg = int4,		-- left unary 
-   procedure = int4fac 
+   rightarg = int8,		-- left unary 
+   procedure = numeric_fac 
 );
 CREATE OPERATOR #@# (
-   leftarg = int4,		-- right unary
-   procedure = int4fac 
+   leftarg = int8,		-- right unary
+   procedure = numeric_fac
 );
 CREATE OPERATOR #%# ( 
-   leftarg = int4,		-- right unary 
-   procedure = int4fac 
+   leftarg = int8,		-- right unary 
+   procedure = numeric_fac 
 );
 -- Test comments
 COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad right unary';
 ERROR:  operator does not exist: integer ######
-COMMENT ON OPERATOR #%# (int4, NONE) IS 'right unary';
-COMMENT ON OPERATOR #%# (int4, NONE) IS NULL;
diff --git a/src/test/regress/sql/create_operator.sql b/src/test/regress/sql/create_operator.sql
index 4167bf3ab825a0d472df192d35071d0883083a61..6637629ea44223e8a3b8b0481338c73eec1ebb07 100644
--- a/src/test/regress/sql/create_operator.sql
+++ b/src/test/regress/sql/create_operator.sql
@@ -18,23 +18,21 @@ CREATE OPERATOR <% (
 );
 
 CREATE OPERATOR @#@ (
-   rightarg = int4,		-- left unary 
-   procedure = int4fac 
+   rightarg = int8,		-- left unary 
+   procedure = numeric_fac 
 );
 
 CREATE OPERATOR #@# (
-   leftarg = int4,		-- right unary
-   procedure = int4fac 
+   leftarg = int8,		-- right unary
+   procedure = numeric_fac
 );
 
 CREATE OPERATOR #%# ( 
-   leftarg = int4,		-- right unary 
-   procedure = int4fac 
+   leftarg = int8,		-- right unary 
+   procedure = numeric_fac 
 );
 
 -- Test comments
 COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad right unary';
-COMMENT ON OPERATOR #%# (int4, NONE) IS 'right unary';
-COMMENT ON OPERATOR #%# (int4, NONE) IS NULL;