summaryrefslogtreecommitdiffstats
path: root/contrib/intarray
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/intarray')
-rw-r--r--contrib/intarray/.gitignore4
-rw-r--r--contrib/intarray/Makefile30
-rw-r--r--contrib/intarray/_int.h191
-rw-r--r--contrib/intarray/_int_bool.c668
-rw-r--r--contrib/intarray/_int_gin.c180
-rw-r--r--contrib/intarray/_int_gist.c624
-rw-r--r--contrib/intarray/_int_op.c432
-rw-r--r--contrib/intarray/_int_selfuncs.c333
-rw-r--r--contrib/intarray/_int_tool.c410
-rw-r--r--contrib/intarray/_intbig_gist.c589
-rwxr-xr-xcontrib/intarray/bench/bench.pl138
-rwxr-xr-xcontrib/intarray/bench/create_test.pl89
-rw-r--r--contrib/intarray/data/test__int.data7000
-rw-r--r--contrib/intarray/expected/_int.out858
-rw-r--r--contrib/intarray/intarray--1.0--1.1.sql49
-rw-r--r--contrib/intarray/intarray--1.1--1.2.sql94
-rw-r--r--contrib/intarray/intarray--1.2--1.3.sql20
-rw-r--r--contrib/intarray/intarray--1.2.sql520
-rw-r--r--contrib/intarray/intarray.control6
-rw-r--r--contrib/intarray/sql/_int.sql181
20 files changed, 12416 insertions, 0 deletions
diff --git a/contrib/intarray/.gitignore b/contrib/intarray/.gitignore
new file mode 100644
index 0000000..5dcb3ff
--- /dev/null
+++ b/contrib/intarray/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/intarray/Makefile b/contrib/intarray/Makefile
new file mode 100644
index 0000000..b68959e
--- /dev/null
+++ b/contrib/intarray/Makefile
@@ -0,0 +1,30 @@
+# contrib/intarray/Makefile
+
+MODULE_big = _int
+OBJS = \
+ $(WIN32RES) \
+ _int_bool.o \
+ _int_gin.o \
+ _int_gist.o \
+ _int_op.o \
+ _int_selfuncs.o \
+ _int_tool.o \
+ _intbig_gist.o
+
+EXTENSION = intarray
+DATA = intarray--1.2--1.3.sql intarray--1.2.sql intarray--1.1--1.2.sql \
+ intarray--1.0--1.1.sql
+PGFILEDESC = "intarray - functions and operators for arrays of integers"
+
+REGRESS = _int
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/intarray
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h
new file mode 100644
index 0000000..304c295
--- /dev/null
+++ b/contrib/intarray/_int.h
@@ -0,0 +1,191 @@
+/*
+ * contrib/intarray/_int.h
+ */
+#ifndef ___INT_H__
+#define ___INT_H__
+
+#include "utils/array.h"
+#include "utils/memutils.h"
+
+/* number ranges for compression */
+#define G_INT_NUMRANGES_DEFAULT 100
+#define G_INT_NUMRANGES_MAX ((GISTMaxIndexKeySize - VARHDRSZ) / \
+ (2 * sizeof(int32)))
+#define G_INT_GET_NUMRANGES() (PG_HAS_OPCLASS_OPTIONS() ? \
+ ((GISTIntArrayOptions *) PG_GET_OPCLASS_OPTIONS())->num_ranges : \
+ G_INT_NUMRANGES_DEFAULT)
+
+/* gist_int_ops opclass options */
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int num_ranges; /* number of ranges */
+} GISTIntArrayOptions;
+
+/* useful macros for accessing int4 arrays */
+#define ARRPTR(x) ( (int32 *) ARR_DATA_PTR(x) )
+#define ARRNELEMS(x) ArrayGetNItems(ARR_NDIM(x), ARR_DIMS(x))
+
+/* reject arrays we can't handle; to wit, those containing nulls */
+#define CHECKARRVALID(x) \
+ do { \
+ if (ARR_HASNULL(x) && array_contains_nulls(x)) \
+ ereport(ERROR, \
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
+ errmsg("array must not contain nulls"))); \
+ } while(0)
+
+#define ARRISEMPTY(x) (ARRNELEMS(x) == 0)
+
+/* sort the elements of the array */
+#define SORT(x) \
+ do { \
+ int _nelems_ = ARRNELEMS(x); \
+ if (_nelems_ > 1) \
+ isort(ARRPTR(x), _nelems_); \
+ } while(0)
+
+/* sort the elements of the array and remove duplicates */
+#define PREPAREARR(x) \
+ do { \
+ int _nelems_ = ARRNELEMS(x); \
+ if (_nelems_ > 1) \
+ if (isort(ARRPTR(x), _nelems_)) \
+ (x) = _int_unique(x); \
+ } while(0)
+
+/* "wish" function */
+#define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
+
+
+/* bigint defines */
+#define SIGLEN_DEFAULT (63 * 4)
+#define SIGLEN_MAX GISTMaxIndexKeySize
+#define SIGLENBIT(siglen) ((siglen) * BITS_PER_BYTE)
+#define GET_SIGLEN() (PG_HAS_OPCLASS_OPTIONS() ? \
+ ((GISTIntArrayBigOptions *) PG_GET_OPCLASS_OPTIONS())->siglen : \
+ SIGLEN_DEFAULT)
+
+typedef char *BITVECP;
+
+#define LOOPBYTE(siglen) \
+ for (i = 0; i < siglen; i++)
+
+/* beware of multiple evaluation of arguments to these macros! */
+#define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITS_PER_BYTE ) ) )
+#define GETBITBYTE(x,i) ( (*((char*)(x)) >> (i)) & 0x01 )
+#define CLRBIT(x,i) GETBYTE(x,i) &= ~( 0x01 << ( (i) % BITS_PER_BYTE ) )
+#define SETBIT(x,i) GETBYTE(x,i) |= ( 0x01 << ( (i) % BITS_PER_BYTE ) )
+#define GETBIT(x,i) ( (GETBYTE(x,i) >> ( (i) % BITS_PER_BYTE )) & 0x01 )
+#define HASHVAL(val, siglen) (((unsigned int)(val)) % SIGLENBIT(siglen))
+#define HASH(sign, val, siglen) SETBIT((sign), HASHVAL(val, siglen))
+
+/* gist_intbig_ops opclass options */
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int siglen; /* signature length in bytes */
+} GISTIntArrayBigOptions;
+
+/*
+ * type of index key
+ */
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int32 flag;
+ char data[FLEXIBLE_ARRAY_MEMBER];
+} GISTTYPE;
+
+#define ALLISTRUE 0x04
+
+#define ISALLTRUE(x) ( ((GISTTYPE*)x)->flag & ALLISTRUE )
+
+#define GTHDRSIZE (VARHDRSZ + sizeof(int32))
+#define CALCGTSIZE(flag, siglen) ( GTHDRSIZE+(((flag) & ALLISTRUE) ? 0 : (siglen)) )
+
+#define GETSIGN(x) ( (BITVECP)( (char*)x+GTHDRSIZE ) )
+
+/*
+ * useful functions
+ */
+bool isort(int32 *a, int len);
+ArrayType *new_intArrayType(int num);
+ArrayType *copy_intArrayType(ArrayType *a);
+ArrayType *resize_intArrayType(ArrayType *a, int num);
+int internal_size(int *a, int len);
+ArrayType *_int_unique(ArrayType *a);
+int32 intarray_match_first(ArrayType *a, int32 elem);
+ArrayType *intarray_add_elem(ArrayType *a, int32 elem);
+ArrayType *intarray_concat_arrays(ArrayType *a, ArrayType *b);
+ArrayType *int_to_intset(int32 elem);
+bool inner_int_overlap(ArrayType *a, ArrayType *b);
+bool inner_int_contains(ArrayType *a, ArrayType *b);
+ArrayType *inner_int_union(ArrayType *a, ArrayType *b);
+ArrayType *inner_int_inter(ArrayType *a, ArrayType *b);
+void rt__int_size(ArrayType *a, float *size);
+void gensign(BITVECP sign, int *a, int len, int siglen);
+
+
+/*****************************************************************************
+ * Boolean Search
+ *****************************************************************************/
+
+#define BooleanSearchStrategy 20
+
+/*
+ * item in polish notation with back link
+ * to left operand
+ */
+typedef struct ITEM
+{
+ int16 type;
+ int16 left;
+ int32 val;
+} ITEM;
+
+typedef struct QUERYTYPE
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int32 size; /* number of ITEMs */
+ ITEM items[FLEXIBLE_ARRAY_MEMBER];
+} QUERYTYPE;
+
+#define HDRSIZEQT offsetof(QUERYTYPE, items)
+#define COMPUTESIZE(size) ( HDRSIZEQT + (size) * sizeof(ITEM) )
+#define QUERYTYPEMAXITEMS ((MaxAllocSize - HDRSIZEQT) / sizeof(ITEM))
+#define GETQUERY(x) ( (x)->items )
+
+/* "type" codes for ITEM */
+#define END 0
+#define ERR 1
+#define VAL 2
+#define OPR 3
+#define OPEN 4
+#define CLOSE 5
+
+/* fmgr macros for QUERYTYPE objects */
+#define DatumGetQueryTypeP(X) ((QUERYTYPE *) PG_DETOAST_DATUM(X))
+#define DatumGetQueryTypePCopy(X) ((QUERYTYPE *) PG_DETOAST_DATUM_COPY(X))
+#define PG_GETARG_QUERYTYPE_P(n) DatumGetQueryTypeP(PG_GETARG_DATUM(n))
+#define PG_GETARG_QUERYTYPE_P_COPY(n) DatumGetQueryTypePCopy(PG_GETARG_DATUM(n))
+
+bool signconsistent(QUERYTYPE *query, BITVECP sign, int siglen, bool calcnot);
+bool execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot);
+
+bool gin_bool_consistent(QUERYTYPE *query, bool *check);
+bool query_has_required_values(QUERYTYPE *query);
+
+int compASC(const void *a, const void *b);
+int compDESC(const void *a, const void *b);
+
+/* sort, either ascending or descending */
+#define QSORT(a, direction) \
+ do { \
+ int _nelems_ = ARRNELEMS(a); \
+ if (_nelems_ > 1) \
+ qsort((void*) ARRPTR(a), _nelems_, sizeof(int32), \
+ (direction) ? compASC : compDESC ); \
+ } while(0)
+
+#endif /* ___INT_H__ */
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
new file mode 100644
index 0000000..4b6a310
--- /dev/null
+++ b/contrib/intarray/_int_bool.c
@@ -0,0 +1,668 @@
+/*
+ * contrib/intarray/_int_bool.c
+ */
+#include "postgres.h"
+
+#include "_int.h"
+#include "miscadmin.h"
+#include "utils/builtins.h"
+
+PG_FUNCTION_INFO_V1(bqarr_in);
+PG_FUNCTION_INFO_V1(bqarr_out);
+PG_FUNCTION_INFO_V1(boolop);
+PG_FUNCTION_INFO_V1(rboolop);
+PG_FUNCTION_INFO_V1(querytree);
+
+
+/* parser's states */
+#define WAITOPERAND 1
+#define WAITENDOPERAND 2
+#define WAITOPERATOR 3
+
+/*
+ * node of query tree, also used
+ * for storing polish notation in parser
+ */
+typedef struct NODE
+{
+ int32 type;
+ int32 val;
+ struct NODE *next;
+} NODE;
+
+typedef struct
+{
+ char *buf;
+ int32 state;
+ int32 count;
+ /* reverse polish notation in list (for temporary usage) */
+ NODE *str;
+ /* number in str */
+ int32 num;
+} WORKSTATE;
+
+/*
+ * get token from query string
+ */
+static int32
+gettoken(WORKSTATE *state, int32 *val)
+{
+ char nnn[16];
+ int innn;
+
+ *val = 0; /* default result */
+
+ innn = 0;
+ while (1)
+ {
+ if (innn >= sizeof(nnn))
+ return ERR; /* buffer overrun => syntax error */
+ switch (state->state)
+ {
+ case WAITOPERAND:
+ innn = 0;
+ if ((*(state->buf) >= '0' && *(state->buf) <= '9') ||
+ *(state->buf) == '-')
+ {
+ state->state = WAITENDOPERAND;
+ nnn[innn++] = *(state->buf);
+ }
+ else if (*(state->buf) == '!')
+ {
+ (state->buf)++;
+ *val = (int32) '!';
+ return OPR;
+ }
+ else if (*(state->buf) == '(')
+ {
+ state->count++;
+ (state->buf)++;
+ return OPEN;
+ }
+ else if (*(state->buf) != ' ')
+ return ERR;
+ break;
+ case WAITENDOPERAND:
+ if (*(state->buf) >= '0' && *(state->buf) <= '9')
+ {
+ nnn[innn++] = *(state->buf);
+ }
+ else
+ {
+ long lval;
+
+ nnn[innn] = '\0';
+ errno = 0;
+ lval = strtol(nnn, NULL, 0);
+ *val = (int32) lval;
+ if (errno != 0 || (long) *val != lval)
+ return ERR;
+ state->state = WAITOPERATOR;
+ return (state->count && *(state->buf) == '\0')
+ ? ERR : VAL;
+ }
+ break;
+ case WAITOPERATOR:
+ if (*(state->buf) == '&' || *(state->buf) == '|')
+ {
+ state->state = WAITOPERAND;
+ *val = (int32) *(state->buf);
+ (state->buf)++;
+ return OPR;
+ }
+ else if (*(state->buf) == ')')
+ {
+ (state->buf)++;
+ state->count--;
+ return (state->count < 0) ? ERR : CLOSE;
+ }
+ else if (*(state->buf) == '\0')
+ return (state->count) ? ERR : END;
+ else if (*(state->buf) != ' ')
+ return ERR;
+ break;
+ default:
+ return ERR;
+ break;
+ }
+ (state->buf)++;
+ }
+}
+
+/*
+ * push new one in polish notation reverse view
+ */
+static void
+pushquery(WORKSTATE *state, int32 type, int32 val)
+{
+ NODE *tmp = (NODE *) palloc(sizeof(NODE));
+
+ tmp->type = type;
+ tmp->val = val;
+ tmp->next = state->str;
+ state->str = tmp;
+ state->num++;
+}
+
+#define STACKDEPTH 16
+
+/*
+ * make polish notation of query
+ */
+static int32
+makepol(WORKSTATE *state)
+{
+ int32 val,
+ type;
+ int32 stack[STACKDEPTH];
+ int32 lenstack = 0;
+
+ /* since this function recurses, it could be driven to stack overflow */
+ check_stack_depth();
+
+ while ((type = gettoken(state, &val)) != END)
+ {
+ switch (type)
+ {
+ case VAL:
+ pushquery(state, type, val);
+ while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
+ stack[lenstack - 1] == (int32) '!'))
+ {
+ lenstack--;
+ pushquery(state, OPR, stack[lenstack]);
+ }
+ break;
+ case OPR:
+ if (lenstack && val == (int32) '|')
+ pushquery(state, OPR, val);
+ else
+ {
+ if (lenstack == STACKDEPTH)
+ ereport(ERROR,
+ (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
+ errmsg("statement too complex")));
+ stack[lenstack] = val;
+ lenstack++;
+ }
+ break;
+ case OPEN:
+ if (makepol(state) == ERR)
+ return ERR;
+ while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
+ stack[lenstack - 1] == (int32) '!'))
+ {
+ lenstack--;
+ pushquery(state, OPR, stack[lenstack]);
+ }
+ break;
+ case CLOSE:
+ while (lenstack)
+ {
+ lenstack--;
+ pushquery(state, OPR, stack[lenstack]);
+ };
+ return END;
+ break;
+ case ERR:
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("syntax error")));
+ return ERR;
+
+ }
+ }
+
+ while (lenstack)
+ {
+ lenstack--;
+ pushquery(state, OPR, stack[lenstack]);
+ };
+ return END;
+}
+
+typedef struct
+{
+ int32 *arrb;
+ int32 *arre;
+} CHKVAL;
+
+/*
+ * is there value 'val' in (sorted) array or not ?
+ */
+static bool
+checkcondition_arr(void *checkval, ITEM *item, void *options)
+{
+ int32 *StopLow = ((CHKVAL *) checkval)->arrb;
+ int32 *StopHigh = ((CHKVAL *) checkval)->arre;
+ int32 *StopMiddle;
+
+ /* Loop invariant: StopLow <= val < StopHigh */
+
+ while (StopLow < StopHigh)
+ {
+ StopMiddle = StopLow + (StopHigh - StopLow) / 2;
+ if (*StopMiddle == item->val)
+ return true;
+ else if (*StopMiddle < item->val)
+ StopLow = StopMiddle + 1;
+ else
+ StopHigh = StopMiddle;
+ }
+ return false;
+}
+
+static bool
+checkcondition_bit(void *checkval, ITEM *item, void *siglen)
+{
+ return GETBIT(checkval, HASHVAL(item->val, (int) (intptr_t) siglen));
+}
+
+/*
+ * evaluate boolean expression, using chkcond() to test the primitive cases
+ */
+static bool
+execute(ITEM *curitem, void *checkval, void *options, bool calcnot,
+ bool (*chkcond) (void *checkval, ITEM *item, void *options))
+{
+ /* since this function recurses, it could be driven to stack overflow */
+ check_stack_depth();
+
+ if (curitem->type == VAL)
+ return (*chkcond) (checkval, curitem, options);
+ else if (curitem->val == (int32) '!')
+ {
+ return calcnot ?
+ ((execute(curitem - 1, checkval, options, calcnot, chkcond)) ? false : true)
+ : true;
+ }
+ else if (curitem->val == (int32) '&')
+ {
+ if (execute(curitem + curitem->left, checkval, options, calcnot, chkcond))
+ return execute(curitem - 1, checkval, options, calcnot, chkcond);
+ else
+ return false;
+ }
+ else
+ { /* |-operator */
+ if (execute(curitem + curitem->left, checkval, options, calcnot, chkcond))
+ return true;
+ else
+ return execute(curitem - 1, checkval, options, calcnot, chkcond);
+ }
+}
+
+/*
+ * signconsistent & execconsistent called by *_consistent
+ */
+bool
+signconsistent(QUERYTYPE *query, BITVECP sign, int siglen, bool calcnot)
+{
+ return execute(GETQUERY(query) + query->size - 1,
+ (void *) sign, (void *) (intptr_t) siglen, calcnot,
+ checkcondition_bit);
+}
+
+/* Array must be sorted! */
+bool
+execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot)
+{
+ CHKVAL chkval;
+
+ CHECKARRVALID(array);
+ chkval.arrb = ARRPTR(array);
+ chkval.arre = chkval.arrb + ARRNELEMS(array);
+ return execute(GETQUERY(query) + query->size - 1,
+ (void *) &chkval, NULL, calcnot,
+ checkcondition_arr);
+}
+
+typedef struct
+{
+ ITEM *first;
+ bool *mapped_check;
+} GinChkVal;
+
+static bool
+checkcondition_gin(void *checkval, ITEM *item, void *options)
+{
+ GinChkVal *gcv = (GinChkVal *) checkval;
+
+ return gcv->mapped_check[item - gcv->first];
+}
+
+bool
+gin_bool_consistent(QUERYTYPE *query, bool *check)
+{
+ GinChkVal gcv;
+ ITEM *items = GETQUERY(query);
+ int i,
+ j = 0;
+
+ if (query->size <= 0)
+ return false;
+
+ /*
+ * Set up data for checkcondition_gin. This must agree with the query
+ * extraction code in ginint4_queryextract.
+ */
+ gcv.first = items;
+ gcv.mapped_check = (bool *) palloc(sizeof(bool) * query->size);
+ for (i = 0; i < query->size; i++)
+ {
+ if (items[i].type == VAL)
+ gcv.mapped_check[i] = check[j++];
+ }
+
+ return execute(GETQUERY(query) + query->size - 1,
+ (void *) &gcv, NULL, true,
+ checkcondition_gin);
+}
+
+static bool
+contains_required_value(ITEM *curitem)
+{
+ /* since this function recurses, it could be driven to stack overflow */
+ check_stack_depth();
+
+ if (curitem->type == VAL)
+ return true;
+ else if (curitem->val == (int32) '!')
+ {
+ /*
+ * Assume anything under a NOT is non-required. For some cases with
+ * nested NOTs, we could prove there's a required value, but it seems
+ * unlikely to be worth the trouble.
+ */
+ return false;
+ }
+ else if (curitem->val == (int32) '&')
+ {
+ /* If either side has a required value, we're good */
+ if (contains_required_value(curitem + curitem->left))
+ return true;
+ else
+ return contains_required_value(curitem - 1);
+ }
+ else
+ { /* |-operator */
+ /* Both sides must have required values */
+ if (contains_required_value(curitem + curitem->left))
+ return contains_required_value(curitem - 1);
+ else
+ return false;
+ }
+}
+
+bool
+query_has_required_values(QUERYTYPE *query)
+{
+ if (query->size <= 0)
+ return false;
+ return contains_required_value(GETQUERY(query) + query->size - 1);
+}
+
+/*
+ * boolean operations
+ */
+Datum
+rboolop(PG_FUNCTION_ARGS)
+{
+ /* just reverse the operands */
+ return DirectFunctionCall2(boolop,
+ PG_GETARG_DATUM(1),
+ PG_GETARG_DATUM(0));
+}
+
+Datum
+boolop(PG_FUNCTION_ARGS)
+{
+ ArrayType *val = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(1);
+ CHKVAL chkval;
+ bool result;
+
+ CHECKARRVALID(val);
+ PREPAREARR(val);
+ chkval.arrb = ARRPTR(val);
+ chkval.arre = chkval.arrb + ARRNELEMS(val);
+ result = execute(GETQUERY(query) + query->size - 1,
+ &chkval, NULL, true,
+ checkcondition_arr);
+ pfree(val);
+
+ PG_FREE_IF_COPY(query, 1);
+ PG_RETURN_BOOL(result);
+}
+
+static void
+findoprnd(ITEM *ptr, int32 *pos)
+{
+ /* since this function recurses, it could be driven to stack overflow. */
+ check_stack_depth();
+
+#ifdef BS_DEBUG
+ elog(DEBUG3, (ptr[*pos].type == OPR) ?
+ "%d %c" : "%d %d", *pos, ptr[*pos].val);
+#endif
+ if (ptr[*pos].type == VAL)
+ {
+ ptr[*pos].left = 0;
+ (*pos)--;
+ }
+ else if (ptr[*pos].val == (int32) '!')
+ {
+ ptr[*pos].left = -1;
+ (*pos)--;
+ findoprnd(ptr, pos);
+ }
+ else
+ {
+ ITEM *curitem = &ptr[*pos];
+ int32 tmp = *pos;
+
+ (*pos)--;
+ findoprnd(ptr, pos);
+ curitem->left = *pos - tmp;
+ findoprnd(ptr, pos);
+ }
+}
+
+
+/*
+ * input
+ */
+Datum
+bqarr_in(PG_FUNCTION_ARGS)
+{
+ char *buf = (char *) PG_GETARG_POINTER(0);
+ WORKSTATE state;
+ int32 i;
+ QUERYTYPE *query;
+ int32 commonlen;
+ ITEM *ptr;
+ NODE *tmp;
+ int32 pos = 0;
+
+#ifdef BS_DEBUG
+ StringInfoData pbuf;
+#endif
+
+ state.buf = buf;
+ state.state = WAITOPERAND;
+ state.count = 0;
+ state.num = 0;
+ state.str = NULL;
+
+ /* make polish notation (postfix, but in reverse order) */
+ makepol(&state);
+ if (!state.num)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("empty query")));
+
+ if (state.num > QUERYTYPEMAXITEMS)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("number of query items (%d) exceeds the maximum allowed (%d)",
+ state.num, (int) QUERYTYPEMAXITEMS)));
+ commonlen = COMPUTESIZE(state.num);
+
+ query = (QUERYTYPE *) palloc(commonlen);
+ SET_VARSIZE(query, commonlen);
+ query->size = state.num;
+ ptr = GETQUERY(query);
+
+ for (i = state.num - 1; i >= 0; i--)
+ {
+ ptr[i].type = state.str->type;
+ ptr[i].val = state.str->val;
+ tmp = state.str->next;
+ pfree(state.str);
+ state.str = tmp;
+ }
+
+ pos = query->size - 1;
+ findoprnd(ptr, &pos);
+#ifdef BS_DEBUG
+ initStringInfo(&pbuf);
+ for (i = 0; i < query->size; i++)
+ {
+ if (ptr[i].type == OPR)
+ appendStringInfo(&pbuf, "%c(%d) ", ptr[i].val, ptr[i].left);
+ else
+ appendStringInfo(&pbuf, "%d ", ptr[i].val);
+ }
+ elog(DEBUG3, "POR: %s", pbuf.data);
+ pfree(pbuf.data);
+#endif
+
+ PG_RETURN_POINTER(query);
+}
+
+
+/*
+ * out function
+ */
+typedef struct
+{
+ ITEM *curpol;
+ char *buf;
+ char *cur;
+ int32 buflen;
+} INFIX;
+
+#define RESIZEBUF(inf,addsize) while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) { \
+ int32 len = inf->cur - inf->buf; \
+ inf->buflen *= 2; \
+ inf->buf = (char*) repalloc( (void*)inf->buf, inf->buflen ); \
+ inf->cur = inf->buf + len; \
+}
+
+static void
+infix(INFIX *in, bool first)
+{
+ /* since this function recurses, it could be driven to stack overflow. */
+ check_stack_depth();
+
+ if (in->curpol->type == VAL)
+ {
+ RESIZEBUF(in, 11);
+ sprintf(in->cur, "%d", in->curpol->val);
+ in->cur = strchr(in->cur, '\0');
+ in->curpol--;
+ }
+ else if (in->curpol->val == (int32) '!')
+ {
+ bool isopr = false;
+
+ RESIZEBUF(in, 1);
+ *(in->cur) = '!';
+ in->cur++;
+ *(in->cur) = '\0';
+ in->curpol--;
+ if (in->curpol->type == OPR)
+ {
+ isopr = true;
+ RESIZEBUF(in, 2);
+ sprintf(in->cur, "( ");
+ in->cur = strchr(in->cur, '\0');
+ }
+ infix(in, isopr);
+ if (isopr)
+ {
+ RESIZEBUF(in, 2);
+ sprintf(in->cur, " )");
+ in->cur = strchr(in->cur, '\0');
+ }
+ }
+ else
+ {
+ int32 op = in->curpol->val;
+ INFIX nrm;
+
+ in->curpol--;
+ if (op == (int32) '|' && !first)
+ {
+ RESIZEBUF(in, 2);
+ sprintf(in->cur, "( ");
+ in->cur = strchr(in->cur, '\0');
+ }
+
+ nrm.curpol = in->curpol;
+ nrm.buflen = 16;
+ nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+
+ /* get right operand */
+ infix(&nrm, false);
+
+ /* get & print left operand */
+ in->curpol = nrm.curpol;
+ infix(in, false);
+
+ /* print operator & right operand */
+ RESIZEBUF(in, 3 + (nrm.cur - nrm.buf));
+ sprintf(in->cur, " %c %s", op, nrm.buf);
+ in->cur = strchr(in->cur, '\0');
+ pfree(nrm.buf);
+
+ if (op == (int32) '|' && !first)
+ {
+ RESIZEBUF(in, 2);
+ sprintf(in->cur, " )");
+ in->cur = strchr(in->cur, '\0');
+ }
+ }
+}
+
+
+Datum
+bqarr_out(PG_FUNCTION_ARGS)
+{
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(0);
+ INFIX nrm;
+
+ if (query->size == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("empty query")));
+
+ nrm.curpol = GETQUERY(query) + query->size - 1;
+ nrm.buflen = 32;
+ nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+ *(nrm.cur) = '\0';
+ infix(&nrm, true);
+
+ PG_FREE_IF_COPY(query, 0);
+ PG_RETURN_POINTER(nrm.buf);
+}
+
+
+/* Useless old "debugging" function for a fundamentally wrong algorithm */
+Datum
+querytree(PG_FUNCTION_ARGS)
+{
+ elog(ERROR, "querytree is no longer implemented");
+ PG_RETURN_NULL();
+}
diff --git a/contrib/intarray/_int_gin.c b/contrib/intarray/_int_gin.c
new file mode 100644
index 0000000..b7958d8
--- /dev/null
+++ b/contrib/intarray/_int_gin.c
@@ -0,0 +1,180 @@
+/*
+ * contrib/intarray/_int_gin.c
+ */
+#include "postgres.h"
+
+#include "_int.h"
+#include "access/gin.h"
+#include "access/stratnum.h"
+
+PG_FUNCTION_INFO_V1(ginint4_queryextract);
+
+Datum
+ginint4_queryextract(PG_FUNCTION_ARGS)
+{
+ int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
+ StrategyNumber strategy = PG_GETARG_UINT16(2);
+ int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
+ Datum *res = NULL;
+
+ *nentries = 0;
+
+ if (strategy == BooleanSearchStrategy)
+ {
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(0);
+ ITEM *items = GETQUERY(query);
+ int i;
+
+ /* empty query must fail */
+ if (query->size <= 0)
+ PG_RETURN_POINTER(NULL);
+
+ /*
+ * If the query doesn't have any required primitive values (for
+ * instance, it's something like '! 42'), we have to do a full index
+ * scan.
+ */
+ if (query_has_required_values(query))
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ else
+ *searchMode = GIN_SEARCH_MODE_ALL;
+
+ /*
+ * Extract all the VAL items as things we want GIN to check for.
+ */
+ res = (Datum *) palloc(sizeof(Datum) * query->size);
+ *nentries = 0;
+
+ for (i = 0; i < query->size; i++)
+ {
+ if (items[i].type == VAL)
+ {
+ res[*nentries] = Int32GetDatum(items[i].val);
+ (*nentries)++;
+ }
+ }
+ }
+ else
+ {
+ ArrayType *query = PG_GETARG_ARRAYTYPE_P(0);
+
+ CHECKARRVALID(query);
+ *nentries = ARRNELEMS(query);
+ if (*nentries > 0)
+ {
+ int32 *arr;
+ int32 i;
+
+ res = (Datum *) palloc(sizeof(Datum) * (*nentries));
+
+ arr = ARRPTR(query);
+ for (i = 0; i < *nentries; i++)
+ res[i] = Int32GetDatum(arr[i]);
+ }
+
+ switch (strategy)
+ {
+ case RTOverlapStrategyNumber:
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ break;
+ case RTContainedByStrategyNumber:
+ case RTOldContainedByStrategyNumber:
+ /* empty set is contained in everything */
+ *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
+ break;
+ case RTSameStrategyNumber:
+ if (*nentries > 0)
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ else
+ *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
+ break;
+ case RTContainsStrategyNumber:
+ case RTOldContainsStrategyNumber:
+ if (*nentries > 0)
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ else /* everything contains the empty set */
+ *searchMode = GIN_SEARCH_MODE_ALL;
+ break;
+ default:
+ elog(ERROR, "ginint4_queryextract: unknown strategy number: %d",
+ strategy);
+ }
+ }
+
+ PG_RETURN_POINTER(res);
+}
+
+PG_FUNCTION_INFO_V1(ginint4_consistent);
+
+Datum
+ginint4_consistent(PG_FUNCTION_ARGS)
+{
+ bool *check = (bool *) PG_GETARG_POINTER(0);
+ StrategyNumber strategy = PG_GETARG_UINT16(1);
+ int32 nkeys = PG_GETARG_INT32(3);
+
+ /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
+ bool *recheck = (bool *) PG_GETARG_POINTER(5);
+ bool res = false;
+ int32 i;
+
+ switch (strategy)
+ {
+ case RTOverlapStrategyNumber:
+ /* result is not lossy */
+ *recheck = false;
+ /* at least one element in check[] is true, so result = true */
+ res = true;
+ break;
+ case RTContainedByStrategyNumber:
+ case RTOldContainedByStrategyNumber:
+ /* we will need recheck */
+ *recheck = true;
+ /* at least one element in check[] is true, so result = true */
+ res = true;
+ break;
+ case RTSameStrategyNumber:
+ /* we will need recheck */
+ *recheck = true;
+ /* Must have all elements in check[] true */
+ res = true;
+ for (i = 0; i < nkeys; i++)
+ {
+ if (!check[i])
+ {
+ res = false;
+ break;
+ }
+ }
+ break;
+ case RTContainsStrategyNumber:
+ case RTOldContainsStrategyNumber:
+ /* result is not lossy */
+ *recheck = false;
+ /* Must have all elements in check[] true */
+ res = true;
+ for (i = 0; i < nkeys; i++)
+ {
+ if (!check[i])
+ {
+ res = false;
+ break;
+ }
+ }
+ break;
+ case BooleanSearchStrategy:
+ {
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(2);
+
+ /* result is not lossy */
+ *recheck = false;
+ res = gin_bool_consistent(query, check);
+ }
+ break;
+ default:
+ elog(ERROR, "ginint4_consistent: unknown strategy number: %d",
+ strategy);
+ }
+
+ PG_RETURN_BOOL(res);
+}
diff --git a/contrib/intarray/_int_gist.c b/contrib/intarray/_int_gist.c
new file mode 100644
index 0000000..fb05b06
--- /dev/null
+++ b/contrib/intarray/_int_gist.c
@@ -0,0 +1,624 @@
+/*
+ * contrib/intarray/_int_gist.c
+ */
+#include "postgres.h"
+
+#include <limits.h>
+
+#include "_int.h"
+#include "access/gist.h"
+#include "access/reloptions.h"
+#include "access/stratnum.h"
+
+#define GETENTRY(vec,pos) ((ArrayType *) DatumGetPointer((vec)->vector[(pos)].key))
+
+/*
+ * Control the maximum sparseness of compressed keys.
+ *
+ * The upper safe bound for this limit is half the maximum allocatable array
+ * size. A lower bound would give more guarantees that pathological data
+ * wouldn't eat excessive CPU and memory, but at the expense of breaking
+ * possibly working (after a fashion) indexes.
+ */
+#define MAXNUMELTS (Min((MaxAllocSize / sizeof(Datum)),((MaxAllocSize - ARR_OVERHEAD_NONULLS(1)) / sizeof(int)))/2)
+/* or: #define MAXNUMELTS 1000000 */
+
+/*
+** GiST support methods
+*/
+PG_FUNCTION_INFO_V1(g_int_consistent);
+PG_FUNCTION_INFO_V1(g_int_compress);
+PG_FUNCTION_INFO_V1(g_int_decompress);
+PG_FUNCTION_INFO_V1(g_int_penalty);
+PG_FUNCTION_INFO_V1(g_int_picksplit);
+PG_FUNCTION_INFO_V1(g_int_union);
+PG_FUNCTION_INFO_V1(g_int_same);
+PG_FUNCTION_INFO_V1(g_int_options);
+
+
+/*
+** The GiST Consistent method for _intments
+** Should return false if for all data items x below entry,
+** the predicate x op query == false, where op is the oper
+** corresponding to strategy in the pg_amop table.
+*/
+Datum
+g_int_consistent(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ ArrayType *query = PG_GETARG_ARRAYTYPE_P_COPY(1);
+ StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ bool *recheck = (bool *) PG_GETARG_POINTER(4);
+ bool retval;
+
+ /* this is exact except for RTSameStrategyNumber */
+ *recheck = (strategy == RTSameStrategyNumber);
+
+ if (strategy == BooleanSearchStrategy)
+ {
+ retval = execconsistent((QUERYTYPE *) query,
+ (ArrayType *) DatumGetPointer(entry->key),
+ GIST_LEAF(entry));
+
+ pfree(query);
+ PG_RETURN_BOOL(retval);
+ }
+
+ /* sort query for fast search, key is already sorted */
+ CHECKARRVALID(query);
+ PREPAREARR(query);
+
+ switch (strategy)
+ {
+ case RTOverlapStrategyNumber:
+ retval = inner_int_overlap((ArrayType *) DatumGetPointer(entry->key),
+ query);
+ break;
+ case RTSameStrategyNumber:
+ if (GIST_LEAF(entry))
+ DirectFunctionCall3(g_int_same,
+ entry->key,
+ PointerGetDatum(query),
+ PointerGetDatum(&retval));
+ else
+ retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key),
+ query);
+ break;
+ case RTContainsStrategyNumber:
+ case RTOldContainsStrategyNumber:
+ retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key),
+ query);
+ break;
+ case RTContainedByStrategyNumber:
+ case RTOldContainedByStrategyNumber:
+ if (GIST_LEAF(entry))
+ retval = inner_int_contains(query,
+ (ArrayType *) DatumGetPointer(entry->key));
+ else
+ {
+ /*
+ * Unfortunately, because empty arrays could be anywhere in
+ * the index, we must search the whole tree.
+ */
+ retval = true;
+ }
+ break;
+ default:
+ retval = false;
+ }
+ pfree(query);
+ PG_RETURN_BOOL(retval);
+}
+
+Datum
+g_int_union(PG_FUNCTION_ARGS)
+{
+ GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+ int *size = (int *) PG_GETARG_POINTER(1);
+ int32 i,
+ *ptr;
+ ArrayType *res;
+ int totlen = 0;
+
+ for (i = 0; i < entryvec->n; i++)
+ {
+ ArrayType *ent = GETENTRY(entryvec, i);
+
+ CHECKARRVALID(ent);
+ totlen += ARRNELEMS(ent);
+ }
+
+ res = new_intArrayType(totlen);
+ ptr = ARRPTR(res);
+
+ for (i = 0; i < entryvec->n; i++)
+ {
+ ArrayType *ent = GETENTRY(entryvec, i);
+ int nel;
+
+ nel = ARRNELEMS(ent);
+ memcpy(ptr, ARRPTR(ent), nel * sizeof(int32));
+ ptr += nel;
+ }
+
+ QSORT(res, 1);
+ res = _int_unique(res);
+ *size = VARSIZE(res);
+ PG_RETURN_POINTER(res);
+}
+
+/*
+** GiST Compress and Decompress methods
+*/
+Datum
+g_int_compress(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ GISTENTRY *retval;
+ ArrayType *r;
+ int num_ranges = G_INT_GET_NUMRANGES();
+ int len,
+ lenr;
+ int *dr;
+ int i,
+ j,
+ cand;
+ int64 min;
+
+ if (entry->leafkey)
+ {
+ r = DatumGetArrayTypePCopy(entry->key);
+ CHECKARRVALID(r);
+ PREPAREARR(r);
+
+ if (ARRNELEMS(r) >= 2 * num_ranges)
+ elog(NOTICE, "input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead",
+ 2 * num_ranges - 1, ARRNELEMS(r));
+
+ retval = palloc(sizeof(GISTENTRY));
+ gistentryinit(*retval, PointerGetDatum(r),
+ entry->rel, entry->page, entry->offset, false);
+
+ PG_RETURN_POINTER(retval);
+ }
+
+ /*
+ * leaf entries never compress one more time, only when entry->leafkey
+ * ==true, so now we work only with internal keys
+ */
+
+ r = DatumGetArrayTypeP(entry->key);
+ CHECKARRVALID(r);
+ if (ARRISEMPTY(r))
+ {
+ if (r != (ArrayType *) DatumGetPointer(entry->key))
+ pfree(r);
+ PG_RETURN_POINTER(entry);
+ }
+
+ if ((len = ARRNELEMS(r)) >= 2 * num_ranges)
+ { /* compress */
+ if (r == (ArrayType *) DatumGetPointer(entry->key))
+ r = DatumGetArrayTypePCopy(entry->key);
+ r = resize_intArrayType(r, 2 * (len));
+
+ dr = ARRPTR(r);
+
+ /*
+ * "len" at this point is the number of ranges we will construct.
+ * "lenr" is the number of ranges we must eventually remove by
+ * merging, we must be careful to remove no more than this number.
+ */
+ lenr = len - num_ranges;
+
+ /*
+ * Initially assume we can merge consecutive ints into a range. but we
+ * must count every value removed and stop when lenr runs out
+ */
+ for (j = i = len - 1; i > 0 && lenr > 0; i--, j--)
+ {
+ int r_end = dr[i];
+ int r_start = r_end;
+
+ while (i > 0 && lenr > 0 && dr[i - 1] == r_start - 1)
+ --r_start, --i, --lenr;
+ dr[2 * j] = r_start;
+ dr[2 * j + 1] = r_end;
+ }
+ /* just copy the rest, if any, as trivial ranges */
+ for (; i >= 0; i--, j--)
+ dr[2 * j] = dr[2 * j + 1] = dr[i];
+
+ if (++j)
+ {
+ /*
+ * shunt everything down to start at the right place
+ */
+ memmove((void *) &dr[0], (void *) &dr[2 * j], 2 * (len - j) * sizeof(int32));
+ }
+
+ /*
+ * make "len" be number of array elements, not ranges
+ */
+ len = 2 * (len - j);
+ cand = 1;
+ while (len > num_ranges * 2)
+ {
+ min = PG_INT64_MAX;
+ for (i = 2; i < len; i += 2)
+ if (min > ((int64) dr[i] - (int64) dr[i - 1]))
+ {
+ min = ((int64) dr[i] - (int64) dr[i - 1]);
+ cand = i;
+ }
+ memmove((void *) &dr[cand - 1], (void *) &dr[cand + 1], (len - cand - 1) * sizeof(int32));
+ len -= 2;
+ }
+
+ /*
+ * check sparseness of result
+ */
+ lenr = internal_size(dr, len);
+ if (lenr < 0 || lenr > MAXNUMELTS)
+ ereport(ERROR,
+ (errmsg("data is too sparse, recreate index using gist__intbig_ops opclass instead")));
+
+ r = resize_intArrayType(r, len);
+ retval = palloc(sizeof(GISTENTRY));
+ gistentryinit(*retval, PointerGetDatum(r),
+ entry->rel, entry->page, entry->offset, false);
+ PG_RETURN_POINTER(retval);
+ }
+ else
+ PG_RETURN_POINTER(entry);
+}
+
+Datum
+g_int_decompress(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ GISTENTRY *retval;
+ ArrayType *r;
+ int num_ranges = G_INT_GET_NUMRANGES();
+ int *dr,
+ lenr;
+ ArrayType *in;
+ int lenin;
+ int *din;
+ int i,
+ j;
+
+ in = DatumGetArrayTypeP(entry->key);
+
+ CHECKARRVALID(in);
+ if (ARRISEMPTY(in))
+ {
+ if (in != (ArrayType *) DatumGetPointer(entry->key))
+ {
+ retval = palloc(sizeof(GISTENTRY));
+ gistentryinit(*retval, PointerGetDatum(in),
+ entry->rel, entry->page, entry->offset, false);
+ PG_RETURN_POINTER(retval);
+ }
+
+ PG_RETURN_POINTER(entry);
+ }
+
+ lenin = ARRNELEMS(in);
+
+ if (lenin < 2 * num_ranges)
+ { /* not compressed value */
+ if (in != (ArrayType *) DatumGetPointer(entry->key))
+ {
+ retval = palloc(sizeof(GISTENTRY));
+ gistentryinit(*retval, PointerGetDatum(in),
+ entry->rel, entry->page, entry->offset, false);
+
+ PG_RETURN_POINTER(retval);
+ }
+ PG_RETURN_POINTER(entry);
+ }
+
+ din = ARRPTR(in);
+ lenr = internal_size(din, lenin);
+ if (lenr < 0 || lenr > MAXNUMELTS)
+ ereport(ERROR,
+ (errmsg("compressed array is too big, recreate index using gist__intbig_ops opclass instead")));
+
+ r = new_intArrayType(lenr);
+ dr = ARRPTR(r);
+
+ for (i = 0; i < lenin; i += 2)
+ for (j = din[i]; j <= din[i + 1]; j++)
+ if ((!i) || *(dr - 1) != j)
+ *dr++ = j;
+
+ if (in != (ArrayType *) DatumGetPointer(entry->key))
+ pfree(in);
+ retval = palloc(sizeof(GISTENTRY));
+ gistentryinit(*retval, PointerGetDatum(r),
+ entry->rel, entry->page, entry->offset, false);
+
+ PG_RETURN_POINTER(retval);
+}
+
+/*
+** The GiST Penalty method for _intments
+*/
+Datum
+g_int_penalty(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
+ float *result = (float *) PG_GETARG_POINTER(2);
+ ArrayType *ud;
+ float tmp1,
+ tmp2;
+
+ ud = inner_int_union((ArrayType *) DatumGetPointer(origentry->key),
+ (ArrayType *) DatumGetPointer(newentry->key));
+ rt__int_size(ud, &tmp1);
+ rt__int_size((ArrayType *) DatumGetPointer(origentry->key), &tmp2);
+ *result = tmp1 - tmp2;
+ pfree(ud);
+
+ PG_RETURN_POINTER(result);
+}
+
+
+
+Datum
+g_int_same(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P(1);
+ bool *result = (bool *) PG_GETARG_POINTER(2);
+ int32 n = ARRNELEMS(a);
+ int32 *da,
+ *db;
+
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
+ if (n != ARRNELEMS(b))
+ {
+ *result = false;
+ PG_RETURN_POINTER(result);
+ }
+ *result = true;
+ da = ARRPTR(a);
+ db = ARRPTR(b);
+ while (n--)
+ {
+ if (*da++ != *db++)
+ {
+ *result = false;
+ break;
+ }
+ }
+
+ PG_RETURN_POINTER(result);
+}
+
+/*****************************************************************
+** Common GiST Method
+*****************************************************************/
+
+typedef struct
+{
+ OffsetNumber pos;
+ float cost;
+} SPLITCOST;
+
+static int
+comparecost(const void *a, const void *b)
+{
+ if (((const SPLITCOST *) a)->cost == ((const SPLITCOST *) b)->cost)
+ return 0;
+ else
+ return (((const SPLITCOST *) a)->cost > ((const SPLITCOST *) b)->cost) ? 1 : -1;
+}
+
+/*
+** The GiST PickSplit method for _intments
+** We use Guttman's poly time split algorithm
+*/
+Datum
+g_int_picksplit(PG_FUNCTION_ARGS)
+{
+ GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+ GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
+ OffsetNumber i,
+ j;
+ ArrayType *datum_alpha,
+ *datum_beta;
+ ArrayType *datum_l,
+ *datum_r;
+ ArrayType *union_d,
+ *union_dl,
+ *union_dr;
+ ArrayType *inter_d;
+ bool firsttime;
+ float size_alpha,
+ size_beta,
+ size_union,
+ size_inter;
+ float size_waste,
+ waste;
+ float size_l,
+ size_r;
+ int nbytes;
+ OffsetNumber seed_1 = 0,
+ seed_2 = 0;
+ OffsetNumber *left,
+ *right;
+ OffsetNumber maxoff;
+ SPLITCOST *costvector;
+
+#ifdef GIST_DEBUG
+ elog(DEBUG3, "--------picksplit %d", entryvec->n);
+#endif
+
+ maxoff = entryvec->n - 2;
+ nbytes = (maxoff + 2) * sizeof(OffsetNumber);
+ v->spl_left = (OffsetNumber *) palloc(nbytes);
+ v->spl_right = (OffsetNumber *) palloc(nbytes);
+
+ firsttime = true;
+ waste = 0.0;
+ for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i))
+ {
+ datum_alpha = GETENTRY(entryvec, i);
+ for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j))
+ {
+ datum_beta = GETENTRY(entryvec, j);
+
+ /* compute the wasted space by unioning these guys */
+ /* size_waste = size_union - size_inter; */
+ union_d = inner_int_union(datum_alpha, datum_beta);
+ rt__int_size(union_d, &size_union);
+ inter_d = inner_int_inter(datum_alpha, datum_beta);
+ rt__int_size(inter_d, &size_inter);
+ size_waste = size_union - size_inter;
+
+ pfree(union_d);
+ pfree(inter_d);
+
+ /*
+ * are these a more promising split that what we've already seen?
+ */
+
+ if (size_waste > waste || firsttime)
+ {
+ waste = size_waste;
+ seed_1 = i;
+ seed_2 = j;
+ firsttime = false;
+ }
+ }
+ }
+
+ left = v->spl_left;
+ v->spl_nleft = 0;
+ right = v->spl_right;
+ v->spl_nright = 0;
+ if (seed_1 == 0 || seed_2 == 0)
+ {
+ seed_1 = 1;
+ seed_2 = 2;
+ }
+
+ datum_alpha = GETENTRY(entryvec, seed_1);
+ datum_l = copy_intArrayType(datum_alpha);
+ rt__int_size(datum_l, &size_l);
+ datum_beta = GETENTRY(entryvec, seed_2);
+ datum_r = copy_intArrayType(datum_beta);
+ rt__int_size(datum_r, &size_r);
+
+ maxoff = OffsetNumberNext(maxoff);
+
+ /*
+ * sort entries
+ */
+ costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+ for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
+ {
+ costvector[i - 1].pos = i;
+ datum_alpha = GETENTRY(entryvec, i);
+ union_d = inner_int_union(datum_l, datum_alpha);
+ rt__int_size(union_d, &size_alpha);
+ pfree(union_d);
+ union_d = inner_int_union(datum_r, datum_alpha);
+ rt__int_size(union_d, &size_beta);
+ pfree(union_d);
+ costvector[i - 1].cost = Abs((size_alpha - size_l) - (size_beta - size_r));
+ }
+ qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
+
+ /*
+ * Now split up the regions between the two seeds. An important property
+ * of this split algorithm is that the split vector v has the indices of
+ * items to be split in order in its left and right vectors. We exploit
+ * this property by doing a merge in the code that actually splits the
+ * page.
+ *
+ * For efficiency, we also place the new index tuple in this loop. This is
+ * handled at the very end, when we have placed all the existing tuples
+ * and i == maxoff + 1.
+ */
+
+
+ for (j = 0; j < maxoff; j++)
+ {
+ i = costvector[j].pos;
+
+ /*
+ * If we've already decided where to place this item, just put it on
+ * the right list. Otherwise, we need to figure out which page needs
+ * the least enlargement in order to store the item.
+ */
+
+ if (i == seed_1)
+ {
+ *left++ = i;
+ v->spl_nleft++;
+ continue;
+ }
+ else if (i == seed_2)
+ {
+ *right++ = i;
+ v->spl_nright++;
+ continue;
+ }
+
+ /* okay, which page needs least enlargement? */
+ datum_alpha = GETENTRY(entryvec, i);
+ union_dl = inner_int_union(datum_l, datum_alpha);
+ union_dr = inner_int_union(datum_r, datum_alpha);
+ rt__int_size(union_dl, &size_alpha);
+ rt__int_size(union_dr, &size_beta);
+
+ /* pick which page to add it to */
+ if (size_alpha - size_l < size_beta - size_r + WISH_F(v->spl_nleft, v->spl_nright, 0.01))
+ {
+ pfree(datum_l);
+ pfree(union_dr);
+ datum_l = union_dl;
+ size_l = size_alpha;
+ *left++ = i;
+ v->spl_nleft++;
+ }
+ else
+ {
+ pfree(datum_r);
+ pfree(union_dl);
+ datum_r = union_dr;
+ size_r = size_beta;
+ *right++ = i;
+ v->spl_nright++;
+ }
+ }
+ pfree(costvector);
+ *right = *left = FirstOffsetNumber;
+
+ v->spl_ldatum = PointerGetDatum(datum_l);
+ v->spl_rdatum = PointerGetDatum(datum_r);
+
+ PG_RETURN_POINTER(v);
+}
+
+Datum
+g_int_options(PG_FUNCTION_ARGS)
+{
+ local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
+
+ init_local_reloptions(relopts, sizeof(GISTIntArrayOptions));
+ add_local_int_reloption(relopts, "numranges",
+ "number of ranges for compression",
+ G_INT_NUMRANGES_DEFAULT, 1, G_INT_NUMRANGES_MAX,
+ offsetof(GISTIntArrayOptions, num_ranges));
+
+ PG_RETURN_VOID();
+}
diff --git a/contrib/intarray/_int_op.c b/contrib/intarray/_int_op.c
new file mode 100644
index 0000000..5b164f6
--- /dev/null
+++ b/contrib/intarray/_int_op.c
@@ -0,0 +1,432 @@
+/*
+ * contrib/intarray/_int_op.c
+ */
+#include "postgres.h"
+
+#include "_int.h"
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(_int_different);
+PG_FUNCTION_INFO_V1(_int_same);
+PG_FUNCTION_INFO_V1(_int_contains);
+PG_FUNCTION_INFO_V1(_int_contained);
+PG_FUNCTION_INFO_V1(_int_overlap);
+PG_FUNCTION_INFO_V1(_int_union);
+PG_FUNCTION_INFO_V1(_int_inter);
+
+Datum
+_int_contained(PG_FUNCTION_ARGS)
+{
+ /* just reverse the operands and call _int_contains */
+ return DirectFunctionCall2(_int_contains,
+ PG_GETARG_DATUM(1),
+ PG_GETARG_DATUM(0));
+}
+
+Datum
+_int_contains(PG_FUNCTION_ARGS)
+{
+ /* Force copy so we can modify the arrays in-place */
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
+ bool res;
+
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+ PREPAREARR(a);
+ PREPAREARR(b);
+ res = inner_int_contains(a, b);
+ pfree(a);
+ pfree(b);
+ PG_RETURN_BOOL(res);
+}
+
+Datum
+_int_different(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_BOOL(!DatumGetBool(DirectFunctionCall2(_int_same,
+ PointerGetDatum(PG_GETARG_POINTER(0)),
+ PointerGetDatum(PG_GETARG_POINTER(1)))));
+}
+
+Datum
+_int_same(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
+ int na,
+ nb;
+ int n;
+ int *da,
+ *db;
+ bool result;
+
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+ na = ARRNELEMS(a);
+ nb = ARRNELEMS(b);
+ da = ARRPTR(a);
+ db = ARRPTR(b);
+
+ result = false;
+
+ if (na == nb)
+ {
+ SORT(a);
+ SORT(b);
+ result = true;
+
+ for (n = 0; n < na; n++)
+ {
+ if (da[n] != db[n])
+ {
+ result = false;
+ break;
+ }
+ }
+ }
+
+ pfree(a);
+ pfree(b);
+
+ PG_RETURN_BOOL(result);
+}
+
+/* _int_overlap -- does a overlap b?
+ */
+Datum
+_int_overlap(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
+ bool result;
+
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+ if (ARRISEMPTY(a) || ARRISEMPTY(b))
+ return false;
+
+ SORT(a);
+ SORT(b);
+
+ result = inner_int_overlap(a, b);
+
+ pfree(a);
+ pfree(b);
+
+ PG_RETURN_BOOL(result);
+}
+
+Datum
+_int_union(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
+ ArrayType *result;
+
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
+ SORT(a);
+ SORT(b);
+
+ result = inner_int_union(a, b);
+
+ pfree(a);
+ pfree(b);
+
+ PG_RETURN_POINTER(result);
+}
+
+Datum
+_int_inter(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
+ ArrayType *result;
+
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
+ SORT(a);
+ SORT(b);
+
+ result = inner_int_inter(a, b);
+
+ pfree(a);
+ pfree(b);
+
+ PG_RETURN_POINTER(result);
+}
+
+
+PG_FUNCTION_INFO_V1(intset);
+PG_FUNCTION_INFO_V1(icount);
+PG_FUNCTION_INFO_V1(sort);
+PG_FUNCTION_INFO_V1(sort_asc);
+PG_FUNCTION_INFO_V1(sort_desc);
+PG_FUNCTION_INFO_V1(uniq);
+PG_FUNCTION_INFO_V1(idx);
+PG_FUNCTION_INFO_V1(subarray);
+PG_FUNCTION_INFO_V1(intarray_push_elem);
+PG_FUNCTION_INFO_V1(intarray_push_array);
+PG_FUNCTION_INFO_V1(intarray_del_elem);
+PG_FUNCTION_INFO_V1(intset_union_elem);
+PG_FUNCTION_INFO_V1(intset_subtract);
+
+Datum
+intset(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_POINTER(int_to_intset(PG_GETARG_INT32(0)));
+}
+
+Datum
+icount(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ int32 count = ARRNELEMS(a);
+
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_INT32(count);
+}
+
+Datum
+sort(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ text *dirstr = (fcinfo->nargs == 2) ? PG_GETARG_TEXT_PP(1) : NULL;
+ int32 dc = (dirstr) ? VARSIZE_ANY_EXHDR(dirstr) : 0;
+ char *d = (dirstr) ? VARDATA_ANY(dirstr) : NULL;
+ int dir = -1;
+
+ CHECKARRVALID(a);
+ if (ARRNELEMS(a) < 2)
+ PG_RETURN_POINTER(a);
+
+ if (dirstr == NULL || (dc == 3
+ && (d[0] == 'A' || d[0] == 'a')
+ && (d[1] == 'S' || d[1] == 's')
+ && (d[2] == 'C' || d[2] == 'c')))
+ dir = 1;
+ else if (dc == 4
+ && (d[0] == 'D' || d[0] == 'd')
+ && (d[1] == 'E' || d[1] == 'e')
+ && (d[2] == 'S' || d[2] == 's')
+ && (d[3] == 'C' || d[3] == 'c'))
+ dir = 0;
+ if (dir == -1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("second parameter must be \"ASC\" or \"DESC\"")));
+ QSORT(a, dir);
+ PG_RETURN_POINTER(a);
+}
+
+Datum
+sort_asc(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+
+ CHECKARRVALID(a);
+ QSORT(a, 1);
+ PG_RETURN_POINTER(a);
+}
+
+Datum
+sort_desc(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+
+ CHECKARRVALID(a);
+ QSORT(a, 0);
+ PG_RETURN_POINTER(a);
+}
+
+Datum
+uniq(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+
+ CHECKARRVALID(a);
+ if (ARRNELEMS(a) < 2)
+ PG_RETURN_POINTER(a);
+ a = _int_unique(a);
+ PG_RETURN_POINTER(a);
+}
+
+Datum
+idx(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ int32 result;
+
+ CHECKARRVALID(a);
+ result = ARRNELEMS(a);
+ if (result)
+ result = intarray_match_first(a, PG_GETARG_INT32(1));
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_INT32(result);
+}
+
+Datum
+subarray(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ int32 start = PG_GETARG_INT32(1);
+ int32 len = (fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0;
+ int32 end = 0;
+ int32 c;
+ ArrayType *result;
+
+ start = (start > 0) ? start - 1 : start;
+
+ CHECKARRVALID(a);
+ if (ARRISEMPTY(a))
+ {
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_POINTER(new_intArrayType(0));
+ }
+
+ c = ARRNELEMS(a);
+
+ if (start < 0)
+ start = c + start;
+
+ if (len < 0)
+ end = c + len;
+ else if (len == 0)
+ end = c;
+ else
+ end = start + len;
+
+ if (end > c)
+ end = c;
+
+ if (start < 0)
+ start = 0;
+
+ if (start >= end || end <= 0)
+ {
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_POINTER(new_intArrayType(0));
+ }
+
+ result = new_intArrayType(end - start);
+ if (end - start > 0)
+ memcpy(ARRPTR(result), ARRPTR(a) + start, (end - start) * sizeof(int32));
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_POINTER(result);
+}
+
+Datum
+intarray_push_elem(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ ArrayType *result;
+
+ result = intarray_add_elem(a, PG_GETARG_INT32(1));
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_POINTER(result);
+}
+
+Datum
+intarray_push_array(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P(1);
+ ArrayType *result;
+
+ result = intarray_concat_arrays(a, b);
+ PG_FREE_IF_COPY(a, 0);
+ PG_FREE_IF_COPY(b, 1);
+ PG_RETURN_POINTER(result);
+}
+
+Datum
+intarray_del_elem(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ int32 elem = PG_GETARG_INT32(1);
+ int32 c;
+ int32 *aa;
+ int32 n = 0,
+ i;
+
+ CHECKARRVALID(a);
+ if (!ARRISEMPTY(a))
+ {
+ c = ARRNELEMS(a);
+ aa = ARRPTR(a);
+ for (i = 0; i < c; i++)
+ {
+ if (aa[i] != elem)
+ {
+ if (i > n)
+ aa[n++] = aa[i];
+ else
+ n++;
+ }
+ }
+ a = resize_intArrayType(a, n);
+ }
+ PG_RETURN_POINTER(a);
+}
+
+Datum
+intset_union_elem(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ ArrayType *result;
+
+ result = intarray_add_elem(a, PG_GETARG_INT32(1));
+ PG_FREE_IF_COPY(a, 0);
+ QSORT(result, 1);
+ PG_RETURN_POINTER(_int_unique(result));
+}
+
+Datum
+intset_subtract(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
+ ArrayType *result;
+ int32 ca;
+ int32 cb;
+ int32 *aa,
+ *bb,
+ *r;
+ int32 n = 0,
+ i = 0,
+ k = 0;
+
+ CHECKARRVALID(a);
+ CHECKARRVALID(b);
+
+ QSORT(a, 1);
+ a = _int_unique(a);
+ ca = ARRNELEMS(a);
+ QSORT(b, 1);
+ b = _int_unique(b);
+ cb = ARRNELEMS(b);
+ result = new_intArrayType(ca);
+ aa = ARRPTR(a);
+ bb = ARRPTR(b);
+ r = ARRPTR(result);
+ while (i < ca)
+ {
+ if (k == cb || aa[i] < bb[k])
+ r[n++] = aa[i++];
+ else if (aa[i] == bb[k])
+ {
+ i++;
+ k++;
+ }
+ else
+ k++;
+ }
+ result = resize_intArrayType(result, n);
+ pfree(a);
+ pfree(b);
+ PG_RETURN_POINTER(result);
+}
diff --git a/contrib/intarray/_int_selfuncs.c b/contrib/intarray/_int_selfuncs.c
new file mode 100644
index 0000000..a3a538a
--- /dev/null
+++ b/contrib/intarray/_int_selfuncs.c
@@ -0,0 +1,333 @@
+/*-------------------------------------------------------------------------
+ *
+ * _int_selfuncs.c
+ * Functions for selectivity estimation of intarray operators
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * contrib/intarray/_int_selfuncs.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "_int.h"
+#include "access/htup_details.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_statistic.h"
+#include "catalog/pg_type.h"
+#include "miscadmin.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/selfuncs.h"
+#include "utils/syscache.h"
+
+PG_FUNCTION_INFO_V1(_int_overlap_sel);
+PG_FUNCTION_INFO_V1(_int_contains_sel);
+PG_FUNCTION_INFO_V1(_int_contained_sel);
+PG_FUNCTION_INFO_V1(_int_overlap_joinsel);
+PG_FUNCTION_INFO_V1(_int_contains_joinsel);
+PG_FUNCTION_INFO_V1(_int_contained_joinsel);
+PG_FUNCTION_INFO_V1(_int_matchsel);
+
+
+static Selectivity int_query_opr_selec(ITEM *item, Datum *values, float4 *freqs,
+ int nmncelems, float4 minfreq);
+static int compare_val_int4(const void *a, const void *b);
+
+/*
+ * Wrappers around the default array selectivity estimation functions.
+ *
+ * The default array selectivity operators for the @>, && and @< operators
+ * work fine for integer arrays. However, if we tried to just use arraycontsel
+ * and arraycontjoinsel directly as the cost estimator functions for our
+ * operators, they would not work as intended, because they look at the
+ * operator's OID. Our operators behave exactly like the built-in anyarray
+ * versions, but we must tell the cost estimator functions which built-in
+ * operators they correspond to. These wrappers just replace the operator
+ * OID with the corresponding built-in operator's OID, and call the built-in
+ * function.
+ */
+
+Datum
+_int_overlap_sel(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_DATUM(DirectFunctionCall4(arraycontsel,
+ PG_GETARG_DATUM(0),
+ ObjectIdGetDatum(OID_ARRAY_OVERLAP_OP),
+ PG_GETARG_DATUM(2),
+ PG_GETARG_DATUM(3)));
+}
+
+Datum
+_int_contains_sel(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_DATUM(DirectFunctionCall4(arraycontsel,
+ PG_GETARG_DATUM(0),
+ ObjectIdGetDatum(OID_ARRAY_CONTAINS_OP),
+ PG_GETARG_DATUM(2),
+ PG_GETARG_DATUM(3)));
+}
+
+Datum
+_int_contained_sel(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_DATUM(DirectFunctionCall4(arraycontsel,
+ PG_GETARG_DATUM(0),
+ ObjectIdGetDatum(OID_ARRAY_CONTAINED_OP),
+ PG_GETARG_DATUM(2),
+ PG_GETARG_DATUM(3)));
+}
+
+Datum
+_int_overlap_joinsel(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_DATUM(DirectFunctionCall5(arraycontjoinsel,
+ PG_GETARG_DATUM(0),
+ ObjectIdGetDatum(OID_ARRAY_OVERLAP_OP),
+ PG_GETARG_DATUM(2),
+ PG_GETARG_DATUM(3),
+ PG_GETARG_DATUM(4)));
+}
+
+Datum
+_int_contains_joinsel(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_DATUM(DirectFunctionCall5(arraycontjoinsel,
+ PG_GETARG_DATUM(0),
+ ObjectIdGetDatum(OID_ARRAY_CONTAINS_OP),
+ PG_GETARG_DATUM(2),
+ PG_GETARG_DATUM(3),
+ PG_GETARG_DATUM(4)));
+}
+
+Datum
+_int_contained_joinsel(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_DATUM(DirectFunctionCall5(arraycontjoinsel,
+ PG_GETARG_DATUM(0),
+ ObjectIdGetDatum(OID_ARRAY_CONTAINED_OP),
+ PG_GETARG_DATUM(2),
+ PG_GETARG_DATUM(3),
+ PG_GETARG_DATUM(4)));
+}
+
+
+/*
+ * _int_matchsel -- restriction selectivity function for intarray @@ query_int
+ */
+Datum
+_int_matchsel(PG_FUNCTION_ARGS)
+{
+ PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
+
+ List *args = (List *) PG_GETARG_POINTER(2);
+ int varRelid = PG_GETARG_INT32(3);
+ VariableStatData vardata;
+ Node *other;
+ bool varonleft;
+ Selectivity selec;
+ QUERYTYPE *query;
+ Datum *mcelems = NULL;
+ float4 *mcefreqs = NULL;
+ int nmcelems = 0;
+ float4 minfreq = 0.0;
+ float4 nullfrac = 0.0;
+ AttStatsSlot sslot;
+
+ /*
+ * If expression is not "variable @@ something" or "something @@ variable"
+ * then punt and return a default estimate.
+ */
+ if (!get_restriction_variable(root, args, varRelid,
+ &vardata, &other, &varonleft))
+ PG_RETURN_FLOAT8(DEFAULT_EQ_SEL);
+
+ /*
+ * Variable should be int[]. We don't support cases where variable is
+ * query_int.
+ */
+ if (vardata.vartype != INT4ARRAYOID)
+ PG_RETURN_FLOAT8(DEFAULT_EQ_SEL);
+
+ /*
+ * Can't do anything useful if the something is not a constant, either.
+ */
+ if (!IsA(other, Const))
+ {
+ ReleaseVariableStats(vardata);
+ PG_RETURN_FLOAT8(DEFAULT_EQ_SEL);
+ }
+
+ /*
+ * The "@@" operator is strict, so we can cope with NULL right away.
+ */
+ if (((Const *) other)->constisnull)
+ {
+ ReleaseVariableStats(vardata);
+ PG_RETURN_FLOAT8(0.0);
+ }
+
+ /* The caller made sure the const is a query, so get it now */
+ query = DatumGetQueryTypeP(((Const *) other)->constvalue);
+
+ /* Empty query matches nothing */
+ if (query->size == 0)
+ {
+ ReleaseVariableStats(vardata);
+ return (Selectivity) 0.0;
+ }
+
+ /*
+ * Get the statistics for the intarray column.
+ *
+ * We're interested in the Most-Common-Elements list, and the NULL
+ * fraction.
+ */
+ if (HeapTupleIsValid(vardata.statsTuple))
+ {
+ Form_pg_statistic stats;
+
+ stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple);
+ nullfrac = stats->stanullfrac;
+
+ /*
+ * For an int4 array, the default array type analyze function will
+ * collect a Most Common Elements list, which is an array of int4s.
+ */
+ if (get_attstatsslot(&sslot, vardata.statsTuple,
+ STATISTIC_KIND_MCELEM, InvalidOid,
+ ATTSTATSSLOT_VALUES | ATTSTATSSLOT_NUMBERS))
+ {
+ Assert(sslot.valuetype == INT4OID);
+
+ /*
+ * There should be three more Numbers than Values, because the
+ * last three (for intarray) cells are taken for minimal, maximal
+ * and nulls frequency. Punt if not.
+ */
+ if (sslot.nnumbers == sslot.nvalues + 3)
+ {
+ /* Grab the lowest frequency. */
+ minfreq = sslot.numbers[sslot.nnumbers - (sslot.nnumbers - sslot.nvalues)];
+
+ mcelems = sslot.values;
+ mcefreqs = sslot.numbers;
+ nmcelems = sslot.nvalues;
+ }
+ }
+ }
+ else
+ memset(&sslot, 0, sizeof(sslot));
+
+ /* Process the logical expression in the query, using the stats */
+ selec = int_query_opr_selec(GETQUERY(query) + query->size - 1,
+ mcelems, mcefreqs, nmcelems, minfreq);
+
+ /* MCE stats count only non-null rows, so adjust for null rows. */
+ selec *= (1.0 - nullfrac);
+
+ free_attstatsslot(&sslot);
+ ReleaseVariableStats(vardata);
+
+ CLAMP_PROBABILITY(selec);
+
+ PG_RETURN_FLOAT8((float8) selec);
+}
+
+/*
+ * Estimate selectivity of single intquery operator
+ */
+static Selectivity
+int_query_opr_selec(ITEM *item, Datum *mcelems, float4 *mcefreqs,
+ int nmcelems, float4 minfreq)
+{
+ Selectivity selec;
+
+ /* since this function recurses, it could be driven to stack overflow */
+ check_stack_depth();
+
+ if (item->type == VAL)
+ {
+ Datum *searchres;
+
+ if (mcelems == NULL)
+ return (Selectivity) DEFAULT_EQ_SEL;
+
+ searchres = (Datum *) bsearch(&item->val, mcelems, nmcelems,
+ sizeof(Datum), compare_val_int4);
+ if (searchres)
+ {
+ /*
+ * The element is in MCELEM. Return precise selectivity (or at
+ * least as precise as ANALYZE could find out).
+ */
+ selec = mcefreqs[searchres - mcelems];
+ }
+ else
+ {
+ /*
+ * The element is not in MCELEM. Punt, but assume that the
+ * selectivity cannot be more than minfreq / 2.
+ */
+ selec = Min(DEFAULT_EQ_SEL, minfreq / 2);
+ }
+ }
+ else if (item->type == OPR)
+ {
+ /* Current query node is an operator */
+ Selectivity s1,
+ s2;
+
+ s1 = int_query_opr_selec(item - 1, mcelems, mcefreqs, nmcelems,
+ minfreq);
+ switch (item->val)
+ {
+ case (int32) '!':
+ selec = 1.0 - s1;
+ break;
+
+ case (int32) '&':
+ s2 = int_query_opr_selec(item + item->left, mcelems, mcefreqs,
+ nmcelems, minfreq);
+ selec = s1 * s2;
+ break;
+
+ case (int32) '|':
+ s2 = int_query_opr_selec(item + item->left, mcelems, mcefreqs,
+ nmcelems, minfreq);
+ selec = s1 + s2 - s1 * s2;
+ break;
+
+ default:
+ elog(ERROR, "unrecognized operator: %d", item->val);
+ selec = 0; /* keep compiler quiet */
+ break;
+ }
+ }
+ else
+ {
+ elog(ERROR, "unrecognized int query item type: %u", item->type);
+ selec = 0; /* keep compiler quiet */
+ }
+
+ /* Clamp intermediate results to stay sane despite roundoff error */
+ CLAMP_PROBABILITY(selec);
+
+ return selec;
+}
+
+/*
+ * Comparison function for binary search in mcelem array.
+ */
+static int
+compare_val_int4(const void *a, const void *b)
+{
+ int32 key = *(int32 *) a;
+ const Datum *t = (const Datum *) b;
+
+ return key - DatumGetInt32(*t);
+}
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;
+}
diff --git a/contrib/intarray/_intbig_gist.c b/contrib/intarray/_intbig_gist.c
new file mode 100644
index 0000000..67c44e9
--- /dev/null
+++ b/contrib/intarray/_intbig_gist.c
@@ -0,0 +1,589 @@
+/*
+ * contrib/intarray/_intbig_gist.c
+ */
+#include "postgres.h"
+
+#include "_int.h"
+#include "access/gist.h"
+#include "access/reloptions.h"
+#include "access/stratnum.h"
+#include "port/pg_bitutils.h"
+
+#define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer((vec)->vector[(pos)].key))
+/*
+** _intbig methods
+*/
+PG_FUNCTION_INFO_V1(g_intbig_consistent);
+PG_FUNCTION_INFO_V1(g_intbig_compress);
+PG_FUNCTION_INFO_V1(g_intbig_decompress);
+PG_FUNCTION_INFO_V1(g_intbig_penalty);
+PG_FUNCTION_INFO_V1(g_intbig_picksplit);
+PG_FUNCTION_INFO_V1(g_intbig_union);
+PG_FUNCTION_INFO_V1(g_intbig_same);
+PG_FUNCTION_INFO_V1(g_intbig_options);
+
+PG_FUNCTION_INFO_V1(_intbig_in);
+PG_FUNCTION_INFO_V1(_intbig_out);
+
+Datum
+_intbig_in(PG_FUNCTION_ARGS)
+{
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("_intbig_in() not implemented")));
+ PG_RETURN_DATUM(0);
+}
+
+Datum
+_intbig_out(PG_FUNCTION_ARGS)
+{
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("_intbig_out() not implemented")));
+ PG_RETURN_DATUM(0);
+}
+
+static GISTTYPE *
+_intbig_alloc(bool allistrue, int siglen, BITVECP sign)
+{
+ int flag = allistrue ? ALLISTRUE : 0;
+ int size = CALCGTSIZE(flag, siglen);
+ GISTTYPE *res = (GISTTYPE *) palloc(size);
+
+ SET_VARSIZE(res, size);
+ res->flag = flag;
+
+ if (!allistrue)
+ {
+ if (sign)
+ memcpy(GETSIGN(res), sign, siglen);
+ else
+ memset(GETSIGN(res), 0, siglen);
+ }
+
+ return res;
+}
+
+
+/*********************************************************************
+** intbig functions
+*********************************************************************/
+static bool
+_intbig_overlap(GISTTYPE *a, ArrayType *b, int siglen)
+{
+ int num = ARRNELEMS(b);
+ int32 *ptr = ARRPTR(b);
+
+ CHECKARRVALID(b);
+
+ while (num--)
+ {
+ if (GETBIT(GETSIGN(a), HASHVAL(*ptr, siglen)))
+ return true;
+ ptr++;
+ }
+
+ return false;
+}
+
+static bool
+_intbig_contains(GISTTYPE *a, ArrayType *b, int siglen)
+{
+ int num = ARRNELEMS(b);
+ int32 *ptr = ARRPTR(b);
+
+ CHECKARRVALID(b);
+
+ while (num--)
+ {
+ if (!GETBIT(GETSIGN(a), HASHVAL(*ptr, siglen)))
+ return false;
+ ptr++;
+ }
+
+ return true;
+}
+
+Datum
+g_intbig_same(PG_FUNCTION_ARGS)
+{
+ GISTTYPE *a = (GISTTYPE *) PG_GETARG_POINTER(0);
+ GISTTYPE *b = (GISTTYPE *) PG_GETARG_POINTER(1);
+ bool *result = (bool *) PG_GETARG_POINTER(2);
+ int siglen = GET_SIGLEN();
+
+ if (ISALLTRUE(a) && ISALLTRUE(b))
+ *result = true;
+ else if (ISALLTRUE(a))
+ *result = false;
+ else if (ISALLTRUE(b))
+ *result = false;
+ else
+ {
+ int32 i;
+ BITVECP sa = GETSIGN(a),
+ sb = GETSIGN(b);
+
+ *result = true;
+ LOOPBYTE(siglen)
+ {
+ if (sa[i] != sb[i])
+ {
+ *result = false;
+ break;
+ }
+ }
+ }
+ PG_RETURN_POINTER(result);
+}
+
+Datum
+g_intbig_compress(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ int siglen = GET_SIGLEN();
+
+ if (entry->leafkey)
+ {
+ GISTENTRY *retval;
+ ArrayType *in = DatumGetArrayTypeP(entry->key);
+ int32 *ptr;
+ int num;
+ GISTTYPE *res = _intbig_alloc(false, siglen, NULL);
+
+ CHECKARRVALID(in);
+ if (ARRISEMPTY(in))
+ {
+ ptr = NULL;
+ num = 0;
+ }
+ else
+ {
+ ptr = ARRPTR(in);
+ num = ARRNELEMS(in);
+ }
+
+ while (num--)
+ {
+ HASH(GETSIGN(res), *ptr, siglen);
+ ptr++;
+ }
+
+ retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+ gistentryinit(*retval, PointerGetDatum(res),
+ entry->rel, entry->page,
+ entry->offset, false);
+
+ if (in != DatumGetArrayTypeP(entry->key))
+ pfree(in);
+
+ PG_RETURN_POINTER(retval);
+ }
+ else if (!ISALLTRUE(DatumGetPointer(entry->key)))
+ {
+ GISTENTRY *retval;
+ int i;
+ BITVECP sign = GETSIGN(DatumGetPointer(entry->key));
+ GISTTYPE *res;
+
+ LOOPBYTE(siglen)
+ {
+ if ((sign[i] & 0xff) != 0xff)
+ PG_RETURN_POINTER(entry);
+ }
+
+ res = _intbig_alloc(true, siglen, sign);
+ retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+ gistentryinit(*retval, PointerGetDatum(res),
+ entry->rel, entry->page,
+ entry->offset, false);
+
+ PG_RETURN_POINTER(retval);
+ }
+
+ PG_RETURN_POINTER(entry);
+}
+
+
+static int32
+sizebitvec(BITVECP sign, int siglen)
+{
+ return pg_popcount(sign, siglen);
+}
+
+static int
+hemdistsign(BITVECP a, BITVECP b, int siglen)
+{
+ int i,
+ diff,
+ dist = 0;
+
+ LOOPBYTE(siglen)
+ {
+ diff = (unsigned char) (a[i] ^ b[i]);
+ /* Using the popcount functions here isn't likely to win */
+ dist += pg_number_of_ones[diff];
+ }
+ return dist;
+}
+
+static int
+hemdist(GISTTYPE *a, GISTTYPE *b, int siglen)
+{
+ if (ISALLTRUE(a))
+ {
+ if (ISALLTRUE(b))
+ return 0;
+ else
+ return SIGLENBIT(siglen) - sizebitvec(GETSIGN(b), siglen);
+ }
+ else if (ISALLTRUE(b))
+ return SIGLENBIT(siglen) - sizebitvec(GETSIGN(a), siglen);
+
+ return hemdistsign(GETSIGN(a), GETSIGN(b), siglen);
+}
+
+Datum
+g_intbig_decompress(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_DATUM(PG_GETARG_DATUM(0));
+}
+
+static int32
+unionkey(BITVECP sbase, GISTTYPE *add, int siglen)
+{
+ int32 i;
+ BITVECP sadd = GETSIGN(add);
+
+ if (ISALLTRUE(add))
+ return 1;
+ LOOPBYTE(siglen)
+ sbase[i] |= sadd[i];
+ return 0;
+}
+
+Datum
+g_intbig_union(PG_FUNCTION_ARGS)
+{
+ GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+ int *size = (int *) PG_GETARG_POINTER(1);
+ int siglen = GET_SIGLEN();
+ int32 i;
+ GISTTYPE *result = _intbig_alloc(false, siglen, NULL);
+ BITVECP base = GETSIGN(result);
+
+ for (i = 0; i < entryvec->n; i++)
+ {
+ if (unionkey(base, GETENTRY(entryvec, i), siglen))
+ {
+ result->flag |= ALLISTRUE;
+ SET_VARSIZE(result, CALCGTSIZE(ALLISTRUE, siglen));
+ break;
+ }
+ }
+
+ *size = VARSIZE(result);
+
+ PG_RETURN_POINTER(result);
+}
+
+Datum
+g_intbig_penalty(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
+ GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
+ float *penalty = (float *) PG_GETARG_POINTER(2);
+ GISTTYPE *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
+ GISTTYPE *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
+ int siglen = GET_SIGLEN();
+
+ *penalty = hemdist(origval, newval, siglen);
+ PG_RETURN_POINTER(penalty);
+}
+
+
+typedef struct
+{
+ OffsetNumber pos;
+ int32 cost;
+} SPLITCOST;
+
+static int
+comparecost(const void *a, const void *b)
+{
+ return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
+}
+
+
+Datum
+g_intbig_picksplit(PG_FUNCTION_ARGS)
+{
+ GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+ GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
+ int siglen = GET_SIGLEN();
+ OffsetNumber k,
+ j;
+ GISTTYPE *datum_l,
+ *datum_r;
+ BITVECP union_l,
+ union_r;
+ int32 size_alpha,
+ size_beta;
+ int32 size_waste,
+ waste = -1;
+ int32 nbytes;
+ OffsetNumber seed_1 = 0,
+ seed_2 = 0;
+ OffsetNumber *left,
+ *right;
+ OffsetNumber maxoff;
+ BITVECP ptr;
+ int i;
+ SPLITCOST *costvector;
+ GISTTYPE *_k,
+ *_j;
+
+ maxoff = entryvec->n - 2;
+ nbytes = (maxoff + 2) * sizeof(OffsetNumber);
+ v->spl_left = (OffsetNumber *) palloc(nbytes);
+ v->spl_right = (OffsetNumber *) palloc(nbytes);
+
+ for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
+ {
+ _k = GETENTRY(entryvec, k);
+ for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
+ {
+ size_waste = hemdist(_k, GETENTRY(entryvec, j), siglen);
+ if (size_waste > waste)
+ {
+ waste = size_waste;
+ seed_1 = k;
+ seed_2 = j;
+ }
+ }
+ }
+
+ left = v->spl_left;
+ v->spl_nleft = 0;
+ right = v->spl_right;
+ v->spl_nright = 0;
+
+ if (seed_1 == 0 || seed_2 == 0)
+ {
+ seed_1 = 1;
+ seed_2 = 2;
+ }
+
+ /* form initial .. */
+ datum_l = _intbig_alloc(ISALLTRUE(GETENTRY(entryvec, seed_1)), siglen,
+ GETSIGN(GETENTRY(entryvec, seed_1)));
+ datum_r = _intbig_alloc(ISALLTRUE(GETENTRY(entryvec, seed_2)), siglen,
+ GETSIGN(GETENTRY(entryvec, seed_2)));
+
+ maxoff = OffsetNumberNext(maxoff);
+ /* sort before ... */
+ costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+ for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
+ {
+ costvector[j - 1].pos = j;
+ _j = GETENTRY(entryvec, j);
+ size_alpha = hemdist(datum_l, _j, siglen);
+ size_beta = hemdist(datum_r, _j, siglen);
+ costvector[j - 1].cost = Abs(size_alpha - size_beta);
+ }
+ qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
+
+ union_l = GETSIGN(datum_l);
+ union_r = GETSIGN(datum_r);
+
+ for (k = 0; k < maxoff; k++)
+ {
+ j = costvector[k].pos;
+ if (j == seed_1)
+ {
+ *left++ = j;
+ v->spl_nleft++;
+ continue;
+ }
+ else if (j == seed_2)
+ {
+ *right++ = j;
+ v->spl_nright++;
+ continue;
+ }
+ _j = GETENTRY(entryvec, j);
+ size_alpha = hemdist(datum_l, _j, siglen);
+ size_beta = hemdist(datum_r, _j, siglen);
+
+ if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
+ {
+ if (ISALLTRUE(datum_l) || ISALLTRUE(_j))
+ {
+ if (!ISALLTRUE(datum_l))
+ MemSet((void *) union_l, 0xff, siglen);
+ }
+ else
+ {
+ ptr = GETSIGN(_j);
+ LOOPBYTE(siglen)
+ union_l[i] |= ptr[i];
+ }
+ *left++ = j;
+ v->spl_nleft++;
+ }
+ else
+ {
+ if (ISALLTRUE(datum_r) || ISALLTRUE(_j))
+ {
+ if (!ISALLTRUE(datum_r))
+ MemSet((void *) union_r, 0xff, siglen);
+ }
+ else
+ {
+ ptr = GETSIGN(_j);
+ LOOPBYTE(siglen)
+ union_r[i] |= ptr[i];
+ }
+ *right++ = j;
+ v->spl_nright++;
+ }
+ }
+
+ *right = *left = FirstOffsetNumber;
+ pfree(costvector);
+
+ v->spl_ldatum = PointerGetDatum(datum_l);
+ v->spl_rdatum = PointerGetDatum(datum_r);
+
+ PG_RETURN_POINTER(v);
+}
+
+Datum
+g_intbig_consistent(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
+ StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ bool *recheck = (bool *) PG_GETARG_POINTER(4);
+ int siglen = GET_SIGLEN();
+ bool retval;
+
+ /* All cases served by this function are inexact */
+ *recheck = true;
+
+ if (ISALLTRUE(DatumGetPointer(entry->key)))
+ PG_RETURN_BOOL(true);
+
+ if (strategy == BooleanSearchStrategy)
+ {
+ retval = signconsistent((QUERYTYPE *) query,
+ GETSIGN(DatumGetPointer(entry->key)),
+ siglen,
+ false);
+ PG_FREE_IF_COPY(query, 1);
+ PG_RETURN_BOOL(retval);
+ }
+
+ CHECKARRVALID(query);
+
+ switch (strategy)
+ {
+ case RTOverlapStrategyNumber:
+ retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key),
+ query, siglen);
+ break;
+ case RTSameStrategyNumber:
+ if (GIST_LEAF(entry))
+ {
+ int i,
+ num = ARRNELEMS(query);
+ int32 *ptr = ARRPTR(query);
+ BITVECP dq = palloc0(siglen),
+ de;
+
+ while (num--)
+ {
+ HASH(dq, *ptr, siglen);
+ ptr++;
+ }
+
+ de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
+ retval = true;
+ LOOPBYTE(siglen)
+ {
+ if (de[i] != dq[i])
+ {
+ retval = false;
+ break;
+ }
+ }
+
+ pfree(dq);
+ }
+ else
+ retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key),
+ query, siglen);
+ break;
+ case RTContainsStrategyNumber:
+ case RTOldContainsStrategyNumber:
+ retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key),
+ query, siglen);
+ break;
+ case RTContainedByStrategyNumber:
+ case RTOldContainedByStrategyNumber:
+ if (GIST_LEAF(entry))
+ {
+ int i,
+ num = ARRNELEMS(query);
+ int32 *ptr = ARRPTR(query);
+ BITVECP dq = palloc0(siglen),
+ de;
+
+ while (num--)
+ {
+ HASH(dq, *ptr, siglen);
+ ptr++;
+ }
+
+ de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
+ retval = true;
+ LOOPBYTE(siglen)
+ {
+ if (de[i] & ~dq[i])
+ {
+ retval = false;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Unfortunately, because empty arrays could be anywhere in
+ * the index, we must search the whole tree.
+ */
+ retval = true;
+ }
+ break;
+ default:
+ retval = false;
+ }
+ PG_FREE_IF_COPY(query, 1);
+ PG_RETURN_BOOL(retval);
+}
+
+Datum
+g_intbig_options(PG_FUNCTION_ARGS)
+{
+ local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
+
+ init_local_reloptions(relopts, sizeof(GISTIntArrayBigOptions));
+ add_local_int_reloption(relopts, "siglen",
+ "signature length in bytes",
+ SIGLEN_DEFAULT, 1, SIGLEN_MAX,
+ offsetof(GISTIntArrayBigOptions, siglen));
+
+ PG_RETURN_VOID();
+}
diff --git a/contrib/intarray/bench/bench.pl b/contrib/intarray/bench/bench.pl
new file mode 100755
index 0000000..daf3feb
--- /dev/null
+++ b/contrib/intarray/bench/bench.pl
@@ -0,0 +1,138 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+# make sure we are in a sane environment.
+use DBI();
+use DBD::Pg();
+use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
+use Getopt::Std;
+
+my %opt;
+getopts('d:b:s:veorauc', \%opt);
+
+if (!(scalar %opt && defined $opt{s}))
+{
+ print <<EOT;
+Usage:
+$0 -d DATABASE -s SECTIONS [-b NUMBER] [-v] [-e] [-o] [-r] [-a] [-u]
+-d DATABASE -DATABASE
+-b NUMBER -number of repeats
+-s SECTIONS -sections, format sid1[,sid2[,sid3[...]]]]
+-v -verbose (show SQL)
+-e -show explain
+-r -use RD-tree index
+-a -AND section
+-o -show output
+-u -unique
+-c -count
+
+EOT
+ exit;
+}
+
+$opt{d} ||= '_int4';
+my $dbi = DBI->connect('DBI:Pg:dbname=' . $opt{d});
+
+my %table;
+my @where;
+
+$table{message} = 1;
+
+if ($opt{a})
+{
+ if ($opt{r})
+ {
+ push @where, "message.sections @ '{$opt{s}}'";
+ }
+ else
+ {
+ foreach my $sid (split(/[,\s]+/, $opt{s}))
+ {
+ push @where, "message.mid = msp$sid.mid";
+ push @where, "msp$sid.sid = $sid";
+ $table{"message_section_map msp$sid"} = 1;
+ }
+ }
+}
+else
+{
+ if ($opt{r})
+ {
+ push @where, "message.sections && '{$opt{s}}'";
+ }
+ else
+ {
+ $table{message_section_map} = 1;
+ push @where, "message.mid = message_section_map.mid";
+ push @where, "message_section_map.sid in ($opt{s})";
+ }
+}
+
+my $outf;
+if ($opt{c})
+{
+ $outf =
+ ($opt{u}) ? 'count( distinct message.mid )' : 'count( message.mid )';
+}
+else
+{
+ $outf = ($opt{u}) ? 'distinct( message.mid )' : 'message.mid';
+}
+my $sql =
+ "select $outf from "
+ . join(', ', keys %table)
+ . " where "
+ . join(' AND ', @where) . ';';
+
+if ($opt{v})
+{
+ print "$sql\n";
+}
+
+if ($opt{e})
+{
+ my @plan =
+ map { "$_->[0]\n" } @{ $dbi->selectall_arrayref("explain $sql") };
+ print @plan;
+}
+
+my $t0 = [gettimeofday];
+my $count = 0;
+my $b = $opt{b};
+$b ||= 1;
+my @a;
+foreach (1 .. $b)
+{
+ @a = exec_sql($dbi, $sql);
+ $count = $#a;
+}
+my $elapsed = tv_interval($t0, [gettimeofday]);
+if ($opt{o})
+{
+ foreach (@a)
+ {
+ print "$_->{mid}\t$_->{sections}\n";
+ }
+}
+print sprintf(
+ "total: %.02f sec; number: %d; for one: %.03f sec; found %d docs\n",
+ $elapsed, $b, $elapsed / $b,
+ $count + 1);
+$dbi->disconnect;
+
+sub exec_sql
+{
+ my ($dbi, $sql, @keys) = @_;
+ my $sth = $dbi->prepare($sql) || die;
+ $sth->execute(@keys) || die;
+ my $r;
+ my @row;
+ while (defined($r = $sth->fetchrow_hashref))
+ {
+ push @row, $r;
+ }
+ $sth->finish;
+ return @row;
+}
diff --git a/contrib/intarray/bench/create_test.pl b/contrib/intarray/bench/create_test.pl
new file mode 100755
index 0000000..3f2a6e4
--- /dev/null
+++ b/contrib/intarray/bench/create_test.pl
@@ -0,0 +1,89 @@
+#!/usr/bin/perl
+
+# contrib/intarray/bench/create_test.pl
+
+use strict;
+use warnings;
+
+print <<EOT;
+create table message (
+ mid int not null,
+ sections int[]
+);
+create table message_section_map (
+ mid int not null,
+ sid int not null
+);
+
+EOT
+
+open(my $msg, '>', "message.tmp") || die;
+open(my $map, '>', "message_section_map.tmp") || die;
+
+srand(1);
+
+#foreach my $i ( 1..1778 ) {
+#foreach my $i ( 1..3443 ) {
+#foreach my $i ( 1..5000 ) {
+#foreach my $i ( 1..29362 ) {
+#foreach my $i ( 1..33331 ) {
+#foreach my $i ( 1..83268 ) {
+foreach my $i (1 .. 200000)
+{
+ my @sect;
+ if (rand() < 0.7)
+ {
+ $sect[0] = int((rand()**4) * 100);
+ }
+ else
+ {
+ my %hash;
+ @sect =
+ grep { $hash{$_}++; $hash{$_} <= 1 }
+ map { int((rand()**4) * 100) } 0 .. (int(rand() * 5));
+ }
+ if ($#sect < 0 || rand() < 0.1)
+ {
+ print $msg "$i\t\\N\n";
+ }
+ else
+ {
+ print $msg "$i\t{" . join(',', @sect) . "}\n";
+ map { print $map "$i\t$_\n" } @sect;
+ }
+}
+close $map;
+close $msg;
+
+copytable('message');
+copytable('message_section_map');
+
+print <<EOT;
+
+CREATE unique index message_key on message ( mid );
+--CREATE unique index message_section_map_key1 on message_section_map ( mid, sid );
+CREATE unique index message_section_map_key2 on message_section_map ( sid, mid );
+CREATE INDEX message_rdtree_idx on message using gist ( sections gist__int_ops );
+VACUUM ANALYZE;
+
+select count(*) from message;
+select count(*) from message_section_map;
+
+
+
+EOT
+
+
+unlink 'message.tmp', 'message_section_map.tmp';
+
+sub copytable
+{
+ my $t = shift;
+
+ print "COPY $t from stdin;\n";
+ open(my $fff, '<', "$t.tmp") || die;
+ while (<$fff>) { print; }
+ close $fff;
+ print "\\.\n";
+ return;
+}
diff --git a/contrib/intarray/data/test__int.data b/contrib/intarray/data/test__int.data
new file mode 100644
index 0000000..b3903d0
--- /dev/null
+++ b/contrib/intarray/data/test__int.data
@@ -0,0 +1,7000 @@
+{18,31,54,95}
+{23,50,13,9,39}
+{99,54,77}
+{79,83,16,63,32}
+{52,41,61,79,94,87}
+{76,59,39,36,21}
+{}
+{41,79,76,96,3}
+{25,59,5,96,32}
+{92,58,12,57}
+{24,48,41,88}
+{39,5,17}
+{10,41,78,25,35}
+{31,89,4}
+{68,74,94}
+{97,78,44,68,81,16}
+{87,76}
+{30,81}
+{72,20,99,26}
+{87,90,98,40,44}
+{24,99,66,61}
+{79,8,48,16}
+{62,99,48,80,75,39}
+{10,60,35,15}
+{45,71,10,97,56}
+{64,79,19,31}
+{30,57,42,31,45}
+{61,42,14,26}
+{12,38,65,36,56,36}
+{17,62,18,56}
+{84,85,90,60,55,17}
+{27,11,82,20,43}
+{14,27,18,48,39,51}
+{53,13,52}
+{56,35,81,60,27}
+{79,89,89,7}
+{65,17,31,17,29,85}
+{21,3}
+{53,55,16,83,4}
+{62,3,63}
+{73,40,99}
+{23,80}
+{2,74,42,37,21}
+{12,16}
+{80,60}
+{19,62,34}
+{38,19,31,6,15,2}
+{63,96,64,4,36,15}
+{9,3}
+{91,87,15,18,7,66}
+{17,10}
+{77,96}
+{11,43,31,2,89}
+{17,77,89,50}
+{24,6,61,88,51}
+{61,50,59,90,5,89}
+{58,1,39,48}
+{78,36,70,92}
+{43,3,22,95,51}
+{}
+{88,64,25,64,86}
+{34,6,49,90,25}
+{86,35,13,22}
+{21,44,83}
+{42,88,72,65,59,96}
+{36,33,1,98}
+{16,54}
+{35,16,44}
+{73,23,20}
+{84,25,1,52,35}
+{27,36,54,87,31}
+{38,47,83,3}
+{64,13}
+{65,84,85,16,22}
+{57,9,39,73}
+{89,11,67,55,73}
+{78,39,84,63,62,45}
+{50,63,8}
+{}
+{96,36,58,65,96}
+{59,86,41,30}
+{90,60,39,47,19}
+{70,100,73,99}
+{}
+{85,14,39}
+{76,53}
+{96,38,52,13,87,85}
+{97,51,15,30,53,87}
+{30,59,9,40,13}
+{31,91,68,79}
+{37,56,39,78,75}
+{82,2,47}
+{33,25,45,40}
+{51,21,92,20,18,76}
+{84,93,36,95,34,69}
+{66,25,5,40}
+{77,6,57,42}
+{}
+{88,81,85,37,12}
+{56,73,38}
+{70,70,6,19}
+{82,54,91}
+{75,8}
+{45,33,64,90,95}
+{8,71,66,12}
+{56,26,68,94}
+{70,77,4,96,62,83}
+{23,87}
+{34,34,4,33}
+{28,84}
+{78,75,77}
+{88,53}
+{27,38}
+{2,2,82}
+{30,52,88,61,33}
+{29,72,94,68}
+{85,72}
+{88,4}
+{63,90,43,66,24,33}
+{88,48,47}
+{3,11,98,37,61}
+{45,65,63,15,38}
+{79,45,56,94}
+{56,74,78,19,76}
+{24,81,64,13,100}
+{93,27,63,71,27,3}
+{74,13,85,86,32,60}
+{98,40,63,13}
+{41,95,19,93,17,84}
+{90,28,100,100,19,2}
+{35,15,54}
+{29,81,77}
+{54,64,63,12,18}
+{38,43,85,21,35}
+{84,28,27,4,80,27}
+{80,77,55,98}
+{13,71,48,55,89,38}
+{58,43,27,5,57}
+{5,33,96,6}
+{73,93,87,69,100,24}
+{58,96,38,85,55,51}
+{37,30,88,4,8,59}
+{24,68,43,48,18,84}
+{23,100,82,30,42}
+{23,36,16,99,27}
+{41,75}
+{66,41,10,37,16,6}
+{54,49,60}
+{4,56,44,72,40}
+{71,96,67,100,59}
+{7,41}
+{8,3,27}
+{38,69,47,68,5,24}
+{43,100,59,62}
+{92,14,34,5,71,48}
+{72,5,91,29,99,36}
+{62,71,37,80,62,50}
+{32,45,17}
+{89,68}
+{52,17,55}
+{21,47,15,92}
+{36,100,5}
+{14,76,59,11,15}
+{59,72}
+{37,55,89,49}
+{87,79,96,20,93}
+{6,44}
+{32,46,25}
+{27,47,76,4,54}
+{2,16}
+{90,36}
+{11,19,27,79}
+{54,4}
+{72,88}
+{14,85,71,69,5,22}
+{31,48}
+{28,35,18}
+{77,55,100,73,57,62}
+{}
+{14,59,53}
+{98,3}
+{13,56}
+{26,61,88,54,88,33}
+{70,12}
+{55,16,15,42,76}
+{13,75}
+{97,38,82,51,86,53}
+{41,76,39,84,32}
+{94,66,47}
+{55,28}
+{}
+{94,65,59,20}
+{55,50,56,14,58}
+{14,94,52,25,69,95}
+{20,96}
+{37,38}
+{26,35,9,98,74}
+{11,9,41,79}
+{36,57,87,69,92,89}
+{11,39,60,4,47,3}
+{97,5}
+{16,58,38,98,42}
+{46,69}
+{35,54}
+{36,79,54}
+{}
+{63,78}
+{12,86,52,29,60,30}
+{29,27,58,86,42,62}
+{42,12,60}
+{90,93,85,29}
+{16,8,45}
+{29,33,85}
+{32,14,6,47,74}
+{14,85,14,26,3}
+{46,71,10,16}
+{30,63}
+{}
+{91,30,56}
+{46,36,68,91,36,88}
+{24,61}
+{66,21,80,14}
+{43,63,50,21,11}
+{38,46,18,51}
+{38,28,70}
+{17,41,76,1,30}
+{47,63}
+{56,80,85,1,7,97}
+{75,5,79,32}
+{5,17,66,51,68}
+{6,83,2}
+{25,40,79,84}
+{58,38,12,68}
+{55,86,20,67,27}
+{58,64}
+{14,51}
+{12,86,57,68}
+{61,91,65,3,83,68}
+{40,31,82,21}
+\N
+{24,64,35,32}
+{32,83,18,27,43,32}
+{50,83}
+{94,84,58,3,25,79}
+{66,2,27,36,24}
+{71,34}
+{17,57}
+{22,40,49,50,10}
+{79,62,94,78}
+{92,79,24,72}
+{23,41}
+{69,60,77,70,18,48}
+{39,45,91,85}
+{27,43,22,21,85}
+{84,51,96,7,18}
+{100,38,69,93,66,39}
+{73,42,35,15,69,98}
+{100,17,37,15,40}
+{1,91,2,17,90,48}
+{18,12,52,24}
+{39,43,89}
+{16,13,88}
+{69,8,75}
+{34,91,54,81}
+{37,68,89,1,56}
+{81,83,39,36,14}
+{12,15,2}
+{14,16,88,43}
+{59,12}
+{1,62,21,94}
+{29,43,70,52,93}
+{29,36,56,78}
+{91,56,86,89,53}
+{14,83,39,94}
+{29,58,72,4,45}
+{76,56,84,28,58}
+{4,52,6,88,43,17}
+{21,1,35,62,77,6}
+{78,74}
+{1,20,93,43}
+\N
+{30,100,35,94,74,64}
+{81,3,21,4}
+{9,19,33}
+{28,62,40,64,26}
+{69,72,26,30,90}
+{52,70,78,43}
+{91,58,33,22,92,26}
+{98,36,96,94,66}
+{86,43,82}
+{93,52,4,58,51}
+\N
+{49,61,80,79,90}
+{50,81,72}
+{57,29}
+{54,31,36}
+{52,31,6,48,2}
+{4,51,37,83,17}
+{60,20,94,82,18}
+{52,64,26,81,69,61}
+{39,8,22,2,8}
+{31,25,95,99}
+{11,72,30,95,20,28}
+{78,87}
+{21,40,98,41,73,33}
+{67,88,42,62,11,47}
+{85,1}
+{4,68,100,72,24}
+{82,43}
+{97,55,47,52}
+{51,52}
+{20,21}
+{69,46,34,59,54,61}
+{9,31,43}
+{68,20}
+{73,63}
+{71,12,93,8,48,10}
+{44,46,42,91,21}
+{98,52}
+{45,60}
+{95,38,30,3}
+{27,77,2,46,53,18}
+{99,5}
+{79,33,34,48,82}
+{3,29,82,72,35}
+{73,75,83}
+{25,43,37,26}
+\N
+{51,95,40}
+{18,23,10,90,15,20}
+{85,66}
+{25,76,22,87,88,18}
+{92,4}
+{27,51}
+{25,77,12,37}
+{44,52,69,39,21,63}
+{94,30,74,36}
+{60,18}
+{62,88,94,93,26}
+{5,72,96,25}
+{99,1,85,98,85,70}
+{33,21,37,19}
+{44,78}
+{47,2,73,32,3}
+{91,35,10,81}
+{80,64,7,45,84}
+{86,16,96,8,88}
+{32,29,84,81,30,8}
+{51,28,6,16}
+{88,51,50,54,56,96}
+{79,19,41,40}
+{40,26,10,26,2}
+{60,34,3,29}
+{68,80,70,56}
+{60,23,39}
+{50,69,6,71,70,25}
+{98,53,94,14,45,11}
+{98,39,64,89,98,32}
+\N
+{45,5,15,23,41,63}
+{54,31,55,58,32}
+{36,56}
+{38,78,65,4,75,38}
+\N
+{40,6,93,40,13,59}
+{42,50,10,65,96}
+{6,94,49}
+{63,44,36,55}
+{40,79}
+{39,75,27}
+{8,31}
+{81,75}
+{99,82,85,34,24,89}
+{86,82,20}
+{63,96}
+{47,83,29}
+{70,46,48}
+{44,11}
+{94,19,84,79,77,22}
+{68,47,100,48,65,77}
+\N
+{76,12,86,58}
+{13,14,79,61,12}
+{68,65,16,93,89}
+{95,18,29,89,92,43}
+{19,12,50,47}
+{82,93,85}
+{71,40,85}
+{95,96,100,86}
+{2,40,71,36,25}
+{11,95,25}
+{79,46,41,35,39}
+\N
+\N
+{88,29}
+{54,14,94,88}
+{59,67,81,41}
+{46,68,78,56,47,30}
+{5,76,87}
+{23,89,47,46}
+{47,98,14,31,1,60}
+{32,14,96,61,37}
+{79,66,93}
+{98,1,77,44}
+{21,68,2,31,17}
+{94,23,15}
+{48,47,57,94,49,71}
+{54,3}
+{99,40,81,86,81}
+{85,12,98,81,5}
+{60,41,21}
+{38,82,55,41,96}
+{11,98,12,69,93}
+{11,70,66,44}
+{23,92,80}
+{10,8,43,97}
+{17,30}
+{78,56,58}
+{84,87,84}
+{12,32,7,58,47,48}
+{29,46}
+{87,34}
+{59,30,72,85,71}
+{67,48,83,98}
+{35,10,73,71,1,77}
+{21,51,16,60,64,12}
+{36,61}
+{54,98}
+{44,74,84}
+{83,14}
+{71,52,48,48,15,92}
+{79,78,98,35}
+{52,29,47,86,96}
+{10,37}
+{21,25}
+{57,22,28,30,97,47}
+{15,28}
+{88,24,98,45,65}
+{78,42}
+{36,70}
+{40,48}
+{72,3,78,69,57,33}
+\N
+{21,96,16,21,75,23}
+{55,5,72,45}
+{99,2,72,29}
+{48,17}
+{84,84,40,1,59}
+{34,11}
+{34,80,45,31}
+{56,82,25,65,22,64}
+{10,4,55}
+{74,67,42,74,80}
+{84,22,42,6,87,30}
+{6,51,89,2,84,78}
+{19,95,93,87,8}
+{45,84,25}
+{7,12,16,92}
+{89,82,16}
+{22,64}
+{16,31,49,48,45,14}
+{69,64,19,14,39,8}
+{40,96,26,48,65}
+{17,45,4,57}
+{73,8}
+{85,89,1,15,74,51}
+\N
+{57,89}
+{25,12,55}
+{39,62,35}
+{85,88,71,98,83}
+{64,63,75,72}
+{100,40,38,1}
+{2,44}
+{13,46,59,43}
+{87,9,93,50}
+{77,7,11,30}
+{61,11,18}
+{19,25,68,83}
+{67,25}
+{54,18,85}
+{96,81,38,11,3}
+{87,32,47,79,62,56}
+{42,49}
+{41,65,24,13,79,75}
+{85,32,96}
+\N
+{3,63,47,84,67,13}
+{53,57,59,61}
+{95,27,8,89,35}
+{76,78,76,76,14,37}
+{31,62,65}
+{97,57,60,80}
+{18,81,93,67}
+{8,10}
+{65,25}
+{68,1,62,63,64,88}
+{27,56,74}
+{29,61,78,40}
+{54,72}
+{96,30,71,21,99}
+{67,11,67}
+{26,65,31}
+{89,90,89,68}
+{56,39,63,39}
+{50,67}
+{72,100,24,84,9}
+{29,57,65,37,3}
+{72,75,79,30}
+{78,44,87,67}
+{100,19}
+{35,60,82}
+{16,83,69,38}
+{29,98,13,60}
+{42,60,87}
+{18,67,60}
+{31,77,50}
+{3,22,40,59,7}
+{82,80}
+\N
+{32,92,70,30,18,35}
+{48,38,92,82}
+{10,92,66,59}
+{4,67,42,21,71}
+{27,88,20,21,9}
+{46,22,27,85,36}
+{42,55,36}
+{24,2,96}
+{96,48,40,48,52}
+{15,5,90,10,68,20}
+{30,2,67,92,96,63}
+{16,82,87,26}
+{88,98,76,29}
+{29,11,94,23}
+{58,20}
+{52,18,55,73}
+{20,81,52,19,37}
+{93,21,97}
+{2,77}
+{46,91,80,48,71,20}
+{87,7,93}
+{68,77,61}
+{59,33,52}
+{67,62,89,2,62,90}
+{30,82,72,44}
+{72,18,60,38}
+{11,14,59}
+{74,65,54,58,67,66}
+{74,56,40,73,50,66}
+{42,17,56,59,53,19}
+{75,25,76,9,72,50}
+{14,57}
+{61,47}
+{90,11,72,13}
+{52,27}
+{80,84,53,55,98}
+{16,26,55,17,79,96}
+{42,73,77}
+{6,84,67,54,96}
+{99,48,99,63,73,77}
+{5,41,72,5,88,81}
+{19,20,20}
+{21,89,55,44}
+{82,67,11,64,61,5}
+{44,34,8,62,53}
+{75,53,66,36,100}
+{46,65,6,70,4}
+{84,10,56,35,18}
+{65,60}
+{88,56,27,11}
+{10,9,97}
+{97,49,100,100,76,32}
+{2,98,57}
+{47,57,84,74,79}
+{80,9,24}
+{96,33,86,28,19}
+{43,76}
+{46,14,55,92}
+{60,69,66,62,22}
+{45,85}
+{45,9,36,13,45,1}
+{24,49,8,37,66,64}
+{98,53,96,47,2}
+{36,44,32,4}
+{77,36,78,51,63}
+{82,36}
+\N
+{54,55,33,45,69,18}
+{82,93}
+{65,59,2,62,10,25}
+{75,70,76,69,7,23}
+{10,34,67,85}
+{94,66,28,40,64,41}
+{35,73,64,28,45,68}
+{75,2}
+{58,49,4,87,19}
+{91,99,11,66,75,70}
+{26,64}
+\N
+{13,51,18}
+{39,33,21,18}
+{27,50,82,2,3,71}
+{51,89,44,53}
+{88,91,34}
+{45,96,27,12,51,52}
+{31,96}
+{2,9,54,89}
+\N
+{57,99}
+{87,84,70,7,98,42}
+{32,80}
+{57,64,28}
+{24,39,76,4,30}
+{59,38,15,45,47,28}
+{71,20,37,1}
+{72,59}
+{7,44}
+{50,37,18,1,58,40}
+{13,18,21,56}
+{72,3,26,74,91}
+{60,22,71,49}
+{55,82,61,8,48,66}
+{28,22,75,41,52}
+{51,63,27,41,16}
+{59,89,40,85,86}
+{12,1}
+{52,11,6}
+{37,10,43,88,15,7}
+{14,94,81}
+{34,56,57,4}
+{81,43,11,88,74,76}
+\N
+{67,10,50,79,70,35}
+{14,51}
+{49,50,23,84}
+{51,41,57,100,19,14}
+{31,55,40,96}
+{8,42,33}
+{83,34,1}
+{56,80,22,93}
+\N
+{8,77,91}
+{58,39}
+{55,30,74}
+{50,22,63,73}
+{80,19,67,70,18}
+{7,99,45,23,59,78}
+{36,97,10,33,22,45}
+{43,78,90}
+\N
+{1,68}
+{63,95,54}
+{5,67,61,37,89}
+{32,97,2,56}
+{83,31,6,80,63}
+\N
+{34,15,30,40,16}
+{13,43,6}
+{35,86,31}
+{45,59,4,95,26}
+{63,48,25}
+{56,97,89,45,87,21}
+{42,81,69}
+{49,99,87}
+{81,21,15,36,70,2}
+{93,41,53}
+{54,71,82}
+{88,90,51}
+{100,35,18}
+{88,81}
+{76,16,87,14}
+{16,83,81,44}
+{16,53,100,91}
+{55,75,92}
+{27,97,76,88,66}
+{14,100,95,95}
+{95,84,93,29,67}
+{32,10}
+{82,12,51}
+{40,6,18,14,29,70}
+{3,100,81}
+{83,69}
+{35,63,31,15}
+{5,100,81,54,37,78}
+{99,76,33}
+{88,85,16}
+{46,20,15,10,6,90}
+{53,15,75,76,94}
+{5,76}
+{16,7,21,70}
+{3,84,15}
+{29,58,73,91}
+{82,39,64}
+{49,66,83,76}
+{79,49,19,67,18,76}
+{9,56,41}
+{12,22,19}
+{62,54}
+{20,73,40}
+{34,53,58,68,96}
+{97,14,61,63}
+{38,55,90,63}
+{83,78,81,29,12,46}
+{96,97,40,89,10}
+{67,33,19,19,74,47}
+{78,31}
+{92,74,93}
+{59,54,90,52,29,87}
+{92,39,55,89,81,21}
+{20,85,64}
+{13,97}
+{88,18,85,24,54,90}
+{67,51,47}
+{27,29,90}
+{48,27,7,92}
+{100,37,24,41,68,66}
+{45,7,100,83,51}
+{34,10}
+{60,36,44}
+{55,46,4}
+{86,64}
+{61,77,98,64}
+{14,82,14,50,1}
+\N
+{53,31}
+{64,43,35,44,98,75}
+{98,15,52,58,76}
+{55,94,92,40,80}
+{1,14,100,42,45,74}
+{13,90,84,97,18,92}
+\N
+{13,91}
+{67,33,15}
+{18,96,38}
+{95,70,34,100}
+{17,29,64,32}
+{19,14,83,69,60,99}
+{69,29,64,61,45,17}
+{78,48,24}
+{40,60,61,93,17}
+{19,89,22,71}
+{48,8,13,11,56}
+{75,18,77,100}
+{29,78}
+{51,92,97,31}
+{83,5,2,97,68,69}
+{39,86,86,94,41}
+{66,21,27}
+{30,84,11,60}
+{50,61,28,46,38,45}
+{12,59,66,80,15,64}
+{69,22}
+{30,54,58,99}
+{14,28,80,22}
+{44,31,14,61,83,72}
+{55,53,78,91,76,55}
+{43,3,90,22,7}
+{51,34,24}
+{3,99,5,72,82}
+{95,38,61}
+{22,8}
+{78,40,93,65,18,26}
+{21,17,19,8,89}
+\N
+\N
+{94,88,27}
+{49,45}
+{67,24,64,86,18,1}
+{5,33,18,84,51}
+{15,71,89,48,94,81}
+{71,69}
+{98,63,73,64}
+{14,75,12}
+{47,42,88,13}
+{35,51,60}
+{63,41}
+{73,11,66,99,8}
+\N
+{2,17,6,44,97}
+{95,24}
+{2,13,35,21}
+{76,29}
+{81,37,21}
+{23,63,27,53}
+{70,66,58,27,4}
+{69,62,22}
+{62,96,44}
+{68,87,99}
+{51,40,81,52,93}
+{81,11,45,92,22,21}
+{5,39,46}
+{44,7}
+{14,63,62,9,12}
+{9,19,90,72,51}
+{70,61,24,36}
+\N
+{29,19,3,30}
+{76,86,28,58,38}
+{59,27}
+{9,65,65,10,37,6}
+{89,51,50,23}
+{65,2}
+{33,51}
+{25,55,69,55,1,78}
+{76,71,93,46,23}
+{70,30,50,11,2,89}
+{74,39}
+{4,29,22,80,15,23}
+{16,30,69,76,61,67}
+{43,34,4,70,36}
+{59,32,25,93,32,98}
+{64,4}
+{52,33,47}
+{31,49,7,62,7,95}
+{44,69,12,45,34,8}
+{81,37,83,35,3}
+{24,74,16,89,94,27}
+{79,71,72,49,88,35}
+{17,96,72,87,48}
+{81,18,50}
+{11,19,70}
+{42,95,42,58,90}
+{27,65,83,86,33}
+{55,7}
+{43,55,92,79}
+{97,55}
+{85,25}
+{93,42,69,44,26,78}
+{2,40,46,19,84}
+{8,42,16,26,87}
+{36,8,42}
+{31,47,61,44,13}
+{85,97,47}
+{27,30,71,88,15,100}
+{69,27,4,19}
+{3,52,31,62,98}
+{64,86}
+{91,6}
+{76,40}
+{57,77,7,40}
+{71,34,48,53,37}
+{36,72}
+{61,99,53,2,31,6}
+{86,15}
+{52,93,59,51}
+{57,27,52}
+{48,67,31,69}
+{34,90,37,73,60,83}
+{71,24,49,59}
+{93,71,90}
+{77,31,77}
+{47,40,32,20}
+{97,40,63,80,44}
+{88,55,10,40}
+{86,36,40,72,38,9}
+{31,97}
+{56,19,55,62,60}
+{53,95}
+{33,36}
+{50,12,55,42,96,100}
+{41,17,100,76}
+{65,1,61,69,64,21}
+{90,92}
+\N
+{74,42,86}
+{2,4}
+{99,78,5,92,1,61}
+{1,69}
+{80,73,60,31}
+\N
+{10,25,13}
+{50,34,75}
+{12,90,6,36,42}
+{23,54,46}
+{67,28,66,87}
+{8,88,88,51,55,32}
+{15,19,24,91,75}
+{80,16,70}
+{41,7,90,37}
+{97,57,32,21}
+{54,74,29,12,55,78}
+{60,76,37,92,44,73}
+{1,56,14}
+{40,79}
+{97,1,30,78,56}
+{36,25,61}
+{33,3,51,30,38}
+{2,94,19,15}
+{7,38,72}
+{96,18,3}
+{18,95,15,62,74,53}
+{59,61}
+{18,66,66,65,4,33}
+{49,83,10}
+{17,52,90,39,61,87}
+{38,92,55,26}
+{8,43}
+{77,51,68,23,47}
+{27,65,24,43,88,73}
+{54,34,30,2,19,62}
+{12,36,81,24,66,8}
+{38,91,90,99,84}
+{51,55,94,97,91,15}
+{50,42,20,22}
+{70,4,22}
+{64,26}
+{56,86,16,21,31,61}
+{7,19,86,49,10,53}
+{81,16,74}
+{95,9,11,46,47}
+{34,23,16}
+{94,38,19,4,4}
+{39,79}
+{41,3,62}
+{84,67,53,90,46}
+{17,46,23}
+{62,1,5,58,52,1}
+{23,83,80,62,19}
+{99,61,77}
+{51,95,48,96,75}
+{39,2,6,95,43,36}
+{69,9,59}
+{62,97,31}
+{75,96}
+{33,29,35,13,94,78}
+{28,71,16,99}
+{72,86,25}
+{5,28,15,33}
+\N
+{13,13,52,20}
+{58,98,83,85,81}
+{13,75,42}
+{7,91,3,83,82,37}
+{72,91}
+{10,67,61}
+\N
+{43,86,76}
+{36,62}
+{64,56}
+{63,13,22,24}
+{76,49,38,23,9,8}
+\N
+{92,58,24,19,96,90}
+{24,37,76,37,1,95}
+{91,9}
+{46,35,48,37,91,76}
+{72,21,6}
+{30,80,39,90,89,18}
+{83,30,67,17}
+{43,36,46,43}
+{4,31,34,36,33,48}
+\N
+{16,49}
+{75,56,8,91,4}
+{92,80}
+{74,72,68,89,7,82}
+{79,17,26}
+{14,15,28,72,58}
+{42,21,9}
+{71,39,98,98,61}
+{68,63,23,74,74,48}
+{91,80,22,100,57,30}
+{63,60}
+{90,9,10,67,89,14}
+{53,93}
+{75,49,34,30,38}
+{2,43}
+{32,4,24,48,23,31}
+{45,24,31,15,51}
+{65,62,21}
+{83,50}
+{10,90,98,86,87,1}
+{63,2,9,17,30}
+\N
+{77,46,60}
+{49,39}
+{37,86,4,63}
+{33,28,37,33}
+{4,88,80,14,47,45}
+{90,64,17,65}
+{60,90,12}
+{7,2,38,33}
+\N
+{39,90,7}
+{89,32}
+{27,47,63,31}
+{54,10,10,73,84,87}
+{55,58,25,87}
+{41,24}
+{71,26,8,31}
+{74,19,33,81,74}
+{47,58}
+{44,16,22,59}
+{2,10,97,16,25}
+{1,98,3,41,6,80}
+{12,13}
+{3,50,61,85}
+{54,5,44,97,71,86}
+{54,72,94}
+{59,13,28,79}
+{73,68,7,13}
+{90,49,63,45}
+{95,47,84}
+{31,79,98,22}
+\N
+{13,15,83,89,87,20}
+{1,58,87}
+{15,21,39}
+{93,27}
+{40,81,13,31}
+{29,52}
+{28,48,36,41}
+\N
+{71,23,89}
+{29,59,31,45,35}
+{49,83,24,19,44,26}
+{41,61,36,34,38,88}
+{66,17,18,9}
+{55,38,93,33}
+{84,42,71,15,12}
+{11,38,78,80,90,92}
+{1,6,28,68,58}
+{96,63,73,22,74,29}
+{65,97,68}
+{92,29,92,36}
+{47,25,30}
+{25,44,67,95,16}
+{7,26,41}
+{79,12,44,69}
+{17,27,4,60}
+{45,30,57}
+{68,24,63}
+{39,64,94,92}
+{27,68,39,68,75,8}
+{88,48,48}
+{86,86,8,54,7,45}
+{93,60,14,90,14}
+{97,42,54,67,38}
+{13,38}
+{84,34,30}
+{34,71,77,71,13}
+{82,18}
+{53,7,79,79}
+{28,65,38,20,93,100}
+{96,10}
+{94,12,93,48,51,20}
+{12,4,41,11,25,59}
+{95,69,23,25,1,19}
+\N
+{44,38}
+{12,4,96,7,48}
+{18,24,52,81,58,77}
+{15,36,1,50,81,23}
+{39,66,74}
+{52,22,99}
+{51,11,77,44,22}
+{51,19,18,91,75}
+{20,17,5,96,63,30}
+{31,56,9,21}
+{45,70,31,62,9}
+{84,22}
+{99,62,97,44,87,90}
+{95,94,95,24,25,47}
+{79,72,57,18,3,26}
+{54,67,37,57}
+{3,90,9,3}
+{95,90,40,7}
+{36,70,76,68,14,71}
+{15,59,7,1,48}
+{91,29,79,62,94}
+{76,36,92,82}
+{50,79,68}
+{55,63,88,87}
+{86,89,49,17}
+{19,74,14,52,8,59}
+{8,58}
+\N
+{77,74,20,39,26,29}
+{38,89}
+{58,21,44,81,17,16}
+{40,72,12,32,90}
+{93,34,92,17,39,85}
+{39,2}
+{43,21,83}
+{81,3,59,28}
+{34,97,52}
+\N
+{84,90,6,74,43,70}
+{41,6,10,98,86,41}
+{13,72,78,11,37,5}
+{100,40,54,75,33}
+{66,31}
+{58,58,75,83}
+{81,90,8,73,87,41}
+{9,63,22}
+{19,66,19,93,52}
+{39,88,13,25,66}
+{80,85,66}
+{66,76,11,71,97,77}
+{70,35,87}
+{36,17,69,2,41}
+{30,85,65,39,38}
+{39,35}
+{64,100}
+{83,53}
+{25,29,29,72}
+{19,63}
+{32,2,82,15}
+{31,31,46,11,2}
+{41,1}
+\N
+{55,41,15}
+{18,61,43,22,100}
+{47,60,16}
+{80,5}
+{52,2,76}
+{40,26}
+{81,12,16,25}
+{31,93,89,20,95,75}
+{26,75,86,1}
+{36,69,70,73,79}
+{38,39}
+{45,49,52}
+{88,53,45,10,49,31}
+{21,14,1,83}
+{7,71}
+{59,38,83,64,44}
+{6,52}
+{99,99,26,54,47,8}
+{13,46,72,5,23}
+{7,86,40,73,55}
+{28,47,50,62,44}
+{32,89}
+{39,48,50,100,62,95}
+{66,56,11,21,58,59}
+{7,44,95,53,95,36}
+{83,33,79}
+{34,65,51,52}
+{67,95,46,45,61}
+{69,84,71,38,46}
+\N
+{24,57,48,27,97}
+{83,91,97,94,37,44}
+{22,31,38,77,21}
+{72,32,53}
+{30,45}
+{93,94,27,95}
+{95,4,79,3}
+{33,90,92,54}
+{55,8,76,39,85,64}
+{82,54,93}
+{31,42,5}
+{38,14,73,12,14}
+{64,13,64,28,32,89}
+{5,28,4,22,72}
+{37,78,94}
+{58,73}
+{24,57,33}
+{48,28}
+{69,42}
+{97,91,75,84}
+{95,69}
+{64,95}
+{1,3}
+{76,38,81,11,90}
+{21,30,54}
+{92,100,97,21}
+{10,76,64}
+{85,79,100,79,76,63}
+{13,96}
+{91,47,84}
+{100,19,45,49}
+{99,71,21,10,69}
+{19,41,7,63,56,85}
+{16,32,6,92}
+\N
+{62,7,22,65}
+{1,86,67,47,83}
+{26,2,100,51,1}
+{20,22,86}
+{74,95,79}
+{8,53}
+{85,59,61,45,83,8}
+{2,76,63,26}
+{40,42,84,55,56,23}
+{37,7,25,14,2,47}
+{86,16,98,41,33}
+{76,30}
+\N
+{16,88,61,4,41,42}
+{59,92,94,76}
+{96,76,57,62,99,61}
+{14,30,23,13,9,32}
+{47,49,86}
+{48,19}
+{73,25,40}
+{29,75,31}
+{53,26}
+{28,95,78,84}
+\N
+{22,77,13,64,68}
+{15,69,82,26}
+{42,37}
+{64,59,95}
+{37,72,86,95}
+{9,59,92,57}
+{65,37,13}
+{93,67,81,54,89}
+{21,52,78,59,30}
+{98,90}
+{17,35,57,4}
+{44,56}
+\N
+\N
+{25,26,13}
+{62,41,60}
+{28,92,16,74,4}
+{92,19,85,77,11}
+{20,67,85,22}
+{75,69,34,29,64,73}
+{70,40,2,29}
+{87,27,70,54,6}
+{10,8,9,62}
+{71,41,14,22,23}
+{83,79,46,37,99}
+{79,42,3,54,20}
+{12,60,42,100,39,33}
+{13,79}
+{95,28,54,52,77,3}
+{55,50,25,41,42,16}
+{96,67,23,54}
+{65,54,32,52,16}
+{100,11,69,96,95}
+{1,18,93}
+{53,78}
+{24,40,47,30,40,11}
+{87,7,12,10,52,90}
+{3,72,95,15,32}
+{60,69,19,8,43,72}
+{88,10,11,55,37}
+{67,48,31,48}
+{98,70,38,97,14}
+\N
+{52,12,94}
+{41,26}
+{81,65}
+{66,74,9,66,12,3}
+{47,6,33,92}
+{95,2,12,90,73,97}
+{23,76,34,23,2,20}
+{7,22,37,83,15}
+{44,61,21,8,36}
+{88,52,8}
+{66,3,67,43,87}
+{16,51,10}
+{66,43,28,69,70}
+{47,2,94}
+{57,67,55}
+{40,59,6}
+{63,19}
+{51,71,68,28}
+{73,97,48,56,70}
+{3,4,28,48,18}
+{31,94,27,70,44}
+{85,18,40,6}
+{78,91,79,88,33}
+{11,90,78,49,97}
+{74,91,27,79,75,53}
+{1,70,3,40,43,99}
+{97,35}
+{58,27,40,6,47,33}
+{43,42,60,94}
+{41,34,23,53}
+{57,44,50}
+{8,10}
+{49,53,22}
+{91,2,90,13}
+{46,80,27,82,42,99}
+{12,96,72,23,83,56}
+{48,82,71,8,35,16}
+{38,69,38,49,47}
+{80,28,13,9}
+\N
+{84,13,12,33}
+{31,57}
+{68,86}
+{4,96,64,19,48,29}
+{66,8}
+{33,86}
+{32,38,86,86,41,84}
+{38,51,31}
+{59,17,76,36}
+{52,87,60,54}
+{7,58}
+{34,52,58,90}
+\N
+{30,67,97,2,1}
+{93,10}
+{47,16,46,8,39,84}
+{90,77,37}
+{92,58}
+{38,94,49,53,11}
+{70,49,35,67,18,28}
+{58,81}
+{79,100,9}
+\N
+{97,13,56}
+{99,40,87,67,58}
+{24,47,19,16}
+{12,27,47,48,3,59}
+{1,58,15}
+{97,28,6}
+{94,50,31}
+{71,34,94,53}
+{26,5}
+{46,66,56,27,37}
+{76,4,1}
+{80,63,40}
+{89,82}
+{39,100,71,82,95,8}
+{81,86,27,83,57,47}
+{30,30,92,8,33}
+{95,20}
+{4,19,8,74}
+{20,32,83,62,19,18}
+{75,29}
+{100,13,6,41,23}
+{63,5,93,72,43}
+{64,13,73}
+{35,91,61,26,41,96}
+{49,56}
+{2,28,80,84}
+{15,48}
+{32,49,96}
+{72,73,57,69,16}
+{95,1,88,64}
+{70,55,88,66}
+{76,66,30,92,1}
+{88,21,74,65,93}
+{72,75,75,3,26}
+{55,32,85,68,84}
+{45,40,93,33,72,20}
+{83,89,6}
+{4,60}
+{72,56}
+{73,7,69,25,96,74}
+{100,72,41,48,63,37}
+{21,72,70,94,67,54}
+{6,9,58,77,35}
+{70,59,35,25}
+{86,96,87,62,13,5}
+{93,52,74,57,58}
+{93,23,88,50,56}
+\N
+{95,72,68}
+{63,52,58,41,54,90}
+{52,23,53,32}
+{93,87,39}
+{23,73,6,46,79,72}
+{44,17,12}
+{79,59}
+{31,62,14,26,75,23}
+{64,72,18,48,63,50}
+{71,40,59,87}
+\N
+{82,17,10}
+{44,29}
+{6,4,39,16,21}
+{94,17}
+{91,61,37,36,9}
+{53,38,7,28,92}
+{95,93,35,18,48}
+{35,77,53,87,97,92}
+{56,28,68,19,28,86}
+\N
+{23,91,56}
+{97,5,89,24}
+{18,81,17,78,63}
+{83,19,46,10,22,66}
+{100,17,45}
+{25,87,61,79}
+{17,57,99,1,39,1}
+\N
+{2,51,26}
+{93,69,84,85,87}
+{40,58,70}
+{86,84,96,41}
+{28,36}
+{39,85}
+{16,84,75,68,87,17}
+{14,84,57}
+{25,85,35,82,56}
+\N
+\N
+{7,30,17,2,66,91}
+{45,17,57,27,98,65}
+{57,86,15,40,68,23}
+{82,32,28,89,41,79}
+{28,3,35,61}
+{76,95,19,81,48,50}
+{34,6,85,47,65,2}
+{70,23,91,33,15}
+{30,24,47,96,61,47}
+{78,88,64,60}
+{87,40,86,97}
+{47,14,54,37,100}
+{48,95,32,77,69}
+{58,12}
+{63,20,49}
+{78,85,41,72,6}
+{39,20,89,21,62,76}
+{71,6,10}
+{63,4,71}
+{51,21,37,63,54}
+{66,6,63,12,58}
+{89,97}
+{64,70}
+{53,1,65}
+{57,73,30,26}
+{15,99,47,89,95,99}
+{12,86,7}
+{50,68,1,31,67}
+{47,86,54,44}
+{78,7,86,76,22}
+{46,71,98,62,67}
+\N
+{64,91,80,63}
+{82,61,17,58}
+{85,64,90}
+{37,26,64,97}
+{68,25,26,61,68}
+{11,21}
+{63,53}
+\N
+{87,88,75,65,10,48}
+{32,7,38,72,44}
+{99,81,59,10}
+{31,58,60,66,41,28}
+{23,27,57,74,4}
+{20,94,28,29}
+{91,5,15,61,50,29}
+{34,58,15,85,65,29}
+{52,50,2,95,87}
+{3,94,54}
+{7,61,96,49}
+{51,70,23}
+{87,49,27,6,7}
+{83,61}
+{36,92,48,57,20,83}
+{53,12,60}
+{60,11}
+{68,43,74,23,66,55}
+{66,8,54,24}
+{48,72,41,74}
+{81,99,50,33,20,13}
+{27,80,60,83,26,74}
+{80,1,59,50,15,99}
+{11,70,20,29}
+{23,84,63}
+{63,24,91,19,28}
+{25,17,95}
+{94,13,81,69,26,89}
+{31,48}
+{45,20,74,51,62,33}
+{77,55,17,63,4,18}
+{89,14}
+{85,85}
+{23,11,85,74}
+{29,76}
+{62,40,96}
+{1,29,25}
+{56,26,12}
+{5,22,6}
+{61,9,6,85}
+\N
+{31,34,49,11,19}
+\N
+{14,20,64,73}
+{63,1,85}
+{2,58,61,100,9}
+{89,92}
+{37,13,81,77}
+{36,26,16,76}
+{78,10,10,92,63}
+{68,6,35,71,92,27}
+{2,88,33,14,85,27}
+{80,95,71,98}
+{8,33,33,55,90}
+{62,74,15,10,64}
+{60,18}
+{6,77}
+{27,38,4,49,27,89}
+{94,84,94,8,98}
+{15,73,47,47,26}
+{73,38,69,90,9,13}
+{17,33,32}
+{51,57,25,40,41,37}
+{77,70}
+{66,10}
+{50,90}
+{96,88,30,65}
+{30,49,100}
+{34,46,19,89,52,24}
+{83,85,62,72,10,64}
+{98,56,23,77,79}
+{97,90,83,85}
+{19,66,70}
+{70,89,59,12,71}
+{24,96,22,4}
+{43,32}
+\N
+{92,85,41}
+{96,90}
+\N
+{4,5,82}
+{58,32,34,86,30}
+{51,8,44}
+{31,96,37,47}
+{51,15,41,97}
+{86,41}
+{41,26,61}
+{62,79,68,73,5}
+{32,9,88,30}
+{89,34,64}
+{70,18}
+{64,31}
+{14,73,1,50,75}
+{57,1}
+{53,92,38,13,56}
+{41,1,87,40,60}
+{83,75,19}
+{69,98,25,64}
+{69,75}
+{84,13,25,8,81}
+{41,52}
+{90,80,17}
+{19,53,72,62,94}
+{29,30,99,32}
+{32,85,73,26,47}
+{6,48,89,93,23}
+{73,47,93,10,48}
+{60,21,26,60,63}
+{85,41}
+{75,61,61,45}
+{51,7,5}
+{9,46}
+{83,36,7,84,96}
+{71,78,55}
+{43,53,88}
+{8,1,80,69}
+{88,86,51,12,37}
+{45,69,40,85}
+\N
+{36,53,60,15,7,7}
+\N
+{92,5}
+\N
+{51,13,34}
+{39,23}
+{16,26,93}
+{91,96,19}
+{89,64,2}
+{8,74,29,24,66}
+{26,19,30,27}
+{81,59,52}
+{99,28}
+{5,12,63,79}
+{14,80,90,83,47,79}
+{67,64,32,58,44,19}
+{27,32,52,79,55}
+{68,87}
+{14,31,20,12}
+{38,99,65,32,15}
+{27,57,35,17,53}
+{63,64,6,60}
+{70,38,47,65}
+{24,87,20,4}
+{86,27,19,56}
+{62,44,1}
+{46,10,26,48}
+{40,57}
+{61,9,59,80,51,20}
+{83,44}
+{77,1}
+{78,63,42}
+{75,93,95,76,9,52}
+{20,58,10,37}
+{72,75,41,73}
+{63,93,5}
+{57,65,47}
+{34,6,51,38,21}
+{54,7,19,9}
+{61,6,47,64,100,86}
+{39,45,55,17}
+{81,53,67,33,70}
+{11,94}
+{57,98}
+{78,81}
+{75,71,20,8,13}
+{3,2,58,95}
+{37,58,5,46,54}
+{40,50,36,27,69}
+{73,42,86}
+{97,73,87,80,38}
+{27,56,94,73}
+{80,81,74}
+{53,79,86}
+{79,4,55,21,34,74}
+{84,63,21,97,92,38}
+{72,38,76,63,97,79}
+\N
+{64,91,100,98}
+{34,10}
+{97,73,7}
+{49,31}
+{87,39,65,96}
+{54,88,60,55,18,4}
+{20,72,96,26}
+{40,51}
+{37,46,89}
+{88,53,3,52,39}
+{10,34,77,95}
+{20,66,84,12}
+{51,19,61}
+{67,35}
+{73,56,89,43,35}
+{94,54,27,63}
+{63,53,21,79,76,49}
+{79,23,28,63,49}
+{47,94,75,11}
+{67,95,56}
+{80,86}
+\N
+{62,73}
+{98,69,11,57,24,90}
+{87,41,77,21,94}
+{21,87}
+{3,40,75}
+{67,53,78,29,16}
+{18,46,70,76,98}
+{14,67,50,63,22}
+{4,2,92,4,8}
+\N
+{41,76,79,95,96,61}
+{35,30,18,57}
+{34,91,89,27}
+{22,25,9,34,85}
+{4,53}
+{23,6,65,86,56,93}
+{54,81,8,59,36,47}
+{90,10,4,25,31,46}
+{91,82,82,80}
+\N
+{64,12,59,21,10}
+{49,93,76,26}
+{22,10,21,15,57}
+{14,29,93,31}
+{68,21}
+{62,95,12}
+{34,74,55,4}
+{26,39,93,31}
+{67,31,63}
+{23,89,98,88}
+{48,93,22,79,28}
+{1,88}
+{95,74,84,18,38}
+\N
+{82,29,22,45,15,81}
+{15,48}
+\N
+{17,36,97,77}
+{93,59,71,15,51,35}
+{67,33,57,11}
+{35,80,72,43}
+{69,89,69,48}
+{52,29,16,52,100,22}
+{60,30,45,19,25}
+{28,3,39,86,13}
+{81,40,25,20,39,5}
+{77,14,93,47,23,6}
+{42,19}
+{52,52,98}
+{9,29}
+{78,77,6,72}
+{2,59,73}
+{13,85,77,26,29}
+{64,63,94}
+{54,76,3}
+{7,1,5,91,100}
+{24,94,57,94,79,55}
+{4,22,1,75}
+{34,53,19,87}
+{69,75}
+{71,47,47,61,42,89}
+{3,32}
+{84,61,4,13,73}
+{74,61}
+{47,65,85}
+{50,84,83,18}
+{51,97,11,3}
+{59,92,4}
+{49,42,65,27,97,52}
+{19,33,40,44,71,100}
+{82,68,99,60,47,59}
+{47,33,82}
+{3,45}
+{47,28,60}
+{3,98,60,30,50}
+\N
+{11,40}
+{33,67,72,43,74}
+{9,49}
+{42,47,48}
+{53,88}
+{17,87,28}
+{20,4,72,62}
+{65,25,22,76,64}
+{9,62,57}
+{59,93,52,93,60}
+{85,85,1,55,50}
+{69,22,57}
+{8,50,81,32,4}
+{80,47}
+{60,88}
+{16,54,80,66}
+{99,87,66,65}
+{60,19,58,18}
+{14,77,66,48,59,41}
+{75,96,82}
+{42,72,93,79}
+{14,23,78,82,40}
+\N
+{29,47,16,41}
+{13,11,45,67,23,92}
+\N
+{8,3,52,41,56}
+{57,41,63}
+{5,50,59,87,50,58}
+{58,99,9}
+{60,99,15,63}
+{59,14,9}
+{68,81,34}
+{83,18,3,94,39}
+{27,52,100,66,48,82}
+{10,23,50,96}
+{72,14,12,68,62}
+\N
+{45,30,55,86,89,48}
+{5,80,97}
+{52,67,86,81}
+{99,4,38,79}
+{21,98,78,71,73}
+{10,23,38,61}
+{12,17,19,70}
+{79,23}
+{55,66,65,60,19}
+{7,34,68,88}
+{37,70,5}
+{41,57,86,31,10,6}
+{70,59,96,78}
+{88,18,32,22,56,21}
+{93,72,81,47,89,72}
+{100,14,49}
+{83,80}
+{73,11,97,14}
+{60,47,32,34,13,29}
+{39,6,88,24,6}
+{54,66,55,52,47}
+{56,89,88,98,94,48}
+{2,37}
+{13,54}
+{68,39,68}
+{60,81,10,85}
+{74,54,14}
+{30,52}
+{41,74,47}
+{77,28,8}
+{90,3,43,89,4}
+{29,46,84,63,79,83}
+{26,15,80,19}
+{76,28,77,6,47,91}
+{51,15}
+{93,15,51}
+{8,68,34,58,15}
+{5,56,57,81}
+{27,87,61,54,41}
+{31,37}
+{68,80,3,98,49,6}
+{96,10,39}
+{25,19,21,72,79}
+{69,1}
+{5,51,61,80}
+{76,25}
+{36,92}
+{54,46,31,87,13,8}
+{25,13,83,57}
+{29,53,73}
+{83,60,26,19}
+{27,89,34,13,20,38}
+{29,74,26,67,65}
+{90,36}
+\N
+{32,15,43,50}
+\N
+{55,86,68,51}
+{91,14,53,70,49,38}
+{75,29,79}
+{19,59,38,44,18,79}
+{43,31,24,20,16}
+{43,83,59,37}
+{61,17,95,61}
+{67,89,1}
+{65,20,46,58,49}
+{72,54,38,52,49}
+{75,12}
+{63,95}
+{99,17,79,11,35}
+{62,60}
+\N
+{69,83,89,73,20}
+{30,60,39,73}
+{78,99,29,45,61,21}
+{38,61}
+{51,15,47,11,4}
+{34,75}
+{57,26,42,42}
+{8,90,4,68}
+{63,70,99,3}
+{74,70,33,50,59}
+{27,18,73,83}
+{36,90}
+{82,77,2,83}
+{90,99}
+{15,25}
+{65,30,39,82,89,34}
+{12,24,64,54,49,83}
+{54,59}
+{63,49,81,36,75,52}
+{6,59,90,55,87}
+\N
+{97,52,54,97,3}
+{8,53,89,42,30}
+{68,42,64}
+{97,42,99,74}
+{19,31,32,52,7}
+{69,83}
+{61,17,35,39}
+{81,47,70,7,63}
+{78,10,63,97,31,48}
+{84,92}
+{64,82,40,39,57,44}
+{39,25,92,33,5}
+{27,74,85}
+{90,67,21,28,84}
+{36,33,62}
+{77,87,98,82,11,88}
+\N
+{11,41,17,91,56}
+{1,1}
+{84,100,8,22,20}
+{57,39,85,5}
+{55,47}
+{13,2,36,59,45}
+{95,66,53,32,29}
+{21,92}
+{35,32,9,58,77}
+{19,71,99,82}
+{19,37,87,43}
+{100,18}
+{67,86,29,40}
+\N
+{66,54,64,55}
+{67,25,18,31}
+{60,26,59,86,26,67}
+{26,21}
+{70,67,30}
+{93,82}
+{89,58,39,91,95}
+{15,86,25,8,12}
+{59,20,41,33,78,87}
+{10,72,89}
+\N
+{52,17,99}
+{77,29,7,7,1}
+{49,96,57,24,66,67}
+{10,26,83,84}
+{82,7,25}
+{66,77,57,25}
+{92,77}
+{24,48}
+{44,26,37,75,11}
+{73,80}
+{51,47,93,21,25,78}
+{76,49,15,98}
+{12,85,63,59,6}
+{25,51,47,58}
+{16,10}
+{17,30}
+{67,5}
+\N
+{54,96,21}
+{12,47}
+{29,90,69,22,89,82}
+{78,93,86,65,66}
+{83,84,58,67,13}
+{85,35,81,27,1,2}
+{76,29}
+{64,82,91}
+{35,89,38,89,10}
+{19,40,96}
+{83,70,85}
+{72,85,70,99}
+{34,1,39,16}
+{84,53,22,86,73}
+{32,23,70,49}
+{15,67,91,11}
+{73,95}
+{71,57,64}
+{88,91,56}
+{12,16}
+\N
+{62,82,26,84}
+{70,51,52,63,96}
+{34,93,49,57}
+{16,5,47}
+{18,59,12,82,83,51}
+{61,93,87,9}
+{46,9,45,38}
+{15,85,28,73}
+{31,99,26,3}
+{66,91,48,73}
+{98,80,9}
+{31,55,42,69,13,58}
+{43,8,70,29,83}
+{39,57,53,70,74}
+{89,13,60,38,89,3}
+{37,28,15}
+{67,77}
+{30,100,89,36,53,75}
+{36,19,48}
+{7,8}
+{12,76,26}
+{14,56,52,47,39,67}
+{87,83,51,2,97,25}
+{51,1}
+{59,69,37}
+{95,93,21}
+{100,92,37}
+{37,23,66,95,7,63}
+{52,56,77,86,46}
+{31,62,17}
+{57,48,79}
+{26,96,40,5,43,54}
+{40,92}
+{75,83,1,73,71}
+{75,61}
+{6,38}
+{35,23,76}
+{52,3,38,25,100,99}
+{45,15,44}
+{96,9,11,35,16,58}
+{9,80,76}
+{22,43,34,43,46}
+{34,68,21}
+{95,70,83}
+{60,7}
+{34,22,68,2}
+{78,30}
+{46,70,90,96}
+{5,24,69,61,32}
+{41,17,79,27}
+{59,88,64}
+{12,48,41,68,15,98}
+{43,84,59,62,36,14}
+{84,8,71,88,4,23}
+{45,67,67,17}
+{14,96,72,66}
+{91,23,4,11,28}
+{18,5}
+{65,51}
+{31,87,33}
+{17,97,76,81,69}
+{56,71}
+{95,23}
+{33,58,66,47}
+{46,99,69}
+{43,87,40}
+{49,1,26}
+{18,36,89,87,25,100}
+{76,37,19}
+{57,91,9,100,23,59}
+{80,60}
+{55,23,32,49}
+{15,73}
+{87,50}
+{43,62,50,54}
+{65,3,89,49,77}
+\N
+{73,12,25,78}
+{79,89,38,59}
+\N
+{44,62,25}
+{96,13,57}
+{35,14,3}
+{90,71}
+{34,8,59,81,63,90}
+{15,90,89,32,69}
+{90,61,54,10,29}
+{22,3,85,41,66}
+{17,4,99,91,45,57}
+{89,32,43,39,61,9}
+{45,40,6}
+{47,100,75,8,85}
+{88,43,89}
+{45,41}
+{54,48,87,66,100,5}
+{58,65,39}
+{17,82}
+{95,14,31,51}
+{30,3,46}
+{8,66,22,52,51,24}
+{61,62,38}
+{4,50,83,32,76}
+{96,36}
+{87,27}
+{82,100,44}
+{30,91,44}
+{29,48,8,38,43,96}
+{56,65}
+{34,36,99,11}
+{11,1,25,65,12,89}
+{17,100,62,53,24}
+{86,81,63}
+{17,63,30,82,87,91}
+{12,63,76,78,85}
+{52,19}
+{21,91,53,86,49,83}
+{67,65,78}
+{8,77}
+{89,1,56,100,72,96}
+{20,51,41,21,30,20}
+{41,73,37,92,9,5}
+{95,34,21,12}
+{28,14,2,62}
+{14,74,33,32}
+{37,82,67}
+{65,99,56,11,21,83}
+{99,51}
+{56,42}
+{59,30,74,40}
+{18,27,63,44,86}
+{48,25,41}
+{5,26,63,88}
+\N
+{24,66,64,1,26}
+{72,74,11,61,70}
+{28,27,90,30}
+{96,35,21}
+{64,100,75,94,88,3}
+{93,79,42}
+\N
+{37,51,4,41}
+{31,68}
+{93,42}
+{76,96,47}
+{8,6,16,57,51,72}
+{67,72}
+{50,36,40}
+{69,28}
+{17,92,40}
+{72,74}
+{76,87,93,22,95,30}
+{14,88}
+{39,56,74,36,25,87}
+{55,68}
+{32,9}
+{35,2,17,86}
+{92,73,82}
+{40,13,95}
+{15,28,95}
+{65,40}
+{47,56}
+{63,72,78,20,22}
+{71,49,4,80}
+{68,16,50,44,29,38}
+{81,96,23}
+{44,73}
+{4,68}
+{30,54,41,66,89}
+{92,33}
+{10,92,49,46,59,42}
+{14,91,18,96,27,37}
+{40,32,12}
+{14,97,15,96,44}
+{75,96,52}
+{50,20,9}
+{39,84,83}
+\N
+{14,48,3}
+{47,85,76,27}
+{5,3,25}
+{55,36,29,76,41,44}
+{34,56}
+{62,29,83,6,58}
+{67,32,85}
+{75,62,4,66,100}
+{47,31,27,43,9,57}
+{92,44,36}
+{31,22}
+{14,88}
+{18,25}
+{82,63}
+{54,67,6,59}
+{90,42,19,91,37,75}
+{70,39,87,52,32}
+{51,20,34}
+{85,62}
+\N
+{95,6,55,93}
+{44,67,15}
+{93,58,20,12}
+{42,6,22,29,36}
+{46,81}
+{57,95,56,52}
+{3,79,69,45,8,74}
+{75,44}
+{4,17,78,96,66,41}
+{27,100}
+{85,76,22,17,45,58}
+{9,12,70,29,96}
+{5,68}
+{54,79,5,19,17,24}
+{99,13,9,52,86}
+{94,6,99,57}
+{71,62}
+{63,50,9}
+{42,42,80}
+{25,96}
+{93,20,10}
+{83,73}
+{14,76,36}
+{57,31,29}
+{17,25,18,18,54,95}
+{34,27,86,37,92,83}
+{57,57,28,32}
+{98,53,60}
+{8,59,41,88,49,46}
+{95,42,30}
+{12,51,98,74,76}
+{6,49,26}
+{21,35,27,32,83,93}
+{16,56,89}
+{85,34,73,74}
+{52,95,22,4,71}
+{96,42,63,88,80,91}
+{78,34,41,99}
+{11,68,27}
+{50,14}
+{78,52,66,15}
+{100,82,1}
+{35,2,93,71,45}
+{4,56,8}
+{83,19,5}
+{82,39,63}
+{50,64,83,87,76}
+{47,59,93,88,22,67}
+{16,6}
+{86,98,88}
+{32,4,52,34,30,71}
+{68,25,97}
+\N
+{19,17,91,84}
+{97,88,89,98,33}
+{37,56,70}
+{27,17}
+{56,58,51}
+{69,80,47,84}
+{89,22,89,88,16,1}
+{95,14}
+{14,95,97}
+{47,15}
+\N
+{19,20,65,74,83,38}
+{57,56}
+{78,67,68,89,1,95}
+{61,84,93}
+{10,56,96,31,56}
+{3,51,90}
+{15,85,42,25,15,41}
+\N
+{50,7,89,89,96}
+{90,10,44}
+{11,43,15,27,30}
+{55,68,48,30,44}
+{38,69,3,95,39,6}
+{57,51,88,94,82,23}
+{69,37,2,67,49}
+{93,94,5,84,39,47}
+{45,47}
+{58,55,79,63,64}
+{63,65,59}
+{42,36,76,75,89,86}
+{41,83,98}
+{13,90,13,46,11,37}
+{76,33,52,65}
+{52,29}
+{20,60,45,23,29}
+{89,6,14,8}
+{91,69,64,72,41}
+{46,91,31,66,83,33}
+{6,58,61,65}
+\N
+\N
+{90,65,16,5}
+{24,46,33,36,47,45}
+{11,62,40,98,21,88}
+{28,95,58,33,27}
+{45,63,99,31,38,90}
+{11,49,41}
+{23,24,82,25,28}
+{42,3,34}
+{52,10,58,88,97,37}
+{20,41,11}
+{86,30}
+{36,92,93,10}
+{5,36,85,50,71}
+{51,75,100,46}
+{55,81,31,45,87,8}
+{83,10,45,81,33}
+{16,94,91,23,76,44}
+{62,73,14,39}
+{16,14,83,100,82,7}
+{25,69,86,12,71}
+{29,86,45}
+{76,62,100,47,57,52}
+{41,21}
+{33,56,58}
+{23,96,44,16,91,86}
+{65,15}
+{3,92,56,4,21}
+{32,39,95}
+{95,87}
+{65,96}
+{16,96,93,100,35,78}
+{64,33,55}
+{96,75,41,40,62}
+{50,50,86,11}
+{93,34,83}
+{19,30,62,67,93,19}
+{53,67}
+{55,46,99}
+{70,32,38,4,84,91}
+{50,36,40}
+{21,93}
+{29,6,10}
+{4,73,45}
+{72,33}
+{36,73,18,55,27,100}
+{65,73,98,90}
+{20,1}
+{59,36,60,87}
+{20,79,63,93,34,31}
+{60,18,92,6}
+{48,34}
+{63,70,78,1,2}
+{15,32}
+{5,15,84,73}
+{32,35,90,11,40,23}
+{91,41,7,52}
+{84,90,88,30}
+{12,10}
+{84,86,36,79}
+{76,45,84,66}
+{41,25,61,96,97}
+{18,100}
+{63,39,17,34,32}
+{22,45,74}
+{83,24,45,48,69,84}
+{43,41,12,44,75,91}
+{69,75,95}
+{100,28,14,66,1,14}
+{94,91,60,36}
+{88,28,54,63}
+{68,78}
+{29,68,6,100}
+{12,84,35,44,59,55}
+{30,59}
+{64,18,40,57}
+{97,97}
+{85,64,73,82,49,88}
+{99,31,24,6,90}
+{23,89,38,20,40,95}
+{84,64}
+{21,3,91,7,7,87}
+{91,74,32,76,43}
+{13,22,96,8,75}
+{59,71}
+\N
+{34,94,45}
+{14,5}
+{95,10,37,74}
+{69,82}
+{6,58,45,49,81}
+{72,72}
+{17,58,10}
+{62,77,9,6,44,62}
+{37,53,49,41}
+{24,11,11}
+{10,57}
+{26,72}
+{18,15,83,60,54,80}
+{88,49,73,92,67}
+{26,88,64,2,59}
+{49,50,3,90,44,49}
+{58,54,43}
+\N
+{86,78,40}
+{42,17,65}
+{1,86,17,6}
+{79,27,37,60,8}
+{46,62,46,22}
+{9,75,17,68,54,35}
+{99,86,64,10,20}
+{3,21,35,6,24,64}
+{25,62,9,50}
+{63,2,79,42,81}
+{44,41,2}
+{99,93,98,78}
+{2,92,9,96}
+{79,82,25,64}
+{47,84,52}
+{97,77}
+\N
+{47,94,38}
+{22,33,76}
+{35,52,11}
+{17,48}
+{1,100,27}
+{87,93,19}
+{72,3,32,78,81}
+{47,28,4,23,79}
+{27,88,7,85}
+{49,40,47}
+\N
+{91,89}
+{80,2}
+{86,78,42,6,81}
+{7,50,25,4,8,22}
+{23,3,64,59,53}
+{1,42,63}
+{95,81,86,31}
+\N
+{81,83,52,47,25,43}
+{17,57,100,49,59,63}
+{44,91,95,72,29,100}
+{80,78,55,41}
+{14,52,20,64,9,87}
+{48,14,82}
+{31,5}
+{64,50,66,38,97}
+{61,2,90,2,64}
+{64,69,26}
+\N
+{64,62,68,89,12}
+{12,10,88,71}
+{41,66}
+\N
+{67,77,25,6}
+{14,75,15,66,19}
+\N
+{88,52}
+{78,56,61}
+{93,88,47,38,52}
+{72,100,54,34,18}
+{77,99,89,53,25}
+{38,51}
+{3,25}
+{83,39,85}
+{60,15,77,59,69}
+{38,64,91,97}
+{65,35,30,8}
+{46,6,48}
+{63,91,29,91,85}
+{43,100,56,60,74,53}
+{95,30}
+{86,63,28,62,37,79}
+{2,48,29}
+{1,44,20,47,56}
+{43,34,86,86,64,14}
+{11,82,99,71,63,41}
+{77,45,74,17,56}
+{18,25}
+{51,82}
+{27,35}
+{1,20,84}
+\N
+{89,37,16,90}
+{58,83,34,88,50,21}
+{61,25,1}
+{41,6}
+{9,100,32,54,38,66}
+{40,53}
+{29,76,16,13,55,31}
+{71,67,54,83,3,82}
+{19,62,18,94,73,38}
+{17,83,8,45,52}
+{80,25,50,59,53}
+{4,2}
+{52,48,6,72}
+{50,32,70}
+{36,97}
+{17,82,36,97,20}
+{22,87}
+{46,29,96,98,14,90}
+{14,92,5}
+{69,9,68}
+{20,86,29,61,54}
+{62,67,87}
+{86,18,31,80,82,45}
+{65,89,67,34,41}
+{44,8,48,38,91}
+{47,32}
+{85,25,56,39}
+{15,54}
+{84,57,44,46}
+{65,61,29,86,77,53}
+\N
+{26,58}
+{76,1,57,93}
+{57,91}
+{13,15,66,11}
+{84,12}
+{43,32}
+{83,24,31}
+{82,9,65,84,27,94}
+{62,93,55,7,39,46}
+{90,100,33,22,61,46}
+{9,51}
+{87,93,82,94}
+{49,45,95,95,66,39}
+{100,56}
+{11,5,78,42,45,37}
+{3,57,80,46,13,34}
+{1,74,53,31,33}
+{11,84,8}
+{27,99,21,31,96,58}
+{99,81,90,17}
+\N
+{66,49,47,55}
+{88,30}
+{76,62,17,88,83}
+{40,7,42,61}
+{17,57,9,64,54,1}
+{9,54,84}
+{50,61}
+{72,15,25,30,6}
+{64,95,69,89,11}
+{64,18,86,25}
+{81,59,70,6,92}
+{78,76}
+{33,40,29}
+{15,63,1,12,14,57}
+{33,81,8,65,26}
+{58,15,56,37,67}
+{2,50,35,92,11,27}
+{17,13}
+{91,100,15,27,39,24}
+{58,48,46}
+{5,95,28}
+{7,21,99}
+{5,15,6,10}
+{82,99}
+{66,22,86,83,76}
+{99,68,39}
+{43,90,22}
+{31,94}
+{21,64,56,26,95,40}
+{7,81,3,53,83}
+{29,42,90,60}
+{53,49}
+\N
+{26,31,14,73,88,51}
+{69,2,100,9,34,16}
+{78,35,97}
+{68,16}
+{34,45,42,73}
+{7,19,55,70,69,11}
+{11,62,61}
+{32,17,51,33,87,6}
+\N
+{54,97,36,13,45,12}
+{46,2,26}
+{14,6,17}
+{99,20,31,61,6,4}
+{60,72,53,31,34,25}
+{88,46,68,78}
+{56,94,49}
+\N
+{33,65}
+{70,51,84}
+{55,91,27,33}
+{22,19}
+{34,78,11,94,3}
+{16,67,91}
+\N
+\N
+{64,5}
+{76,18,83,5}
+{57,13,30,56}
+{60,92,25,31,43}
+{38,17,54,5,2}
+{56,58,39}
+{42,43,5,69,56,89}
+\N
+{50,23,97,85,70,39}
+{97,56,33,90,64,2}
+{9,54,51,26,24,99}
+{18,7,59}
+{44,5,40,69,18}
+{77,96}
+{44,58,47,17,26,45}
+{90,71}
+{88,32,11,96,17,13}
+{42,3}
+{97,28,56,10}
+{38,36}
+{50,52,47,31}
+{64,5,99,77,83}
+{11,56,1}
+{91,92}
+{7,53,35,52}
+{93,65,47,97,44,82}
+\N
+{64,66}
+\N
+{62,4,57,23,34,91}
+{52,55,75,99,27}
+{29,54,44,87,61,96}
+{21,3,66,35,25,80}
+{96,68}
+{3,41,66,81,78}
+{49,98,79,65}
+{71,38}
+{88,79,70,37,3,82}
+{49,74}
+{19,29}
+{57,68,9,8,99}
+{81,88,14}
+{99,29,24,99}
+{55,96,29,89,49}
+\N
+{56,2,84,79,74}
+{30,52,64,74,62,5}
+{88,32,19,25,9}
+{40,11,49}
+{98,52,27}
+{11,86,29,86,6}
+{91,53,63,53,44,28}
+{88,10,30,48}
+{75,64,75}
+{14,92}
+{98,62,35,67,66,35}
+{40,65,11,80,73}
+{1,1,63}
+{85,32,53}
+{91,27,68,50,66,63}
+{66,54,38}
+\N
+{45,43,14,94}
+{62,84}
+{54,24,83,33,46}
+{93,72,2}
+{43,4,14}
+{18,11,5,99,79,94}
+{26,59,9,2}
+{58,69,70,45,14,54}
+{84,5,42,97}
+{7,82,41}
+{69,53,8,55,20}
+{4,13,6,45,83}
+{41,92,41,98,51,85}
+{72,85,74}
+{19,50,79}
+{79,47,47}
+{25,25}
+{17,56,46,30,73,78}
+\N
+{92,42,83,34,92,29}
+{8,52,76,80,9,55}
+{80,100,2,52,24,4}
+{55,15,92,27,86,50}
+{83,79,41,88,86,53}
+\N
+{44,16,90,54}
+{99,20,64}
+{44,30,26,26}
+{35,35,24,74,72}
+{97,24,94,55}
+{78,42,32,76,100,98}
+{31,86,12,87,72,86}
+{87,35,33,88,33}
+{31,83,23}
+{46,51,5,6,71,31}
+{39,97,91,53,39}
+{19,18,25}
+{16,4}
+{65,77,13}
+{61,30,13,26,75}
+{67,9}
+\N
+{31,3}
+{15,19}
+{97,39,71,30}
+{12,96}
+{36,96,82,62,5,74}
+{81,22,46,11,19}
+{97,55}
+{58,67}
+{10,68,79,74,23}
+{29,71}
+{50,59,8,1}
+{12,51,32,7}
+{62,16}
+{48,82}
+{84,21,24,13}
+{46,86}
+{100,96,32,54,13}
+{72,41,3,67}
+{61,9,7,75}
+{39,44,50,30,38,6}
+{63,63,6}
+{69,35,6}
+\N
+{7,91,82,48,55}
+{57,22,31,57}
+{55,72,91}
+\N
+{76,98,43,71,10}
+{100,34}
+{78,53,14,73,23}
+{42,90,28,44,44}
+{90,34,22,81}
+{60,32,56}
+{98,53,58,58,61}
+{61,70,59,78}
+{2,96,27}
+{83,99,25,47,13}
+{17,54,11,47,70}
+{70,43,11,89}
+{93,70,82}
+{72,57}
+{35,95,49,36,19}
+{82,25,16,49,43,93}
+{2,51,96,48,88}
+{20,81}
+{74,4}
+{66,83}
+{90,75,98}
+{25,87,59,92,55,96}
+\N
+{20,80,92,93}
+{59,63,39,3,7,38}
+{64,10,85,22}
+{63,32,18,38,83}
+{49,38,83,54,1}
+{27,97}
+{18,34,84,58,7,86}
+{93,4,67}
+{43,49,32}
+\N
+{29,14,5,50,30}
+{59,15}
+\N
+{76,31,31,47,17,35}
+{95,41,71,27}
+{47,43}
+{75,80,56,78}
+{56,75,43}
+{99,10,100,76,44,1}
+{5,31,72,3,25}
+{21,90,59}
+{59,45,75,93,78,88}
+{76,55,4}
+{20,87,44,94,56,78}
+{38,87,71,13,23}
+{33,6,79,91,92,27}
+{13,15,31,15,11}
+{57,18,57,71,11}
+{67,60,64}
+{66,15}
+{57,45,74}
+{93,91,97,30,12,94}
+{37,83,62,18,28}
+{94,88}
+{12,11,85,10}
+{42,96,89}
+{15,65,5,65}
+{52,58,36,27,10}
+{72,88,76,50,96}
+{40,70,55,93}
+{80,33,24}
+{53,35,50}
+{11,37,55}
+{25,80,32,91,68}
+{11,2,52,39,37}
+{17,51,45,44,85,84}
+{81,21,77,15}
+{67,93,27,70,72,94}
+{86,99,95,98,83,28}
+{9,65}
+{1,26,5,23,5,17}
+{57,82,42,60}
+{46,67,65,98,69,79}
+{41,50,94}
+{77,81}
+{87,82,18,57}
+{88,27}
+\N
+{32,58,81,88,94,90}
+{23,37,65,38,29}
+{61,11,65,77,25}
+{50,53}
+{38,2,11,9,27,94}
+{64,9}
+{1,45,97}
+{61,41,67,46}
+{13,41,90,15,80,82}
+{83,6,9,22,25,37}
+{95,74,22,64}
+{16,17,4,80,66,33}
+{25,42,43,84,96,85}
+{25,93,50,87,6}
+{35,67,90}
+{82,37,59}
+{4,44,83,2,81}
+{78,46}
+{64,79}
+{18,41,3}
+{56,20,51,83}
+{26,77,52,70,93,13}
+{54,53,12,47,57,63}
+{94,48}
+{39,12,41,5,3}
+{28,33,93}
+{20,29,9}
+{75,38,10}
+{96,54,96}
+{47,87}
+{19,35,11,3,80,72}
+{75,56,84,24,55,48}
+{58,5,13,6}
+{10,53,32,6}
+{23,8,59}
+{71,2,35}
+{41,16,99}
+{77,6,16}
+{30,27,56,85,11}
+{47,21,93,82}
+{50,68,85,34,19,57}
+{14,76,58}
+{78,81}
+{68,99}
+{19,79,67}
+{91,73,82,88,44,36}
+{49,18,75,32}
+{54,18,99,74,9}
+{51,58,60,30}
+{99,86,83,22,88}
+{24,42,76,30}
+{86,16,54,69}
+{37,39,72,45}
+{92,62,3,36}
+{31,80}
+{43,22,11,15}
+{38,88,95,25,49}
+{92,21,10,28,47,55}
+{99,18}
+{26,64,72}
+{29,12,17}
+{54,69,49,84}
+{57,42,4,61,10}
+{60,85,74}
+{24,29}
+{91,71}
+{96,49}
+{47,51}
+{88,67,59,18,86}
+{32,18,64,54,41,27}
+{78,100}
+{77,30,85,93,2,20}
+{80,90,68}
+{49,37,5,42}
+{88,12,94,51}
+{85,65,2,41}
+{60,38}
+{87,37,20}
+{27,81,94,37,54,84}
+\N
+\N
+{38,74,78,78,89}
+{3,100}
+{42,80,68}
+{34,17,96,91}
+{7,29,83,71,87,26}
+{28,81,76,8,43,48}
+{74,11}
+{28,85,84,78,59,69}
+{30,22}
+{3,83,75,60,78,11}
+{20,62,18}
+{74,69}
+{91,44,50,62}
+{57,18,9}
+{14,48,21,33}
+{91,1,53,58,92,51}
+{64,41,90,52}
+{81,95,38,78,7,44}
+{65,25,15,90,40,51}
+{66,41,31}
+{5,92}
+{17,98,7,57}
+{97,36,99,77,50,88}
+{96,56}
+{40,62,88,8,53,62}
+{18,91,63,93,94}
+{88,79,43}
+{31,87,98,85}
+{12,88,58,53,77,38}
+{83,10,37,69,1,7}
+{13,47,66}
+{85,33,39,48,6,39}
+{74,87}
+\N
+{26,50,26}
+{48,78,10,39,17}
+{27,43}
+{58,17,18,80}
+{86,43,58,77,67}
+{53,12}
+{9,79,9}
+{85,79,89,88}
+{35,77,22,52}
+{93,64}
+{47,52,90,17}
+{75,15,25,68,28}
+{35,6,68,37,18,53}
+{80,14,2,89,4}
+{52,49,5,66,59,44}
+{5,26,96,1,84}
+{71,8,61,19,72}
+{17,94,84,72,55,83}
+{72,10,16,40,17,75}
+{6,70,15}
+{22,99,7,19}
+{55,19,4}
+{6,47,69,42}
+{17,9,63,44,15}
+{23,20,72}
+{10,80,20,87}
+{99,3,23}
+{11,76,8,77,58,38}
+{45,14}
+{22,89,73,63,54,9}
+{16,19}
+{1,26,29}
+{92,20,65,33,16,40}
+{27,64}
+{22,19,95}
+{36,16,9,30,31,14}
+{40,50,68,52,77,58}
+{35,15,11}
+{67,2}
+\N
+{63,48,76,25}
+{14,65,42,60}
+{61,58,31,51,70,4}
+{35,41,72,29,46,62}
+{98,48}
+{90,23}
+{1,79,80}
+{10,5,54,59,16}
+{15,1,9,75}
+{34,100,90}
+{73,76,25,77}
+{98,82,77,67}
+{79,5,20}
+{9,69,9,52,2}
+{23,22,77,80,79}
+{32,51}
+{23,52,5,33}
+{95,20,96,78,48}
+{100,37,6,15}
+{98,1,53,20,97}
+{5,28,26,78,33}
+{19,75}
+{49,42,30,72}
+{50,98,56,26,87}
+{76,59}
+{51,16,18,48,46,97}
+{80,60,51,43,58,28}
+{23,12,70}
+{40,16,14,18,46,21}
+{72,79,47,57,23}
+{7,17}
+{49,95,6}
+{14,24,29,13,90}
+{82,28,34,55,15,87}
+{31,24,3,50,45}
+{86,95}
+{97,22,17}
+{27,14,27}
+{61,63,31,74}
+{55,81,87,67,90}
+{81,9,79}
+{100,29,43}
+{41,88,37,29}
+{62,57,16,91,60,65}
+{94,90,34,94,27,48}
+{15,36,80,30,23,90}
+{47,91,6,42,93}
+{53,74,5}
+{84,14,56}
+{30,56}
+{10,12,92}
+{33,7,75}
+{96,39,50,77}
+{89,85}
+{20,39,63,22,44,18}
+\N
+{90,23,79,91,85,8}
+\N
+{73,70,52}
+{75,100}
+{27,4,29,96,25}
+{56,31,80,59}
+{1,91}
+{16,67}
+\N
+{17,88,59,41}
+{13,49,29,76,71,9}
+{41,38,16,29,66,40}
+{68,67}
+{39,74,47,71,63,80}
+{4,74,33,92}
+{17,60,82,7,52}
+{62,88,39,19,22}
+{77,21,1,95,42,2}
+{98,62}
+{55,17,81,31,11,88}
+{73,52,18,94}
+{16,64,90,33}
+{87,41,81,95,85}
+{20,55,96,75}
+{71,72,11,11,83}
+{75,94,89,47,41,7}
+{56,48}
+{76,29,74,31,67}
+{47,70,68,36,70}
+{5,69,10,94,54,32}
+{29,96,71}
+{64,28,86,58}
+{82,57}
+{42,2}
+{64,48,59,8,45}
+{61,69,43,40,1}
+{69,84}
+{68,51}
+{32,20}
+{21,7,5,60,35}
+{100,40,18,98,37}
+{50,96}
+{87,10,12,27}
+{47,3,46,43}
+{60,87,10,31}
+{92,87,50,37,72,73}
+{99,61,77,87,29}
+{23,95,31}
+{96,100,43}
+{17,64,84}
+{13,19,57}
+{65,86,4,75,46,69}
+{49,60,99,37,50,11}
+{77,82,88,12}
+{12,95,66,98,63}
+{83,78,68}
+{76,14,87,25,29,14}
+{20,9,99,73,67}
+{42,51}
+{36,22,33,6,63}
+{53,46,22}
+{40,89}
+{37,7,89,17}
+{32,89,16}
+{65,87,4}
+{16,16,57,35}
+{34,90}
+{80,54,1}
+{11,93,34}
+{5,19,31,50,99,33}
+{98,1,33,54,7}
+{45,39,23,78}
+{37,47,98,83,10,5}
+{55,88}
+{42,76,18,99}
+{86,31,25,5,45}
+{67,87,47,1}
+{23,15}
+{78,88,66,96}
+{58,55,41,67,86,41}
+{21,53}
+{90,14,28,38,95,71}
+{20,5,13,52,1,88}
+{29,98,50,75}
+{91,3,24,75,82}
+{62,33}
+{56,69,31,95,66}
+{46,85,40}
+{17,22,67,57,39,16}
+{58,25,92}
+{31,53,82,64,69,40}
+{40,12,30,1,39}
+{78,10,42,40,25}
+{58,27,1,12}
+{28,11,80}
+{36,89,69}
+{50,95}
+{61,63,59,62}
+{51,77}
+{90,24,88,84}
+{61,27,57}
+{51,81,33,75,48}
+{47,30,33,23,44}
+\N
+{79,51}
+{62,44,5}
+{98,83,80}
+{31,33,89,69,19,40}
+{22,38,61}
+\N
+{90,70,10}
+{37,90,49,65,95,52}
+{95,42,4,47}
+{92,100,43,31,27,1}
+{39,17,88,20,2,80}
+{82,64,36,84}
+{31,18,21,18,52,34}
+{3,35,36,33}
+{26,39,69}
+{67,63,66}
+{54,85}
+{65,71}
+{26,14,84}
+{63,82,73,30}
+{66,79,21}
+{71,13}
+{57,25,40,14,22}
+{63,9,91,31}
+{70,63,36,32,93}
+\N
+{11,85,47,31,54}
+{34,47}
+{42,78,92,85}
+{75,64,12,83}
+{33,98,52,91}
+{22,25,91,79,33}
+{33,51,20,77,23,65}
+{83,66,46,24}
+{54,65,31}
+{43,41}
+{52,47,66}
+\N
+{59,85,85,63,83,53}
+{16,76}
+{44,97,48,52}
+{26,36,72}
+{26,55,98,7}
+{70,88,7,87,62,37}
+{11,42}
+{98,38,36,72}
+{51,90,82,33,92}
+{59,80,79}
+{76,77,18,71}
+{34,56,62}
+{85,12,37,66}
+{34,64,74}
+{77,63,28,76,11}
+{2,63,87,50}
+{60,98,60,19,15,57}
+{93,66,33,71,36,3}
+{41,94}
+{62,72,87,19}
+{57,83,36}
+{63,64,21,13,70,32}
+{71,36,9,55,34}
+{92,52,90,45,88}
+{59,54}
+{4,51}
+{55,25,35,90,93,2}
+\N
+{75,15}
+{25,86,43,18,77}
+\N
+{31,40}
+{55,49}
+{67,1,84,20,9}
+{15,1,48,18,100}
+{62,46}
+{4,39,86,55}
+{49,17}
+{65,20,71,49,55,49}
+{40,57,63,14,3}
+{48,68}
+{67,97,58,55,5,34}
+{3,73}
+{79,97}
+{82,63,87,66,32}
+{19,49,96,50,55}
+{32,19,41}
+{17,53}
+{64,81,70}
+{66,75,18,92,54,93}
+{7,94,38,86}
+{16,62,45,19,10,11}
+{18,47}
+{58,96,69}
+{65,25,58,98}
+{29,51,37,40,44}
+{91,78}
+{37,84,85,65}
+{70,61,31,22,32,22}
+{67,12,99,39,78}
+{41,79,46,54,84,22}
+{38,26,43,4,45,75}
+{29,68,35}
+{69,59,69,33}
+{4,46,52,49}
+{1,25,44,12,71,29}
+{38,75,99}
+{83,58,86,6}
+{93,35,35,34}
+{85,26}
+{15,46,95,60}
+{62,63,65,49,10}
+{44,67,19,80,83}
+{63,41,30,43,85}
+{13,46}
+\N
+{13,95,1,34,72,37}
+{4,32,22,47,6}
+{67,65,77,3}
+{40,70,22,44}
+{74,9}
+{44,28,5,32,67,51}
+{55,14}
+{41,3,72,68}
+{64,82,72}
+\N
+{11,88}
+{91,90,92}
+{68,66,95,80,58,54}
+{30,49,11}
+{54,86,59,69,67}
+{56,83,36}
+{15,67,9,47}
+{92,30,78,2,87}
+{12,54,2,1,59,36}
+{84,25,67,38,19,53}
+{28,45}
+{54,84,9,75,59,26}
+{47,35,54,93}
+{36,96,59,75}
+{78,78,52,93}
+{87,96,67}
+{5,61,15,13,27}
+{53,58,6,78,86}
+{43,70}
+{72,38,15,61,58}
+{75,27,30,12,35,71}
+{18,72,35,62,81}
+{45,10}
+{36,91,73,25}
+{81,85,22,34,29}
+\N
+{15,97,82,44,19,83}
+{51,23,18,6,74}
+{53,75}
+{62,9,73,95,37}
+{58,42,33,41,71}
+{5,97}
+{30,2,89,81,93,61}
+{32,3,18,84,24}
+{6,97,20,89,23}
+{27,74}
+{22,86,81}
+{77,19,42}
+{92,9}
+{58,90,59,91,30,54}
+{29,51,92,34}
+{85,68,59}
+{36,83,75}
+{37,50,86,9}
+{79,70}
+{33,46,93}
+{97,17,6,88,10}
+{18,42,88,4}
+{41,95,71,27,95}
+{8,2,81,56}
+{54,94,54,28,70}
+{34,87,20,10,5}
+{36,76,87,5,100}
+{97,91,25,89,89,95}
+{76,26,73}
+{82,23,7,42,58,72}
+{53,16,99}
+{10,34,57,47,2,96}
+{81,93,26,19}
+{8,1}
+{79,55,37,61,62,3}
+{34,16,69,58}
+\N
+{41,7,99,87}
+{70,21,86}
+{59,2,49,45,91,97}
+{37,2,74,2,61,68}
+{97,39,15,4,13,1}
+{67,71,8}
+{51,2,84,38}
+{55,8}
+\N
+{75,27}
+{37,36,49,70,82,41}
+{70,20,85,89,99,90}
+{69,61,100,49,75,35}
+{11,4,67,4,91,17}
+{77,56,65,78,25,8}
+{16,58,6}
+\N
+{88,38,19,88,27,27}
+{12,46}
+{36,67}
+{62,33,96,94,80,96}
+{56,94,12,1,65,54}
+{58,73}
+{19,80,27,72}
+{47,55}
+{14,91}
+{94,75,92,32,19}
+{99,12,91,4,85}
+{56,55}
+{86,83,77,66,66,87}
+{46,68,13,45}
+{49,75,62,35,39}
+{20,25,33}
+\N
+{91,47,56,68,14}
+{88,43,24,42,4}
+{50,24,94,18}
+\N
+{71,54,91,66,97,22}
+{81,16,19,67,6}
+{78,46,81}
+{63,93,71,75,87}
+{90,38,10,85,12}
+{11,24,93,42,25,77}
+{30,14,32,67,70}
+\N
+{86,91,77}
+{73,74,64,66}
+\N
+{7,18}
+{85,94}
+{37,15,55,100,59}
+{55,18,44,79,57}
+\N
+{52,40,97,75}
+{60,53}
+{38,9}
+{27,67,77}
+\N
+{43,83,82,24,35,64}
+{22,75,29}
+{9,19}
+{67,1}
+{15,35,11}
+{65,45,95}
+{65,9}
+{63,84,99,89,6,77}
+{20,44,31}
+{82,50,88}
+{29,12,46,21,98,7}
+{98,71,3,73,6,86}
+{61,44,74,2,45,33}
+{16,56}
+{31,87}
+{72,30,37,94}
+{65,30,82,17,12}
+{86,19}
+{55,76,96,61}
+\N
+{44,92,83}
+{41,22,79,95,20}
+{36,33,86,9,61}
+{22,88,8,57,73,30}
+{63,97}
+{36,53}
+{56,52,48}
+\N
+{35,8,3,93}
+\N
+{53,52}
+{7,48,78,46,70,14}
+{33,92,55,17}
+{39,57}
+{71,43,72,7}
+{92,85,55,38,35}
+{68,30,67,8,18,92}
+{9,85,82,24}
+{46,46,19,14}
+{96,97,31,59}
+{35,99}
+{54,7,20,28,29}
+{20,21,56,82,19,40}
+{2,39}
+{33,49,63,49,93}
+{35,40,26}
+{30,35}
+{94,70,2,23,91,74}
+{34,37,72,19,15}
+{92,21}
+{72,63,64,35,40}
+{59,11,9}
+{24,3}
+{93,75}
+{22,14}
+{63,99}
+{39,47,10,14,3,45}
+{51,74,5,85,70}
+{6,33,15,4,89,20}
+{97,82,29,15,66}
+{47,47}
+{88,79,57,10,68}
+{18,22,13,100,100,67}
+{75,50,9}
+{3,12,34}
+{39,51,20}
+{56,5,63,18}
+{83,44,86,46,37}
+\N
+\N
+{60,16,54,75,62}
+{91,95}
+{39,55,11}
+{37,7}
+{29,49}
+{38,4,52,85,67,38}
+{36,56,2}
+{52,14,92,39,77,16}
+{42,25,49,55}
+{70,10,33}
+{53,46}
+{83,15,28,59}
+{35,69,82,4,58,46}
+{73,55,64,9}
+\N
+\N
+{60,25,8,8,39}
+{50,71,61,64,64}
+\N
+{65,67,67,34}
+{77,59,18,64,16}
+{43,72,32,44,59}
+{55,57}
+{12,47}
+{30,75,89,81}
+{23,92,16,31}
+{64,45,21,74,19}
+{4,47,49,47,96}
+{37,14,20,18,87}
+{61,45,38,39,1,87}
+{4,98,99,52,27}
+\N
+{23,6,50}
+{22,61,46,79}
+{90,54,60,9,49,42}
+{73,27,51,72}
+{73,11,23,60}
+{7,31,52,34}
+{27,68,39}
+{39,8,21,48,64}
+{86,64,92,60}
+{55,36,40,46,23,46}
+{32,79,86,44}
+{72,29}
+{33,87,57}
+{57,87,61,22}
+{67,84}
+{32,99,26,92}
+{22,27,34,82,8}
+{99,25,99}
+\N
+{29,75}
+{39,63,25,45,7}
+{39,67,18,13,18}
+{23,83}
+{77,69,22}
+{60,13,46}
+{2,10,42}
+{37,20,27}
+{30,21}
+{85,15,52}
+{6,89,38}
+{68,22,26,37,96}
+{6,85}
+{93,51,63,46,26,64}
+{79,77,15,26}
+{90,6,39}
+\N
+{50,58,85,27}
+{69,8,72,47}
+{7,59}
+{55,16,54,95}
+{96,5,50}
+\N
+{77,92,13}
+{46,30}
+{43,65}
+{17,65,32}
+{10,6,46,1,47,75}
+{48,82,71}
+{63,12}
+{68,14,10,97,34}
+{15,45,58,100,7,74}
+{9,23,88,1,95}
+{61,60,15,12,58}
+{84,51,46,41,71,26}
+{58,62,39}
+{86,67,31}
+{32,31,89,2,30}
+\N
+{90,74}
+{65,79,76}
+{22,30,77,47,40,23}
+{67,99,56,73}
+{11,24,30,93,89}
+{70,17,65,78}
+{100,6,67,29}
+{39,4,22,59}
+{84,29,70,9}
+{74,43,72,27,55,27}
+{12,39}
+{1,83,100}
+{48,23,9}
+{21,88,21,35,16}
+{92,34,44}
+{91,96,13}
+{93,57,40,79,81}
+{86,3,94,82,43}
+{78,70,19,97,49}
+{47,22,98,36}
+{20,59,65,54,81,27}
+{58,13,73,19,54,96}
+{26,20}
+{70,75,14,70,82}
+{77,67,53,33,83}
+{2,43,36}
+{84,17,28}
+{68,25,95,62,92}
+{47,90,15,69,85,23}
+{92,92,24,37}
+{96,14,14,38,38}
+{80,4}
+{66,86,28,15}
+{18,90,74}
+{93,76}
+{64,96,14}
+{76,41,86,67,64}
+{58,95,2,86}
+{12,60,96,70}
+{22,37,58}
+{1,67}
+{75,23,24,7}
+{3,57,66}
+{57,30,68,100}
+{68,57,33}
+{26,32,65,51,75}
+{40,14,60,97,83}
+{88,96,42}
+{66,21,21,78,34}
+{15,56}
+{86,60,66,66,16}
+{94,6,58}
+{99,63,70,57,10}
+{82,59,62,38,82,51}
+{48,61,9,46,28,57}
+{29,23,61}
+{12,30,42,20}
+{99,65,24,7,97}
+{20,5}
+{6,49,85,56,97,4}
+{62,93,88,86,75,29}
+{46,2,94}
+{57,71,45}
+{38,60,21,78}
+{95,53,92}
+{61,1,88}
+{67,80,49}
+{59,82,1,48}
+{19,94}
+{25,64,16}
+{96,73,50,85}
+{28,17,46}
+{81,51,50,18}
+{57,99,66,93}
+\N
+{23,62,57,94,40}
+{21,6,83}
+{4,11}
+{83,16,50}
+{46,41,23,1}
+{4,15,8}
+{86,51,29,80}
+{48,34,55,81,89}
+{5,2,43,67,66}
+{42,59,37,91,1}
+{14,98,27,80,33}
+{18,58}
+{49,93,60,91,94,88}
+{32,62,64,63,48}
+{51,1,90}
+{56,8,68,49}
+{16,34,79,18,76}
+{66,88,41}
+{31,66,93,44,96,40}
+{100,99,30}
+{37,49,95,91,18,43}
+{95,2,94}
+{84,15,70,31,30,84}
+{31,41,45}
+{9,73,2,7,34}
+{17,35,43,1,25,72}
+{8,70,8}
+{1,93,32,16,71,61}
+{98,51,27,56,46,65}
+{1,11,57,72,33,7}
+{48,96,64,55,75}
+{83,82}
+{7,74,70,29,59,60}
+{29,44,5,77,52}
+{84,58}
+{87,63,62,52,69}
+{29,58,32,11,13,17}
+{35,99,67,67,93}
+{54,31}
+{53,24}
+{58,59,32,22}
+{8,76,23,63,94,54}
+{3,88,75,17,64,91}
+{29,30}
+{3,81,39,9,77,82}
+{77,85,59,56,8}
+{47,12,63,13,40}
+{66,81}
+{67,33}
+{39,46,28,79,95,67}
+{49,13,98,63,10,58}
+{14,42}
+{80,70,60,92}
+{63,54}
+{30,70}
+{60,89,14,62}
+{56,40,94,55}
+{70,31,46,20,95}
+{18,65,89,7,75}
+{60,33,80,43,37,4}
+{85,19,98,79,36,84}
+{69,1,48}
+\N
+{30,87,9,22,99,60}
+\N
+{23,96,9,85}
+{22,94,39,58}
+{30,38,4,97}
+{16,70,62,5}
+{35,52}
+{32,10,72}
+{35,34,40,31,66,80}
+{7,77,14,48,97}
+{67,64,37,22,69}
+{51,53}
+{67,71,90}
+{87,71,45}
+{44,84}
+{19,58,11,34,45,85}
+{68,19,55}
+{27,16}
+{7,14,92,22,33,46}
+{47,2,49,53,63,32}
+{15,39}
+{13,47,84}
+{29,74,97}
+{51,74}
+{70,26,46,33,51}
+{31,86,14,23,61}
+{20,85}
+{21,10,57}
+{90,94,59,72,97}
+{97,30,74,84}
+{15,89,69}
+{11,40,2}
+{68,19,47,28}
+{47,65}
+{2,7,52,53,44}
+{40,74,34,36,78,71}
+{22,60}
+\N
+{37,75,47}
+{53,78,2}
+{4,32,42}
+{35,76,69,88}
+{95,13,3,38,3}
+{74,74,62,90}
+{8,72,42,2}
+{11,43,5,43,70,16}
+{69,19}
+{61,37,26,49}
+{16,100,69,32,35}
+{58,77,26,76}
+{74,87,37,47,84}
+{8,82,29,93,15}
+{74,88,93,85,97,95}
+\N
+{29,23,99,98,36,93}
+{8,36,87,64}
+{71,90,43}
+{7,28,78,46,52}
+{62,25}
+{33,90,7}
+{60,72,39,18,86}
+{98,59,73,24}
+{17,69,2}
+{49,16,63,56}
+{13,37,62,1,95}
+{98,89,69,92}
+{50,26,34}
+{90,16}
+\N
+{40,54,3,79,51,19}
+{29,24}
+{6,12,82,24}
+{92,52}
+{89,2}
+{64,25,68,55,81,2}
+{64,77}
+{71,46,58,50,56,34}
+{94,17,35,30,60,33}
+{37,30,2,40}
+{98,15,16,92,2,50}
+{44,19,82,57}
+{37,34,6}
+{59,43,1,53,79}
+{7,37,14,14,92}
+{80,78,49,81,23,17}
+\N
+{91,51,12,35,79}
+{9,14,2,84}
+{62,3,77}
+{25,5,40,12,40,79}
+{65,88,82,94,89,90}
+{20,35}
+{80,71,83}
+{6,9,83}
+{94,58}
+{2,76,55,61,42,53}
+{60,53,45,82,3}
+{1,37,75,96}
+{82,61,81,10}
+{36,46,1,31,90,45}
+{22,55,11,25,21}
+{69,13,29,20}
+{95,54}
+{16,79,82,67}
+{4,58,84,84}
+{52,7}
+{25,14,94}
+{69,8,67,54}
+{30,71,36}
+{81,78,23,38,76,58}
+{86,59,61}
+{11,42,63,74,99}
+{66,4,55,34,16}
+{39,57}
+{10,81,9,8,21,10}
+{75,55,64,97,7,45}
+{8,46,86}
+{39,100,52}
+{30,51,7,13,54}
+{72,85}
+{10,52}
+\N
+{61,7}
+{93,1}
+\N
+{74,31,3}
+{90,96,26,84}
+{88,58,74}
+{28,45,74,24,74}
+{95,88}
+{42,70,43,64,22}
+{46,83,48,36}
+{81,99,100,43,11}
+{47,24}
+{46,67,63}
+{26,15,36,89}
+{90,11,78,70,81,87}
+{65,90}
+{89,99,21,81,47,38}
+{37,42}
+\N
+{94,51}
+{12,57,95,63,29}
+\N
+{68,99}
+{27,8}
+{16,52,11}
+{72,5,85,44,57,51}
+{11,6,91,7}
+{87,80}
+{94,61,1,38,77,89}
+{93,60,6,98,46}
+{52,47,44}
+{93,66,61,22}
+{7,61}
+{15,83,93,91,12,40}
+{66,3,5,72,72,36}
+{67,72,68}
+{42,42}
+{38,17}
+{75,60,47,39}
+{58,28,51}
+{61,8,61,81,65}
+{46,52,97,84,27,47}
+{97,53,47}
+{64,93,83,72,27}
+{34,79,34,36}
+{25,5,92,37}
+{12,20,55,94}
+{17,43}
+{39,37,16,70}
+{79,62,15,16,64,28}
+{80,87,96,41}
+{51,55,1,94,72}
+{75,22,56}
+{2,55,7,20,39}
+{8,91}
+{73,8,42,73,31}
+{90,90,23}
+{82,68}
+{63,64,68,12,59,19}
+{100,80,23,24,17}
+{23,46}
+{25,13,31}
+{43,95,54,85}
+{40,62,21,21,82}
+{70,20,16}
+{90,11,23,18}
+{16,9}
+{51,57,30,27,21}
+{50,55,75,77,53,33}
+{84,92}
+{14,66,32}
+{44,100,16,30,82}
+{41,48,58,60,7,44}
+{81,76,13}
+{18,26,82}
+{84,35,15,98}
+{52,84}
+{13,80,36,35,28}
+{91,16,71,55}
+{87,89,6,20,28}
+{12,75,92}
+{48,41,55}
+{59,75,26}
+{48,19,48,72}
+{91,4,100,25,17}
+{46,52,97,78,94}
+{7,81,76}
+{54,54,49}
+{89,37}
+{78,22,57}
+{75,25,83}
+{25,89,10,38,96}
+{52,12,1,74,35}
+{13,48,88,7}
+{6,97,20,19,91}
+{53,2,99,76}
+{4,58,46}
+{30,30,89}
+{97,2,87,47,55}
+{14,11,72,83,97,74}
+{44,69,11,51}
+{47,17,86,27}
+{15,19,56,96,24,94}
+{81,67}
+{11,11}
+{20,94,49,36,39}
+{39,78,40,46}
+{33,87}
+{76,89,58}
+{94,74,25}
+{33,77,5,47,55}
+{28,67,99,81,93,83}
+{31,10,19,65,60}
+{53,25,74,24,48}
+{73,69,23,45,88}
+{70,56,41}
+{21,73,72,28,99,5}
+{75,69}
+{78,99}
+{66,49,89,86,2}
+{30,53,18,21}
+{67,69}
+{1,98,38}
+{91,25,16,39}
+\N
+{75,54,93,39,18}
+{96,84}
+\N
+{64,71}
+{6,15,78,50}
+{8,45,26,15,25}
+{8,90,94}
+{52,66,13,98,86,69}
+{3,25,28,56,88}
+{84,72,89}
+{10,33,46,6,57,100}
+{13,91,99,2,49}
+{83,59}
+{88,64,42,50,77,16}
+{81,12,27,45}
+{12,17,31,93,22,53}
+\N
+{28,84,85,35,3}
+\N
+{42,12,86,76,37,63}
+{46,23,18}
+{45,80,76}
+{94,18,100}
+{17,80,84,80}
+{84,88,29,16,10}
+{7,42,90,51,33,40}
+{79,51,22,2}
+{31,30,72,24,23,84}
+\N
+{55,50}
+{69,47,82,29,83}
+{94,56,69,18}
+{7,81,71}
+{95,13,32}
+{66,59,68,62}
+{52,19,62,51,80,32}
+{38,18}
+{73,24,81,58,22}
+{11,59,41,19,96}
+{61,11,56,89,89}
+{61,72,9}
+{63,12,8}
+{76,54,75,84,6,44}
+{74,3,11,62,30,74}
+{46,60,71,55}
+{28,47,52,71,33,33}
+{35,51,37}
+{38,89,40,29,30}
+{18,26,99,89}
+{36,44,8,100,72}
+{1,23,6,5,23}
+\N
+{84,17,16,44,81}
+{29,70,24,85}
+{23,57}
+{20,98,30,23,1,66}
+{82,3}
+{70,7}
+{15,49,58}
+{19,40,70,88,35}
+{45,10}
+{62,89,47,71,55}
+{34,100,88,44,3,91}
+{92,65,16,24,7,9}
+{20,12,61,95,7}
+\N
+{57,49,42,87,88,14}
+{89,99,86,31}
+{32,55,51,78}
+{55,66,78,10,12}
+{37,19}
+{13,5,36,66}
+{89,7,40,45}
+{41,58,41,24,11}
+{98,8,9,27,40}
+{49,83,89}
+{91,36,78,44,100,62}
+{76,78,9,52,57,27}
+{100,59,37}
+{51,1}
+{92,83}
+{45,1,85}
+{8,81,45,94,32}
+{52,26,9,98,7}
+{97,52,4,85,13,11}
+{94,38,58,4,72,91}
+{5,39,26,14,74,51}
+{31,44,37,24,89}
+{8,74}
+{56,93,36,3}
+{23,46,25,90,42}
+{4,98}
+{31,95,27,26,20}
+{3,7,79,9,90}
+{29,22}
+\N
+{35,34}
+{80,28,12,21}
+\N
+\N
+\N
+{36,49,94,83,25,9}
+{6,62,89,93,59}
+{67,75,3,93}
+\N
+{94,62,3}
+{97,36}
+{43,89,26,94}
+{46,56,22}
+{50,15}
+{45,47,39,61}
+{23,32,24,45,43,11}
+{97,66,29,8,52,67}
+{37,1,48}
+{30,84,86,91}
+{4,46,59,35}
+{76,37,41,90}
+{26,28,92,27,88,17}
+{76,37,27,41}
+{74,51,31}
+{16,33}
+{66,85,68}
+{4,81,72,62}
+{65,14}
+\N
+{11,43,28,14,9,43}
+{60,88,95,1}
+{52,92,69,48}
+{37,81,85}
+{57,73,8,79}
+{50,26}
+{52,41,99,6,33}
+{9,34,58,22,9}
+{56,37,19,77,50}
+{93,21,18,90,41,40}
+{28,89,76}
+{4,36}
+{89,54}
+{70,28}
+{66,11,3,47,30,43}
+{69,54,86}
+{45,41,57,34,18}
+{91,46,32,68,42,68}
+{25,87}
+{75,57,12}
+{55,15,68}
+{6,63}
+{22,39,88}
+{77,39,10}
+{39,49,69,61,66,77}
+{78,25,42,73,89}
+{17,47,36,27,79}
+{33,83,44}
+{27,75,12,96,94,87}
+{50,17,95,42,25}
+{67,13,22}
+{59,85,95,2}
+{81,57,83}
+{25,11,72}
+{32,84,97,6,65,52}
+{62,25,24,27,50}
+{80,64,23,74,54,75}
+{97,17,15,100}
+{50,11,41}
+{57,82,40}
+{10,90,41,52,39}
+{4,11,86}
+{79,17,51}
+{48,100,92,77,58}
+{88,67,19}
+{40,96,52,35,16}
+{89,63,32,81,28,63}
+{44,56,66,50,55}
+{28,73,46}
+{32,40}
+{52,65,85}
+\N
+{51,34,18,82,83}
+{49,49,90,71}
+{84,16,74,78,86,10}
+\N
+{73,9,47}
+{51,59,49,90}
+{85,13,78}
+{98,77,18,15,92,85}
+{40,94,66,94}
+{89,51,80,12}
+{23,26,75,17}
+{96,2,51}
+{88,62,90,32}
+{85,19,87,89,30,15}
+{33,38,9,46,19,87}
+{27,45,15}
+{39,79,82,88}
+{31,33}
+{41,64,10,1}
+{35,61,22,76,74}
+{75,11,90,16}
+{71,23,43}
+{35,3,97}
+{88,4,97}
+{100,61,28}
+\N
+{64,74}
+{9,44,81,98,55}
+\N
+\N
+{76,89}
+{18,34,80}
+{77,83,91,50,20,41}
+{65,50,26,65}
+{79,18,90}
+{5,60}
+{42,21}
+{31,70,80}
+{20,98,15,14}
+{58,65,45,6,64}
+\N
+\N
+{88,82,98}
+{75,81,32,34,59}
+{37,14}
+{30,36,55,70,65}
+{84,55,26}
+{56,64,1}
+{31,41,89}
+{46,43,43,90,34,100}
+{78,36,21,14,69}
+{100,10,45}
+{73,69}
+{60,86,5,70,78,99}
+{6,89,92,8}
+{86,68}
+{44,4,71}
+{41,36}
+{95,80,42,94,34}
+{73,29,50,49}
+{61,20,57,17,36}
+{37,58,67}
+{56,83,77,37}
+{98,67,40,10,35,76}
+{54,84,6}
+{7,71}
+{65,74,43,6}
+{62,98,74}
+{81,26,17,22,47}
+{49,32,59,35,11,94}
+{80,50}
+{91,1,50,97}
+{71,35,84}
+{97,4,46,45,8,36}
+\N
+{81,62,76}
+{69,78}
+{89,3,16,64,17,17}
+{78,72,26,88,81}
+{25,34,9}
+{50,27,34}
+\N
+{55,44}
+{61,51,39,53,44,46}
+{23,94,32,92,90}
+{91,47,67}
+{1,13,76,57,63}
+{77,19,73,18,95}
+{100,82,87,6,83,23}
+{69,58,48,97,60,50}
+{4,83,85,6}
+{3,5,91,37,94}
+{91,72,31,32,80}
+{57,23,39,46,50,20}
+{92,28,53}
+{71,27,46}
+\N
+{59,73,29,21,89,30}
+{1,83,96}
+{34,41,65,35}
+{52,89}
+{62,68,80,7}
+{82,82}
+\N
+{11,2,62,46,28,9}
+{9,16}
+\N
+{22,44,73,82,39,86}
+{97,52}
+{46,36,76,56}
+{17,97,26,72}
+{16,78,9,70}
+{65,55,30,91,16}
+{27,45,76}
+{17,5,90}
+{86,52,93,89,42,27}
+{51,70,41,35,1}
+{91,57,66}
+{53,59,62,57,52,56}
+{100,100}
+{32,78,87}
+{61,57,74}
+{86,79}
+{55,94,64}
+{81,20,26,22,23}
+{9,96}
+{86,65,35,19,88}
+{1,37,90,51}
+{79,47}
+{93,93}
+{32,85,69}
+{49,12,6,69}
+{6,44,92,37}
+{28,42,57,28,2,69}
+\N
+{63,90,25}
+{53,28,74,42}
+{83,79,94,37,64,69}
+{93,100,57,84,80}
+{39,93,80}
+{97,92,55}
+{27,6}
+{20,100}
+{19,66,3,66}
+{7,76,15}
+{7,56,92,11}
+{61,76,6,98,52}
+{20,46,51}
+{12,77,45,67}
+{78,79,32,22,21,47}
+{62,35,1}
+{86,66,57,10,47,43}
+{43,24,76,18,87,68}
+{39,52,71,35,87}
+{81,78,8,10}
+{33,70,53,54}
+{25,77,27,68,95}
+{29,53,89,62,51}
+{21,76,33,72,39}
+{13,22}
+{1,1,51,73,20}
+{26,97}
+{64,75,23,94,62,68}
+{25,20,84,57,27}
+{26,7}
+{92,80,17,48,72,73}
+{73,49,88}
+{24,36,70,53}
+{7,79}
+{80,58,33,25,91}
+{19,43,61}
+{54,49,73}
+{51,88,4}
+{9,32,5,83}
+{17,68,90,15,30}
+{98,50,42}
+{29,52}
+{32,41,4}
+{33,97,69,34}
+{94,2,60,5,83}
+{23,86,43,74,35}
+{63,37,38,58,39,14}
+{56,7,82}
+{88,81}
+{50,75}
+{78,49,67,68}
+{10,61,58}
+{84,35,20,30}
+{36,34,48,31,16}
+{35,7,47,22}
+{98,40,56,43}
+{16,4,7,9,44,55}
+{86,90,30,80,47,91}
+{34,91}
+\N
+{12,67,77,23,11}
+{94,8}
+{5,68,31,82}
+{26,65}
+{51,19,86}
+{55,83,39,39,96,51}
+{31,22,70}
+{20,50,15,93}
+{1,55,64}
+{8,2,14,3,40}
+{2,71,25,41,5,5}
+{98,61}
+{21,64}
+{100,76,99,18,78}
+{17,4,69,97,61}
+{52,79,97}
+{52,26}
+\N
+{90,54,2,62,11,51}
+{33,12,34,45,2}
+{91,63,51,42,82}
+{100,79,73,70,54,14}
+{57,94,81,55}
+{13,18,94,17,16,34}
+{58,79}
+{90,64,68,46,95}
+\N
+{37,46}
+{91,94,10,85,100,24}
+{65,86}
+{94,89,7}
+{72,79,77,53,95}
+{65,19,92}
+{41,79,53,8,63}
+{28,60,50,42,9,32}
+\N
+{6,23,97,23,10}
+{12,28,16,39,70,50}
+{26,97,61,48,79,23}
+{38,98,21,34,65,89}
+{29,13,36,19,13,45}
+{72,65,58,81}
+{43,98,84,5}
+{79,41,100}
+{35,30,69,42}
+{59,13}
+{65,90}
+{40,38,21,23}
+{2,19,26,38,66}
+{5,16}
+{84,85,97,84}
+{34,26}
+{87,17,21,32,29,25}
+{75,66,87,90,18}
+{84,32,29,51,71,68}
+{57,25,73,24,53,2}
+{74,16,92}
+{99,60,19}
+{98,14,70,72}
+{24,34}
+{37,34,81,100}
+{67,10,17,60,16,55}
+{39,58,5,23,85,95}
+{75,93,19,31,47}
+{13,27}
+{42,14,32,90}
+{59,79,70}
+{48,96,45,38,58}
+{96,87,84}
+{23,70}
+{25,31,81,36,75,32}
+{64,49}
+{30,18,38}
+{69,27}
+{76,82,43,96,73,17}
+{84,95,97,12,20}
+{57,69,36}
+{60,79,19,67,9,12}
+{32,39,3,21}
+{55,83,51,48}
+\N
+{37,11,98,53,11}
+{2,73,24,18,77,74}
+{69,96,17,49}
+{53,2}
+{1,76,72}
+{35,93}
+{35,36,36,25}
+{59,77,30,13}
+{35,69,36,31}
+\N
+{20,23,51}
+{81,83,57}
+{87,43,40,56,81,64}
+{24,63}
+{29,51,45,93}
+{73,85}
+{59,1}
+\N
+{13,57,14,11,34,91}
+{69,1,4,28,77}
+{63,68,41,53,64,43}
+{11,1,46,40,6,88}
+{51,19,77,10,86,66}
+{74,40}
+{25,54,46,62}
+{94,17,64,15,20,36}
+{100,71}
+{63,66}
+{33,88,5,92}
+{92,86}
+{91,69,75,13,20}
+{57,22,32,33}
+{72,87,44,64,46,6}
+{50,56}
+{36,23,7}
+{74,63,3,6,14,29}
+{91,42,8,11,49}
+{32,64,94,88}
+{91,78,55,27,59}
+{2,20}
+{52,95}
+{57,59,35}
+{51,15,52,24,14,13}
+{64,16,18}
+{50,98,71,10}
+{92,99,92,80,77,73}
+{96,12,70,85,54,73}
+{10,44,30,77}
+{29,47}
+{40,55,62,58,30}
+{59,93,7,21,6,20}
+{58,91}
+{5,70}
+{36,23,58,80}
+{16,93,54}
+{20,8,97}
+{78,32}
+{10,31}
+{24,10}
+{56,14,28,10,45}
+{1,79,53}
+{56,58,86}
+{93,83,17,89,93}
+{12,4,26,45,97,17}
+{42,67,17,13}
+{31,90,59,38,4,20}
+{86,52,67,10}
+\N
+{49,59,10,25}
+{69,88,31,38,7,36}
+{84,21,57}
+\N
+{60,8,19}
+{35,81,66,96}
+{13,95,54,38,31}
+{27,25,34,11,65,64}
+{54,43,20,20,65,95}
+\N
+{19,27,100,69,43}
+{91,8}
+{30,65,98,87,84}
+{83,85,100,16,20,18}
+{80,48,56}
+{61,5,92}
+{14,94,43,91}
+{35,52,60,43}
+{73,25,26,61}
+{66,41,39,16}
+{2,96,90,37,99,92}
+{25,31}
+{72,57,50,82}
+{40,69,5}
+{98,34,66}
+{90,44}
+{34,78,93,15,65,71}
+{98,1,28,36}
+{16,59,79}
+{88,1,14,45}
+{41,91,87,20,72}
+{46,9,81,90,63,32}
+{2,84,29,56}
+{2,57,92,69,63,46}
+{3,32,76,62,36}
+{11,81,3,81,90,16}
+{36,1,42,51}
+{29,86,53,51,85}
+{17,66,16}
+{4,21,25,17,65,92}
+{13,26,33}
+{74,6,46}
+{69,19}
+{47,78,85,46,41}
+{41,62,100,85}
+{22,71,66}
+{28,15,58,84,22,92}
+{68,82,82,85,15,54}
+{34,58,72,35,99}
+{51,100,40,13,61}
+{80,89,94,31,96}
+{48,29,33}
+{32,85,75}
+{76,43,17}
+{79,70,3,64}
+{76,64,85}
+{94,90,3,85}
+{86,21,1,8,54}
+{87,92,30,36,59}
+{20,51,62,17}
+{81,61,86,96,47,67}
+{5,75,97}
+{60,24,79,3}
+{85,49,49,48,61}
+{66,60,58,92,88,90}
+{2,18}
+{42,54}
+{42,83,68}
+{98,76,42,25,90,32}
+{64,36,39,45,34,95}
+{56,43,78,10,63,18}
+{51,40,98}
+{85,11,74,41,14,25}
+{37,12}
+{76,32}
+{6,77,16,86,36,25}
+{23,93,18}
+{75,51,67,29}
+{22,9}
+{18,58,25,88}
+{95,31,12,20,62,54}
+{23,97,89,63,73}
+{77,41,11,27}
+{91,86,97,98}
+{84,6}
+{74,69,55}
+{58,42,92,65,52}
+{77,31}
+{8,91}
+{5,83}
+{64,48}
+{1,37}
+{51,4,49,97,64}
+{29,70,3,62,57,1}
+{91,8,31}
+{86,71}
+\N
+{61,50,8,6,59,76}
+{83,8,54}
+{50,45,66,86,52}
+{75,48,18,88,82}
+{1,52,60,78,45}
+{46,65}
+{53,2,63}
+\N
+{89,97}
+\N
+{75,23}
+{30,58,13,50,2}
+{59,73,52,8,70,39}
+{20,35,77,34,10}
+{55,86,14,74,14}
+{67,46,48}
+{20,9}
+{20,92,62,75,34,98}
+\N
+{72,14,18,46}
+{48,71,92,17,31,13}
+{47,46,42}
+{42,75,14,86}
+{97,55,97,78,72}
+{8,4,96}
+{44,13,13,18,15}
+{16,40,87}
+{87,66,79}
+{14,44}
+{35,79,25,57,99,96}
+{23,66}
+{90,49,24,11,8}
+{50,3,24,55}
+{60,94,68,36}
+{11,20,83}
+{66,100,47,4,56,38}
+{36,34,69}
+{41,57,15,32,84}
+{32,25,100,45,44,44}
+{70,32}
+{15,37,67,63,71,34}
+\N
+{81,62,20,91}
+{32,62,1,68,86,54}
+{20,91,40}
+{79,69,22,98,14}
+{45,42,24,2}
+{30,53,15,62}
+{81,100,42,20,96,42}
+{93,19,7,59,100,49}
+{25,7,18,64}
+{11,27,1}
+{89,67,65}
+{39,97}
+{47,62,30,61,58}
+{4,11,83,18}
+{38,30,95,58,13,81}
+{83,6,33,73,64}
+{89,51,77,45,58,16}
+{13,11,88}
+{96,79,71}
+\N
+{18,66,83,52,84,76}
+{52,17}
+{74,95,16,5,16,51}
+{21,20,16,39,84,71}
+\N
+{75,47,36}
+{65,45,12,5,100}
+{41,74,84,21,73}
+\N
+{8,90,46,39,30}
+{47,84,42,49,17}
+{76,100,35,89,17}
+{61,53,50,31,8}
+{94,53,20,33,15}
+{97,46,62,85,74}
+{8,59,40}
+{95,71,21,41,85,81}
+{55,71,20,74}
+{70,95}
+{61,42}
+{83,74,25,84,18}
+{56,43,46,40}
+{42,78}
+{95,48,98,93,35,98}
+{77,34}
+{4,54,58}
+\N
+{13,54}
+{87,66}
+{12,88,90,95,6,95}
+{65,20,10}
+{62,74,59}
+{49,17,51}
+{14,17,65,3,27,41}
+{43,42,43,46,79}
+{88,75}
+{21,46,84,95,31}
+{17,17,28}
+{32,73,29,11,46,94}
+{3,34,81}
+{80,83,1,92,69,100}
+{9,24,56,17}
+{3,80,57,36,14,94}
+{39,89,54,17,31}
+{70,19,67,21,31,72}
+{82,48,68,52}
+{96,81}
+{92,18,39,50,18}
+{6,54,27,52,28,100}
+{23,40,7,74,93,50}
+{87,51,38,88}
+{98,42,43,30,8,71}
+{33,26}
+{20,21,83,35,99,100}
+{28,77,94,32,1,13}
+{17,15}
+{35,100,9}
+{42,6}
+{16,28,55}
+{7,94,81,60,91}
+{100,63,21,28}
+{65,20,35,16,76}
+{95,3,88,62,1}
+{73,44,46,13,55,69}
+\N
+{60,49,71,77}
+{93,39,75,63,69}
+{97,36}
+\N
+{77,16}
+\N
+{57,30}
+{39,31,56,51}
+{62,78,62,38,54}
+{69,86,99,10,12}
+{11,43}
+{60,70,83}
+{83,82,3,1,60}
+{24,55,61,85}
+{65,72,13,77,79,100}
+\N
+\N
+{28,97,71,78,68,95}
+{34,1,72,79,84}
+{10,49,91,44,27,51}
+{15,48,80,37,69}
+{42,46,32,34,86}
+{80,21,26,50,5,8}
+{61,71,100,78,54,50}
+{36,20,80}
+{67,40,47,68}
+{60,7,36,36,55,2}
+{32,91,13,98,88}
+{15,56,65,23,13}
+{20,66,81}
+{19,36,99,54,86,92}
+{82,28}
+{43,32,91,37,70,68}
+{71,78,82,50}
+{1,31,23,48,10,12}
+{88,96,1,44}
+{27,49,97,29,89,35}
+{63,72,58}
+{79,9,32,64}
+{75,67}
+{46,31,83,54}
+{66,24,6,89}
+{82,10,64}
+\N
+{19,31,52,34,89}
+{16,36,11,12,23}
+{55,50,6,20}
+{81,72}
+{71,74,8,6,31}
+{6,20,96,80}
+{95,85,56,91}
+{36,33,88,12,50}
+{77,44,52,50,50}
+{94,12,7}
+{97,44,40,43,8,21}
+\N
+{61,14,40,75,87}
+{43,21,67,66}
+{46,19,80,12,46,28}
+{56,11,14,59}
+{31,94,50}
+{45,26,61,15}
+{84,45,44,82}
+{9,16,86,54,93,30}
+{50,39,37}
+{35,60,64,55,73,90}
+{61,65,87,20,30}
+{12,59,44}
+{23,8,97}
+{30,59,7}
+{85,32,14,95,38}
+{18,91}
+{10,40,20,8,58}
+{5,58,4,94}
+{100,11,96,70}
+{66,72,7}
+{5,31,89,89,4}
+{81,68,44,37}
+{22,22,76,67,72}
+{22,26,30}
+{73,47,27,18,54,30}
+{44,13,73,95,83}
+{18,93,72}
+{30,22,73,13,16}
+{14,11,66}
+{45,33,59,72,92,81}
+{97,82}
+{30,4}
+{1,9,46,70}
+{47,50,20,71,48,60}
+{26,62,53,70,63,49}
+{39,26}
+{47,94,9}
+{55,3,18,1,75,22}
+{42,87,74,57,60,55}
+{95,46,21,38,27}
+\N
+{13,35,48}
+{24,39,24,67}
+{44,83,49,72}
+{22,8}
+{77,39,87}
+{37,41,44}
+{100,57}
+{48,54,58,79}
+{14,84,40}
+{11,51}
+{23,80}
+{80,82,43,59,2}
+{92,53,56,44,90,66}
+{44,67,78,9}
+{43,91}
+{70,74,100,69}
+{12,5,75}
+{65,51,22,65,56,36}
+{52,54}
+{38,78}
+{30,45,38,99}
+{18,88,88,63,51}
+{61,24,53}
+{72,24,77}
+{61,46}
+{11,83,49,86,27,60}
+{86,60,83,34,33,28}
+{65,15,10,51}
+{98,92}
+{49,49,60,3}
+{58,56,43}
+{19,25,15}
+{24,40,36,49,61}
+{5,62,9}
+{72,8,71}
+{64,85}
+{72,84,67}
+\N
+\N
+{80,87,30,70,21}
+{30,86,95,19,21}
+{17,90,15,89,81}
+{40,51}
+{77,88}
+{14,89,82,62}
+{40,66,93,16,55,45}
+{22,46,31,17,4,71}
+{8,41,88,94,25,61}
+{80,8,23,71,59,53}
+{61,70,23}
+{2,4,79,6,67}
+{27,70,42,68,33}
+{46,27,10}
+{1,93,42,12,8}
+{31,9,19,32,62,15}
+{16,42,81}
+{56,29,12,17,61}
+{52,100,98,42}
+\N
+{29,38}
+{49,40,47,63,22,4}
+{99,70,13}
+{70,28,67,100}
+{37,75,65,63,35}
+{45,67,37,28}
+{42,78,71,39}
+{33,35,76,69}
+{65,84,57,63}
+{17,12,86,23}
+{31,62,79}
+{3,22}
+{85,81,59}
+{38,5,15,100,1,27}
+{36,96,93,46,75}
+{44,61,85,70,71}
+{79,72,86,71,77,9}
+{23,51,47}
+{4,59,48,38,44}
+{93,54,86,98}
+{60,29}
+{49,38}
+{54,84}
+{72,25}
+{51,40,25,27,68}
+{24,17}
+{95,3,82,31,95}
+{56,37,57}
+{15,84,98,16,53}
+{47,36,15}
+{27,36,76}
+{38,82,26}
+{47,70}
+{60,89}
+{59,73,99,7,28,89}
+{87,49,70,76}
+{71,93,76,81,11,46}
+{74,87,92,24,43,22}
+\N
+{26,1,85}
+{18,73,43,94}
+{92,2,73}
+{5,58,85}
+{20,7,39,18,59,90}
+{11,16,19,77,60,56}
+{77,1,95}
+{4,4,11}
+{48,40,56,74,96,29}
+{71,1,62,69}
+\N
+{34,61,26}
+{86,75,13,73,28}
+{17,35}
+{100,29,37,26,47}
+{69,36,52,61}
+\N
+{81,51,54}
+{54,78,46}
+{1,78,96}
+{33,54}
+{72,9,37,30,100}
+{67,10,52}
+{77,19,74}
+{52,27,41,37,98,73}
+{8,74,86}
+{4,40,99,6,59}
+\N
+{98,43}
+{74,91}
+{69,45,73,59,19}
+{87,43,31,85}
+{2,51,54,3}
+{45,73,8,86,4,40}
+{2,51,96}
+{74,5,8,64,1,46}
+{5,64,86,63,12,75}
+{6,62,71,24}
+{56,84,54}
+{61,37,79,63}
+{81,39,78,23,86,74}
+{50,79,34,23}
+{85,36,78,80,19}
+{34,94,1,46}
+{5,23,38,4,78,2}
+{85,100,80,13,73}
+{48,86,9}
+{47,22,65}
+{49,81,18,52,36}
+{84,85}
+{89,15,71,88,44}
+{1,21,81,52,2}
+{53,18,7,53,50,11}
+{91,89}
+\N
+{20,6,20,70,12,32}
+{98,94,70,52,41,35}
+{43,25,2,63}
+{95,86,6,82,2,41}
+{79,24,63}
+{12,96,7,18,48,67}
+{55,35,4,75,28,39}
+{48,46,33,75}
+{10,99,5,5,98,25}
+{43,87,5,53,76,64}
+\N
+{100,13,9,4}
+{4,35,65,56}
+{27,74,88}
+{59,66,10}
+\N
+{59,85,39,48,17,29}
+{59,42,17}
+{27,99,12,21}
+{9,10}
+{15,4,80,25,67,59}
+{12,89,96}
+{50,32,92,49}
+{40,74,10,6,26,43}
+{80,71,29,54}
+{74,82}
+{22,25,27,65,12}
+{84,88,53,43,75}
+{84,16,51,84,46}
+{10,9,44,95}
+{87,19,22,10,44,80}
+{18,20,87,41,86}
+\N
+{9,64,4,33}
+{65,87,23,65,32,92}
+{50,2,23,68}
+{29,8,82,28}
+{54,92,6,2,28,70}
+{23,11,65,78,34}
+{77,85}
+{30,49,59,8,60}
+{77,30,34}
+{55,73}
+{89,68,55,81,8,81}
+{54,28}
+{35,22,67,63,48}
+{43,37,46,56,81}
+{16,78,32,81,77,37}
+{35,80,41,76}
+{4,93}
+{3,32,23}
+{43,18,50}
+{87,5}
+{30,40,91}
+{36,69,17,82,70,57}
+{73,71,47,63,58}
+{24,11,36}
+{2,72,61,76,9}
+{61,97,10,85,92,56}
+{5,44,47}
+{24,57,79}
+{69,39,97,8}
+{78,16}
+{62,52,17,35,28}
+{48,79,66,64,36}
+{14,72,75,30}
+{17,21,41,25}
+{28,100,66,56,15}
+{89,3,32,86,6}
+{67,34,16}
+\N
+{48,27,70,60,1,40}
+{69,34,36,46,95}
+{59,24,84}
+{44,21,90}
+{22,30,5,62,13,58}
+{79,67,44,10,1}
+{67,8}
+{40,48}
+{64,5,65,35}
+{74,45,75,15,31,69}
+{42,3,49,33,52,97}
+{86,59,69,84,53}
+{64,64,41,64,99}
+{47,95,16,78,73,68}
+{54,11,52,90}
+{54,62,79,58,96,59}
+{28,34}
+{52,94,17,42,9}
+{94,22,77,7,56}
+{72,24,47}
+{6,11,3,23}
+{9,6,97,82,40,39}
+{73,47,57,8,7,97}
+{27,26,1,2}
+{64,45,38}
+{71,6,6,83,33}
+{78,28,40}
+{25,8,17,15}
+{24,67,53}
+{72,42}
+{66,25,56,36,32,93}
+{18,11,22}
+{88,9,75,23}
+{20,32,24,44,51,34}
+{76,86,11,7,1,61}
+{11,77,41,55,87,59}
+{62,53,94,46}
+{77,20}
+{74,97,59,78,9}
+{7,94,26,18,77}
+\N
+{49,59}
+{72,22,42,89,14,80}
+{49,14,38,19}
+{43,88,25,58,39,24}
+{21,34,37,65}
+{85,3,46}
+\N
+{11,60,86,65,49,83}
+{51,98,7,28}
+{85,17,34,59,14,86}
+{89,81,48}
+{67,40,11,60,75}
+{13,45,42,22,82,82}
+{98,21,89}
+{30,63}
+{35,45,68}
+{9,29}
+{43,71}
+{82,44,59,72,48}
+{1,48,29,44,14,11}
+{75,33,85}
+{7,32,92}
+{62,14}
+{29,31,1,36,51}
+{92,12,28,20}
+{13,67}
+{88,72,14,22,61,42}
+{15,98,49}
+{65,27,9,76}
+\N
+{15,95,26,12,52,40}
+{17,20,74}
+{57,63,15,22,38}
+{93,71,8}
+{26,84,82}
+{20,52,3,3}
+{72,95}
+{10,9,80}
+{9,9,18,51}
+{74,24,63,63,57,89}
+{64,91,95,18,15}
+{64,37,20,36,74}
+{52,9,53,6}
+{17,31,42}
+{3,73,92,13,62}
+{57,81,58,49}
+{52,56,2,26,18}
+\N
+\N
+{90,90}
+{16,92}
+{66,51,7,19,10}
+{100,81,69,86,95}
+{48,64,81}
+{87,54,73}
+{6,80,100,24,26,8}
+{44,67}
+{27,94,2,25,34}
+{80,25}
+{12,2,77,75,15}
+{63,14,30}
+{85,75,59}
+{72,73,54,44,25,76}
+{95,44,69,91,62}
+{94,73,78,5}
+{28,52}
+{86,31}
+{69,90,95,66}
+{6,10}
+{68,72,112}
+{9,165}
+{91,132,164}
+{57,82,144,167,184}
+{3,6,101,118}
+{111,158}
+{22,29,30,174}
+{41,66}
+{39,76,189}
+{7,20,21,196}
+{52,126,169,171,184}
+{21,77,91,176,196}
+{16,97,121}
+{83,135,137}
+{8,140,160,164,165,195}
+{38,65,185}
+{112,152}
+{111,129,134,148}
+{47,80,114,135,147,165}
+{24,98,119,123}
+{43,48,60,147,154}
+{19,54,138,171,186}
+{156,175}
+{20,51,123,193,193}
+{37,41,136,173,192}
+{14,22,111,125}
+{44,125,160,184}
+{19,75,99,103,107,164}
+{24,113,145}
+{27,157}
+{12,107,133,134}
+{72,94,102,158,194}
+{104,157}
+{122,171}
+{28,47,89,104,112}
+{25,35,82,105,155}
+{106,107,139,181}
+{50,110,132,136}
+{90,110,166}
+{1,1,55,60,85,108}
+{8,22,31,106,172,196}
+{24,69,109,121,154}
+{0,26,44,59,132,175}
+{103,125,172,188,190}
+{11,23,78,109,131}
+{81,146,169,181,196}
+{2,84,113,189}
+{8,46,126,131}
+{13,73,73,125,127}
+{67,117,139,184}
+{29,65,77,120,182}
+{0,87,100,102,135}
+{111,146,156}
+{13,87,123,137,182,197}
+{60,61,164}
+{7,20,186}
+{0,24,53,135,147}
+{94,136}
+{47,168}
+{70,80}
+{43,148}
+{3,81,104,191}
+{104,171,189}
+{9,14,117,160,180}
+{67,158}
+{50,57,66,78,170,197}
+{31,60,73,101,193,197}
+{37,89,92,96,127}
+{29,179}
+{17,47,137,155,157,187}
+{33,77,154}
+{48,63,85,150,184}
+{32,53,61,95,172}
+{20,35,47,171,179,196}
+{2,17,40,169,184}
+{116,127,131,142}
+{16,26,27,87,164,198}
+{58,129}
+{67,98,108,132,157,197}
+{145,157}
+{13,49,56}
+{59,103,180,196}
+{35,65,104,106,120,126}
+{18,96,115,133}
+{27,61}
+{61,194,197}
+{11,27,36,94}
+{15,36,101,128,197}
+{51,62,115,149}
+{83,198}
+{30,120,127,145,184}
+{50,149}
+{13,35,87,117,135,158}
+{57,60,74,113,128,178}
+{11,90,123,163,170}
+{39,121,148,171,198,199}
+{30,77,78,137,140,162}
+{52,69,120,141}
+{9,100,137}
+{56,161}
+{44,57,75,110,154}
+{98,123,155,167}
+{10,60,85,105,164,168}
+{13,92,179,186}
+{13,171,173,176,178}
+{33,53,88,123,144,172}
+{21,57,70,131,151}
+{13,51,63,169,169}
+{36,104,119,166}
+{54,59,84,166,172}
+{7,87,100,102,142,187}
+{2,5,6,43,174}
+{4,26,29,59,77}
+{10,82,98,103,104}
+{104,147}
+{47,55,99}
+{102,154,165}
+{0,96,107,139,157,159}
+{66,167,174}
+{92,97,117}
+{21,75,180,185}
+{54,64,139,180}
+{23,141,189}
+{32,38,147}
+{82,87}
+{6,34,34,161,183}
+{25,64,69,97,122}
+{80,152,170,189}
+{44,78,143,162}
+{52,53,64,69,112,158}
+{77,80,123,150,175}
+{110,121,125,125,128,198}
+{0,8,57,104,127,188}
+{17,46,48,93,129,150}
+{135,193}
+{89,111,135,166,184}
+{132,181}
+{47,54,101,108,125}
+{18,55,103,142}
+{11,125}
+{18,49,58,68,122,153}
+{37,47,137,179,185}
+{57,78,167,187,192}
+{28,32,38,67,77,184}
+{67,83}
+{43,104,191}
+{22,40,118,194}
+{24,53,66,195}
+{27,87,89,101,130,191}
+{71,86,157,167,183}
+{31,87,102}
+{48,53,70,101,149,174}
+{21,33,59,129,195}
+{144,160}
+{4,8,174,194}
+{69,103,127,127,160}
+{6,29,62,77,132}
+{61,69,108,144,174}
+{51,55,109,128,153}
+{10,30}
+{2,5,6,70,146,183}
+{0,1,75,97,166,180}
+{53,78,104}
+{31,45,68,108,161}
+{3,40,78,103,109,130}
+{33,44,159}
+{28,82,93,136,148,157}
+{31,32,76,143,157}
+{2,55,106}
+{21,66,80,129,129,152}
+{1,34,59,128,154,195}
+{10,154,172,177}
+{2,7,31,47,82,125}
+{60,131,149,156}
+{20,141}
+{23,38,43,100}
+{51,70}
+{3,41,164}
+{126,160,165,169}
+{61,71,143}
+{65,70,81,100,146}
+{40,48,57,75,85,85}
+{116,153}
+{31,42,49,103,183}
+{28,44,62,85,133,177}
+{50,68,164,170}
+{4,26,60,87,119,141}
+{5,102,160}
+{20,129,177}
+{98,120,135,157,164,168}
+{66,150}
+{101,101}
+{164,187}
+{43,65,96,166,189}
+{18,36,58,109,118}
+{25,32,135,161,170}
+{55,104,183}
+{69,139,144,181,182}
+{84,131,155}
+{6,18,63,156,159}
+{7,66,67,88}
+{8,46,52,95,178}
+{58,58,83,119,119,163}
+{27,143}
+{78,80,122,149,164,176}
+{6,83,107,183,198}
+{86,199}
+{22,74}
+{28,62,64,114}
+{15,56}
+{41,97,139,152,161,161}
+{48,192}
+{16,62,99,138,155}
+{32,84,145}
+{108,137}
+{93,112,120,155}
+{73,117}
+{20,26,197}
+{4,141}
+{110,132}
+{95,133,142,152,183,193}
+{85,141}
+{53,76,86,131}
+{5,59,73,74,101,130}
+{0,1,64,151,188}
+{15,131,131,174}
+{80,98,106,187}
+{41,102,167,173}
+{9,42,133}
+{103,110,110,134,175,185}
+{168,187}
+{42,47,108,121,165,198}
+{81,171}
+{38,122,123,149}
+{16,79}
+{45,64,131,176,182,197}
+{35,82,87,100,123,196}
+{41,52}
+{33,68}
+{60,140}
+{12,41,152}
+{54,71}
+{88,95,95,146,148,180}
+{47,66,89,121,168,182}
+{15,70,94,122,137,154}
+{42,48,129,162}
+{70,151}
+{11,55,89,118}
+{36,74,121,130,152}
+{46,48,52,120,179}
+{70,81}
+{96,146,183}
+{76,78,108,153}
+{71,168}
+{66,106,108,167}
+{22,44,49,85,87,195}
+{17,52,143,175}
+{86,103}
+{16,46,176}
+{95,111,162,173,198}
+{44,191}
+{7,48,107,115,116}
+{12,120,141,179,184}
+{83,188}
+{83,85,86,139,154}
+{50,74,89,154,179}
+{79,87,120,128,183}
+{13,121}
+{16,52,62,86,168,199}
+{7,16,29,35,157,181}
+{23,48,65,119,180}
+{10,173}
+{7,98,128,143,145,162}
+{23,27,88,91,127}
+{35,53,56,56,118}
+{7,161}
+{0,42,67,174}
+{44,161}
+{75,80,110,170}
+{17,93,117,140,168,196}
+{18,100,150,184}
+{108,132}
+{54,90,97,103,149}
+{9,12,30,43,82,95}
+{131,163}
+{67,99,168}
+{91,150,172}
+{47,164,195}
+{72,90,98}
+{24,78,130,172}
+{1,27,32,64,66,156}
+{7,26,72,88,130,140}
+{56,126,130}
+{1,76,81,122,169,188}
+{60,154}
+{101,103,135,150}
+{22,25,33}
+{99,117}
+{24,95,122,186}
+{48,95,102,108,125,170}
+{13,113,154}
+{155,177}
+{37,73,106}
+{7,64,124,195}
+{101,124,133,157,166,188}
+{27,34,60,100}
+{26,104,163}
+{34,43,108,133,165}
+{64,79,89,122,132}
+{10,96,168}
+{2,22,89,118,122,198}
+{122,192}
+{42,101,104,135,168,181}
+{7,38,63,86,101,152}
+{29,84,89,114,123,184}
+{33,46,59,137,153,175}
+{3,54,66,92}
+{31,34,148,159,185}
+{3,52,97,99}
+{3,26}
+{42,57,62,148,199}
+{15,26,198}
+{14,34,109,111,128,193}
+{107,197}
+{16,107}
+{9,21,136,169}
+{67,97,99,153,165,173}
+{46,76,89,100,164}
+{96,102,150,167,180}
+{31,103,137,146,180}
+{21,40,157,163,170,183}
+{139,170}
+{1,75,82,148,169,198}
+{13,39,107}
+{13,50,97,101,106}
+{52,176}
+{18,169}
+{129,140,146,183,189}
+{95,122,145}
+{5,6,102,130,151}
+{5,118,140,153}
+{27,78,140,164,182}
+{36,140,148}
+{58,100,127}
+{9,16}
+{26,33,119}
+{1,17,18,165}
+{14,182}
+{11,13,48,89,140,165}
+{9,19,78,113}
+{121,171}
+{18,23,46,113,159,162}
+{17,104}
+{50,104,132,167,179}
+{55,89,102,132,176}
+{19,109}
+{60,70,73,153,163}
+{18,127,145}
+{80,106,146,170}
+{10,39,72,74,84,150}
+{3,71}
+{1,10,64}
+{82,95,127,132,141,152}
+{43,55,57,89,120,197}
+{155,182}
+{23,34,57,111,153}
+{99,188}
+{86,114,124}
+{113,191}
+{31,129,184}
+{125,159,159}
+{22,27,81,156}
+{3,54,80,122,128,168}
+{76,112}
+{152,174}
+{22,27,70,172}
+{26,86}
+{49,59,102,186}
+{53,55,75,125}
+{152,199}
+{11,15,46,102,105,168}
+{132,148,154}
+{24,114,121,126,138,165}
+{82,107}
+{36,93,122,184,194}
+{1,59,76,146}
+{73,165}
+{38,98,176}
+{53,72,121,153}
+{127,147}
+{31,77,128,177}
+{107,186,189}
+{119,126,127,160}
+{24,74,148,197}
+{85,126,134,146}
+{76,77,81,134}
+{67,112,159,174,183}
+{22,169,170}
+{79,112,177,199}
+{1,56}
+{21,42,50,172}
+{6,63,105,166,189}
+{31,95,106,152,171,177}
+{21,49,99,101,122,187}
+{63,104,113,161,186}
+{37,126,144,166,173}
+{32,53,147}
+{123,123,130}
+{78,85,177}
+{2,69,95,146,187}
+{6,11,14,43,121}
+{76,105,184}
+{63,96,114,122,195}
+{11,22,34,45,120,156}
+{22,83,119,131,138,167}
+{9,56,96,106,114}
+{92,132,162}
+{25,45,83,119,139,150}
+{19,21,56,59,141}
+{14,26,62,119,180,190}
+{6,34,49,99,139,170}
+{10,56,150,166,166}
+{14,57,119,153,167,198}
+{26,41,150,158,169}
+{152,167}
+{1,61,93,180}
+{46,110,138,199}
+{4,56,81,110,173}
+{28,32,148,185}
+{8,9,28,29,39,195}
+{14,39,68,144}
+{26,37,79,81,110}
+{115,158,161}
+{6,39,145,191}
+{67,118,125,142,184,198}
+{127,163}
+{52,118}
+{22,78,131,156}
+{46,68,86,142,145,197}
+{85,188}
+{37,54,64,147,158}
+{31,134,141,183,185}
+{10,33,135,198}
+{41,124,173,180}
+{0,14,92,129,154,198}
+{39,73,128,154,182,196}
+{40,83,94,168}
+{106,142}
+{76,99}
+{19,62,77,108,165,186}
+{68,90,97,119,176}
+{44,108,193}
+{2,124}
+{137,174,175,176,180}
+{28,62,81,132,165,186}
+{98,112,148,181}
+{86,125}
+{70,161}
+{5,13,188}
+{136,168}
+{82,87}
+{30,42,57}
+{132,136,152}
+{20,59,87,98,195}
+{6,53,112,113,183,195}
+{64,147,157}
+{61,140,192}
+{44,59,88,123,161}
+{90,175}
+{38,46,105,121,159}
+{35,62,66,90,155}
+{2,2,21,38}
+{123,144}
+{117,155}
+{60,86}
+{4,39,129,146,179}
+{66,71,87,135,148,157}
+{29,67,108,196}
+{30,64,76,124,172}
+{36,39,79,130,140,149}
+{30,44,136,196}
+{5,15,20,117,198}
+{20,87,87,121}
+{42,136,142,148}
+{0,56}
+{16,38,56,57}
+{52,138}
+{103,115}
+{10,29,43,93,120,134}
+{44,140,150,180}
+{74,98,132,160}
+{2,62,98,160}
+{14,32,43,63,92}
+{23,87,128,152,177,197}
+{30,86,111,178,180}
+{49,61,114,195,196}
+{133,158,195}
+{18,105,165,190}
+{77,83,175}
+{29,33,51,166,188}
+{37,51,96,103,127}
+{119,125,128,140}
+{8,80,93,189}
+{76,96,110,131,170}
+{81,90}
+{13,25,28,41,128,142}
+{56,62,73,110}
+{60,62,128,136,166,193}
+{34,34,61,74}
+{32,84,87,92,112,181}
+{10,66,93,153}
+{23,77,182}
+{2,7,156}
+{5,13,49,61,103,179}
+{67,136,136,163,181,196}
+{26,60,74,100,160}
+{39,59,69,93,111}
+{9,77,90}
+{1,20,52,75,156,169}
+{25,95,103,157,163,193}
+{95,136}
+{47,108,137,157,164}
+{37,99,151,153,169,189}
+{112,126,139,171,184,195}
+{39,188}
+{4,20,71,80,136,156}
+{24,33,77,82}
+{103,188}
+{74,116}
+{82,90,110,154,194,195}
+{25,149,180}
+{120,123,130,171}
+{20,38,104,126,175,176}
+{14,62,97,130,135,193}
+{35,118}
+{20,42,64,73,76,120}
+{11,40,60,74,144,148}
+{13,26,46,63,76}
+{24,29,98,106}
+{6,139,171,186}
+{5,109,197}
+{20,45,84,125}
+{1,137,150,195}
+{1,8,80,111}
+{57,90,102,167}
+{53,186}
+{8,31,115,145,156,165}
+{10,18,31,116,164}
+{43,47}
+{33,143,154}
+{106,153,174,190}
+{73,106,158}
+{18,137,158,173}
+{73,80,107,123,141,199}
+{17,43,123,130,130,155}
+{15,31,37,91,164,181}
+{38,86}
+{49,105,142,145,173,190}
+{18,107,108,135,138}
+{43,65,107,112,193}
+{8,68,68,74}
+{54,106,108,109,164}
+{53,153}
+{59,134,154,173,180}
+{34,93}
+{11,33,124}
+{8,104}
+{27,37,46,65,125,174}
+{0,122,189}
+{15,74,107,147,188}
+{35,63,78}
+{28,49,123,129,177,193}
+{11,89,104}
+{117,171,197}
+{11,15,62,136,145,145}
+{2,127,193}
+{17,28,42,113,145}
+{31,44,118,148}
+{52,103,128,161,182}
+{45,47,70,102,161,184}
+{15,52,82,86}
+{60,87,102,108,127,170}
+{24,57,102,145,181}
+{12,53}
+{5,52,92,129,164}
+{87,128}
+{80,143,170}
+{59,85,134,139}
+{61,67,110,117,156,157}
+{6,8,60,112,154,170}
+{92,122,133}
+{121,148,161}
+{9,22,61,187}
+{12,40,78,107,176}
+{30,45,58,189,198}
+{83,107,123,148}
+{3,66,98,124,126,150}
+{13,34}
+{16,41,132}
+{16,85}
+{3,25}
+{30,58,138,167}
+{24,36,87,151,159,186}
+{2,4,121,196}
+{79,95,99,107}
+{11,49,146,169}
+{51,90}
+{76,155}
+{26,26,116,120,146,182}
+{44,66,72,117,132,174}
+{7,161,179,197}
+{2,81,158}
+{4,22,59,107,146,170}
+{0,0,133,192}
+{57,82}
+{17,61}
+{28,29,42,77,89,124}
+{53,78,127,188}
+{31,57,103,104,162}
+{9,84,100}
+{3,52,114,133,161,188}
+{8,37,97,158,189}
+{0,13,88}
+{29,79,92,158,160,171}
+{59,63,77,139,165}
+{25,77,116,169}
+{50,88,151,166}
+{52,162,167}
+{32,149,191,194,194}
+{47,57,74,95,97}
+{30,65,96,153,184}
+{80,130,150,172}
+{79,91,141,153,157}
+{93,110,114,194}
+{62,66,156,175}
+{55,56,97,117}
+{74,152,171,186}
+{13,24,50,50,131}
+{0,16,95,141,146,161}
+{1,51,158}
+{37,71,96,122}
+{71,104,145}
+{47,52,124,131,169}
+{111,188}
+{59,61,95,152,156,157}
+{5,31,106,164,176}
+{44,82,113,134,188}
+{13,55,65,99,150}
+{25,73,130,192}
+{88,120,193}
+{79,123,153,175}
+{24,158,162}
+{52,53,81}
+{5,32,78,102}
+{73,97,111,151}
+{71,72,102,151}
+{5,61,73,85,129,151}
+{66,177}
+{26,77,139,152}
+{46,117}
+{55,72,122,148,157,174}
+{3,53,76,184,196}
+{34,36,41,61,194}
+{8,153,163,182}
+{51,59}
+{113,115,149}
+{54,57,78}
+{39,137}
+{75,81,93}
+{5,30,44,80,86,126}
+{68,107,128,160,179}
+{98,108,162}
+{55,126}
+{24,54,121,122}
+{75,90}
+{10,83,139}
+{16,120,148}
+{97,175}
+{53,70,71,120,135,189}
+{9,110,123,150}
+{24,42,44,96,138,170}
+{17,61}
+{23,65,110,135,155,157}
+{19,59,139}
+{50,65,127,179}
+{15,138,152,162}
+{15,34}
+{25,29,63,135,161}
+{47,113,123,129,163}
+{25,138,157,184}
+{50,92,199}
+{110,116}
+{15,36,134,145,165,182}
+{4,75,82,175}
+{24,49,63,89,128}
+{174,182}
+{103,116,119}
+{101,125,180,192}
+{47,66,113,127,148}
+{15,60,118}
+{20,51,90,91,117}
+{25,72,146,199}
+{34,93,199}
+{31,71,106,115,186}
+{1,10,119,144,188,197}
+{49,80,185}
+{134,178,188}
+{42,67,170,172}
+{13,43,91,91}
+{13,31,48,98,155,158}
+{37,44,70,76,141,160}
+{50,60,72}
+{51,65,166,188}
+{11,103,129,144}
+{136,167,181}
+{165,178}
+{34,107}
+{54,120}
+{33,132,136,165,178}
+{60,79,119,127,187,197}
+{27,31,130,132}
+{125,129}
+{97,111}
+{71,171,187,191}
+{68,91,94}
+{94,119,159,178}
+{2,29,51,173}
+{37,61,97,113,147}
+{11,35,79,91}
+{67,71}
+{4,20,103,107,169,179}
+{35,77}
+{71,94}
+{29,31,67,101,172,174}
+{52,122}
+{87,125}
+{129,142,164}
+{13,30,85,139}
+{17,57,65,170,179}
+{46,65,151,167,192,197}
+{31,78,132,136,158}
+{38,161}
+{15,101,111,134}
+{42,118,139,142,178}
+{57,95,132,134}
+{5,42,116,152,173,192}
+{144,199}
+{38,70,77,143,175,188}
+{38,84,93,149}
+{56,98,153,165,170,191}
+{1,52,112,112,131,145}
+{16,132,150,184}
+{14,60,111,153}
+{49,109,112,165}
+{69,136,152}
+{59,90,94,158,168}
+{42,47}
+{18,194}
+{33,70,94,167,175,177}
+{40,57,125,138,159}
+{3,10,31}
+{2,5,8,26,141,181}
+{27,29,142,175,186,195}
+{31,49,99,120}
+{109,123}
+{21,76,112,119,124}
+{41,49,146,173}
+{101,173}
+{49,73,85,89,179}
+{22,36,154,192}
+{136,163}
+{111,165}
+{94,128}
+{81,167}
+{35,165}
+{41,109,119}
+{13,74,80,114}
+{72,106,189}
+{65,172}
+{30,31,35,52,63}
+{80,116}
+{0,149}
+{139,189}
+{0,65,107,153,179}
+{15,40,46,51,75,160}
+{12,28,48,79,105}
+{76,98,146,157,180}
+{45,62,79,83,113,155}
+{130,162,184}
+{78,140,145,181,196,198}
+{108,168}
+{3,13,14,15,77}
+{22,29,68,117,142,143}
+{67,110,122,167,183}
+{22,25,58,93,143,151}
+{53,82,170}
+{1,18,50,98,108,174}
+{58,140}
+{49,179,196}
+{109,171}
+{38,82,132,183}
+{32,151,175}
+{53,90,106,169,187}
+{99,136,141,146,171}
+{27,108,111,155,192}
+{28,77,86}
+{11,109,118,149,154,183}
+{7,74,122,137,185}
+{70,110,151,154,175}
+{7,48,88,181,181,182}
+{97,101,105,123,139,156}
+{19,139}
+{17,107,134}
+{63,64,178}
+{100,133,143}
+{64,173}
+{1,88,109,120,145,160}
+{113,198}
+{84,112,121,184}
+{90,185,193}
+{91,135,155,185}
+{56,191}
+{14,15,48,61,92,171}
+{18,139,152,199}
+{16,80,107,125,144,166}
+{8,92,112,173,176}
+{27,196}
+{9,169,183,190}
+{20,29,40,98,106,182}
+{77,115,149,181}
+{31,65}
+{7,29,62,90,157,178}
+{10,33,79,186}
+{42,74,113,178,192}
+{17,86,88,118}
+{27,58,104,122,166}
+{16,97,102,105,192}
+{16,59,115,127}
+{27,56,60}
+{104,175}
+{52,84}
+{127,137}
+{7,13,18,81,139,140}
+{11,31,81,150,189}
+{44,55,107}
+{45,58,127,137}
+{70,76,80,93,145}
+{27,60}
+{40,76,172}
+{7,123,192}
+{55,170}
+{61,137,137,184,187}
+{49,50,190}
+{99,126,152,164}
+{56,79,88,98,132}
+{45,74,119,123,158,175}
+{66,96}
+{100,114}
+{62,84,111,122}
+{8,22,141,172,181}
+{70,141}
+{3,48,106,193}
+{33,114,168,174,183}
+{46,186,194}
+{58,71,82,122,190}
+{60,67}
+{14,30,132,144,174}
+{9,113,124}
+{11,14,29,63,110,182}
+{4,64,102,168,178}
+{90,108,110,160,165,199}
+{44,86,191}
+{6,19,84,125,125,156}
+{53,105,122,154,175,190}
+{83,177,183}
+{96,103,181}
+{38,156}
+{2,6,60,116,131}
+{12,144}
+{13,73,93,132}
+{142,167}
+{37,61,71,75,121,144}
+{32,43,146}
+{41,59,144,176}
+{11,14,44,54,92,177}
+{37,198}
+{39,80,81,104,138,193}
+{13,73,92,127,149,194}
+{34,57,69,104,118,186}
+{7,48,84,96,108}
+{32,41,64,111}
+{108,131,150,174,195}
+{50,53,184,191}
+{8,32}
+{26,76,88}
+{4,50,100,134,134}
+{36,40,148,158,177}
+{7,16,57,59}
+{35,96,113,129,167}
+{46,63,128,163}
+{8,46,94,97,105,178}
+{12,70}
+{45,93,134,135,188,195}
+{11,52,76,103,131,192}
+{19,45,57,119,123,136}
+{19,62}
+{1,49,64,197}
+{0,42,60,102,134,147}
+{102,152,156,160}
+{51,54,129}
+{50,68,71,72,170}
+{0,11,184}
+{19,105}
+{144,185,191}
+{17,51,76,98,118,135}
+{52,64,143,171}
+{1,46,62,74,81}
+{8,36,129}
+{5,25,96,113,146,152}
+{19,28,59,110,131,142}
+{7,18,176,179}
+{17,21,48,63,121}
+{34,79,81,85,152,155}
+{8,82,104,122,139,193}
+{34,50,128,140,175}
+{51,173}
+{48,128,138}
+{126,129,178}
+{42,51,61,141,170,180}
+{59,91,144}
+{64,74,118,170,191}
+{12,55,116,157,159}
+{97,157}
+{32,34,102,105,178}
+{36,103,125}
+{15,36,184}
+{6,13}
+{0,100,144,185,198}
+{32,47,64,66,118,143}
+{23,112,117}
+{34,44,47,81,124,135}
+{21,49,115}
+{29,158}
+{34,114,127,151}
+{111,199}
+{23,53,76,113,122,123}
+{89,113,117,137}
+{52,76,126,155,164}
+{4,48,78,114,147,179}
+{27,56,151,191}
+{3,183}
+{30,41,72,145}
+{15,41,152,177,196}
+{44,58,124,164,177}
+{9,51,70,174}
+{13,18,81,136,178}
+{85,139,142}
+{12,62,118,156}
+{50,142,149,175}
+{35,38,99,100,128}
+{53,54,92,123,153,160}
+{121,133}
+{12,63,117,148,149,187}
+{88,153,170,192,195}
+{22,51,67,104,141}
+{186,198}
+{39,40,82,159,189}
+{59,74,149}
+{88,99,136,145,191}
+{5,48,90,120,138,193}
+{22,76,155,180}
+{118,122,141,176}
+{87,104,116,159,172,191}
+{63,104,155}
+{8,153,168}
+{119,141,178,179}
+{100,110}
+{14,65,164}
+{2,92,97,117,188}
+{47,59,64,141,148,187}
+{109,137,139,151,169}
+{68,78,156}
+{37,39,103,183,190,194}
+{50,58,74,180}
+{12,121,155,175}
+{26,43,97}
+{102,159,161}
+{3,138,163,179}
+{55,69,78,164}
+{67,87,136}
+{67,150}
+{74,113,199}
+{103,126,187}
+{39,141,155}
+{6,19,25,75,157}
+{10,49,71,105,114,154}
+{3,24,35,54,88}
+{16,25,73,114,181,191}
+{2,2,63,154}
+{68,74,107,187,199}
+{13,235}
+{40,122,203,232,233,235}
+{115,152,193,202,242}
+{3,50,86,111,248}
+{25,66,181,188,279}
+{80,116}
+{38,83,106,119,134}
+{29,63,203}
+{7,27,186,200,201}
+{88,92,94,272,295}
+{35,68,136,158}
+{148,225,293}
+{1,87,195}
+{48,100,203}
+{0,35,61,91,280}
+{130,160,168,216}
+{4,104,148,164}
+{35,40,91,145,155,214}
+{46,107}
+{21,276}
+{42,143,150,238,291}
+{64,70,140,165,228,257}
+{0,148,197}
+{72,131,195,202,251,270}
+{99,195,224,264,292}
+{5,184,186,243}
+{93,132,137,148,228,251}
+{66,125,198,211,285}
+{29,79,180}
+{41,60,65,66,254}
+{4,69,79,207}
+{113,182,203,252,259,298}
+{10,20}
+{99,200,276}
+{109,262}
+{4,87,193,207,220,273}
+{30,183,215}
+{7,138,202,215,217}
+{25,79,194,203,260}
+{128,178}
+{62,152,211,279}
+{57,99,204,280}
+{41,59}
+{18,52,200}
+{81,132,190,275}
+{89,158}
+{32,72,122,228,245,249}
+{24,72,196,233,299}
+{0,5,46,122,213}
+{197,242}
+{43,105,241,272}
+{74,118,158,173,208,288}
+{145,149,197,238,252,297}
+{32,39,189}
+{98,240}
+{65,140,149,197,203,204}
+{103,225,266}
+{84,277,283}
+{35,246}
+{10,101,239}
+{40,75,192,253}
+{106,152,247,272,287}
+{50,293}
+{85,134}
+{59,204}
+{54,64,88,269,286}
+{4,92,111,121,154,182}
+{80,163,202,234,277,298}
+{129,147,158,196,283,290}
+{49,144,232,293}
+{20,29,226,244,274}
+{64,101,185,189,234,268}
+{23,157}
+{56,93,133}
+{9,57,241,289}
+{50,124,181,194,238}
+{11,38,67,69,213}
+{149,220}
+{168,189,267}
+{34,133,235,264,284}
+{81,239,241,260}
+{35,78,80,201,262,297}
+{0,196,285}
+{71,108,239,258,277,278}
+{4,94}
+{77,132,140,251}
+{11,78,132}
+{43,145,188}
+{97,144,148,161,254}
+{109,132}
+{48,83,189,242}
+{115,176,276}
+{162,210}
+{88,109,136,153,154,159}
+{265,280}
+{74,86,195}
+{17,112,188,213,231,266}
+{36,136,160,218,239}
+{179,273}
+{79,118,136,154,200,259}
+{161,212}
+{24,98,178}
+{161,187}
+{45,169,227,236}
+{218,253}
+{10,18,74,258}
+{70,199,210,213,285,291}
+{12,50,69,92,184,186}
+{130,131,163,295}
+{198,239,297}
+{49,86,125,176,234,282}
+{7,129,146,223,269}
+{144,173}
+{30,52,133,228}
+{21,88,176}
+{5,70,299}
+{37,69,285}
+{14,17,45,72,99,197}
+{125,196}
+{30,220}
+{55,103,127,251}
+{108,114,156,200,207,217}
+{7,195,250}
+{64,111,193,202,236}
+{92,115,232,233,240}
+{22,232,260}
+{18,44,191,253,294}
+{40,158}
+{86,92,103,154,207,294}
+{33,177,191,223,235}
+{65,116,158,253}
+{49,125,152,194}
+{100,149,191,266,288}
+{13,64,103,254,283}
+{42,75,80,103,155}
+{77,128,198,280}
+{118,218,287}
+{0,36,52,101,148}
+{1,64,181,201,221}
+{6,44,47,71,150,225}
+{13,85,88,167}
+{31,40,69,91,99,281}
+{60,115,157,224,252,273}
+{30,87,200,270,285}
+{171,293}
+{24,33}
+{59,69,74,118,190,216}
+{147,258,288}
+{62,73,219,232,266}
+{50,74,225,238,271}
+{6,88,115,185,205,262}
+{97,230}
+{76,76,150,211,228,262}
+{134,195}
+{104,235}
+{38,41,204}
+{64,71,124}
+{44,63,111,231}
+{186,188}
+{5,132,225}
+{113,286}
+{43,161,276}
+{8,294}
+{18,90,105,169}
+{213,213}
+{29,45,161,289}
+{79,152}
+{10,110,162,177,217,238}
+{63,98,192,244}
+{118,147,187,281}
+{5,15,36,94,263}
+{40,81,220}
+{29,74,76,157,162,206}
+{11,28,53,68,126,222}
+{73,73,181,239}
+{36,60,164}
+{16,47,82,152,167,289}
+{149,149,219,268,294}
+{97,169}
+{32,160,210,257}
+{32,69}
+{7,63,73,195}
+{54,110}
+{61,75,135,270}
+{22,43,127,174,184,208}
+{106,113,174}
+{0,70,90,239}
+{191,260}
+{43,80,168}
+{25,54,257,263}
+{118,213}
+{110,207,220,251,287}
+{126,139,161,248,252}
+{51,79,116,132,190,291}
+{183,199,200,254}
+{86,233}
+{105,109,176,211}
+{12,109}
+{3,65,158}
+{21,86}
+{12,15,191}
+{181,223,224,256,259,276}
+{112,191,219,232,239}
+{51,215}
+{36,46,278}
+{68,75,169,228,244,270}
+{10,16,52,172,189,274}
+{177,191,197,209,222,282}
+{41,119,190,202}
+{128,277,292,298}
+{34,38}
+{22,36,81,117}
+{81,161,248,279}
+{75,85,103,149,190,211}
+{127,279}
+{50,74,152}
+{122,168,209,240,276,282}
+{66,102,208,239,291}
+{9,113}
+{72,199,237}
+{110,112,135,141,270}
+{26,109,130,159,291}
+{108,206}
+{2,289}
+{63,238}
+{4,57,104,119,142,214}
+{46,97,239}
+{210,297}
+{207,268}
+{13,64,80}
+{62,109,171,195,232}
+{11,260,262,276,292}
+{21,75,78,80,140,226}
+{38,56}
+{122,251,297}
+{108,180,213}
+{57,58,135,231,233}
+{75,136,185,211}
+{52,109,122,174,178,255}
+{65,91,234,249}
+{5,24,53,218}
+{90,211,246}
+{106,242,260}
+{61,136}
+{49,87,177,280}
+{38,89,104,189,297}
+{43,76,293,298}
+{182,255,289}
+{25,57,64,272}
+{23,122,149}
+{49,50,129,153}
+{183,188,204}
+{27,164,226,230}
+{0,13,67,145,160,259}
+{22,32,43,85,105,124}
+{20,199}
+{31,119}
+{14,16,152,158,196}
+{5,59,91,202,217,280}
+{100,128,187}
+{20,193,214,258,272}
+{17,27,55,151,177,219}
+{53,55,63,208,213,230}
+{15,160,258,260}
+{71,147,235,258}
+{26,49,173,234,271}
+{50,52,58,167,257}
+{15,154,213,232}
+{6,35,86,94,286}
+{0,4,83,262,281}
+{93,148,284}
+{28,165,262,290}
+{18,99,160,266}
+{63,223,291,295}
+{103,154,180}
+{12,110,144,221}
+{9,158,203}
+{20,207,275}
+{9,20,48,88,120,289}
+{67,110,133,151,225,297}
+{71,102}
+{168,208}
+{48,137,163,164,280,287}
+{90,209}
+{28,244}
+{107,224,293}
+{86,206}
+{8,113,147,165,285,286}
+{7,159,160,237}
+{0,66,87,146,225,294}
+{58,100,112,124,189}
+{13,108}
+{121,168,216,253}
+{147,242,282}
+{236,240}
+{21,28,83,103,166}
+{30,88,108,280,295}
+{23,136,298}
+{125,290}
+{140,249,276,277}
+{49,81,135,147,164,267}
+{28,63,198,297}
+{30,101,216,232,267,287}
+{54,195,204,223,236,251}
+{27,176,179,204,264,291}
+{136,164,172,273}
+{43,67,81,121,277}
+{128,131,256,269}
+{176,219,289}
+{127,175,259}
+{35,94,153,177,222,253}
+{29,154,178,240,260}
+{165,176,201,243,259}
+{17,298}
+{29,203,232,241,289}
+{107,136,153,238}
+{49,198}
+{68,179,202,253}
+{157,178}
+{23,199,287}
+{131,228}
+{19,19,39,111,138,277}
+{49,86,178,194,223,226}
+{114,201}
+{149,282}
+{109,147,150,176,209,229}
+{122,131,167,228,258}
+{5,40,120,154,266}
+{135,207,238,263}
+{75,128}
+{80,117,296}
+{60,82,122,131,138}
+{57,146,159,233,244,278}
+{15,80,157,182,244,272}
+{114,116,160,176,287}
+{10,133,279}
+{27,115,126,293}
+{89,161}
+{95,120,218}
+{26,269}
+{109,281}
+{53,62,103,107,118,239}
+{185,186,227,252}
+{3,125,146,161,288}
+{171,245,256,283}
+{23,153,201,238}
+{0,82,93,218,242}
+{101,124,137,150,194}
+{21,96,104,201,244,266}
+{88,121,147,155,173,225}
+{24,106,112,193}
+{26,67,115,212,283}
+{23,120,280}
+{45,99}
+{30,66,136,199}
+{17,213}
+{14,37,55,103,265}
+{52,258,284}
+{119,213,272,274,285}
+{43,45,105,254,288}
+{64,81,123,126,164,292}
+{88,229,260}
+{25,117}
+{7,149,197,227,258}
+{74,83,240,246,284,292}
+{2,4,63,103,115,289}
+{92,239}
+{12,26,130,228,265}
+{53,99,131,142,164,291}
+{63,248,259,283}
+{186,215,282}
+{67,110,160}
+{166,191}
+{33,156,224}
+{152,166,190,250,297}
+{123,126,153,199,204}
+{49,70,199,238,238,289}
+{14,18,65,74,146,235}
+{63,77,172,180,186,225}
+{1,48,105,170}
+{37,56,113,133,196}
+{193,261,266}
+{190,273}
+{38,129,261}
+{251,252,253,254,275,296}
+{249,275}
+{167,205,266}
+{27,152,256}
+{19,72,248}
+{40,73,141,249}
+{105,197}
+{156,243,277,282}
+{165,168,227,298}
+{8,31,202,271}
+{10,101,109,167,236,277}
+{33,91,165,192,206,211}
+{102,122,232}
+{190,239,283}
+{160,185}
+{2,13,65,70}
+{11,68,170,192,229,284}
+{66,90,228,237}
+{1,6,92,99,222,242}
+{42,128,133,207,289}
+{12,100,164,191}
+{26,31,120,176,204,220}
+{13,39,95,105,120,182}
+{114,120,295}
+{31,34,55,181,197,235}
+{24,52,64,80,142}
+{3,49,148,255,268}
+{132,175,254}
+{32,71,141}
+{112,116,186,270,271}
+{64,106,209,228,297}
+{128,268}
+{107,208,299}
+{151,173,187,192,213}
+{3,296}
+{20,31,135,153,289}
+{138,193,212,269,277,288}
+{73,92,130,295}
+{73,80,105}
+{50,96,138,199,265}
+{4,7,8,183,260,267}
+{66,71,118,145}
+{15,63,116,160,175,181}
+{88,217}
+{56,69,106,106,127,274}
+{84,205}
+{83,101,241,269}
+{21,254}
+{22,32,83,150,293}
+{198,221}
+{30,46,95,179,197}
+{46,85,208}
+{56,112,236}
+{71,217}
+{31,57,145,253}
+{34,133,170}
+{48,53,119,187,268,287}
+{111,203,229,239}
+{62,136}
+{49,54,187,254,298}
+{20,26,148,159,190,286}
+{3,13,193,252,284}
+{40,137,154,167,248,259}
+{3,47,242,278}
+{77,100,143,232}
+{51,130}
+{66,90,148,220,242,273}
+{143,151,211}
+{10,23}
+{21,30,179}
+{17,47,105,156,193,213}
+{0,23,25,125,144,146}
+{179,209}
+{79,113,117,192}
+{5,53,216,275,285}
+{187,197}
+{22,68,218,221}
+{0,71,78,110,120,173}
+{46,97,117,149,253,286}
+{10,20,129,162,171,195}
+{60,97,130,163,190}
+{57,145,179,283}
+{99,274}
+{151,161,228,251}
+{3,177,192,286}
+{21,81,142}
+{180,283}
+{13,102,131,149,246}
+{19,99,132,162,167,257}
+{15,86,188,260}
+{203,251,281}
+{5,45,138,155,157}
+{1,2,4,213,278}
+{21,123,208,219,263,267}
+{36,106,181,231,238}
+{103,120,168,184,224,287}
+{53,104,139,251}
+{1,91,141,202,268}
+{75,115,216,253}
+{56,167,268,296}
+{66,158,235,249}
+{82,124,198}
+{56,67,112,140,170,176}
+{16,75,266}
+{38,165,200,219,291,297}
+{86,151,229,241,275}
+{0,57,141,176,229,258}
+{18,72,164,195,235}
+{94,282}
+{83,139,242,269,294}
+{9,44,145,251,272}
+{132,203,249,282}
+{7,41,170,254}
+{6,153,193,291}
+{18,134,137,227,261}
+{14,36,115,124,172,229}
+{54,206}
+{49,91,131,185,204}
+{7,242}
+{41,57,161}
+{93,224,241,288}
+{119,288}
+{90,99,117,196,296}
+{67,85,154}
+{147,169,216,264}
+{79,92,164}
+{19,120,132,197,267}
+{76,264}
+{30,133}
+{27,37,93,138,218}
+{152,155,244}
+{41,149,182,259}
+{29,178,224}
+{115,201,268}
+{141,166,253,282}
+{3,65,125,245,264}
+{6,150,159,202,206,277}
+{217,276}
+{28,96,144,193}
+{7,59,190}
+{144,217}
+{10,79,96,100,126,222}
+{7,61,253}
+{14,69,263}
+{3,30,63,125,186,277}
+{2,10,79,100,223}
+{131,131,239}
+{116,195,199,240}
+{87,99,158}
+{52,180}
+{7,12,140,208,275}
+{65,67,83,280}
+{4,52,125,126,137,176}
+{9,48,79,203,217,243}
+{43,206,251}
+{19,112,196,263,266}
+{29,70,256}
+{161,236,258}
+{8,25,42,97,291}
+{63,144,242,271}
+{7,17}
+{1,85,250}
+{104,244,250}
+{18,22,31,99,266,281}
+{51,138,237,268,288}
+{8,40,91,221,273}
+{0,176,230,249,254,255}
+{44,140,176,194,197}
+{56,197,264}
+{229,246,283}
+{53,128,173,233,282}
+{45,193,221}
+{21,80,286}
+{4,18,267}
+{15,97,220}
+{62,70,83,147,149,244}
+{120,134,159,174,250}
+{116,269}
+{23,108}
+{10,91,239}
+{7,128,142,243,286}
+{134,201,245,275,278}
+{13,208,227,288}
+{30,78,85}
+{107,179}
+{31,59,153,217,240,298}
+{27,130,233,282,286}
+{15,59,136,262}
+{85,186,233}
+{10,152,165,181,181}
+{137,183}
+{40,56,125,256,265,280}
+{12,22,120,183}
+{62,229}
+{38,59,81,113,261}
+{67,194,229}
+{7,173}
+{37,43,296}
+{59,162,285}
+{171,200,213,213}
+{116,123,209,234,277}
+{52,175}
+{189,213}
+{30,94,99,228,238}
+{46,101,154,260,272,274}
+{30,32,59}
+{65,172,292}
+{18,22,131,170,271}
+{2,53,88,104,264,265}
+{60,194,288}
+{15,108,121,161,201}
+{40,85,173,195,201,221}
+{54,86,107,174,287}
+{20,71,190,227}
+{16,46,66,175,197,252}
+{130,243,252,282}
+{142,219,266,272}
+{14,202,204,231,241,276}
+{161,172,212,222}
+{15,183,275}
+{83,270}
+{67,204}
+{65,184,264}
+{73,119,183,190,242}
+{53,287}
+{24,171}
+{72,220,220}
+{101,136,176,204,224,280}
+{39,47,282}
+{106,162,238,252}
+{23,242,247,265}
+{98,108,189,209,273}
+{122,245,270}
+{109,127,128,244,299}
+{41,162,186,191}
+{60,196}
+{0,123,129,213,248}
+{29,79,89,91}
+{172,298}
+{122,140,162,228,263,268}
+{2,116,247,294}
+{6,138}
+{17,98,287}
+{53,166,187,219,248,296}
+{15,26,90,175,196}
+{184,193,198}
+{17,69,76,105,183,264}
+{56,101,110}
+{15,108,139,168,272}
+{5,71,104,141}
+{136,179}
+{72,189}
+{54,79,208}
+{98,113,150,184,190,246}
+{37,69,132,210,285}
+{1,29,45,74,109,145}
+{11,72,133,149,216}
+{34,57,84,212,280}
+{131,211,294}
+{70,84,173}
+{193,213,230,266,285,299}
+{57,94,163,182,227}
+{44,133,143}
+{31,32,211}
+{130,142,165,188,194,231}
+{52,61,139,226,239,287}
+{7,103,157}
+{155,224,230}
+{127,135,139}
+{77,237,294}
+{10,213,278}
+{28,90,185,274}
+{59,105,282,297}
+{39,128,174,268}
+{32,158,215}
+{24,145,189,213,278}
+{78,148,230,263}
+{42,68,93,160,287,299}
+{4,12,70,91,191,237}
+{20,294}
+{45,53,77,113,211,240}
+{232,237}
+{125,152,284}
+{58,81,155,215,296}
+{4,8,44}
+{1,52,102,128,184,218}
+{185,199,226,299}
+{10,178,262,285}
+{80,95,230,240,266}
+{4,5,213}
+{156,187,271,298}
+{88,298}
+{109,233,290}
+{47,65,91,105,249,269}
+{97,129}
+{46,92,207}
+{2,163,249,259,291}
+{89,102,140,158,231}
+{162,184,283}
+{36,213}
+{163,259}
+{47,220,250}
+{37,89,105,124,143,198}
+{3,71}
+{142,165,190,256,269,269}
+{152,256}
+{27,49,191,198,220,285}
+{71,73,87,189,260}
+{11,54,90,106,130,216}
+{193,245,252}
+{2,8,57,91,163,184}
+{18,171,283}
+{28,41,110,112}
+{5,57}
+{137,262,285}
+{19,57,156,229,269}
+{138,179,190,199,281}
+{35,98,196,242}
+{122,152}
+{83,132,181,212,280,288}
+{219,298}
+{57,88,103}
+{5,203}
+{98,156,266}
+{10,45,72,169,211}
+{45,101,156,214,269}
+{68,73,81}
+{16,127,259}
+{9,32,246}
+{66,173,261,261,274}
+{17,115,157,169,251}
+{49,158}
+{25,37}
+{2,73,103,178,194,236}
+{238,269,273}
+{162,178,276}
+{48,52,160,237,288}
+{54,82,130,135,169,275}
+{29,142}
+{205,249,253,275,291}
+{60,76,84,115,126}
+{48,108,153,213,231}
+{23,124,175,210,226,293}
+{9,181}
+{20,99,112,166,201,242}
+{102,150,201}
+{41,98,240,244,260}
+{7,44,98,293}
+{0,125,177,283}
+{28,118,124,148,241,290}
+{73,91,122}
+{9,72,109,130,202,290}
+{70,111,120,160,216,262}
+{59,175,296}
+{2,201}
+{83,297}
+{76,293}
+{83,127,136,242,275,285}
+{169,190,195}
+{83,122,186,189,217,229}
+{98,210,229}
+{117,133}
+{74,294}
+{6,31,59,143,156,273}
+{98,180,241}
+{26,52,114,243}
+{112,240}
+{104,217}
+{148,162,259,279}
+{92,101,150,226,272,295}
+{55,86,118,202,237,275}
+{81,203}
+{79,126,177,265}
+{57,193}
+{169,240,244}
+{21,171,190,250,263}
+{23,37,215,235}
+{40,54,240,286}
+{105,177,190,276,285}
+{44,45,122,151}
+{28,31,187}
+{127,135,211}
+{5,13,150,194,259}
+{136,181,280}
+{20,147,158,189,200}
+{15,83,88,128,169}
+{10,14,25,26,150,158}
+{42,101,172,205}
+{85,185,226,236,271}
+{34,127,188,250,268}
+{27,143}
+{26,48,99,110,117,207}
+{22,56,190,269,287}
+{200,278}
+{70,134,138,204,216,298}
+{175,219,297}
+{99,273}
+{206,216}
+{23,214}
+{131,140}
+{11,140,240}
+{73,148}
+{7,66,125,210}
+{2,61,92}
+{0,137}
+{143,188,265}
+{177,238}
+{0,93,163,229}
+{35,49}
+{8,8,111,144,165}
+{99,278}
+{21,44,71,224,252,270}
+{119,150,175,233,245,294}
+{15,87}
+{84,211,217,225}
+{20,41,87,123,124,299}
+{62,120,169}
+{37,43,92,175,206,222}
+{95,168,180,250,269,296}
+{60,228,278,285}
+{173,195,232,276}
+{1,2,139,256,278}
+{51,119}
+{212,238,291}
+{120,172,292}
+{138,279}
+{251,261}
+{151,181,278,296}
+{163,207,220,289,295}
+{89,278,290}
+{24,137,157,206,271,278}
+{7,63,83,89,155,189}
+{2,5,172,195,215,260}
+{243,281}
+{60,125}
+{74,87,222,236}
+{45,70,159,194}
+{69,159,250}
+{150,214,296}
+{101,158,250}
+{56,134}
+{57,87,160,167,247,285}
+{123,269}
+{235,242}
+{79,95,115,167,287}
+{31,56,132,244,276}
+{25,218,241,241}
+{57,82,151,170,204}
+{69,103,288}
+{88,138,154,292}
+{14,98,138,227,245,249}
+{175,222,274}
+{38,139,193,208,277}
+{79,141}
+{5,77,197,209}
+{15,37,77,110,116}
+{26,226}
+{68,93,101,140,233}
+{53,96,170,192,290}
+{29,89,102,216,220}
+{11,85,136,239}
+{158,180,195,200,226}
+{10,49,118,137,172}
+{144,172,183}
+{14,176,188,215,272}
+{42,97,125}
+{114,166}
+{52,61,162,171,249}
+{140,195,242}
+{59,99,233}
+{31,76,136,181,187}
+{81,112,157,168,271,294}
+{8,35,44,48,190,297}
+{145,195,201}
+{160,248,291}
+{94,270,285}
+{116,139,225}
+{111,131,140}
+{158,277}
+{59,229,257}
+{25,47,99,123,239}
+{8,36,205,274,295}
+{132,152,178,192,235}
+{19,40,96,204}
+{7,77}
+{211,282}
+{26,100,180,244,281,296}
+{200,212,286}
+{5,94,151,290}
+{75,80,128,179,269,269}
+{7,111}
+{7,26,69,158,269,276}
+{7,36,74,94,171,215}
+{2,62,65,93,124,271}
+{78,96,109,189}
+{182,197,280,298}
+{17,78,82,85,85,208}
+{6,122,155}
+{14,33,130}
+{1,21,167,169}
+{49,85,158,175,213}
+{59,194}
+{125,132,259,285}
+{20,38,81,89,234,274}
+{106,140,156,287}
+{57,125}
+{53,103,158,204,234,267}
+{0,49,160,189,235}
+{34,115,142,207}
+{162,173,181,190,298}
+{11,76,116,166,191}
+{2,87,99,236,279}
+{40,203}
+{2,33,39,215,254}
+{53,69,83,224,228}
+{79,136,183,216,226,227}
+{10,109,137,163,240}
+{24,126,141}
+{69,255}
+{103,138,230,246,259,283}
+{136,290}
+{13,34,78,145,166,242}
+{38,74,83,242,294}
+{54,248,273}
+{107,162}
+{50,170,176,191,207,275}
+{32,134,166,288,292}
+{163,167,186,274,291,296}
+{31,86,123,156,160}
+{114,133,136,176,281,290}
+{105,147,211}
+{124,151,179,222,299}
+{87,101}
+{145,169,181,205,247}
+{6,266}
+{26,33,52,56,106,116}
+{19,21,65,89,104,168}
+{164,181,208}
+{36,67,92,116,248}
+{145,200,247}
+{155,215}
+{49,212}
+{29,57,105,117,131}
+{2,13,68,128,139,140}
+{193,273,273}
+{3,78,105,111,297}
+{49,142,244}
+{32,259}
+{161,205}
+{96,146,179,259}
+{44,45,211,233}
+{56,91,146,166,285}
+{87,107,120,262,299}
+{76,160,276,297}
+{248,266}
+{5,12,188,240,247}
+{164,206,293}
+{15,18,60,163}
+{53,134,172,230,287,290}
+{117,137,146,153,155}
+{72,270}
+{171,251}
+{80,125,137,141,169}
+{52,108,200,219,225,271}
+{29,78,106,221}
+{21,74,110,273}
+{28,88,98,170}
+{83,104}
+{12,152}
+{7,69,143,246,265,269}
+{62,106,157,200}
+{113,260,272,272,294}
+{16,35,80,121,165,176}
+{96,154,172,198,263}
+{29,53,109,128,129,195}
+{131,230,271,273,295,299}
+{53,160,208,231}
+{23,180,208,249,272}
+{45,208,264}
+{14,29,169}
+{116,147,272}
+{7,193,237,271}
+{158,198,253}
+{41,60,71}
+{110,133,200,249}
+{24,159,255}
+{26,39,61,114,218,229}
+{141,286,299}
+{74,278}
+{67,71,155}
+{151,257,284}
+{13,28,72,131,206}
+{60,152,275,295}
+{88,105,184,185}
+{85,190,205,256,283,285}
+{202,285}
+{14,92,160,200,246,279}
+{42,95,157,195}
+{50,99,224,276}
+{32,97,101,122}
+{66,85}
+{19,146,180,242,269,286}
+{24,86,247,274}
+{54,264,270,284}
+{72,77,85,124,127,285}
+{47,249}
+{25,73,102,237}
+{33,68,84,117,120}
+{29,62,172,240,242,273}
+{42,140,182,248,261,282}
+{118,228,284}
+{1,89,158,294}
+{29,89,122,155,208,283}
+{173,208,229}
+{6,22,142,267,299}
+{22,122,173,245,293}
diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.out
new file mode 100644
index 0000000..a09d40e
--- /dev/null
+++ b/contrib/intarray/expected/_int.out
@@ -0,0 +1,858 @@
+CREATE EXTENSION intarray;
+-- Check whether any of our opclasses fail amvalidate
+SELECT amname, opcname
+FROM pg_opclass opc LEFT JOIN pg_am am ON am.oid = opcmethod
+WHERE opc.oid >= 16384 AND NOT amvalidate(opc.oid);
+ amname | opcname
+--------+---------
+(0 rows)
+
+SELECT intset(1234);
+ intset
+--------
+ {1234}
+(1 row)
+
+SELECT icount('{1234234,234234}');
+ icount
+--------
+ 2
+(1 row)
+
+SELECT sort('{1234234,-30,234234}');
+ sort
+----------------------
+ {-30,234234,1234234}
+(1 row)
+
+SELECT sort('{1234234,-30,234234}','asc');
+ sort
+----------------------
+ {-30,234234,1234234}
+(1 row)
+
+SELECT sort('{1234234,-30,234234}','desc');
+ sort
+----------------------
+ {1234234,234234,-30}
+(1 row)
+
+SELECT sort_asc('{1234234,-30,234234}');
+ sort_asc
+----------------------
+ {-30,234234,1234234}
+(1 row)
+
+SELECT sort_desc('{1234234,-30,234234}');
+ sort_desc
+----------------------
+ {1234234,234234,-30}
+(1 row)
+
+SELECT uniq('{1234234,-30,-30,234234,-30}');
+ uniq
+--------------------------
+ {1234234,-30,234234,-30}
+(1 row)
+
+SELECT uniq(sort_asc('{1234234,-30,-30,234234,-30}'));
+ uniq
+----------------------
+ {-30,234234,1234234}
+(1 row)
+
+SELECT idx('{1234234,-30,-30,234234,-30}',-30);
+ idx
+-----
+ 2
+(1 row)
+
+SELECT subarray('{1234234,-30,-30,234234,-30}',2,3);
+ subarray
+------------------
+ {-30,-30,234234}
+(1 row)
+
+SELECT subarray('{1234234,-30,-30,234234,-30}',-1,1);
+ subarray
+----------
+ {-30}
+(1 row)
+
+SELECT subarray('{1234234,-30,-30,234234,-30}',0,-1);
+ subarray
+--------------------------
+ {1234234,-30,-30,234234}
+(1 row)
+
+SELECT #'{1234234,234234}'::int[];
+ ?column?
+----------
+ 2
+(1 row)
+
+SELECT '{123,623,445}'::int[] + 1245;
+ ?column?
+--------------------
+ {123,623,445,1245}
+(1 row)
+
+SELECT '{123,623,445}'::int[] + 445;
+ ?column?
+-------------------
+ {123,623,445,445}
+(1 row)
+
+SELECT '{123,623,445}'::int[] + '{1245,87,445}';
+ ?column?
+---------------------------
+ {123,623,445,1245,87,445}
+(1 row)
+
+SELECT '{123,623,445}'::int[] - 623;
+ ?column?
+-----------
+ {123,445}
+(1 row)
+
+SELECT '{123,623,445}'::int[] - '{1623,623}';
+ ?column?
+-----------
+ {123,445}
+(1 row)
+
+SELECT '{123,623,445}'::int[] | 623;
+ ?column?
+---------------
+ {123,445,623}
+(1 row)
+
+SELECT '{123,623,445}'::int[] | 1623;
+ ?column?
+--------------------
+ {123,445,623,1623}
+(1 row)
+
+SELECT '{123,623,445}'::int[] | '{1623,623}';
+ ?column?
+--------------------
+ {123,445,623,1623}
+(1 row)
+
+SELECT '{123,623,445}'::int[] & '{1623,623}';
+ ?column?
+----------
+ {623}
+(1 row)
+
+SELECT '{-1,3,1}'::int[] & '{1,2}';
+ ?column?
+----------
+ {1}
+(1 row)
+
+SELECT '{1}'::int[] & '{2}'::int[];
+ ?column?
+----------
+ {}
+(1 row)
+
+SELECT array_dims('{1}'::int[] & '{2}'::int[]);
+ array_dims
+------------
+
+(1 row)
+
+SELECT ('{1}'::int[] & '{2}'::int[]) = '{}'::int[];
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT ('{}'::int[] & '{}'::int[]) = '{}'::int[];
+ ?column?
+----------
+ t
+(1 row)
+
+--test query_int
+SELECT '1'::query_int;
+ query_int
+-----------
+ 1
+(1 row)
+
+SELECT ' 1'::query_int;
+ query_int
+-----------
+ 1
+(1 row)
+
+SELECT '1 '::query_int;
+ query_int
+-----------
+ 1
+(1 row)
+
+SELECT ' 1 '::query_int;
+ query_int
+-----------
+ 1
+(1 row)
+
+SELECT ' ! 1 '::query_int;
+ query_int
+-----------
+ !1
+(1 row)
+
+SELECT '!1'::query_int;
+ query_int
+-----------
+ !1
+(1 row)
+
+SELECT '1|2'::query_int;
+ query_int
+-----------
+ 1 | 2
+(1 row)
+
+SELECT '1|!2'::query_int;
+ query_int
+-----------
+ 1 | !2
+(1 row)
+
+SELECT '!1|2'::query_int;
+ query_int
+-----------
+ !1 | 2
+(1 row)
+
+SELECT '!1|!2'::query_int;
+ query_int
+-----------
+ !1 | !2
+(1 row)
+
+SELECT '!(!1|!2)'::query_int;
+ query_int
+--------------
+ !( !1 | !2 )
+(1 row)
+
+SELECT '!(!1|2)'::query_int;
+ query_int
+-------------
+ !( !1 | 2 )
+(1 row)
+
+SELECT '!(1|!2)'::query_int;
+ query_int
+-------------
+ !( 1 | !2 )
+(1 row)
+
+SELECT '!(1|2)'::query_int;
+ query_int
+------------
+ !( 1 | 2 )
+(1 row)
+
+SELECT '1&2'::query_int;
+ query_int
+-----------
+ 1 & 2
+(1 row)
+
+SELECT '!1&2'::query_int;
+ query_int
+-----------
+ !1 & 2
+(1 row)
+
+SELECT '1&!2'::query_int;
+ query_int
+-----------
+ 1 & !2
+(1 row)
+
+SELECT '!1&!2'::query_int;
+ query_int
+-----------
+ !1 & !2
+(1 row)
+
+SELECT '(1&2)'::query_int;
+ query_int
+-----------
+ 1 & 2
+(1 row)
+
+SELECT '1&(2)'::query_int;
+ query_int
+-----------
+ 1 & 2
+(1 row)
+
+SELECT '!(1)&2'::query_int;
+ query_int
+-----------
+ !1 & 2
+(1 row)
+
+SELECT '!(1&2)'::query_int;
+ query_int
+------------
+ !( 1 & 2 )
+(1 row)
+
+SELECT '1|2&3'::query_int;
+ query_int
+-----------
+ 1 | 2 & 3
+(1 row)
+
+SELECT '1|(2&3)'::query_int;
+ query_int
+-----------
+ 1 | 2 & 3
+(1 row)
+
+SELECT '(1|2)&3'::query_int;
+ query_int
+---------------
+ ( 1 | 2 ) & 3
+(1 row)
+
+SELECT '1|2&!3'::query_int;
+ query_int
+------------
+ 1 | 2 & !3
+(1 row)
+
+SELECT '1|!2&3'::query_int;
+ query_int
+------------
+ 1 | !2 & 3
+(1 row)
+
+SELECT '!1|2&3'::query_int;
+ query_int
+------------
+ !1 | 2 & 3
+(1 row)
+
+SELECT '!1|(2&3)'::query_int;
+ query_int
+------------
+ !1 | 2 & 3
+(1 row)
+
+SELECT '!(1|2)&3'::query_int;
+ query_int
+----------------
+ !( 1 | 2 ) & 3
+(1 row)
+
+SELECT '(!1|2)&3'::query_int;
+ query_int
+----------------
+ ( !1 | 2 ) & 3
+(1 row)
+
+SELECT '1|(2|(4|(5|6)))'::query_int;
+ query_int
+-------------------------------
+ 1 | ( 2 | ( 4 | ( 5 | 6 ) ) )
+(1 row)
+
+SELECT '1|2|4|5|6'::query_int;
+ query_int
+-------------------------------
+ ( ( ( 1 | 2 ) | 4 ) | 5 ) | 6
+(1 row)
+
+SELECT '1&(2&(4&(5&6)))'::query_int;
+ query_int
+-------------------
+ 1 & 2 & 4 & 5 & 6
+(1 row)
+
+SELECT '1&2&4&5&6'::query_int;
+ query_int
+-------------------
+ 1 & 2 & 4 & 5 & 6
+(1 row)
+
+SELECT '1&(2&(4&(5|6)))'::query_int;
+ query_int
+-----------------------
+ 1 & 2 & 4 & ( 5 | 6 )
+(1 row)
+
+SELECT '1&(2&(4&(5|!6)))'::query_int;
+ query_int
+------------------------
+ 1 & 2 & 4 & ( 5 | !6 )
+(1 row)
+
+CREATE TABLE test__int( a int[] );
+\copy test__int from 'data/test__int.data'
+ANALYZE test__int;
+SELECT count(*) from test__int WHERE a && '{23,50}';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23|50';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23&50';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+ count
+-------
+ 10
+(1 row)
+
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+ count
+-------
+ 1
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '50&68';
+ count
+-------
+ 9
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+ count
+-------
+ 6566
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+ count
+-------
+ 6343
+(1 row)
+
+SET enable_seqscan = off; -- not all of these would use index by default
+CREATE INDEX text_idx on test__int using gist ( a gist__int_ops );
+SELECT count(*) from test__int WHERE a && '{23,50}';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23|50';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23&50';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+ count
+-------
+ 10
+(1 row)
+
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+ count
+-------
+ 1
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '50&68';
+ count
+-------
+ 9
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+ count
+-------
+ 6566
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+ count
+-------
+ 6343
+(1 row)
+
+DROP INDEX text_idx;
+CREATE INDEX text_idx on test__int using gist (a gist__int_ops(numranges = 0));
+ERROR: value 0 out of bounds for option "numranges"
+DETAIL: Valid values are between "1" and "252".
+CREATE INDEX text_idx on test__int using gist (a gist__int_ops(numranges = 253));
+ERROR: value 253 out of bounds for option "numranges"
+DETAIL: Valid values are between "1" and "252".
+CREATE INDEX text_idx on test__int using gist (a gist__int_ops(numranges = 252));
+SELECT count(*) from test__int WHERE a && '{23,50}';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23|50';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23&50';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+ count
+-------
+ 10
+(1 row)
+
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+ count
+-------
+ 1
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '50&68';
+ count
+-------
+ 9
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+ count
+-------
+ 6566
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+ count
+-------
+ 6343
+(1 row)
+
+DROP INDEX text_idx;
+CREATE INDEX text_idx on test__int using gist (a gist__intbig_ops(siglen = 0));
+ERROR: value 0 out of bounds for option "siglen"
+DETAIL: Valid values are between "1" and "2024".
+CREATE INDEX text_idx on test__int using gist (a gist__intbig_ops(siglen = 2025));
+ERROR: value 2025 out of bounds for option "siglen"
+DETAIL: Valid values are between "1" and "2024".
+CREATE INDEX text_idx on test__int using gist (a gist__intbig_ops(siglen = 2024));
+SELECT count(*) from test__int WHERE a && '{23,50}';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23|50';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23&50';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+ count
+-------
+ 10
+(1 row)
+
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+ count
+-------
+ 1
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '50&68';
+ count
+-------
+ 9
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+ count
+-------
+ 6566
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+ count
+-------
+ 6343
+(1 row)
+
+DROP INDEX text_idx;
+CREATE INDEX text_idx on test__int using gist ( a gist__intbig_ops );
+SELECT count(*) from test__int WHERE a && '{23,50}';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23|50';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23&50';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+ count
+-------
+ 10
+(1 row)
+
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+ count
+-------
+ 1
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '50&68';
+ count
+-------
+ 9
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+ count
+-------
+ 6566
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+ count
+-------
+ 6343
+(1 row)
+
+DROP INDEX text_idx;
+CREATE INDEX text_idx on test__int using gin ( a gin__int_ops );
+SELECT count(*) from test__int WHERE a && '{23,50}';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23|50';
+ count
+-------
+ 403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23&50';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+ count
+-------
+ 12
+(1 row)
+
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+ count
+-------
+ 10
+(1 row)
+
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+ count
+-------
+ 1
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '50&68';
+ count
+-------
+ 9
+(1 row)
+
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+ count
+-------
+ 21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+ count
+-------
+ 6566
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+ count
+-------
+ 6343
+(1 row)
+
+RESET enable_seqscan;
diff --git a/contrib/intarray/intarray--1.0--1.1.sql b/contrib/intarray/intarray--1.0--1.1.sql
new file mode 100644
index 0000000..fecebdd
--- /dev/null
+++ b/contrib/intarray/intarray--1.0--1.1.sql
@@ -0,0 +1,49 @@
+/* contrib/intarray/intarray--1.0--1.1.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "ALTER EXTENSION intarray UPDATE TO '1.1'" to load this file. \quit
+
+CREATE FUNCTION _int_matchsel(internal, oid, internal, integer)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE;
+
+ALTER OPERATOR @@ (_int4, query_int) SET (RESTRICT = _int_matchsel);
+ALTER OPERATOR ~~ (query_int, _int4) SET (RESTRICT = _int_matchsel);
+
+CREATE FUNCTION _int_overlap_sel(internal, oid, internal, integer)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE;
+
+CREATE FUNCTION _int_contains_sel(internal, oid, internal, integer)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE;
+
+CREATE FUNCTION _int_contained_sel(internal, oid, internal, integer)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE;
+
+CREATE FUNCTION _int_overlap_joinsel(internal, oid, internal, smallint, internal)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE;
+
+CREATE FUNCTION _int_contains_joinsel(internal, oid, internal, smallint, internal)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE;
+
+CREATE FUNCTION _int_contained_joinsel(internal, oid, internal, smallint, internal)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE;
+
+ALTER OPERATOR && (_int4, _int4) SET (RESTRICT = _int_overlap_sel, JOIN = _int_overlap_joinsel);
+ALTER OPERATOR @> (_int4, _int4) SET (RESTRICT = _int_contains_sel, JOIN = _int_contains_joinsel);
+ALTER OPERATOR <@ (_int4, _int4) SET (RESTRICT = _int_contained_sel, JOIN = _int_contained_joinsel);
+
+ALTER OPERATOR @ (_int4, _int4) SET (RESTRICT = _int_contains_sel, JOIN = _int_contains_joinsel);
+ALTER OPERATOR ~ (_int4, _int4) SET (RESTRICT = _int_contained_sel, JOIN = _int_contained_joinsel);
diff --git a/contrib/intarray/intarray--1.1--1.2.sql b/contrib/intarray/intarray--1.1--1.2.sql
new file mode 100644
index 0000000..919340e
--- /dev/null
+++ b/contrib/intarray/intarray--1.1--1.2.sql
@@ -0,0 +1,94 @@
+/* contrib/intarray/intarray--1.1--1.2.sql */
+
+-- complain if script is sourced in psql, rather than via ALTER EXTENSION
+\echo Use "ALTER EXTENSION intarray UPDATE TO '1.2'" to load this file. \quit
+
+-- Update procedure signatures the hard way.
+-- We use to_regprocedure() so that query doesn't fail if run against 9.6beta1 definitions,
+-- wherein the signatures have been updated already. In that case to_regprocedure() will
+-- return NULL and no updates will happen.
+DO LANGUAGE plpgsql
+$$
+DECLARE
+ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema());
+ old_path pg_catalog.text := pg_catalog.current_setting('search_path');
+BEGIN
+-- for safety, transiently set search_path to just pg_catalog+pg_temp
+PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true);
+
+UPDATE pg_catalog.pg_proc SET
+ proargtypes = pg_catalog.array_to_string(newtypes::pg_catalog.oid[], ' ')::pg_catalog.oidvector,
+ pronargs = pg_catalog.array_length(newtypes, 1)
+FROM (VALUES
+(NULL::pg_catalog.text, NULL::pg_catalog.text[]), -- establish column types
+('g_int_consistent(internal,_int4,int4,oid,internal)', '{internal,_int4,int2,oid,internal}'),
+('g_intbig_consistent(internal,internal,int4,oid,internal)', '{internal,_int4,int2,oid,internal}'),
+('g_intbig_same(internal,internal,internal)', '{SCH.intbig_gkey,SCH.intbig_gkey,internal}'),
+('ginint4_queryextract(internal,internal,int2,internal,internal,internal,internal)', '{_int4,internal,int2,internal,internal,internal,internal}'),
+('ginint4_consistent(internal,int2,internal,int4,internal,internal,internal,internal)', '{internal,int2,_int4,int4,internal,internal,internal,internal}')
+) AS update_data (oldproc, newtypestext),
+LATERAL (
+ SELECT array_agg(replace(typ, 'SCH', my_schema)::regtype) as newtypes FROM unnest(newtypestext) typ
+) ls
+WHERE oid = to_regprocedure(my_schema || '.' || replace(oldproc, 'SCH', my_schema));
+
+UPDATE pg_catalog.pg_proc SET
+ prorettype = (my_schema || '.intbig_gkey')::pg_catalog.regtype
+WHERE oid = pg_catalog.to_regprocedure(my_schema || '.g_intbig_union(internal,internal)');
+
+PERFORM pg_catalog.set_config('search_path', old_path, true);
+END
+$$;
+
+ALTER FUNCTION bqarr_in(cstring) PARALLEL SAFE;
+ALTER FUNCTION bqarr_out(query_int) PARALLEL SAFE;
+ALTER FUNCTION querytree(query_int) PARALLEL SAFE;
+ALTER FUNCTION boolop(_int4, query_int) PARALLEL SAFE;
+ALTER FUNCTION rboolop(query_int, _int4) PARALLEL SAFE;
+ALTER FUNCTION _int_matchsel(internal, oid, internal, integer) PARALLEL SAFE;
+ALTER FUNCTION _int_contains(_int4, _int4) PARALLEL SAFE;
+ALTER FUNCTION _int_contained(_int4, _int4) PARALLEL SAFE;
+ALTER FUNCTION _int_overlap(_int4, _int4) PARALLEL SAFE;
+ALTER FUNCTION _int_same(_int4, _int4) PARALLEL SAFE;
+ALTER FUNCTION _int_different(_int4, _int4) PARALLEL SAFE;
+ALTER FUNCTION _int_union(_int4, _int4) PARALLEL SAFE;
+ALTER FUNCTION _int_inter(_int4, _int4) PARALLEL SAFE;
+ALTER FUNCTION _int_overlap_sel(internal, oid, internal, integer) PARALLEL SAFE;
+ALTER FUNCTION _int_contains_sel(internal, oid, internal, integer) PARALLEL SAFE;
+ALTER FUNCTION _int_contained_sel(internal, oid, internal, integer) PARALLEL SAFE;
+ALTER FUNCTION _int_overlap_joinsel(internal, oid, internal, smallint, internal) PARALLEL SAFE;
+ALTER FUNCTION _int_contains_joinsel(internal, oid, internal, smallint, internal) PARALLEL SAFE;
+ALTER FUNCTION _int_contained_joinsel(internal, oid, internal, smallint, internal) PARALLEL SAFE;
+ALTER FUNCTION intset(int4) PARALLEL SAFE;
+ALTER FUNCTION icount(_int4) PARALLEL SAFE;
+ALTER FUNCTION sort(_int4, text) PARALLEL SAFE;
+ALTER FUNCTION sort(_int4) PARALLEL SAFE;
+ALTER FUNCTION sort_asc(_int4) PARALLEL SAFE;
+ALTER FUNCTION sort_desc(_int4) PARALLEL SAFE;
+ALTER FUNCTION uniq(_int4) PARALLEL SAFE;
+ALTER FUNCTION idx(_int4, int4) PARALLEL SAFE;
+ALTER FUNCTION subarray(_int4, int4, int4) PARALLEL SAFE;
+ALTER FUNCTION subarray(_int4, int4) PARALLEL SAFE;
+ALTER FUNCTION intarray_push_elem(_int4, int4) PARALLEL SAFE;
+ALTER FUNCTION intarray_push_array(_int4, _int4) PARALLEL SAFE;
+ALTER FUNCTION intarray_del_elem(_int4, int4) PARALLEL SAFE;
+ALTER FUNCTION intset_union_elem(_int4, int4) PARALLEL SAFE;
+ALTER FUNCTION intset_subtract(_int4, _int4) PARALLEL SAFE;
+ALTER FUNCTION g_int_consistent(internal, _int4, smallint, oid, internal) PARALLEL SAFE;
+ALTER FUNCTION g_int_compress(internal) PARALLEL SAFE;
+ALTER FUNCTION g_int_decompress(internal) PARALLEL SAFE;
+ALTER FUNCTION g_int_penalty(internal, internal, internal) PARALLEL SAFE;
+ALTER FUNCTION g_int_picksplit(internal, internal) PARALLEL SAFE;
+ALTER FUNCTION g_int_union(internal, internal) PARALLEL SAFE;
+ALTER FUNCTION g_int_same(_int4, _int4, internal) PARALLEL SAFE;
+ALTER FUNCTION _intbig_in(cstring) PARALLEL SAFE;
+ALTER FUNCTION _intbig_out(intbig_gkey) PARALLEL SAFE;
+ALTER FUNCTION g_intbig_consistent(internal, _int4, smallint, oid, internal) PARALLEL SAFE;
+ALTER FUNCTION g_intbig_compress(internal) PARALLEL SAFE;
+ALTER FUNCTION g_intbig_decompress(internal) PARALLEL SAFE;
+ALTER FUNCTION g_intbig_penalty(internal, internal, internal) PARALLEL SAFE;
+ALTER FUNCTION g_intbig_picksplit(internal, internal) PARALLEL SAFE;
+ALTER FUNCTION g_intbig_union(internal, internal) PARALLEL SAFE;
+ALTER FUNCTION g_intbig_same(intbig_gkey, intbig_gkey, internal) PARALLEL SAFE;
+ALTER FUNCTION ginint4_queryextract(_int4, internal, int2, internal, internal, internal, internal) PARALLEL SAFE;
+ALTER FUNCTION ginint4_consistent(internal, int2, _int4, int4, internal, internal, internal, internal) PARALLEL SAFE;
diff --git a/contrib/intarray/intarray--1.2--1.3.sql b/contrib/intarray/intarray--1.2--1.3.sql
new file mode 100644
index 0000000..790d159
--- /dev/null
+++ b/contrib/intarray/intarray--1.2--1.3.sql
@@ -0,0 +1,20 @@
+/* contrib/intarray/intarray--1.2--1.3.sql */
+
+-- complain if script is sourced in psql, rather than via ALTER EXTENSION
+\echo Use "ALTER EXTENSION intarray UPDATE TO '1.3'" to load this file. \quit
+
+CREATE FUNCTION g_int_options(internal)
+RETURNS void
+AS 'MODULE_PATHNAME', 'g_int_options'
+LANGUAGE C IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION g_intbig_options(internal)
+RETURNS void
+AS 'MODULE_PATHNAME', 'g_intbig_options'
+LANGUAGE C IMMUTABLE PARALLEL SAFE;
+
+ALTER OPERATOR FAMILY gist__int_ops USING gist
+ADD FUNCTION 10 (_int4) g_int_options (internal);
+
+ALTER OPERATOR FAMILY gist__intbig_ops USING gist
+ADD FUNCTION 10 (_int4) g_intbig_options (internal);
diff --git a/contrib/intarray/intarray--1.2.sql b/contrib/intarray/intarray--1.2.sql
new file mode 100644
index 0000000..f10b53d
--- /dev/null
+++ b/contrib/intarray/intarray--1.2.sql
@@ -0,0 +1,520 @@
+/* contrib/intarray/intarray--1.2.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION intarray" to load this file. \quit
+
+--
+-- Create the user-defined type for the 1-D integer arrays (_int4)
+--
+
+-- Query type
+CREATE FUNCTION bqarr_in(cstring)
+RETURNS query_int
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION bqarr_out(query_int)
+RETURNS cstring
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE TYPE query_int (
+ INTERNALLENGTH = -1,
+ INPUT = bqarr_in,
+ OUTPUT = bqarr_out
+);
+
+--only for debug
+CREATE FUNCTION querytree(query_int)
+RETURNS text
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+
+CREATE FUNCTION boolop(_int4, query_int)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+COMMENT ON FUNCTION boolop(_int4, query_int) IS 'boolean operation with array';
+
+CREATE FUNCTION rboolop(query_int, _int4)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+COMMENT ON FUNCTION rboolop(query_int, _int4) IS 'boolean operation with array';
+
+CREATE FUNCTION _int_matchsel(internal, oid, internal, integer)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
+CREATE OPERATOR @@ (
+ LEFTARG = _int4,
+ RIGHTARG = query_int,
+ PROCEDURE = boolop,
+ COMMUTATOR = '~~',
+ RESTRICT = _int_matchsel,
+ JOIN = contjoinsel
+);
+
+CREATE OPERATOR ~~ (
+ LEFTARG = query_int,
+ RIGHTARG = _int4,
+ PROCEDURE = rboolop,
+ COMMUTATOR = '@@',
+ RESTRICT = _int_matchsel,
+ JOIN = contjoinsel
+);
+
+
+--
+-- External C-functions for R-tree methods
+--
+
+-- Comparison methods
+
+CREATE FUNCTION _int_contains(_int4, _int4)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+COMMENT ON FUNCTION _int_contains(_int4, _int4) IS 'contains';
+
+CREATE FUNCTION _int_contained(_int4, _int4)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+COMMENT ON FUNCTION _int_contained(_int4, _int4) IS 'contained in';
+
+CREATE FUNCTION _int_overlap(_int4, _int4)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+COMMENT ON FUNCTION _int_overlap(_int4, _int4) IS 'overlaps';
+
+CREATE FUNCTION _int_same(_int4, _int4)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+COMMENT ON FUNCTION _int_same(_int4, _int4) IS 'same as';
+
+CREATE FUNCTION _int_different(_int4, _int4)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+COMMENT ON FUNCTION _int_different(_int4, _int4) IS 'different';
+
+-- support routines for indexing
+
+CREATE FUNCTION _int_union(_int4, _int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION _int_inter(_int4, _int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION _int_overlap_sel(internal, oid, internal, integer)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
+CREATE FUNCTION _int_contains_sel(internal, oid, internal, integer)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
+CREATE FUNCTION _int_contained_sel(internal, oid, internal, integer)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
+CREATE FUNCTION _int_overlap_joinsel(internal, oid, internal, smallint, internal)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
+CREATE FUNCTION _int_contains_joinsel(internal, oid, internal, smallint, internal)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
+CREATE FUNCTION _int_contained_joinsel(internal, oid, internal, smallint, internal)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
+--
+-- OPERATORS
+--
+
+CREATE OPERATOR && (
+ LEFTARG = _int4,
+ RIGHTARG = _int4,
+ PROCEDURE = _int_overlap,
+ COMMUTATOR = '&&',
+ RESTRICT = _int_overlap_sel,
+ JOIN = _int_overlap_joinsel
+);
+
+--CREATE OPERATOR = (
+-- LEFTARG = _int4,
+-- RIGHTARG = _int4,
+-- PROCEDURE = _int_same,
+-- COMMUTATOR = '=',
+-- NEGATOR = '<>',
+-- RESTRICT = eqsel,
+-- JOIN = eqjoinsel,
+-- SORT1 = '<',
+-- SORT2 = '<'
+--);
+
+--CREATE OPERATOR <> (
+-- LEFTARG = _int4,
+-- RIGHTARG = _int4,
+-- PROCEDURE = _int_different,
+-- COMMUTATOR = '<>',
+-- NEGATOR = '=',
+-- RESTRICT = neqsel,
+-- JOIN = neqjoinsel
+--);
+
+CREATE OPERATOR @> (
+ LEFTARG = _int4,
+ RIGHTARG = _int4,
+ PROCEDURE = _int_contains,
+ COMMUTATOR = '<@',
+ RESTRICT = _int_contains_sel,
+ JOIN = _int_contains_joinsel
+);
+
+CREATE OPERATOR <@ (
+ LEFTARG = _int4,
+ RIGHTARG = _int4,
+ PROCEDURE = _int_contained,
+ COMMUTATOR = '@>',
+ RESTRICT = _int_contained_sel,
+ JOIN = _int_contained_joinsel
+);
+
+-- obsolete:
+CREATE OPERATOR @ (
+ LEFTARG = _int4,
+ RIGHTARG = _int4,
+ PROCEDURE = _int_contains,
+ COMMUTATOR = '~',
+ RESTRICT = _int_contains_sel,
+ JOIN = _int_contains_joinsel
+);
+
+CREATE OPERATOR ~ (
+ LEFTARG = _int4,
+ RIGHTARG = _int4,
+ PROCEDURE = _int_contained,
+ COMMUTATOR = '@',
+ RESTRICT = _int_contained_sel,
+ JOIN = _int_contained_joinsel
+);
+
+--------------
+CREATE FUNCTION intset(int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION icount(_int4)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE OPERATOR # (
+ RIGHTARG = _int4,
+ PROCEDURE = icount
+);
+
+CREATE FUNCTION sort(_int4, text)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION sort(_int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION sort_asc(_int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION sort_desc(_int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION uniq(_int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION idx(_int4, int4)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE OPERATOR # (
+ LEFTARG = _int4,
+ RIGHTARG = int4,
+ PROCEDURE = idx
+);
+
+CREATE FUNCTION subarray(_int4, int4, int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION subarray(_int4, int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION intarray_push_elem(_int4, int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE OPERATOR + (
+ LEFTARG = _int4,
+ RIGHTARG = int4,
+ PROCEDURE = intarray_push_elem
+);
+
+CREATE FUNCTION intarray_push_array(_int4, _int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE OPERATOR + (
+ LEFTARG = _int4,
+ RIGHTARG = _int4,
+ COMMUTATOR = +,
+ PROCEDURE = intarray_push_array
+);
+
+CREATE FUNCTION intarray_del_elem(_int4, int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE OPERATOR - (
+ LEFTARG = _int4,
+ RIGHTARG = int4,
+ PROCEDURE = intarray_del_elem
+);
+
+CREATE FUNCTION intset_union_elem(_int4, int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE OPERATOR | (
+ LEFTARG = _int4,
+ RIGHTARG = int4,
+ PROCEDURE = intset_union_elem
+);
+
+CREATE OPERATOR | (
+ LEFTARG = _int4,
+ RIGHTARG = _int4,
+ COMMUTATOR = |,
+ PROCEDURE = _int_union
+);
+
+CREATE FUNCTION intset_subtract(_int4, _int4)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE OPERATOR - (
+ LEFTARG = _int4,
+ RIGHTARG = _int4,
+ PROCEDURE = intset_subtract
+);
+
+CREATE OPERATOR & (
+ LEFTARG = _int4,
+ RIGHTARG = _int4,
+ COMMUTATOR = &,
+ PROCEDURE = _int_inter
+);
+--------------
+
+-- define the GiST support methods
+CREATE FUNCTION g_int_consistent(internal,_int4,smallint,oid,internal)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_int_compress(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_int_decompress(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_int_penalty(internal,internal,internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_int_picksplit(internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_int_union(internal, internal)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_int_same(_int4, _int4, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+
+-- Create the operator class for indexing
+
+CREATE OPERATOR CLASS gist__int_ops
+DEFAULT FOR TYPE _int4 USING gist AS
+ OPERATOR 3 &&,
+ OPERATOR 6 = (anyarray, anyarray),
+ OPERATOR 7 @>,
+ OPERATOR 8 <@,
+ OPERATOR 13 @,
+ OPERATOR 14 ~,
+ OPERATOR 20 @@ (_int4, query_int),
+ FUNCTION 1 g_int_consistent (internal, _int4, smallint, oid, internal),
+ FUNCTION 2 g_int_union (internal, internal),
+ FUNCTION 3 g_int_compress (internal),
+ FUNCTION 4 g_int_decompress (internal),
+ FUNCTION 5 g_int_penalty (internal, internal, internal),
+ FUNCTION 6 g_int_picksplit (internal, internal),
+ FUNCTION 7 g_int_same (_int4, _int4, internal);
+
+
+---------------------------------------------
+-- intbig
+---------------------------------------------
+-- define the GiST support methods
+
+CREATE FUNCTION _intbig_in(cstring)
+RETURNS intbig_gkey
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION _intbig_out(intbig_gkey)
+RETURNS cstring
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE TYPE intbig_gkey (
+ INTERNALLENGTH = -1,
+ INPUT = _intbig_in,
+ OUTPUT = _intbig_out
+);
+
+CREATE FUNCTION g_intbig_consistent(internal,_int4,smallint,oid,internal)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_intbig_compress(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_intbig_decompress(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_intbig_penalty(internal,internal,internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_intbig_picksplit(internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_intbig_union(internal, internal)
+RETURNS intbig_gkey
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION g_intbig_same(intbig_gkey, intbig_gkey, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+-- register the opclass for indexing (not as default)
+
+CREATE OPERATOR CLASS gist__intbig_ops
+FOR TYPE _int4 USING gist
+AS
+ OPERATOR 3 &&,
+ OPERATOR 6 = (anyarray, anyarray),
+ OPERATOR 7 @>,
+ OPERATOR 8 <@,
+ OPERATOR 13 @,
+ OPERATOR 14 ~,
+ OPERATOR 20 @@ (_int4, query_int),
+ FUNCTION 1 g_intbig_consistent (internal, _int4, smallint, oid, internal),
+ FUNCTION 2 g_intbig_union (internal, internal),
+ FUNCTION 3 g_intbig_compress (internal),
+ FUNCTION 4 g_intbig_decompress (internal),
+ FUNCTION 5 g_intbig_penalty (internal, internal, internal),
+ FUNCTION 6 g_intbig_picksplit (internal, internal),
+ FUNCTION 7 g_intbig_same (intbig_gkey, intbig_gkey, internal),
+ STORAGE intbig_gkey;
+
+--GIN
+
+CREATE FUNCTION ginint4_queryextract(_int4, internal, int2, internal, internal, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION ginint4_consistent(internal, int2, _int4, int4, internal, internal, internal, internal)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE OPERATOR CLASS gin__int_ops
+FOR TYPE _int4 USING gin
+AS
+ OPERATOR 3 &&,
+ OPERATOR 6 = (anyarray, anyarray),
+ OPERATOR 7 @>,
+ OPERATOR 8 <@,
+ OPERATOR 13 @,
+ OPERATOR 14 ~,
+ OPERATOR 20 @@ (_int4, query_int),
+ FUNCTION 1 btint4cmp (int4, int4),
+ FUNCTION 2 ginarrayextract (anyarray, internal, internal),
+ FUNCTION 3 ginint4_queryextract (_int4, internal, int2, internal, internal, internal, internal),
+ FUNCTION 4 ginint4_consistent (internal, int2, _int4, int4, internal, internal, internal, internal),
+ STORAGE int4;
diff --git a/contrib/intarray/intarray.control b/contrib/intarray/intarray.control
new file mode 100644
index 0000000..db7746b
--- /dev/null
+++ b/contrib/intarray/intarray.control
@@ -0,0 +1,6 @@
+# intarray extension
+comment = 'functions, operators, and index support for 1-D arrays of integers'
+default_version = '1.3'
+module_pathname = '$libdir/_int'
+relocatable = true
+trusted = true
diff --git a/contrib/intarray/sql/_int.sql b/contrib/intarray/sql/_int.sql
new file mode 100644
index 0000000..b26fc57
--- /dev/null
+++ b/contrib/intarray/sql/_int.sql
@@ -0,0 +1,181 @@
+CREATE EXTENSION intarray;
+
+-- Check whether any of our opclasses fail amvalidate
+SELECT amname, opcname
+FROM pg_opclass opc LEFT JOIN pg_am am ON am.oid = opcmethod
+WHERE opc.oid >= 16384 AND NOT amvalidate(opc.oid);
+
+SELECT intset(1234);
+SELECT icount('{1234234,234234}');
+SELECT sort('{1234234,-30,234234}');
+SELECT sort('{1234234,-30,234234}','asc');
+SELECT sort('{1234234,-30,234234}','desc');
+SELECT sort_asc('{1234234,-30,234234}');
+SELECT sort_desc('{1234234,-30,234234}');
+SELECT uniq('{1234234,-30,-30,234234,-30}');
+SELECT uniq(sort_asc('{1234234,-30,-30,234234,-30}'));
+SELECT idx('{1234234,-30,-30,234234,-30}',-30);
+SELECT subarray('{1234234,-30,-30,234234,-30}',2,3);
+SELECT subarray('{1234234,-30,-30,234234,-30}',-1,1);
+SELECT subarray('{1234234,-30,-30,234234,-30}',0,-1);
+
+SELECT #'{1234234,234234}'::int[];
+SELECT '{123,623,445}'::int[] + 1245;
+SELECT '{123,623,445}'::int[] + 445;
+SELECT '{123,623,445}'::int[] + '{1245,87,445}';
+SELECT '{123,623,445}'::int[] - 623;
+SELECT '{123,623,445}'::int[] - '{1623,623}';
+SELECT '{123,623,445}'::int[] | 623;
+SELECT '{123,623,445}'::int[] | 1623;
+SELECT '{123,623,445}'::int[] | '{1623,623}';
+SELECT '{123,623,445}'::int[] & '{1623,623}';
+SELECT '{-1,3,1}'::int[] & '{1,2}';
+SELECT '{1}'::int[] & '{2}'::int[];
+SELECT array_dims('{1}'::int[] & '{2}'::int[]);
+SELECT ('{1}'::int[] & '{2}'::int[]) = '{}'::int[];
+SELECT ('{}'::int[] & '{}'::int[]) = '{}'::int[];
+
+
+--test query_int
+SELECT '1'::query_int;
+SELECT ' 1'::query_int;
+SELECT '1 '::query_int;
+SELECT ' 1 '::query_int;
+SELECT ' ! 1 '::query_int;
+SELECT '!1'::query_int;
+SELECT '1|2'::query_int;
+SELECT '1|!2'::query_int;
+SELECT '!1|2'::query_int;
+SELECT '!1|!2'::query_int;
+SELECT '!(!1|!2)'::query_int;
+SELECT '!(!1|2)'::query_int;
+SELECT '!(1|!2)'::query_int;
+SELECT '!(1|2)'::query_int;
+SELECT '1&2'::query_int;
+SELECT '!1&2'::query_int;
+SELECT '1&!2'::query_int;
+SELECT '!1&!2'::query_int;
+SELECT '(1&2)'::query_int;
+SELECT '1&(2)'::query_int;
+SELECT '!(1)&2'::query_int;
+SELECT '!(1&2)'::query_int;
+SELECT '1|2&3'::query_int;
+SELECT '1|(2&3)'::query_int;
+SELECT '(1|2)&3'::query_int;
+SELECT '1|2&!3'::query_int;
+SELECT '1|!2&3'::query_int;
+SELECT '!1|2&3'::query_int;
+SELECT '!1|(2&3)'::query_int;
+SELECT '!(1|2)&3'::query_int;
+SELECT '(!1|2)&3'::query_int;
+SELECT '1|(2|(4|(5|6)))'::query_int;
+SELECT '1|2|4|5|6'::query_int;
+SELECT '1&(2&(4&(5&6)))'::query_int;
+SELECT '1&2&4&5&6'::query_int;
+SELECT '1&(2&(4&(5|6)))'::query_int;
+SELECT '1&(2&(4&(5|!6)))'::query_int;
+
+
+CREATE TABLE test__int( a int[] );
+\copy test__int from 'data/test__int.data'
+ANALYZE test__int;
+
+SELECT count(*) from test__int WHERE a && '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23|50';
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23&50';
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+SELECT count(*) from test__int WHERE a @@ '50&68';
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+
+SET enable_seqscan = off; -- not all of these would use index by default
+
+CREATE INDEX text_idx on test__int using gist ( a gist__int_ops );
+
+SELECT count(*) from test__int WHERE a && '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23|50';
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23&50';
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+SELECT count(*) from test__int WHERE a @@ '50&68';
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+
+DROP INDEX text_idx;
+CREATE INDEX text_idx on test__int using gist (a gist__int_ops(numranges = 0));
+CREATE INDEX text_idx on test__int using gist (a gist__int_ops(numranges = 253));
+CREATE INDEX text_idx on test__int using gist (a gist__int_ops(numranges = 252));
+
+SELECT count(*) from test__int WHERE a && '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23|50';
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23&50';
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+SELECT count(*) from test__int WHERE a @@ '50&68';
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+
+DROP INDEX text_idx;
+CREATE INDEX text_idx on test__int using gist (a gist__intbig_ops(siglen = 0));
+CREATE INDEX text_idx on test__int using gist (a gist__intbig_ops(siglen = 2025));
+CREATE INDEX text_idx on test__int using gist (a gist__intbig_ops(siglen = 2024));
+
+SELECT count(*) from test__int WHERE a && '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23|50';
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23&50';
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+SELECT count(*) from test__int WHERE a @@ '50&68';
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+
+DROP INDEX text_idx;
+CREATE INDEX text_idx on test__int using gist ( a gist__intbig_ops );
+
+SELECT count(*) from test__int WHERE a && '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23|50';
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23&50';
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+SELECT count(*) from test__int WHERE a @@ '50&68';
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+
+DROP INDEX text_idx;
+CREATE INDEX text_idx on test__int using gin ( a gin__int_ops );
+
+SELECT count(*) from test__int WHERE a && '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23|50';
+SELECT count(*) from test__int WHERE a @> '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23&50';
+SELECT count(*) from test__int WHERE a @> '{20,23}';
+SELECT count(*) from test__int WHERE a <@ '{73,23,20}';
+SELECT count(*) from test__int WHERE a = '{73,23,20}';
+SELECT count(*) from test__int WHERE a @@ '50&68';
+SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+SELECT count(*) from test__int WHERE a @@ '20 | !21';
+SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+
+RESET enable_seqscan;