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);