pg.ddx.io pgsql-docs@postgresql.org mailing list archive
help / color / mirror / Atom feedNumeric version of factorial()
9+ messages / 3 participants
[nested] [flat]
* Numeric version of factorial()
@ 2003-08-01 00:58 Gavin Sherry <swm@linuxworld.com.au>
0 siblings, 3 replies; 9+ messages in thread
From: Gavin Sherry @ 2003-08-01 00:58 UTC (permalink / raw)
To: pgsql-patches@postgresql.org
Attached is a patch implementing factorial(), returning numeric. Points to
note:
1) arttype is numeric. I thought this was the best way of allowing
arbitarily large factorials, even though factorial(2^63) is a large
number. Happy to change to integers if this is overkill.
2) since we're accepting numeric arguments, the patch tests for floats. If
a numeric is passed with non-zero decimal portion, an error is raised
since (from memory) they are undefined.
3) I have not removed factorial([int2|int4|int8]), not their operator
counterparts since I didn't know what people would want done with these.
4) I haven't added any documentation but am happy to once I know if people
want int or numeric arguments.
Thanks,
Gavin
Attachments:
factorial.diff (text/plain, 5.9K) download
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 14:48:23 -0000
***************
*** 1312,1315 ****
--- 1312,1429 ----
*/
+ /*
+ * numeric_fac()
+ * Computer factorial
+ */
+
+ Datum
+ numeric_fac(PG_FUNCTION_ARGS)
+ {
+
+ Numeric num1 = PG_GETARG_NUMERIC(0);
+ NumericVar count;
+ NumericVar fact;
+ NumericVar one;
+ NumericVar zerovar;
+ NumericVar result;
+ NumericVar tmp;
+ Numeric res;
+ int ret;
+ bool firstcall = true;
+
+ /*
+ * Handle NaN
+ */
+ if (NUMERIC_IS_NAN(num1))
+ PG_RETURN_NUMERIC(make_result(&const_nan));
+
+ init_var(&fact);
+ init_var(&one);
+ set_var_from_num(num1, &fact);
+ int8_to_numericvar((int64)1, &one);
+
+ ret = cmp_var(&fact, &one);
+
+ /* if <= 1, return(1) */
+
+ if(ret < 1) {
+ res = make_result(&one);
+ free_var(&fact);
+ free_var(&one);
+ PG_RETURN_NUMERIC(res);
+ }
+
+ init_var(&tmp);
+ set_var_from_num(num1, &fact);
+
+ /*
+ * n.x! is undefined, truncate factorial, and compare
+ * to original
+ */
+
+ set_var_from_var(&fact, &tmp);
+ trunc_var(&tmp,0);
+ ret = cmp_var(&fact, &tmp);
+ if(ret != 0) {
+ elog(ERROR,"Factorials can only be calculated on natural numbers");
+ }
+
+ /*
+ * Truncate factorial anyway, since n.0000 might have been passed
+ */
+
+ trunc_var(&fact, 0);
+
+ init_var(&count);
+ init_var(&result);
+ init_var(&zerovar);
+ zero_var(&zerovar);
+
+
+ int8_to_numericvar((int64)1, &one);
+ set_var_from_var(&one, &count);
+
+ /*
+ * Interate through N ... 1, multipling `count' by `fact' each time
+ */
+
+ while(1) {
+ if(!firstcall) {
+ free_var(&count);
+ init_var(&count);
+ set_var_from_var(&result,&count);
+
+ free_var(&result);
+ init_var(&result);
+
+ sub_var(&fact, &one, &result);
+ free_var(&fact);
+ init_var(&fact);
+ set_var_from_var(&result,&fact);
+
+ ret = cmp_var(&fact, &zerovar);
+ if(ret == 0) {
+ break;
+ }
+
+ free_var(&result);
+ init_var(&result);
+ } else {
+ firstcall = false;
+ }
+ mul_var(&count, &fact, &result, count.dscale + fact.dscale);
+ }
+
+ res = make_result(&count);
+
+ free_var(&count);
+ free_var(&fact);
+ free_var(&result);
+ free_var(&one);
+ 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 14:03:54 -0000
***************
*** 123,126 ****
--- 123,128 ----
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 1700 0 1700 0 0 0 0 0 0 numeric_fac - - ));
+ DATA(insert OID = 381 ( "!!" PGNSP PGUID r f 1700 0 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 ));
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 14:42:12 -0000
***************
*** 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");
--- 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 = 111 ( numeric_fac PGNSP PGUID 12 f f t f i 1 1700 "1700" 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");
***************
*** 1758,1761 ****
--- 1758,1763 ----
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 = 1376 ( factorial PGNSP PGUID 12 f f t f i 1 1700 "1700" 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 31 Jul 2003 18:21:12 -0000
***************
*** 705,708 ****
--- 705,709 ----
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);
^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: Numeric version of factorial()
@ 2003-08-01 01:37 Tom Lane <tgl@sss.pgh.pa.us>
parent: Gavin Sherry <swm@linuxworld.com.au>
2 siblings, 1 reply; 9+ messages in thread
From: Tom Lane @ 2003-08-01 01:37 UTC (permalink / raw)
To: Gavin Sherry <swm@linuxworld.com.au>; +Cc: pgsql-patches@postgresql.org
Gavin Sherry <swm@linuxworld.com.au> writes:
> 2) since we're accepting numeric arguments, the patch tests for floats. If
> a numeric is passed with non-zero decimal portion, an error is raised
> since (from memory) they are undefined.
There is a standard mathematical definition for it (gamma function,
IIRC) but this is probably plenty good enough for our purposes. I would
suggest though that you reject fractions before you short-circuit for
x <= 1.
> 3) I have not removed factorial([int2|int4|int8]), not their operator
> counterparts since I didn't know what people would want done with these.
We had already decided to nuke the int2 and int4 versions, since they
overflow far too easily. I'd go with nuking int8 too and providing only
the numeric variant ...
> + int8_to_numericvar((int64)1, &one);
> +
> + ret = cmp_var(&fact, &one);
Uh, why not use const_one?
regards, tom lane
^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: Numeric version of factorial()
@ 2003-08-01 01:57 Gavin Sherry <swm@linuxworld.com.au>
parent: Tom Lane <tgl@sss.pgh.pa.us>
0 siblings, 1 reply; 9+ messages in thread
From: Gavin Sherry @ 2003-08-01 01:57 UTC (permalink / raw)
To: Tom Lane <tgl@sss.pgh.pa.us>; +Cc: pgsql-patches@postgresql.org
On Thu, 31 Jul 2003, Tom Lane wrote:
> Gavin Sherry <swm@linuxworld.com.au> writes:
> > 2) since we're accepting numeric arguments, the patch tests for floats. If
> > a numeric is passed with non-zero decimal portion, an error is raised
> > since (from memory) they are undefined.
>
> There is a standard mathematical definition for it (gamma function,
> IIRC) but this is probably plenty good enough for our purposes. I would
> suggest though that you reject fractions before you short-circuit for
> x <= 1.
Oops.
>
> > 3) I have not removed factorial([int2|int4|int8]), not their operator
> > counterparts since I didn't know what people would want done with these.
>
> We had already decided to nuke the int2 and int4 versions, since they
> overflow far too easily. I'd go with nuking int8 too and providing only
> the numeric variant ...
What are your feelings about numeric argument vs. int4/int8 arguments?
>
> > + int8_to_numericvar((int64)1, &one);
> > +
> > + ret = cmp_var(&fact, &one);
>
> Uh, why not use const_one?
Umm.. didn't notice it :-).
Thanks,
Gavin
^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: Numeric version of factorial()
@ 2003-08-01 02:08 Tom Lane <tgl@sss.pgh.pa.us>
parent: Gavin Sherry <swm@linuxworld.com.au>
0 siblings, 1 reply; 9+ messages in thread
From: Tom Lane @ 2003-08-01 02:08 UTC (permalink / raw)
To: Gavin Sherry <swm@linuxworld.com.au>; +Cc: pgsql-patches@postgresql.org
Gavin Sherry <swm@linuxworld.com.au> 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.
regards, tom lane
^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: Numeric version of factorial()
@ 2003-08-01 03:31 Gavin Sherry <swm@linuxworld.com.au>
parent: Tom Lane <tgl@sss.pgh.pa.us>
0 siblings, 1 reply; 9+ messages in thread
From: Gavin Sherry @ 2003-08-01 03:31 UTC (permalink / raw)
To: Tom Lane <tgl@sss.pgh.pa.us>; +Cc: pgsql-patches@postgresql.org
On Thu, 31 Jul 2003, Tom Lane wrote:
> Gavin Sherry <swm@linuxworld.com.au> 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
Attachments:
factorial2.diff (text/plain, 13.1K) download
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 #@# (
! 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 #@# (
! 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 #@# (
! 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 #@# (
! leftarg = int8, -- right unary
! procedure = numeric_fac
);
CREATE OPERATOR #%# (
! leftarg = int8, -- right unary
! procedure = numeric_fac
);
^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: Numeric version of factorial()
@ 2003-12-01 04:48 Bruce Momjian <pgman@candle.pha.pa.us>
parent: Gavin Sherry <swm@linuxworld.com.au>
0 siblings, 0 replies; 9+ messages in thread
From: Bruce Momjian @ 2003-12-01 04:48 UTC (permalink / raw)
To: Gavin Sherry <swm@linuxworld.com.au>; +Cc: Tom Lane <tgl@sss.pgh.pa.us>; pgsql-patches@postgresql.org
Your patch has been added to the PostgreSQL unapplied patches list at:
http://momjian.postgresql.org/cgi-bin/pgpatches
I will try to apply it within the next 48 hours.
---------------------------------------------------------------------------
Gavin Sherry wrote:
> On Thu, 31 Jul 2003, Tom Lane wrote:
>
> > Gavin Sherry <swm@linuxworld.com.au> 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
Content-Description:
[ Attachment, skipping... ]
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
> (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: Numeric version of factorial()
@ 2003-12-01 21:36 Bruce Momjian <pgman@candle.pha.pa.us>
parent: Gavin Sherry <swm@linuxworld.com.au>
2 siblings, 0 replies; 9+ messages in thread
From: Bruce Momjian @ 2003-12-01 21:36 UTC (permalink / raw)
To: Gavin Sherry <swm@linuxworld.com.au>; +Cc: pgsql-patches@postgresql.org
Patch attached and applied. Thanks.
I adjusted the oid so prevent a duplicate, and adjusted the regression
test to remove comments on now non-existant functions.
I also tested the output and it looks good:
test=> select numeric_fac(10);
numeric_fac
-------------
3628800
(1 row)
test=> select numeric_fac(1);
numeric_fac
-------------
1
(1 row)
test=> select numeric_fac(2);
numeric_fac
-------------
2
(1 row)
test=> select numeric_fac(4);
numeric_fac
-------------
24
(1 row)
test=> select numeric_fac(3);
numeric_fac
-------------
6
(1 row)
I will check the docs now.
---------------------------------------------------------------------------
Gavin Sherry wrote:
> Attached is a patch implementing factorial(), returning numeric. Points to
> note:
>
> 1) arttype is numeric. I thought this was the best way of allowing
> arbitarily large factorials, even though factorial(2^63) is a large
> number. Happy to change to integers if this is overkill.
> 2) since we're accepting numeric arguments, the patch tests for floats. If
> a numeric is passed with non-zero decimal portion, an error is raised
> since (from memory) they are undefined.
> 3) I have not removed factorial([int2|int4|int8]), not their operator
> counterparts since I didn't know what people would want done with these.
> 4) I haven't added any documentation but am happy to once I know if people
> want int or numeric arguments.
> 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().
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Attachments:
/bjm/33 (text/plain, 15.3K) download
Index: src/backend/utils/adt/int.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/adt/int.c,v
retrieving revision 1.58
diff -c -c -r1.58 int.c
*** src/backend/utils/adt/int.c 29 Nov 2003 19:51:58 -0000 1.58
--- src/backend/utils/adt/int.c 1 Dec 2003 21:30:41 -0000
***************
*** 26,32 ****
* intpl, intmi, int4mul, intdiv
*
* Arithmetic operators:
! * intmod, int4fac
*/
#include "postgres.h"
--- 26,32 ----
* intpl, intmi, int4mul, intdiv
*
* Arithmetic operators:
! * intmod
*/
#include "postgres.h"
***************
*** 849,888 ****
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
--- 849,854 ----
Index: src/backend/utils/adt/int8.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/adt/int8.c,v
retrieving revision 1.49
diff -c -c -r1.49 int8.c
*** src/backend/utils/adt/int8.c 29 Nov 2003 19:51:58 -0000 1.49
--- src/backend/utils/adt/int8.c 1 Dec 2003 21:30:41 -0000
***************
*** 561,586 ****
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)
--- 561,566 ----
Index: src/backend/utils/adt/numeric.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/adt/numeric.c,v
retrieving revision 1.68
diff -c -c -r1.68 numeric.c
*** src/backend/utils/adt/numeric.c 29 Nov 2003 19:51:59 -0000 1.68
--- src/backend/utils/adt/numeric.c 1 Dec 2003 21:30:45 -0000
***************
*** 1288,1293 ****
--- 1288,1342 ----
* ----------------------------------------------------------------------
*/
+ /*
+ * 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() -
Index: src/include/catalog/pg_operator.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/catalog/pg_operator.h,v
retrieving revision 1.122
diff -c -c -r1.122 pg_operator.h
*** src/include/catalog/pg_operator.h 29 Nov 2003 22:40:58 -0000 1.122
--- src/include/catalog/pg_operator.h 1 Dec 2003 21:30:48 -0000
***************
*** 122,133 ****
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 ));
DATA(insert OID = 411 ( "<>" PGNSP PGUID b f 20 20 16 411 410 0 0 0 0 int8ne neqsel neqjoinsel ));
--- 122,133 ----
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 = 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,183 ****
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 ));
--- 176,181 ----
***************
*** 507,514 ****
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 ));
--- 505,510 ----
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v
retrieving revision 1.316
diff -c -c -r1.316 pg_proc.h
*** src/include/catalog/pg_proc.h 29 Nov 2003 22:40:58 -0000 1.316
--- src/include/catalog/pg_proc.h 1 Dec 2003 21:30:53 -0000
***************
*** 208,215 ****
/* 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_ ));
--- 208,213 ----
***************
*** 231,237 ****
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 = 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_ ));
--- 229,235 ----
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,301 ****
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_ ));
--- 292,297 ----
***************
*** 571,579 ****
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_ ));
--- 567,572 ----
***************
*** 1758,1768 ****
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_ ));
DESCR("factorial");
DATA(insert OID = 1394 ( abs PGNSP PGUID 12 f f t f i 1 700 "700" float4abs - _null_ ));
DESCR("absolute value");
--- 1751,1757 ----
DESCR("finite interval?");
! 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");
Index: src/include/utils/builtins.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/utils/builtins.h,v
retrieving revision 1.230
diff -c -c -r1.230 builtins.h
*** src/include/utils/builtins.h 29 Nov 2003 22:41:15 -0000 1.230
--- src/include/utils/builtins.h 1 Dec 2003 21:30:53 -0000
***************
*** 159,166 ****
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);
--- 159,164 ----
***************
*** 720,725 ****
--- 718,724 ----
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);
Index: src/include/utils/int8.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/utils/int8.h,v
retrieving revision 1.39
diff -c -c -r1.39 int8.h
*** src/include/utils/int8.h 29 Nov 2003 22:41:15 -0000 1.39
--- src/include/utils/int8.h 1 Dec 2003 21:30:53 -0000
***************
*** 72,78 ****
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);
--- 72,77 ----
Index: src/test/regress/expected/create_operator.out
===================================================================
RCS file: /cvsroot/pgsql-server/src/test/regress/expected/create_operator.out,v
retrieving revision 1.5
diff -c -c -r1.5 create_operator.out
*** src/test/regress/expected/create_operator.out 21 Nov 2003 22:32:49 -0000 1.5
--- src/test/regress/expected/create_operator.out 1 Dec 2003 21:30:54 -0000
***************
*** 15,33 ****
negator = >=%
);
CREATE OPERATOR @#@ (
! rightarg = int4, -- left unary
! procedure = int4fac
);
CREATE OPERATOR #@# (
! leftarg = int4, -- right unary
! procedure = int4fac
);
CREATE OPERATOR #%# (
! leftarg = int4, -- right unary
! procedure = int4fac
);
-- 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;
--- 15,31 ----
negator = >=%
);
CREATE OPERATOR @#@ (
! rightarg = int8, -- left unary
! procedure = numeric_fac
);
CREATE OPERATOR #@# (
! leftarg = int8, -- right unary
! procedure = numeric_fac
);
CREATE OPERATOR #%# (
! leftarg = int8, -- right unary
! procedure = numeric_fac
);
-- Test comments
COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad right unary';
ERROR: operator does not exist: integer ######
Index: src/test/regress/sql/create_operator.sql
===================================================================
RCS file: /cvsroot/pgsql-server/src/test/regress/sql/create_operator.sql,v
retrieving revision 1.5
diff -c -c -r1.5 create_operator.sql
*** src/test/regress/sql/create_operator.sql 21 Nov 2003 22:32:49 -0000 1.5
--- src/test/regress/sql/create_operator.sql 1 Dec 2003 21:30:54 -0000
***************
*** 18,40 ****
);
CREATE OPERATOR @#@ (
! rightarg = int4, -- left unary
! procedure = int4fac
);
CREATE OPERATOR #@# (
! leftarg = int4, -- right unary
! procedure = int4fac
);
CREATE OPERATOR #%# (
! leftarg = int4, -- right unary
! procedure = int4fac
);
-- 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;
--- 18,38 ----
);
CREATE OPERATOR @#@ (
! rightarg = int8, -- left unary
! procedure = numeric_fac
);
CREATE OPERATOR #@# (
! leftarg = int8, -- right unary
! procedure = numeric_fac
);
CREATE OPERATOR #%# (
! leftarg = int8, -- right unary
! procedure = numeric_fac
);
-- Test comments
COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad right unary';
^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: [PATCHES] Numeric version of factorial()
@ 2003-12-01 21:54 Bruce Momjian <pgman@candle.pha.pa.us>
parent: Gavin Sherry <swm@linuxworld.com.au>
2 siblings, 1 reply; 9+ messages in thread
From: Bruce Momjian @ 2003-12-01 21:54 UTC (permalink / raw)
To: Gavin Sherry <swm@linuxworld.com.au>; +Cc: pgsql-docs
I had to remove the factorial example from the casting docs because
factorial is now defined only for numeric. Would someone take the
attached example and make a new one with a different operator?
Thanks.
---------------------------------------------------------------------------
Gavin Sherry wrote:
> Attached is a patch implementing factorial(), returning numeric. Points to
> note:
>
> 1) arttype is numeric. I thought this was the best way of allowing
> arbitarily large factorials, even though factorial(2^63) is a large
> number. Happy to change to integers if this is overkill.
> 2) since we're accepting numeric arguments, the patch tests for floats. If
> a numeric is passed with non-zero decimal portion, an error is raised
> since (from memory) they are undefined.
> 3) I have not removed factorial([int2|int4|int8]), not their operator
> counterparts since I didn't know what people would want done with these.
> 4) I haven't added any documentation but am happy to once I know if people
> want int or numeric arguments.
>
> Thanks,
>
> Gavin
Content-Description:
[ Attachment, skipping... ]
>
> ---------------------------(end of broadcast)---------------------------
> TIP 3: if posting/reading through Usenet, please send an appropriate
> subscribe-nomail command to majordomo@postgresql.org so that your
> message can get through to the mailing list cleanly
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Attachments:
/pgpatches/factorial (text/plain, 1.2K) download
Index: doc/src/sgml/typeconv.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/typeconv.sgml,v
retrieving revision 1.39
diff -c -c -r1.39 typeconv.sgml
*** doc/src/sgml/typeconv.sgml 29 Nov 2003 19:51:38 -0000 1.39
--- doc/src/sgml/typeconv.sgml 1 Dec 2003 21:42:04 -0000
***************
*** 437,466 ****
ERROR: "-4.5e500" is out of range for type double precision
</screen>
</para>
-
- <para>
- On the other hand, the postfix operator <literal>!</> (factorial)
- 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 "factorial";
-
- 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 "factorial";
-
- factorial
- ---------------------
- 2432902008176640000
- (1 row)
- </screen>
- </para>
</example>
</sect1>
--- 437,442 ----
^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: [PATCHES] Numeric version of factorial()
@ 2003-12-02 00:27 Tom Lane <tgl@sss.pgh.pa.us>
parent: Bruce Momjian <pgman@candle.pha.pa.us>
0 siblings, 0 replies; 9+ messages in thread
From: Tom Lane @ 2003-12-02 00:27 UTC (permalink / raw)
To: Bruce Momjian <pgman@candle.pha.pa.us>; +Cc: Gavin Sherry <swm@linuxworld.com.au>; pgsql-docs
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> I had to remove the factorial example from the casting docs because
> factorial is now defined only for numeric. Would someone take the
> attached example and make a new one with a different operator?
Done.
regards, tom lane
^ permalink raw reply [nested|flat] 9+ messages in thread
end of thread, other threads:[~2003-12-02 00:27 UTC | newest]
Thread overview: 9+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2003-08-01 00:58 Numeric version of factorial() Gavin Sherry <swm@linuxworld.com.au>
2003-08-01 01:37 ` Tom Lane <tgl@sss.pgh.pa.us>
2003-08-01 01:57 ` Gavin Sherry <swm@linuxworld.com.au>
2003-08-01 02:08 ` Tom Lane <tgl@sss.pgh.pa.us>
2003-08-01 03:31 ` Gavin Sherry <swm@linuxworld.com.au>
2003-12-01 04:48 ` Bruce Momjian <pgman@candle.pha.pa.us>
2003-12-01 21:36 ` Bruce Momjian <pgman@candle.pha.pa.us>
2003-12-01 21:54 ` Bruce Momjian <pgman@candle.pha.pa.us>
2003-12-02 00:27 ` Tom Lane <tgl@sss.pgh.pa.us>
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox