On Thu, 31 Jul 2003, Tom Lane wrote:
> Gavin Sherry <[EMAIL PROTECTED]> writes:
> > What are your feelings about numeric argument vs. int4/int8 arguments?
>
> Actually I think it'd be fine to take int8. We'd not be able to cope
> with any larger input anyway, and the inner loop could be noticeably
> faster if the control logic just deals with int.
>
> We could leave the factorial(numeric) case open for a future
> implementation that uses gamma, if anyone gets hot to do it.
>
Attached is a revised patch based on your Tom's comments. It removes
int[248]fac(), modifies regression tests (which referenced int4fac()), and
implements a much cleaned numeric_fac().
> regards, tom lane
>
Thanks,
Gavin
Index: src/backend/utils/adt/int.c
===================================================================
RCS file: /usr/local/cvsroot/pgsql-server/src/backend/utils/adt/int.c,v
retrieving revision 1.54
diff -2 -c -r1.54 int.c
*** src/backend/utils/adt/int.c 9 May 2003 15:44:40 -0000 1.54
--- src/backend/utils/adt/int.c 1 Aug 2003 17:11:18 -0000
***************
*** 27,31 ****
*
* Arithmetic operators:
! * intmod, int4fac
*/
--- 27,31 ----
*
* Arithmetic operators:
! * intmod
*/
***************
*** 835,872 ****
}
- /* 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()
--- 835,838 ----
Index: src/backend/utils/adt/int8.c
===================================================================
RCS file: /usr/local/cvsroot/pgsql-server/src/backend/utils/adt/int8.c,v
retrieving revision 1.44
diff -2 -c -r1.44 int8.c
*** src/backend/utils/adt/int8.c 9 May 2003 15:44:40 -0000 1.44
--- src/backend/utils/adt/int8.c 1 Aug 2003 17:00:09 -0000
***************
*** 552,575 ****
}
- /* 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
--- 552,555 ----
Index: src/backend/utils/adt/numeric.c
===================================================================
RCS file: /usr/local/cvsroot/pgsql-server/src/backend/utils/adt/numeric.c,v
retrieving revision 1.62
diff -2 -c -r1.62 numeric.c
*** src/backend/utils/adt/numeric.c 3 Jul 2003 19:41:47 -0000 1.62
--- src/backend/utils/adt/numeric.c 1 Aug 2003 16:43:30 -0000
***************
*** 1312,1315 ****
--- 1312,1364 ----
*/
+ /*
+ * 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);
+ }
+
/*
Index: src/include/catalog/pg_operator.h
===================================================================
RCS file: /usr/local/cvsroot/pgsql-server/src/include/catalog/pg_operator.h,v
retrieving revision 1.118
diff -2 -c -r1.118 pg_operator.h
*** src/include/catalog/pg_operator.h 27 Jun 2003 00:33:25 -0000 1.118
--- src/include/catalog/pg_operator.h 1 Aug 2003 16:55:58 -0000
***************
*** 123,132 ****
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 = 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 ));
--- 123,132 ----
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 = 380 ( "!" PGNSP PGUID r f 20 0 1700 0 0 0 0 0
0 numeric_fac - - ));
+ DATA(insert OID = 381 ( "!!" 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 = 410 ( "=" PGNSP PGUID b t 20 20 16 410
411 412 412 412 413 int8eq eqsel eqjoinsel ));
***************
*** 177,182 ****
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 ));
--- 177,180 ----
***************
*** 507,512 ****
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. */
--- 505,508 ----
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /usr/local/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v
retrieving revision 1.309
diff -2 -c -r1.309 pg_proc.h
*** src/include/catalog/pg_proc.h 1 Jul 2003 00:04:38 -0000 1.309
--- src/include/catalog/pg_proc.h 1 Aug 2003 17:10:49 -0000
***************
*** 209,214 ****
/* 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");
--- 209,212 ----
***************
*** 232,236 ****
DATA(insert OID = 110 ( unknownout PGNSP PGUID 12 f f t f i 1 2275 "705"
unknownout - _null_ ));
DESCR("I/O");
!
DATA(insert OID = 112 ( text PGNSP PGUID 12 f f t f i 1 25 "23"
int4_text - _null_ ));
DESCR("convert int4 to text");
--- 230,234 ----
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");
***************
*** 295,300 ****
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");
--- 293,296 ----
***************
*** 574,580 ****
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?");
--- 570,573 ----
***************
*** 1753,1761 ****
! 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_ ));
DESCR("factorial");
DATA(insert OID = 1394 ( abs PGNSP PGUID 12 f f t f i 1 700
"700" float4abs - _null_ ));
--- 1746,1750 ----
! 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_ ));
Index: src/include/utils/builtins.h
===================================================================
RCS file: /usr/local/cvsroot/pgsql-server/src/include/utils/builtins.h,v
retrieving revision 1.223
diff -2 -c -r1.223 builtins.h
*** src/include/utils/builtins.h 27 Jun 2003 00:33:26 -0000 1.223
--- src/include/utils/builtins.h 1 Aug 2003 17:00:29 -0000
***************
*** 160,165 ****
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);
--- 160,163 ----
***************
*** 705,708 ****
--- 703,707 ----
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);
Index: src/include/utils/int8.h
===================================================================
RCS file: /usr/local/cvsroot/pgsql-server/src/include/utils/int8.h,v
retrieving revision 1.37
diff -2 -c -r1.37 int8.h
*** src/include/utils/int8.h 9 May 2003 15:44:42 -0000 1.37
--- src/include/utils/int8.h 1 Aug 2003 17:00:47 -0000
***************
*** 73,77 ****
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);
--- 73,76 ----
Index: src/test/regress/expected/create_operator.out
===================================================================
RCS file:
/usr/local/cvsroot/pgsql-server/src/test/regress/expected/create_operator.out,v
retrieving revision 1.4
diff -2 -c -r1.4 create_operator.out
*** src/test/regress/expected/create_operator.out 5 Jan 2000 17:31:08 -0000
1.4
--- src/test/regress/expected/create_operator.out 1 Aug 2003 17:21:32 -0000
***************
*** 16,28 ****
);
CREATE OPERATOR @#@ (
! rightarg = int4, -- left unary
! procedure = int4fac
);
CREATE OPERATOR [EMAIL PROTECTED] (
! leftarg = int4, -- right unary
! procedure = int4fac
);
CREATE OPERATOR #%# (
! leftarg = int4, -- right unary
! procedure = int4fac
);
--- 16,28 ----
);
CREATE OPERATOR @#@ (
! rightarg = int8, -- left unary
! procedure = numeric_fac
);
CREATE OPERATOR [EMAIL PROTECTED] (
! leftarg = int8, -- right unary
! procedure = numeric_fac
);
CREATE OPERATOR #%# (
! leftarg = int8, -- right unary
! procedure = numeric_fac
);
Index: src/test/regress/sql/create_operator.sql
===================================================================
RCS file: /usr/local/cvsroot/pgsql-server/src/test/regress/sql/create_operator.sql,v
retrieving revision 1.4
diff -2 -c -r1.4 create_operator.sql
*** src/test/regress/sql/create_operator.sql 5 Jan 2000 17:32:29 -0000 1.4
--- src/test/regress/sql/create_operator.sql 1 Aug 2003 17:19:08 -0000
***************
*** 19,34 ****
CREATE OPERATOR @#@ (
! rightarg = int4, -- left unary
! procedure = int4fac
);
CREATE OPERATOR [EMAIL PROTECTED] (
! leftarg = int4, -- right unary
! procedure = int4fac
);
CREATE OPERATOR #%# (
! leftarg = int4, -- right unary
! procedure = int4fac
);
--- 19,34 ----
CREATE OPERATOR @#@ (
! rightarg = int8, -- left unary
! procedure = numeric_fac
);
CREATE OPERATOR [EMAIL PROTECTED] (
! leftarg = int8, -- right unary
! procedure = numeric_fac
);
CREATE OPERATOR #%# (
! leftarg = int8, -- right unary
! procedure = numeric_fac
);
---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])