summaryrefslogtreecommitdiffstats
path: root/contrib/intarray/_int_tool.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--contrib/intarray/_int_tool.c410
1 files changed, 410 insertions, 0 deletions
diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c
new file mode 100644
index 0000000..91690af
--- /dev/null
+++ b/contrib/intarray/_int_tool.c
@@ -0,0 +1,410 @@
+/*
+ * contrib/intarray/_int_tool.c
+ */
+#include "postgres.h"
+
+#include <limits.h>
+
+#include "_int.h"
+#include "catalog/pg_type.h"
+#include "lib/qunique.h"
+
+/* arguments are assumed sorted & unique-ified */
+bool
+inner_int_contains(ArrayType *a, ArrayType *b)
+{
+ int na,
+ nb;
+ int i,
+ j,
+ n;
+ int *da,
+ *db;
+
+ na = ARRNELEMS(a);
+ nb = ARRNELEMS(b);
+ da = ARRPTR(a);
+ db = ARRPTR(b);
+
+ i = j = n = 0;
+ while (i < na && j < nb)
+ {
+ if (da[i] < db[j])
+ i++;
+ else if (da[i] == db[j])
+ {
+ n++;
+ i++;
+ j++;
+ }
+ else
+ break; /* db[j] is not in da */
+ }
+
+ return (n == nb) ? true : false;
+}
+
+/* arguments are assumed sorted */
+bool
+inner_int_overlap(ArrayType *a, ArrayType *b)
+{
+ int na,
+ nb;
+ int i,
+ j;
+ int *da,
+ *db;
+
+ na = ARRNELEMS(a);
+ nb = ARRNELEMS(b);
+ da = ARRPTR(a);
+ db = ARRPTR(b);
+
+ i = j = 0;
+ while (i < na && j < nb)
+ {
+ if (da[i] < db[j])
+ i++;
+ else if (da[i] == db[j])
+ return true;
+ else
+ j++;
+ }
+
+ return false;
+}
+
+ArrayType *
+inner_int_union(ArrayType *a, ArrayType *b)
+{
+ ArrayType *r = NULL;
+
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
+ if (ARRISEMPTY(a) && ARRISEMPTY(b))
+ return new_intArrayType(0);
+ if (ARRISEMPTY(a))
+ r = copy_intArrayType(b);
+ if (ARRISEMPTY(b))
+ r = copy_intArrayType(a);
+
+ if (!r)
+ {
+ int na = ARRNELEMS(a),
+ nb = ARRNELEMS(b);
+ int *da = ARRPTR(a),
+ *db = ARRPTR(b);
+ int i,
+ j,
+ *dr;
+
+ r = new_intArrayType(na + nb);
+ dr = ARRPTR(r);
+
+ /* union */
+ i = j = 0;
+ while (i < na && j < nb)
+ {
+ if (da[i] == db[j])
+ {
+ *dr++ = da[i++];
+ j++;
+ }
+ else if (da[i] < db[j])
+ *dr++ = da[i++];
+ else
+ *dr++ = db[j++];
+ }
+
+ while (i < na)
+ *dr++ = da[i++];
+ while (j < nb)
+ *dr++ = db[j++];
+
+ r = resize_intArrayType(r, dr - ARRPTR(r));
+ }
+
+ if (ARRNELEMS(r) > 1)
+ r = _int_unique(r);
+
+ return r;
+}
+
+ArrayType *
+inner_int_inter(ArrayType *a, ArrayType *b)
+{
+ ArrayType *r;
+ int na,
+ nb;
+ int *da,
+ *db,
+ *dr;
+ int i,
+ j,
+ k;
+
+ if (ARRISEMPTY(a) || ARRISEMPTY(b))
+ return new_intArrayType(0);
+
+ na = ARRNELEMS(a);
+ nb = ARRNELEMS(b);
+ da = ARRPTR(a);
+ db = ARRPTR(b);
+ r = new_intArrayType(Min(na, nb));
+ dr = ARRPTR(r);
+
+ i = j = k = 0;
+ while (i < na && j < nb)
+ {
+ if (da[i] < db[j])
+ i++;
+ else if (da[i] == db[j])
+ {
+ if (k == 0 || dr[k - 1] != db[j])
+ dr[k++] = db[j];
+ i++;
+ j++;
+ }
+ else
+ j++;
+ }
+
+ if (k == 0)
+ {
+ pfree(r);
+ return new_intArrayType(0);
+ }
+ else
+ return resize_intArrayType(r, k);
+}
+
+void
+rt__int_size(ArrayType *a, float *size)
+{
+ *size = (float) ARRNELEMS(a);
+}
+
+/* qsort_arg comparison function for isort() */
+static int
+isort_cmp(const void *a, const void *b, void *arg)
+{
+ int32 aval = *((const int32 *) a);
+ int32 bval = *((const int32 *) b);
+
+ if (aval < bval)
+ return -1;
+ if (aval > bval)
+ return 1;
+
+ /*
+ * Report if we have any duplicates. If there are equal keys, qsort must
+ * compare them at some point, else it wouldn't know whether one should go
+ * before or after the other.
+ */
+ *((bool *) arg) = true;
+ return 0;
+}
+
+/* Sort the given data (len >= 2). Return true if any duplicates found */
+bool
+isort(int32 *a, int len)
+{
+ bool r = false;
+
+ qsort_arg(a, len, sizeof(int32), isort_cmp, (void *) &r);
+ return r;
+}
+
+/* Create a new int array with room for "num" elements */
+ArrayType *
+new_intArrayType(int num)
+{
+ ArrayType *r;
+ int nbytes;
+
+ /* if no elements, return a zero-dimensional array */
+ if (num <= 0)
+ {
+ Assert(num == 0);
+ r = construct_empty_array(INT4OID);
+ return r;
+ }
+
+ nbytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int) * num;
+
+ r = (ArrayType *) palloc0(nbytes);
+
+ SET_VARSIZE(r, nbytes);
+ ARR_NDIM(r) = 1;
+ r->dataoffset = 0; /* marker for no null bitmap */
+ ARR_ELEMTYPE(r) = INT4OID;
+ ARR_DIMS(r)[0] = num;
+ ARR_LBOUND(r)[0] = 1;
+
+ return r;
+}
+
+ArrayType *
+resize_intArrayType(ArrayType *a, int num)
+{
+ int nbytes;
+ int i;
+
+ /* if no elements, return a zero-dimensional array */
+ if (num <= 0)
+ {
+ Assert(num == 0);
+ a = construct_empty_array(INT4OID);
+ return a;
+ }
+
+ if (num == ARRNELEMS(a))
+ return a;
+
+ nbytes = ARR_DATA_OFFSET(a) + sizeof(int) * num;
+
+ a = (ArrayType *) repalloc(a, nbytes);
+
+ SET_VARSIZE(a, nbytes);
+ /* usually the array should be 1-D already, but just in case ... */
+ for (i = 0; i < ARR_NDIM(a); i++)
+ {
+ ARR_DIMS(a)[i] = num;
+ num = 1;
+ }
+ return a;
+}
+
+ArrayType *
+copy_intArrayType(ArrayType *a)
+{
+ ArrayType *r;
+ int n = ARRNELEMS(a);
+
+ r = new_intArrayType(n);
+ memcpy(ARRPTR(r), ARRPTR(a), n * sizeof(int32));
+ return r;
+}
+
+/* num for compressed key */
+int
+internal_size(int *a, int len)
+{
+ int i;
+ int64 size = 0;
+
+ for (i = 0; i < len; i += 2)
+ {
+ if (!i || a[i] != a[i - 1]) /* do not count repeated range */
+ size += (int64) (a[i + 1]) - (int64) (a[i]) + 1;
+ }
+
+ if (size > (int64) INT_MAX || size < (int64) INT_MIN)
+ return -1; /* overflow */
+ return (int) size;
+}
+
+/* unique-ify elements of r in-place ... r must be sorted already */
+ArrayType *
+_int_unique(ArrayType *r)
+{
+ int num = ARRNELEMS(r);
+ bool duplicates_found; /* not used */
+
+ num = qunique_arg(ARRPTR(r), num, sizeof(int), isort_cmp,
+ &duplicates_found);
+
+ return resize_intArrayType(r, num);
+}
+
+void
+gensign(BITVECP sign, int *a, int len, int siglen)
+{
+ int i;
+
+ /* we assume that the sign vector is previously zeroed */
+ for (i = 0; i < len; i++)
+ {
+ HASH(sign, *a, siglen);
+ a++;
+ }
+}
+
+int32
+intarray_match_first(ArrayType *a, int32 elem)
+{
+ int32 *aa,
+ c,
+ i;
+
+ CHECKARRVALID(a);
+ c = ARRNELEMS(a);
+ aa = ARRPTR(a);
+ for (i = 0; i < c; i++)
+ if (aa[i] == elem)
+ return (i + 1);
+ return 0;
+}
+
+ArrayType *
+intarray_add_elem(ArrayType *a, int32 elem)
+{
+ ArrayType *result;
+ int32 *r;
+ int32 c;
+
+ CHECKARRVALID(a);
+ c = ARRNELEMS(a);
+ result = new_intArrayType(c + 1);
+ r = ARRPTR(result);
+ if (c > 0)
+ memcpy(r, ARRPTR(a), c * sizeof(int32));
+ r[c] = elem;
+ return result;
+}
+
+ArrayType *
+intarray_concat_arrays(ArrayType *a, ArrayType *b)
+{
+ ArrayType *result;
+ int32 ac = ARRNELEMS(a);
+ int32 bc = ARRNELEMS(b);
+
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+ result = new_intArrayType(ac + bc);
+ if (ac)
+ memcpy(ARRPTR(result), ARRPTR(a), ac * sizeof(int32));
+ if (bc)
+ memcpy(ARRPTR(result) + ac, ARRPTR(b), bc * sizeof(int32));
+ return result;
+}
+
+ArrayType *
+int_to_intset(int32 n)
+{
+ ArrayType *result;
+ int32 *aa;
+
+ result = new_intArrayType(1);
+ aa = ARRPTR(result);
+ aa[0] = n;
+ return result;
+}
+
+int
+compASC(const void *a, const void *b)
+{
+ if (*(const int32 *) a == *(const int32 *) b)
+ return 0;
+ return (*(const int32 *) a > *(const int32 *) b) ? 1 : -1;
+}
+
+int
+compDESC(const void *a, const void *b)
+{
+ if (*(const int32 *) a == *(const int32 *) b)
+ return 0;
+ return (*(const int32 *) a < *(const int32 *) b) ? 1 : -1;
+}