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

Reply via email to