Re: [PATCHES] WIP: rewrite numeric division

2007-06-18 Thread Tom Lane
Gregory Stark <[EMAIL PROTECTED]> writes:
> Where did we get the CVS-HEAD algorithm from anyways?

IIRC it's from Smith's "FM" library cited in numeric.c, which is also
where most of numeric.c's higher-order-function algorithms came from.
It's good code but oriented to scientific computing, which means it
thinks that a close approximation to the right answer is good enough.
In hindsight, there are too many people out there who expect div and mod
to be exact for us to go with that approach.

> wikipedia lists a whole
> bunch of multiplication algorithms -- none of which sound like this -- but
> only two division algorithms, "school-book" which is O(n^2) and Newton's
> Method which has complexity equal to the multiplication method used.

Yeah, my proposed patch is schoolbook division.  I don't think I'd trust
Newton's method to give anything but a close approximation, which is
what we have in HEAD already.

regards, tom lane

---(end of broadcast)---
TIP 5: don't forget to increase your free space map settings


Re: [PATCHES] WIP: rewrite numeric division

2007-06-18 Thread Gregory Stark
"Tom Lane" <[EMAIL PROTECTED]> writes:

> The bad news is that it's significantly slower than the CVS-HEAD code;
> it appears that for long inputs, div_var is something like 4X slower
> than before, depending on platform.  

Where did we get the CVS-HEAD algorithm from anyways? wikipedia lists a whole
bunch of multiplication algorithms -- none of which sound like this -- but
only two division algorithms, "school-book" which is O(n^2) and Newton's
Method which has complexity equal to the multiplication method used.

I'm not sure I see how to apply Newton's Method and get such low complexity
though. It seems to me like you would have to repeatedly multiply so you
should get an additional factor in the complexity representing the number of
iterations necessary.

> Still this is a bit annoying.  Anyone see a way to speed it up, or
> have another approach?

What order of complexity is this algorithm? It looks basically like O(n^2)
school-book division or is there something more clever going on?

-- 
  Gregory Stark
  EnterpriseDB  http://www.enterprisedb.com


---(end of broadcast)---
TIP 7: You can help support the PostgreSQL project by donating at

http://www.postgresql.org/about/donate


[PATCHES] Updated version of Numeric508

2007-06-18 Thread Simon Riggs
See -hackers thread for discussion.

Updated version of num508, against current CVS HEAD.

-- 
  Simon Riggs 
  EnterpriseDB   http://www.enterprisedb.com

Index: src/backend/utils/adt/numeric.c
===
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/numeric.c,v
retrieving revision 1.105
diff -c -r1.105 numeric.c
*** src/backend/utils/adt/numeric.c	15 Jun 2007 20:56:50 -	1.105
--- src/backend/utils/adt/numeric.c	17 Jun 2007 20:30:43 -
***
*** 85,93 
  #define MUL_GUARD_DIGITS	2	/* these are measured in NBASE digits */
  #define DIV_GUARD_DIGITS	4
  
! typedef int16 NumericDigit;
  #endif
  
  
  /* --
   * The value represented by a NumericVar is determined by the sign, weight,
--- 85,113 
  #define MUL_GUARD_DIGITS	2	/* these are measured in NBASE digits */
  #define DIV_GUARD_DIGITS	4
  
! typedef uint16 NumericDigit;
  #endif
  
+ /* -
+  * The storage format for NUMERIC is
+  *
+  * numeric header
+  *  int32		varlen is the standard variable length header			
+  *  weight		8 bits in int8 so +/-127; -128 is reserved for NUMERIC_NAN
+  *  scale		9 bits
+  *  first 8 bits in uint8
+  *  9th bit is the high order bit of first digit
+  *  signis the second highest bit of first digit
+  *
+  * numeric digits
+  *  an array of NumericDigits, each element storing NBASE
+  *  digits. All trailing and leading zeros are not stored,
+  *  apart from when the value is Zero AND the scale > 255
+  *  in which case we store a single zero digit, with the
+  *  sign set to NUMERIC_POS so the actual stored value
+  *  is equal to NUMERIC_DSCALE9_1
+  *--
+  */
  
  /* --
   * The value represented by a NumericVar is determined by the sign, weight,
***
*** 131,138 
  typedef struct NumericVar
  {
  	int			ndigits;		/* # of digits in digits[] - can be 0! */
! 	int			weight;			/* weight of first digit */
! 	int			sign;			/* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */
  	int			dscale;			/* display scale */
  	NumericDigit *buf;			/* start of palloc'd space for digits[] */
  	NumericDigit *digits;		/* base-NBASE digits */
--- 151,158 
  typedef struct NumericVar
  {
  	int			ndigits;		/* # of digits in digits[] - can be 0! */
! 	int			weight;			/* weight of first digit, or NUMERIC_NAN */
! 	int			sign;			/* NUMERIC_POS, NUMERIC_NEG */
  	int			dscale;			/* display scale */
  	NumericDigit *buf;			/* start of palloc'd space for digits[] */
  	NumericDigit *digits;		/* base-NBASE digits */
***
*** 200,206 
  {2, 0, NUMERIC_POS, 1, NULL, const_one_point_one_data};
  
  static NumericVar const_nan =
! {0, 0, NUMERIC_NAN, 0, NULL, NULL};
  
  #if DEC_DIGITS == 4
  static const int round_powers[4] = {0, 1000, 100, 10};
--- 220,226 
  {2, 0, NUMERIC_POS, 1, NULL, const_one_point_one_data};
  
  static NumericVar const_nan =
! {0, NUMERIC_NAN, 0, 0, NULL, NULL};
  
  #if DEC_DIGITS == 4
  static const int round_powers[4] = {0, 1000, 100, 10};
***
*** 381,386 
--- 401,412 
   *
   * External format is a sequence of int16's:
   * ndigits, weight, sign, dscale, NumericDigits.
+  *
+  * Note that the internal format is now different to the external format
+  * for the representation of NaN. In the external format, a value of
+  * NUMERIC_NAN_EXTERNAL in the sign field indicates NaN, which is converted
+  * into a NUMERIC_NAN in the weight field for the internal storage format and
+  * var formats. Sending data reverses this.
   */
  Datum
  numeric_recv(PG_FUNCTION_ARGS)
***
*** 407,426 
  	alloc_var(&value, len);
  
  	value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
  	value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
  	if (!(value.sign == NUMERIC_POS ||
  		  value.sign == NUMERIC_NEG ||
! 		  value.sign == NUMERIC_NAN))
  		ereport(ERROR,
  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
   errmsg("invalid sign in external \"numeric\" value")));
  
  	value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
  	for (i = 0; i < len; i++)
  	{
  		NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
  
! 		if (d < 0 || d >= NBASE)
  			ereport(ERROR,
  	(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
  	 errmsg("invalid digit in external \"numeric\" value")));
--- 433,469 
  	alloc_var(&value, len);
  
  	value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
+ 	if (!(value.weight > NUMERIC_NAN ||
+ 		  value.weight < NUMERIC_WEIGHT_MAX))
+ 		ereport(ERROR,
+ (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
+  errmsg("invalid weight in external \"numeric\" value")));
+ 
  	value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
  	if (!(value.sign == NUMERIC_POS ||
  		  value.sign == NUMERIC_NEG ||
! 		  value.sign == NUMERIC_NAN_EXTERNAL))
  		ereport(ERROR,

Re: [PATCHES] Remove comment about tab-complete.c

2007-06-18 Thread Magnus Hagander
On Mon, Jun 18, 2007 at 10:02:21AM +0100, Simon Riggs wrote:
> Remove line from guc.c
> 
> 6. Add it to src/bin/psql/tab-complete.c, if it's a USERSET option.
> 
> No longer required for parameters.

Wow, a simple enough patch that I could "review" it in no time :-)

Thanks, applied.

//Magnus

---(end of broadcast)---
TIP 4: Have you searched our list archives?

   http://archives.postgresql.org


[PATCHES] Remove comment about tab-complete.c

2007-06-18 Thread Simon Riggs
Remove line from guc.c

6. Add it to src/bin/psql/tab-complete.c, if it's a USERSET option.

No longer required for parameters.

-- 
  Simon Riggs 
  EnterpriseDB   http://www.enterprisedb.com

Index: src/backend/utils/misc/guc.c
===
RCS file: /projects/cvsroot/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.397
diff -c -r1.397 guc.c
*** src/backend/utils/misc/guc.c	13 Jun 2007 21:24:56 -	1.397
--- src/backend/utils/misc/guc.c	18 Jun 2007 09:01:32 -
***
*** 417,427 
   * 5. Add it to src/backend/utils/misc/postgresql.conf.sample, if
   *	  appropriate
   *
!  * 6. Add it to src/bin/psql/tab-complete.c, if it's a USERSET option.
   *
!  * 7. Don't forget to document the option.
!  *
!  * 8. If it's a new GUC_LIST option you must edit pg_dumpall.c to ensure
   *	  it is not single quoted at dump time.
   */
  
--- 417,425 
   * 5. Add it to src/backend/utils/misc/postgresql.conf.sample, if
   *	  appropriate
   *
!  * 6. Don't forget to document the option.
   *
!  * 7. If it's a new GUC_LIST option you must edit pg_dumpall.c to ensure
   *	  it is not single quoted at dump time.
   */
  

---(end of broadcast)---
TIP 6: explain analyze is your friend


Re: [PATCHES] Maintaining cluster order on insert

2007-06-18 Thread Gregory Stark
"Heikki Linnakangas" <[EMAIL PROTECTED]> writes:

> The reason for switching to the new API instead of the amsuggestblock API is
> CPU overhead. It avoids constructing the IndexTuple twice and descending the
> tree twice.

I wonder if it's possible to finesse this. Have the suggestblock function
remember the last block it suggested and somehow recognize when it's given the
same tuple to index. Keeping the block pinned would still be the sticky point
though.


-- 
  Gregory Stark
  EnterpriseDB  http://www.enterprisedb.com


---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly