Skip to content

Commit 04a4821

Browse files
committed
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
1 parent af03663 commit 04a4821

File tree

9 files changed

+74
-100
lines changed

9 files changed

+74
-100
lines changed

src/backend/utils/adt/int.c

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.58 2003/11/29 19:51:58 pgsql Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.59 2003/12/01 21:52:37 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -26,7 +26,7 @@
2626
* intpl, intmi, int4mul, intdiv
2727
*
2828
* Arithmetic operators:
29-
* intmod, int4fac
29+
* intmod
3030
*/
3131

3232
#include "postgres.h"
@@ -849,40 +849,6 @@ int42mod(PG_FUNCTION_ARGS)
849849
PG_RETURN_INT32(arg1 % arg2);
850850
}
851851

852-
/* int[24]fac()
853-
* Factorial
854-
*/
855-
Datum
856-
int4fac(PG_FUNCTION_ARGS)
857-
{
858-
int32 arg1 = PG_GETARG_INT32(0);
859-
int32 result;
860-
861-
if (arg1 == 0)
862-
result = 1;
863-
else if (arg1 < 0)
864-
result = 0;
865-
else
866-
for (result = 1; arg1 > 0; --arg1)
867-
result *= arg1;
868-
PG_RETURN_INT32(result);
869-
}
870-
871-
Datum
872-
int2fac(PG_FUNCTION_ARGS)
873-
{
874-
int16 arg1 = PG_GETARG_INT16(0);
875-
int32 result;
876-
877-
if (arg1 == 0)
878-
result = 1;
879-
else if (arg1 < 0)
880-
result = 0;
881-
else
882-
for (result = 1; arg1 > 0; --arg1)
883-
result *= arg1;
884-
PG_RETURN_INT32(result);
885-
}
886852

887853
/* int[24]abs()
888854
* Absolute value

src/backend/utils/adt/int8.c

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.49 2003/11/29 19:51:58 pgsql Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.50 2003/12/01 21:52:37 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -561,26 +561,6 @@ int8mod(PG_FUNCTION_ARGS)
561561
PG_RETURN_INT64(result);
562562
}
563563

564-
/* int8fac()
565-
* Factorial
566-
*/
567-
Datum
568-
int8fac(PG_FUNCTION_ARGS)
569-
{
570-
int64 arg1 = PG_GETARG_INT64(0);
571-
int64 result;
572-
int64 i;
573-
574-
if (arg1 == 0)
575-
result = 1;
576-
else if (arg1 < 1)
577-
result = 0;
578-
else
579-
for (i = arg1, result = 1; i > 0; --i)
580-
result *= i;
581-
582-
PG_RETURN_INT64(result);
583-
}
584564

585565
Datum
586566
int8inc(PG_FUNCTION_ARGS)

src/backend/utils/adt/numeric.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* Copyright (c) 1998-2003, PostgreSQL Global Development Group
1515
*
1616
* IDENTIFICATION
17-
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.68 2003/11/29 19:51:59 pgsql Exp $
17+
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.69 2003/12/01 21:52:37 momjian Exp $
1818
*
1919
*-------------------------------------------------------------------------
2020
*/
@@ -1288,6 +1288,55 @@ numeric_larger(PG_FUNCTION_ARGS)
12881288
* ----------------------------------------------------------------------
12891289
*/
12901290

1291+
/*
1292+
* numeric_fac()
1293+
* Computer factorial
1294+
*/
1295+
1296+
Datum
1297+
numeric_fac(PG_FUNCTION_ARGS)
1298+
{
1299+
1300+
int64 num = PG_GETARG_INT64(0);
1301+
NumericVar count;
1302+
NumericVar fact;
1303+
NumericVar zerovar;
1304+
NumericVar result;
1305+
Numeric res;
1306+
1307+
if(num < 1) {
1308+
res = make_result(&const_one);
1309+
PG_RETURN_NUMERIC(res);
1310+
}
1311+
1312+
1313+
init_var(&fact);
1314+
init_var(&count);
1315+
init_var(&result);
1316+
init_var(&zerovar);
1317+
zero_var(&zerovar);
1318+
1319+
int8_to_numericvar((int64)num, &result);
1320+
set_var_from_var(&const_one, &count);
1321+
1322+
for(num = num - 1; num > 0; num--) {
1323+
set_var_from_var(&result,&count);
1324+
1325+
int8_to_numericvar((int64)num,&fact);
1326+
1327+
mul_var(&count, &fact, &result, count.dscale + fact.dscale);
1328+
}
1329+
1330+
res = make_result(&count);
1331+
1332+
free_var(&count);
1333+
free_var(&fact);
1334+
free_var(&result);
1335+
free_var(&zerovar);
1336+
1337+
PG_RETURN_NUMERIC(res);
1338+
}
1339+
12911340

12921341
/*
12931342
* numeric_sqrt() -

src/include/catalog/pg_operator.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.122 2003/11/29 22:40:58 pgsql Exp $
11+
* $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.123 2003/12/01 21:52:37 momjian Exp $
1212
*
1313
* NOTES
1414
* 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
122122

123123
DATA(insert OID = 352 ( "=" PGNSP PGUID b t 28 28 16 352 0 0 0 0 0 xideq eqsel eqjoinsel ));
124124
DATA(insert OID = 353 ( "=" PGNSP PGUID b f 28 23 16 0 0 0 0 0 0 xideqint4 eqsel eqjoinsel ));
125+
DATA(insert OID = 388 ( "!" PGNSP PGUID r f 20 0 1700 0 0 0 0 0 0 numeric_fac - - ));
126+
DATA(insert OID = 389 ( "!!" PGNSP PGUID l f 0 20 1700 0 0 0 0 0 0 numeric_fac - - ));
125127
DATA(insert OID = 385 ( "=" PGNSP PGUID b t 29 29 16 385 0 0 0 0 0 cideq eqsel eqjoinsel ));
126128
DATA(insert OID = 386 ( "=" PGNSP PGUID b t 22 22 16 386 0 0 0 0 0 int2vectoreq eqsel eqjoinsel ));
127129
DATA(insert OID = 387 ( "=" PGNSP PGUID b f 27 27 16 387 0 0 0 0 0 tideq eqsel eqjoinsel ));
128130
#define TIDEqualOperator 387
129-
DATA(insert OID = 388 ( "!" PGNSP PGUID r f 20 0 20 0 0 0 0 0 0 int8fac - - ));
130-
DATA(insert OID = 389 ( "!!" PGNSP PGUID l f 0 20 20 0 0 0 0 0 0 int8fac - - ));
131131

132132
DATA(insert OID = 410 ( "=" PGNSP PGUID b t 20 20 16 410 411 412 412 412 413 int8eq eqsel eqjoinsel ));
133133
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_
176176
DATA(insert OID = 512 ( "@" PGNSP PGUID b f 600 602 16 755 0 0 0 0 0 on_ppath - - ));
177177
DATA(insert OID = 513 ( "@@" PGNSP PGUID l f 0 603 600 0 0 0 0 0 0 box_center - - ));
178178
DATA(insert OID = 514 ( "*" PGNSP PGUID b f 23 23 23 514 0 0 0 0 0 int4mul - - ));
179-
DATA(insert OID = 515 ( "!" PGNSP PGUID r f 23 0 23 0 0 0 0 0 0 int4fac - - ));
180-
DATA(insert OID = 516 ( "!!" PGNSP PGUID l f 0 23 23 0 0 0 0 0 0 int4fac - - ));
181179
DATA(insert OID = 517 ( "<->" PGNSP PGUID b f 600 600 701 517 0 0 0 0 0 point_distance - - ));
182180
DATA(insert OID = 518 ( "<>" PGNSP PGUID b f 23 23 16 518 96 0 0 0 0 int4ne neqsel neqjoinsel ));
183181
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
507505
DATA(insert OID = 1134 ( "<=" PGNSP PGUID b f 701 700 16 1125 1133 0 0 0 0 float84le scalarltsel scalarltjoinsel ));
508506
DATA(insert OID = 1135 ( ">=" PGNSP PGUID b f 701 700 16 1124 1132 0 0 0 0 float84ge scalargtsel scalargtjoinsel ));
509507

510-
DATA(insert OID = 1158 ( "!" PGNSP PGUID r f 21 0 23 0 0 0 0 0 0 int2fac - - ));
511-
DATA(insert OID = 1175 ( "!!" PGNSP PGUID l f 0 21 23 0 0 0 0 0 0 int2fac - - ));
512508

513509
/* LIKE hacks by Keith Parks. */
514510
DATA(insert OID = 1207 ( "~~" PGNSP PGUID b f 19 25 16 0 1208 0 0 0 0 namelike likesel likejoinsel ));

src/include/catalog/pg_proc.h

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.316 2003/11/29 22:40:58 pgsql Exp $
10+
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.317 2003/12/01 21:52:37 momjian Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -208,8 +208,6 @@ DESCR("PostgreSQL version string");
208208

209209
/* OIDS 100 - 199 */
210210

211-
DATA(insert OID = 100 ( int8fac PGNSP PGUID 12 f f t f i 1 20 "20" int8fac - _null_ ));
212-
DESCR("factorial");
213211
DATA(insert OID = 101 ( eqsel PGNSP PGUID 12 f f t f s 4 701 "2281 26 2281 23" eqsel - _null_ ));
214212
DESCR("restriction selectivity of = and related operators");
215213
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
231229
DESCR("I/O");
232230
DATA(insert OID = 110 ( unknownout PGNSP PGUID 12 f f t f i 1 2275 "705" unknownout - _null_ ));
233231
DESCR("I/O");
234-
232+
DATA(insert OID = 111 ( numeric_fac PGNSP PGUID 12 f f t f i 1 1700 "20" numeric_fac - _null_ ));
235233
DATA(insert OID = 112 ( text PGNSP PGUID 12 f f t f i 1 25 "23" int4_text - _null_ ));
236234
DESCR("convert int4 to text");
237235
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
294292
DESCR("join selectivity for area-comparison operators");
295293
DATA(insert OID = 141 ( int4mul PGNSP PGUID 12 f f t f i 2 23 "23 23" int4mul - _null_ ));
296294
DESCR("multiply");
297-
DATA(insert OID = 142 ( int4fac PGNSP PGUID 12 f f t f i 1 23 "23" int4fac - _null_ ));
298-
DESCR("factorial");
299295
DATA(insert OID = 144 ( int4ne PGNSP PGUID 12 f f t f i 2 16 "23 23" int4ne - _null_ ));
300296
DESCR("not equal");
301297
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");
571567
DATA(insert OID = 275 ( isfinite PGNSP PGUID 12 f f t f i 1 16 "702" abstime_finite - _null_ ));
572568
DESCR("finite abstime?");
573569

574-
DATA(insert OID = 276 ( int2fac PGNSP PGUID 12 f f t f i 1 23 "21" int2fac - _null_ ));
575-
DESCR("factorial");
576-
577570
DATA(insert OID = 277 ( inter_sl PGNSP PGUID 12 f f t f i 2 16 "601 628" inter_sl - _null_ ));
578571
DESCR("intersect?");
579572
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
17581751
DESCR("finite interval?");
17591752

17601753

1761-
DATA(insert OID = 1391 ( factorial PGNSP PGUID 12 f f t f i 1 23 "21" int2fac - _null_ ));
1762-
DESCR("factorial");
1763-
DATA(insert OID = 1392 ( factorial PGNSP PGUID 12 f f t f i 1 23 "23" int4fac - _null_ ));
1764-
DESCR("factorial");
1765-
DATA(insert OID = 1393 ( factorial PGNSP PGUID 12 f f t f i 1 20 "20" int8fac - _null_ ));
1754+
DATA(insert OID = 1376 ( factorial PGNSP PGUID 12 f f t f i 1 1700 "20" numeric_fac - _null_ ));
17661755
DESCR("factorial");
17671756
DATA(insert OID = 1394 ( abs PGNSP PGUID 12 f f t f i 1 700 "700" float4abs - _null_ ));
17681757
DESCR("absolute value");

src/include/utils/builtins.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.230 2003/11/29 22:41:15 pgsql Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.231 2003/12/01 21:52:38 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -159,8 +159,6 @@ extern Datum int4mod(PG_FUNCTION_ARGS);
159159
extern Datum int2mod(PG_FUNCTION_ARGS);
160160
extern Datum int24mod(PG_FUNCTION_ARGS);
161161
extern Datum int42mod(PG_FUNCTION_ARGS);
162-
extern Datum int4fac(PG_FUNCTION_ARGS);
163-
extern Datum int2fac(PG_FUNCTION_ARGS);
164162
extern Datum int2larger(PG_FUNCTION_ARGS);
165163
extern Datum int2smaller(PG_FUNCTION_ARGS);
166164
extern Datum int4larger(PG_FUNCTION_ARGS);
@@ -720,6 +718,7 @@ extern Datum numeric_mod(PG_FUNCTION_ARGS);
720718
extern Datum numeric_inc(PG_FUNCTION_ARGS);
721719
extern Datum numeric_smaller(PG_FUNCTION_ARGS);
722720
extern Datum numeric_larger(PG_FUNCTION_ARGS);
721+
extern Datum numeric_fac(PG_FUNCTION_ARGS);
723722
extern Datum numeric_sqrt(PG_FUNCTION_ARGS);
724723
extern Datum numeric_exp(PG_FUNCTION_ARGS);
725724
extern Datum numeric_ln(PG_FUNCTION_ARGS);

src/include/utils/int8.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.39 2003/11/29 22:41:15 pgsql Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.40 2003/12/01 21:52:38 momjian Exp $
1111
*
1212
* NOTES
1313
* These data types are supported on all 64-bit architectures, and may
@@ -72,7 +72,6 @@ extern Datum int8mi(PG_FUNCTION_ARGS);
7272
extern Datum int8mul(PG_FUNCTION_ARGS);
7373
extern Datum int8div(PG_FUNCTION_ARGS);
7474
extern Datum int8abs(PG_FUNCTION_ARGS);
75-
extern Datum int8fac(PG_FUNCTION_ARGS);
7675
extern Datum int8mod(PG_FUNCTION_ARGS);
7776
extern Datum int8inc(PG_FUNCTION_ARGS);
7877
extern Datum int8larger(PG_FUNCTION_ARGS);

src/test/regress/expected/create_operator.out

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,17 @@ CREATE OPERATOR <% (
1515
negator = >=%
1616
);
1717
CREATE OPERATOR @#@ (
18-
rightarg = int4, -- left unary
19-
procedure = int4fac
18+
rightarg = int8, -- left unary
19+
procedure = numeric_fac
2020
);
2121
CREATE OPERATOR #@# (
22-
leftarg = int4, -- right unary
23-
procedure = int4fac
22+
leftarg = int8, -- right unary
23+
procedure = numeric_fac
2424
);
2525
CREATE OPERATOR #%# (
26-
leftarg = int4, -- right unary
27-
procedure = int4fac
26+
leftarg = int8, -- right unary
27+
procedure = numeric_fac
2828
);
2929
-- Test comments
3030
COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad right unary';
3131
ERROR: operator does not exist: integer ######
32-
COMMENT ON OPERATOR #%# (int4, NONE) IS 'right unary';
33-
COMMENT ON OPERATOR #%# (int4, NONE) IS NULL;

src/test/regress/sql/create_operator.sql

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,21 @@ CREATE OPERATOR <% (
1818
);
1919

2020
CREATE OPERATOR @#@ (
21-
rightarg = int4, -- left unary
22-
procedure = int4fac
21+
rightarg = int8, -- left unary
22+
procedure = numeric_fac
2323
);
2424

2525
CREATE OPERATOR #@# (
26-
leftarg = int4, -- right unary
27-
procedure = int4fac
26+
leftarg = int8, -- right unary
27+
procedure = numeric_fac
2828
);
2929

3030
CREATE OPERATOR #%# (
31-
leftarg = int4, -- right unary
32-
procedure = int4fac
31+
leftarg = int8, -- right unary
32+
procedure = numeric_fac
3333
);
3434

3535
-- Test comments
3636
COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad right unary';
37-
COMMENT ON OPERATOR #%# (int4, NONE) IS 'right unary';
38-
COMMENT ON OPERATOR #%# (int4, NONE) IS NULL;
3937

4038

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy