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);
---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
       choose an index scan if your joining column's datatypes do not
       match

Reply via email to