Search Postgresql Archives

Re: intarray internals

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

[I'm trying to share some of my thoughts about intarray contrib module.
If this is the wrong way to achieve this, please warn me. (Should I
first get in touch with Teodor Sigaev and Oleg Bartunov?)]

[6]
_int_same() in _int_op.c looks like making some redundant sorting and
not taking advantage of sorted arrays while comparing each other. Here's
the related code piece:

SORT(a);
SORT(b);
na = ARRNELEMS(a);
nb = ARRNELEMS(b);
da = ARRPTR(a);
db = ARRPTR(b);

result = FALSE;

if (na == nb)                                                                      
{   
    result = TRUE;
    for (n = 0; n < na; n++)
        if (da[n] != db[n])
        {
            result = FALSE;
            break;
        }
}

IMHO, SORT() macro should be called after "if (na == nb)" block. (SORT()
doesn't remove duplicates.) Also, in the inner block, while comparing
two arrays, we can take advantage of sorting of arrays. While current
behaviour is like

if (A[0] == B[0] && A[1] == B[1] && ...)

we can replace it with sth like

if (A[0] == B[0] && A[  N] == B[  N] &&
    A[1] == B[1] && A[N-1] == B[N-1] &&
    ...)

Attached patch tries to implement both behaviours mentioned above and
some minor hacking for arrays of 1,2 and 3 items.


Regards.
Index: contrib/intarray/_int_op.c
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/intarray/_int_op.c,v
retrieving revision 1.4
diff -c -r1.4 _int_op.c
*** contrib/intarray/_int_op.c	19 Nov 2005 03:00:09 -0000	1.4
--- contrib/intarray/_int_op.c	8 May 2006 18:50:43 -0000
***************
*** 69,77 ****
  	ArrayType  *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
  	int			na,
  				nb;
- 	int			n;
- 	int		   *da,
- 			   *db;
  	bool		result;
  	bool		avoid;
  	bool		bvoid;
--- 69,74 ----
***************
*** 83,106 ****
  	if (avoid || bvoid)
  		return (avoid && bvoid) ? TRUE : FALSE;
  
- 	SORT(a);
- 	SORT(b);
  	na = ARRNELEMS(a);
  	nb = ARRNELEMS(b);
! 	da = ARRPTR(a);
! 	db = ARRPTR(b);
! 
  	result = FALSE;
  
  	if (na == nb)
  	{
! 		result = TRUE;
! 		for (n = 0; n < na; n++)
! 			if (da[n] != db[n])
! 			{
! 				result = FALSE;
  				break;
  			}
  	}
  
  	pfree(a);
--- 80,155 ----
  	if (avoid || bvoid)
  		return (avoid && bvoid) ? TRUE : FALSE;
  
  	na = ARRNELEMS(a);
  	nb = ARRNELEMS(b);
! 	
  	result = FALSE;
  
  	if (na == nb)
  	{
! 		int	*da;
! 		int *db;
! 		
! 		SORT(a);
! 		SORT(b);
! 		da = ARRPTR(a);
! 		db = ARRPTR(b);
! 
! 		switch (na)
! 		{
! 			/*
! 			 * Some little hack for small length arrays.
! 			 */
! 			case 1:
! 				result = (da[0] == db[0]) ? TRUE : FALSE;
  				break;
+ 
+ 			case 2:
+ 				result = (da[0] == db[0] &&
+ 						  da[1] == db[1]) ? TRUE : FALSE;
+ 				break;
+ 
+ 			case 3:
+ 				result = (da[0] == db[0] &&
+ 						  da[1] == db[1] &&
+ 						  da[2] == db[2]) ? TRUE : FALSE;
+ 				break;
+ 
+ 			/*
+ 			 * Instead of making a brute force comparison, trying to take
+ 			 * advantage of sorted arrays.
+ 			 */
+ 			default:
+ 			{
+ 				int head = 0;
+ 				int toe = na - 1;
+ 				
+ 				result = TRUE;
+ 				
+ 				/*
+ 				 * Don't bother with even length arrays. Consume their first
+ 				 * element and carry on as arrays' lengths are odd.
+ 				 */
+ 				if (na % 2 == 0)
+ 				{
+ 					result = (*da++ == *db++) ? TRUE : FALSE;
+ 					toe--;
+ 				}
+ 		
+ 				if (result == TRUE)
+ 					while (head <= toe)
+ 					{
+ 						if (da[head] != db[head] || da[toe] != db[toe])
+ 						{
+ 							result = FALSE;
+ 							break;
+ 						}
+ 		
+ 						head++;
+ 						toe--;
+ 					}
  			}
+ 		}
  	}
  
  	pfree(a);

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]
  Powered by Linux