diff options
author | Bruce Momjian <bruce@momjian.us> | 2003-12-01 21:52:38 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2003-12-01 21:52:38 +0000 |
commit | 04a4821adef38155b7920ba9eb83c4c3c29156f8 (patch) | |
tree | c778c2d286441d98a2453f06f5af9c2b214ffc3e /src/backend/utils/adt/numeric.c | |
parent | af03663878b257f7fb93a80eec03a8dd070b22b7 (diff) | |
download | postgresql-04a4821adef38155b7920ba9eb83c4c3c29156f8.tar.gz postgresql-04a4821adef38155b7920ba9eb83c4c3c29156f8.zip |
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.
Gavin Sherry
Diffstat (limited to 'src/backend/utils/adt/numeric.c')
-rw-r--r-- | src/backend/utils/adt/numeric.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index b2ffefa9da4..7f16ee37a24 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() - |