1.0 version
authorTeodor Sigaev <teodor@sigaev.ru>
Wed, 25 Apr 2012 16:23:49 +0000 (20:23 +0400)
committerTeodor Sigaev <teodor@sigaev.ru>
Wed, 25 Apr 2012 16:23:49 +0000 (20:23 +0400)
85 files changed:
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
expected/bit.out [new file with mode: 0644]
expected/bytea.out [new file with mode: 0644]
expected/char.out [new file with mode: 0644]
expected/cidr.out [new file with mode: 0644]
expected/composite_int4.out [new file with mode: 0644]
expected/composite_text.out [new file with mode: 0644]
expected/date.out [new file with mode: 0644]
expected/float4.out [new file with mode: 0644]
expected/float8.out [new file with mode: 0644]
expected/inet.out [new file with mode: 0644]
expected/int2.out [new file with mode: 0644]
expected/int4.out [new file with mode: 0644]
expected/int4g.out [new file with mode: 0644]
expected/int4i.out [new file with mode: 0644]
expected/int8.out [new file with mode: 0644]
expected/int8g.out [new file with mode: 0644]
expected/int8i.out [new file with mode: 0644]
expected/interval.out [new file with mode: 0644]
expected/intervalg.out [new file with mode: 0644]
expected/intervali.out [new file with mode: 0644]
expected/macaddr.out [new file with mode: 0644]
expected/money.out [new file with mode: 0644]
expected/numeric.out [new file with mode: 0644]
expected/oid.out [new file with mode: 0644]
expected/smlar.out [new file with mode: 0644]
expected/text.out [new file with mode: 0644]
expected/textg.out [new file with mode: 0644]
expected/texti.out [new file with mode: 0644]
expected/time.out [new file with mode: 0644]
expected/timestamp.out [new file with mode: 0644]
expected/timestamptz.out [new file with mode: 0644]
expected/timetz.out [new file with mode: 0644]
expected/varbit.out [new file with mode: 0644]
expected/varchar.out [new file with mode: 0644]
smlar--1.0.sql [new file with mode: 0644]
smlar--unpackaged--1.0.sql [new file with mode: 0644]
smlar.c [new file with mode: 0644]
smlar.control [new file with mode: 0644]
smlar.h [new file with mode: 0644]
smlar.sql.in.in [new file with mode: 0644]
smlar_cache.c [new file with mode: 0644]
smlar_gin.c [new file with mode: 0644]
smlar_gist.c [new file with mode: 0644]
smlar_guc.c [new file with mode: 0644]
smlar_stat.c [new file with mode: 0644]
sql/bit.sql [new file with mode: 0644]
sql/bytea.sql [new file with mode: 0644]
sql/char.sql [new file with mode: 0644]
sql/cidr.sql [new file with mode: 0644]
sql/composite_int4.sql [new file with mode: 0644]
sql/composite_text.sql [new file with mode: 0644]
sql/date.sql [new file with mode: 0644]
sql/float4.sql [new file with mode: 0644]
sql/float8.sql [new file with mode: 0644]
sql/inet.sql [new file with mode: 0644]
sql/int2.sql [new file with mode: 0644]
sql/int4.sql [new file with mode: 0644]
sql/int4g.sql [new file with mode: 0644]
sql/int4i.sql [new file with mode: 0644]
sql/int8.sql [new file with mode: 0644]
sql/int8g.sql [new file with mode: 0644]
sql/int8i.sql [new file with mode: 0644]
sql/int8n.sql [new file with mode: 0644]
sql/interval.sql [new file with mode: 0644]
sql/intervalg.sql [new file with mode: 0644]
sql/intervali.sql [new file with mode: 0644]
sql/intervaln.sql [new file with mode: 0644]
sql/macaddr.sql [new file with mode: 0644]
sql/money.sql [new file with mode: 0644]
sql/numeric.sql [new file with mode: 0644]
sql/oid.sql [new file with mode: 0644]
sql/smlar.sql [new file with mode: 0644]
sql/text.sql [new file with mode: 0644]
sql/textg.sql [new file with mode: 0644]
sql/texti.sql [new file with mode: 0644]
sql/textn.sql [new file with mode: 0644]
sql/time.sql [new file with mode: 0644]
sql/timestamp.sql [new file with mode: 0644]
sql/timestamptz.sql [new file with mode: 0644]
sql/timetz.sql [new file with mode: 0644]
sql/varbit.sql [new file with mode: 0644]
sql/varchar.sql [new file with mode: 0644]
tsarr.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..20d5541
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,26 @@
+
+MODULE_big = smlar
+OBJS = smlar.o smlar_gist.o smlar_gin.o smlar_cache.o \
+               tsarr.o smlar_guc.o smlar_stat.o 
+
+EXTENSION = smlar
+DATA = smlar--1.0.sql  smlar--unpackaged--1.0.sql
+REGRESS = smlar int2 int4 int8 float4 float8 money oid \
+               timestamp timestamptz time timetz date interval \
+               macaddr inet cidr \
+               text varchar char bytea bit varbit numeric \
+               int4g int8g intervalg textg \
+               int4i int8i intervali texti \
+               composite_int4 composite_text
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/smlar
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..8fa81c5
--- /dev/null
+++ b/README
@@ -0,0 +1,116 @@
+float4 smlar(anyarray, anyarray)
+       - computes similary of two arrays. Arrays should be the same type.
+
+float4 smlar(anyarray, anyarray, bool useIntersect)
+       -  computes similary of two arrays of composite types. Composite type looks like:
+               CREATE TYPE type_name AS (element_name anytype, weight_name FLOAT4);
+          useIntersect option points to use only intersected elements in denominator
+          see an exmaples in sql/composite_int4.sql or sql/composite_text.sql
+
+float4 smlar( anyarray a, anyarray b, text formula );
+       - computes similary of two arrays by given formula, arrays should 
+       be the same type. 
+       Predefined variables in formula:
+         N.i   - number of common elements in both array (intersection)
+         N.a   - number of uniqueelements in first array
+         N.b   - number of uniqueelements in second array
+       Example:
+       smlar('{1,4,6}'::int[], '{5,4,6}' )
+       smlar('{1,4,6}'::int[], '{5,4,6}', 'N.i / sqrt(N.a * N.b)' )
+       That calls are equivalent.
+
+anyarray % anyarray
+       - returns true if similarity of that arrays is greater than limit
+
+float4 show_smlar_limit()  - deprecated
+       - shows the limit for % operation
+
+float4 set_smlar_limit(float4) - deprecated
+       - sets the limit for % operation
+
+Use instead of show_smlar_limit/set_smlar_limit GUC variable 
+smlar.threshold (see below)
+
+
+text[] tsvector2textarray(tsvector)
+       - transforms tsvector type to text array
+
+anyarray array_unique(anyarray)
+       - sort and unique array
+
+float4 inarray(anyarray, anyelement)
+       - returns zero if second argument does not present in a first one
+         and 1.0 in opposite case
+
+float4 inarray(anyarray, anyelement, float4, float4)
+       - returns fourth argument if second argument does not present in 
+         a first one and third argument in opposite case
+
+GUC configuration variables:
+
+smlar.threshold  FLOAT
+       Array's with similarity lower than threshold are not similar 
+       by % operation
+
+smlar.persistent_cache BOOL
+       Cache of global stat is stored in transaction-independent memory
+
+smlar.type  STRING
+       Type of similarity formula: cosine(default), tfidf, overlap
+
+smlar.stattable        STRING
+       Name of table stored set-wide statistic. Table should be 
+       defined as
+       CREATE TABLE table_name (
+               value   data_type UNIQUE,
+               ndoc    int4 (or bigint)  NOT NULL CHECK (ndoc>0)
+       );
+       And row with null value means total number of documents.
+       See an examples in sql/*g.sql files
+       Note: used on for smlar.type = 'tfidf'
+
+smlar.tf_method STRING
+       Calculation method for term frequency. Values:
+               "n"     - simple counting of entries (default)
+               "log"   - 1 + log(n)
+               "const" - TF is equal to 1
+       Note: used on for smlar.type = 'tfidf'
+
+smlar.idf_plus_one BOOL
+       If false (default), calculate idf as log(d/df),
+       if true - as log(1+d/df)
+       Note: used on for smlar.type = 'tfidf'
+
+Module provides several GUC variables smlar.threshold, it's highly
+recommended to add to postgesql.conf:
+custom_variable_classes = 'smlar'       # list of custom variable class names
+smlar.threshold = 0.6  #or any other value > 0 and < 1
+and other smlar.* variables
+
+GiST/GIN support for % and  && operations for:
+  Array Type   |  GIN operator class  | GiST operator class  
+---------------+----------------------+----------------------
+ bit[]         | _bit_sml_ops         | 
+ bytea[]       | _bytea_sml_ops       | _bytea_sml_ops
+ char[]        | _char_sml_ops        | _char_sml_ops
+ cidr[]        | _cidr_sml_ops        | _cidr_sml_ops
+ date[]        | _date_sml_ops        | _date_sml_ops
+ float4[]      | _float4_sml_ops      | _float4_sml_ops
+ float8[]      | _float8_sml_ops      | _float8_sml_ops
+ inet[]        | _inet_sml_ops        | _inet_sml_ops
+ int2[]        | _int2_sml_ops        | _int2_sml_ops
+ int4[]        | _int4_sml_ops        | _int4_sml_ops
+ int8[]        | _int8_sml_ops        | _int8_sml_ops
+ interval[]    | _interval_sml_ops    | _interval_sml_ops
+ macaddr[]     | _macaddr_sml_ops     | _macaddr_sml_ops
+ money[]       | _money_sml_ops       | 
+ numeric[]     | _numeric_sml_ops     | _numeric_sml_ops
+ oid[]         | _oid_sml_ops         | _oid_sml_ops
+ text[]        | _text_sml_ops        | _text_sml_ops
+ time[]        | _time_sml_ops        | _time_sml_ops
+ timestamp[]   | _timestamp_sml_ops   | _timestamp_sml_ops
+ timestamptz[] | _timestamptz_sml_ops | _timestamptz_sml_ops
+ timetz[]      | _timetz_sml_ops      | _timetz_sml_ops
+ varbit[]      | _varbit_sml_ops      | 
+ varchar[]     | _varchar_sml_ops     | _varchar_sml_ops
+
diff --git a/expected/bit.out b/expected/bit.out
new file mode 100644 (file)
index 0000000..980cbaf
--- /dev/null
@@ -0,0 +1,104 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::int4::bit(10)
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_bit
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]) AS s FROM test_bit WHERE v % '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]) AS s FROM test_bit WHERE v % '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_bit ON test_bit USING gin (v _bit_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]) AS s FROM test_bit WHERE v % '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]) AS s FROM test_bit WHERE v % '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/bytea.out b/expected/bytea.out
new file mode 100644 (file)
index 0000000..6e98885
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::text::bytea
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_bytea
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_bytea WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_bytea WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_bytea ON test_bytea USING gist (v _bytea_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_bytea WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_bytea WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_bytea;
+CREATE INDEX idx_test_bytea ON test_bytea USING gin (v _bytea_sml_ops);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_bytea WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_bytea WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/char.out b/expected/char.out
new file mode 100644 (file)
index 0000000..b754250
--- /dev/null
@@ -0,0 +1,58 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::varchar(1)::"char"
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_char
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{3,2,1}') AS s FROM test_char WHERE v % '{3,2,1}' ORDER BY s DESC, t;
+ t |    s     
+---+----------
+ 3 |        1
+ 4 | 0.866025
+ 2 | 0.816497
+ 5 | 0.774597
+ 6 | 0.707107
+ 7 | 0.654654
+ 8 | 0.612372
+(7 rows)
+
+CREATE INDEX idx_test_char ON test_char USING gist (v _char_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{3,2,1}') AS s FROM test_char WHERE v % '{3,2,1}' ORDER BY s DESC, t;
+ t |    s     
+---+----------
+ 3 |        1
+ 4 | 0.866025
+ 2 | 0.816497
+ 5 | 0.774597
+ 6 | 0.707107
+ 7 | 0.654654
+ 8 | 0.612372
+(7 rows)
+
+DROP INDEX idx_test_char;
+CREATE INDEX idx_test_char ON test_char USING gin (v _char_sml_ops);
+SELECT  t, smlar(v, '{3,2,1}') AS s FROM test_char WHERE v % '{3,2,1}' ORDER BY s DESC, t;
+ t |    s     
+---+----------
+ 3 |        1
+ 4 | 0.866025
+ 2 | 0.816497
+ 5 | 0.774597
+ 6 | 0.707107
+ 7 | 0.654654
+ 8 | 0.612372
+(7 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/cidr.out b/expected/cidr.out
new file mode 100644 (file)
index 0000000..38d1ad4
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       ( '192.168.1.' || (v % 256) )::cidr
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_cidr
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_cidr ON test_cidr USING gist (v _cidr_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_cidr;
+CREATE INDEX idx_test_cidr ON test_cidr USING gin (v _cidr_sml_ops);
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/composite_int4.out b/expected/composite_int4.out
new file mode 100644 (file)
index 0000000..fc1d243
--- /dev/null
@@ -0,0 +1,541 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+CREATE TYPE cint AS (id int, w float4);
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       (ROW(v::int4, v::float4))::cint
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_composite_int4
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[]) AS s 
+       FROM test_composite_int4 
+       WHERE v % '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[] AS s 
+       FROM test_composite_int4 
+       WHERE v % '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[]) ORDER BY s DESC, t;
+ERROR:  syntax error at or near "AS"
+LINE 1: ..."(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[] AS s 
+                                                                  ^
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[]) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[]) > 0.6 ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[]) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[]) > 0.6 ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[], false) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[], false) > 0.6 ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 | 0.886405
+  9 | 0.842927
+  8 | 0.797053
+ 11 | 0.773192
+  7 | 0.748331
+  6 | 0.696143
+ 12 | 0.682191
+  5 | 0.639602
+ 13 | 0.607744
+(9 rows)
+
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[], false) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[], false) > 0.6 ORDER BY s DESC, t;
+ t |    s     
+---+----------
+ 8 | 0.730632
+ 7 | 0.668153
+ 9 | 0.618147
+(3 rows)
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[], true) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[], true) > 0.6 ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   1 |        1
+   2 | 0.948683
+   3 |  0.92582
+   4 | 0.912871
+   5 | 0.904534
+   6 | 0.898717
+   7 | 0.894427
+   8 | 0.891133
+   9 | 0.888523
+  10 | 0.886405
+  11 | 0.886405
+  12 | 0.886405
+  13 | 0.886405
+  14 | 0.886405
+  15 | 0.886405
+  16 | 0.886405
+  17 | 0.886405
+  18 | 0.886405
+  19 | 0.886405
+  20 | 0.886405
+  21 | 0.886405
+  22 | 0.886405
+  23 | 0.886405
+  24 | 0.886405
+  25 | 0.886405
+  26 | 0.886405
+  27 | 0.886405
+  28 | 0.886405
+  29 | 0.886405
+  30 | 0.886405
+  31 | 0.886405
+  32 | 0.886405
+  33 | 0.886405
+  34 | 0.886405
+  35 | 0.886405
+  36 | 0.886405
+  37 | 0.886405
+  38 | 0.886405
+  39 | 0.886405
+  40 | 0.886405
+  41 | 0.886405
+  42 | 0.886405
+  43 | 0.886405
+  44 | 0.886405
+  45 | 0.886405
+  46 | 0.886405
+  47 | 0.886405
+  48 | 0.886405
+  49 | 0.886405
+  50 | 0.886405
+  51 | 0.886405
+  52 | 0.886405
+  53 | 0.886405
+  54 | 0.886405
+  55 | 0.886405
+  56 | 0.886405
+  57 | 0.886405
+  58 | 0.886405
+  59 | 0.886405
+  60 | 0.886405
+  61 | 0.886405
+  62 | 0.886405
+  63 | 0.886405
+  64 | 0.886405
+  65 | 0.886405
+  66 | 0.886405
+  67 | 0.886405
+  68 | 0.886405
+  69 | 0.886405
+  70 | 0.886405
+  71 | 0.886405
+  72 | 0.886405
+  73 | 0.886405
+  74 | 0.886405
+  75 | 0.886405
+  76 | 0.886405
+  77 | 0.886405
+  78 | 0.886405
+  79 | 0.886405
+  80 | 0.886405
+  81 | 0.886405
+  82 | 0.886405
+  83 | 0.886405
+  84 | 0.886405
+  85 | 0.886405
+  86 | 0.886405
+  87 | 0.886405
+  88 | 0.886405
+  89 | 0.886405
+  90 | 0.886405
+  91 | 0.886405
+  92 | 0.886405
+  93 | 0.886405
+  94 | 0.886405
+  95 | 0.886405
+  96 | 0.886405
+  97 | 0.886405
+  98 | 0.886405
+  99 | 0.886405
+ 100 | 0.886405
+ 101 | 0.886405
+ 102 | 0.886405
+ 103 | 0.886405
+ 104 | 0.886405
+ 105 | 0.886405
+ 106 | 0.886405
+ 107 | 0.886405
+ 108 | 0.886405
+ 109 | 0.886405
+ 110 | 0.886405
+ 111 | 0.886405
+ 112 | 0.886405
+ 113 | 0.886405
+ 114 | 0.886405
+ 115 | 0.886405
+ 116 | 0.886405
+ 117 | 0.886405
+ 118 | 0.886405
+ 119 | 0.886405
+ 120 | 0.886405
+ 121 | 0.886405
+ 122 | 0.886405
+ 123 | 0.886405
+ 124 | 0.886405
+ 125 | 0.886405
+ 126 | 0.886405
+ 127 | 0.886405
+ 128 | 0.886405
+ 129 | 0.886405
+ 130 | 0.886405
+ 131 | 0.886405
+ 132 | 0.886405
+ 133 | 0.886405
+ 134 | 0.886405
+ 135 | 0.886405
+ 136 | 0.886405
+ 137 | 0.886405
+ 138 | 0.886405
+ 139 | 0.886405
+ 140 | 0.886405
+ 141 | 0.886405
+ 142 | 0.886405
+ 143 | 0.886405
+ 144 | 0.886405
+ 145 | 0.886405
+ 146 | 0.886405
+ 147 | 0.886405
+ 148 | 0.886405
+ 149 | 0.886405
+ 150 | 0.886405
+ 151 | 0.886405
+ 152 | 0.886405
+ 153 | 0.886405
+ 154 | 0.886405
+ 155 | 0.886405
+ 156 | 0.886405
+ 157 | 0.886405
+ 158 | 0.886405
+ 159 | 0.886405
+ 160 | 0.886405
+ 161 | 0.886405
+ 162 | 0.886405
+ 163 | 0.886405
+ 164 | 0.886405
+ 165 | 0.886405
+ 166 | 0.886405
+ 167 | 0.886405
+ 168 | 0.886405
+ 169 | 0.886405
+ 170 | 0.886405
+ 171 | 0.886405
+ 172 | 0.886405
+ 173 | 0.886405
+ 174 | 0.886405
+ 175 | 0.886405
+ 176 | 0.886405
+ 177 | 0.886405
+ 178 | 0.886405
+ 179 | 0.886405
+ 180 | 0.886405
+ 181 | 0.886405
+ 182 | 0.886405
+ 183 | 0.886405
+ 184 | 0.886405
+ 185 | 0.886405
+ 186 | 0.886405
+ 187 | 0.886405
+ 188 | 0.886405
+ 189 | 0.886405
+ 190 | 0.886405
+ 191 | 0.886405
+ 192 | 0.886405
+ 193 | 0.886405
+ 194 | 0.886405
+ 195 | 0.886405
+ 196 | 0.886405
+ 197 | 0.886405
+ 198 | 0.886405
+ 199 | 0.886405
+ 200 | 0.886405
+(200 rows)
+
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[], true) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[], true) > 0.6 ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   1 |        1
+   2 | 0.948683
+   3 | 0.948683
+   8 | 0.893198
+   9 | 0.893198
+  10 | 0.893198
+  11 | 0.893198
+  12 | 0.893198
+  13 | 0.893198
+  14 | 0.893198
+  15 | 0.893198
+  16 | 0.893198
+  17 | 0.893198
+  18 | 0.893198
+  19 | 0.893198
+  20 | 0.893198
+  21 | 0.893198
+  22 | 0.893198
+  23 | 0.893198
+  24 | 0.893198
+  25 | 0.893198
+  26 | 0.893198
+  27 | 0.893198
+  28 | 0.893198
+  29 | 0.893198
+  30 | 0.893198
+  31 | 0.893198
+  32 | 0.893198
+   7 |  0.89172
+   6 | 0.888957
+   5 | 0.884652
+   4 | 0.881917
+  50 | 0.663459
+  51 | 0.663459
+  52 | 0.663459
+  53 | 0.663459
+  54 | 0.663459
+  55 | 0.663459
+  56 | 0.663459
+  57 | 0.663459
+  58 | 0.663459
+  59 | 0.663459
+  60 | 0.663459
+  61 | 0.663459
+  62 | 0.663459
+  63 | 0.663459
+  64 | 0.663459
+  65 | 0.663459
+  66 | 0.663459
+  67 | 0.663459
+  68 | 0.663459
+  69 | 0.663459
+  70 | 0.663459
+  71 | 0.663459
+  72 | 0.663459
+  73 | 0.663459
+  74 | 0.663459
+  75 | 0.663459
+  76 | 0.663459
+  77 | 0.663459
+  78 | 0.663459
+  79 | 0.663459
+  80 | 0.663459
+  81 | 0.663459
+  82 | 0.663459
+  83 | 0.663459
+  84 | 0.663459
+  85 | 0.663459
+  86 | 0.663459
+  87 | 0.663459
+  88 | 0.663459
+  89 | 0.663459
+  90 | 0.663459
+  91 | 0.663459
+  92 | 0.663459
+  93 | 0.663459
+  94 | 0.663459
+  95 | 0.663459
+  96 | 0.663459
+  97 | 0.663459
+  98 | 0.663459
+  99 | 0.663459
+ 100 | 0.663459
+ 101 | 0.663459
+ 102 | 0.663459
+ 103 | 0.663459
+ 104 | 0.663459
+ 105 | 0.663459
+ 106 | 0.663459
+ 107 | 0.663459
+ 108 | 0.663459
+ 109 | 0.663459
+ 110 | 0.663459
+ 111 | 0.663459
+ 112 | 0.663459
+ 113 | 0.663459
+ 114 | 0.663459
+ 115 | 0.663459
+ 116 | 0.663459
+ 117 | 0.663459
+ 118 | 0.663459
+ 119 | 0.663459
+ 120 | 0.663459
+ 121 | 0.663459
+ 122 | 0.663459
+ 123 | 0.663459
+ 124 | 0.663459
+ 125 | 0.663459
+ 126 | 0.663459
+ 127 | 0.663459
+ 128 | 0.663459
+ 129 | 0.663459
+ 130 | 0.663459
+ 131 | 0.663459
+ 132 | 0.663459
+ 133 | 0.663459
+ 134 | 0.663459
+ 135 | 0.663459
+ 136 | 0.663459
+ 137 | 0.663459
+ 138 | 0.663459
+ 139 | 0.663459
+ 140 | 0.663459
+ 141 | 0.663459
+ 142 | 0.663459
+ 143 | 0.663459
+ 144 | 0.663459
+ 145 | 0.663459
+ 146 | 0.663459
+ 147 | 0.663459
+ 148 | 0.663459
+ 149 | 0.663459
+ 150 | 0.663459
+ 151 | 0.663459
+ 152 | 0.663459
+ 153 | 0.663459
+ 154 | 0.663459
+ 155 | 0.663459
+ 156 | 0.663459
+ 157 | 0.663459
+ 158 | 0.663459
+ 159 | 0.663459
+ 160 | 0.663459
+ 161 | 0.663459
+ 162 | 0.663459
+ 163 | 0.663459
+ 164 | 0.663459
+ 165 | 0.663459
+ 166 | 0.663459
+ 167 | 0.663459
+ 168 | 0.663459
+ 169 | 0.663459
+ 170 | 0.663459
+ 171 | 0.663459
+ 172 | 0.663459
+ 173 | 0.663459
+ 174 | 0.663459
+ 175 | 0.663459
+ 176 | 0.663459
+ 177 | 0.663459
+ 178 | 0.663459
+ 179 | 0.663459
+ 180 | 0.663459
+ 181 | 0.663459
+ 182 | 0.663459
+ 183 | 0.663459
+ 184 | 0.663459
+ 185 | 0.663459
+ 186 | 0.663459
+ 187 | 0.663459
+ 188 | 0.663459
+ 189 | 0.663459
+ 190 | 0.663459
+ 191 | 0.663459
+ 192 | 0.663459
+ 193 | 0.663459
+ 194 | 0.663459
+ 195 | 0.663459
+ 196 | 0.663459
+ 197 | 0.663459
+ 198 | 0.663459
+ 199 | 0.663459
+ 200 | 0.663459
+  33 | 0.651203
+  34 | 0.651203
+  35 | 0.651203
+  36 | 0.651203
+  37 | 0.651203
+  38 | 0.651203
+  39 | 0.651203
+  40 | 0.651203
+  41 | 0.651203
+  42 | 0.651203
+  43 | 0.651203
+  44 | 0.651203
+  45 | 0.651203
+  46 | 0.651203
+  47 | 0.651203
+  48 | 0.651203
+  49 | 0.631477
+(200 rows)
+
diff --git a/expected/composite_text.out b/expected/composite_text.out
new file mode 100644 (file)
index 0000000..0b77edc
--- /dev/null
@@ -0,0 +1,550 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+CREATE TYPE ctext AS (id text, w float4);
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       (ROW(v::text, v::float4))::ctext
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_composite_text
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[]) AS s 
+       FROM test_composite_text 
+       WHERE v % '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[]) AS s 
+       FROM test_composite_text 
+       WHERE v % '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[]) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[]) > 0.6 ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[]) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[]) > 0.6 ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[], false) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[], false) > 0.6 ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 | 0.886405
+  9 | 0.842927
+  8 | 0.797053
+ 11 | 0.773192
+  7 | 0.748331
+  6 | 0.696143
+ 12 | 0.682191
+  5 | 0.639602
+ 13 | 0.607744
+(9 rows)
+
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[], false) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[], false) > 0.6 ORDER BY s DESC, t;
+ t |    s     
+---+----------
+ 8 | 0.730632
+ 7 | 0.668153
+ 9 | 0.618147
+(3 rows)
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[], true) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[], true) > 0.6 ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   1 |        1
+   2 | 0.948683
+   3 |  0.92582
+   4 | 0.912871
+   5 | 0.904534
+   6 | 0.898717
+   7 | 0.894427
+   8 | 0.891133
+   9 | 0.888523
+  10 | 0.886405
+  11 | 0.886405
+  12 | 0.886405
+  13 | 0.886405
+  14 | 0.886405
+  15 | 0.886405
+  16 | 0.886405
+  17 | 0.886405
+  18 | 0.886405
+  19 | 0.886405
+  20 | 0.886405
+  21 | 0.886405
+  22 | 0.886405
+  23 | 0.886405
+  24 | 0.886405
+  25 | 0.886405
+  26 | 0.886405
+  27 | 0.886405
+  28 | 0.886405
+  29 | 0.886405
+  30 | 0.886405
+  31 | 0.886405
+  32 | 0.886405
+  33 | 0.886405
+  34 | 0.886405
+  35 | 0.886405
+  36 | 0.886405
+  37 | 0.886405
+  38 | 0.886405
+  39 | 0.886405
+  40 | 0.886405
+  41 | 0.886405
+  42 | 0.886405
+  43 | 0.886405
+  44 | 0.886405
+  45 | 0.886405
+  46 | 0.886405
+  47 | 0.886405
+  48 | 0.886405
+  49 | 0.886405
+  50 | 0.886405
+  51 | 0.886405
+  52 | 0.886405
+  53 | 0.886405
+  54 | 0.886405
+  55 | 0.886405
+  56 | 0.886405
+  57 | 0.886405
+  58 | 0.886405
+  59 | 0.886405
+  60 | 0.886405
+  61 | 0.886405
+  62 | 0.886405
+  63 | 0.886405
+  64 | 0.886405
+  65 | 0.886405
+  66 | 0.886405
+  67 | 0.886405
+  68 | 0.886405
+  69 | 0.886405
+  70 | 0.886405
+  71 | 0.886405
+  72 | 0.886405
+  73 | 0.886405
+  74 | 0.886405
+  75 | 0.886405
+  76 | 0.886405
+  77 | 0.886405
+  78 | 0.886405
+  79 | 0.886405
+  80 | 0.886405
+  81 | 0.886405
+  82 | 0.886405
+  83 | 0.886405
+  84 | 0.886405
+  85 | 0.886405
+  86 | 0.886405
+  87 | 0.886405
+  88 | 0.886405
+  89 | 0.886405
+  90 | 0.886405
+  91 | 0.886405
+  92 | 0.886405
+  93 | 0.886405
+  94 | 0.886405
+  95 | 0.886405
+  96 | 0.886405
+  97 | 0.886405
+  98 | 0.886405
+  99 | 0.886405
+ 100 | 0.886405
+ 101 | 0.886405
+ 102 | 0.886405
+ 103 | 0.886405
+ 104 | 0.886405
+ 105 | 0.886405
+ 106 | 0.886405
+ 107 | 0.886405
+ 108 | 0.886405
+ 109 | 0.886405
+ 110 | 0.886405
+ 111 | 0.886405
+ 112 | 0.886405
+ 113 | 0.886405
+ 114 | 0.886405
+ 115 | 0.886405
+ 116 | 0.886405
+ 117 | 0.886405
+ 118 | 0.886405
+ 119 | 0.886405
+ 120 | 0.886405
+ 121 | 0.886405
+ 122 | 0.886405
+ 123 | 0.886405
+ 124 | 0.886405
+ 125 | 0.886405
+ 126 | 0.886405
+ 127 | 0.886405
+ 128 | 0.886405
+ 129 | 0.886405
+ 130 | 0.886405
+ 131 | 0.886405
+ 132 | 0.886405
+ 133 | 0.886405
+ 134 | 0.886405
+ 135 | 0.886405
+ 136 | 0.886405
+ 137 | 0.886405
+ 138 | 0.886405
+ 139 | 0.886405
+ 140 | 0.886405
+ 141 | 0.886405
+ 142 | 0.886405
+ 143 | 0.886405
+ 144 | 0.886405
+ 145 | 0.886405
+ 146 | 0.886405
+ 147 | 0.886405
+ 148 | 0.886405
+ 149 | 0.886405
+ 150 | 0.886405
+ 151 | 0.886405
+ 152 | 0.886405
+ 153 | 0.886405
+ 154 | 0.886405
+ 155 | 0.886405
+ 156 | 0.886405
+ 157 | 0.886405
+ 158 | 0.886405
+ 159 | 0.886405
+ 160 | 0.886405
+ 161 | 0.886405
+ 162 | 0.886405
+ 163 | 0.886405
+ 164 | 0.886405
+ 165 | 0.886405
+ 166 | 0.886405
+ 167 | 0.886405
+ 168 | 0.886405
+ 169 | 0.886405
+ 170 | 0.886405
+ 171 | 0.886405
+ 172 | 0.886405
+ 173 | 0.886405
+ 174 | 0.886405
+ 175 | 0.886405
+ 176 | 0.886405
+ 177 | 0.886405
+ 178 | 0.886405
+ 179 | 0.886405
+ 180 | 0.886405
+ 181 | 0.886405
+ 182 | 0.886405
+ 183 | 0.886405
+ 184 | 0.886405
+ 185 | 0.886405
+ 186 | 0.886405
+ 187 | 0.886405
+ 188 | 0.886405
+ 189 | 0.886405
+ 190 | 0.886405
+ 191 | 0.886405
+ 192 | 0.886405
+ 193 | 0.886405
+ 194 | 0.886405
+ 195 | 0.886405
+ 196 | 0.886405
+ 197 | 0.886405
+ 198 | 0.886405
+ 199 | 0.886405
+ 200 | 0.886405
+(200 rows)
+
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[], true) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[], true) > 0.6 ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   1 |        1
+   2 | 0.948683
+   3 | 0.948683
+   8 | 0.893198
+   9 | 0.893198
+  10 | 0.893198
+  11 | 0.893198
+  12 | 0.893198
+  13 | 0.893198
+  14 | 0.893198
+  15 | 0.893198
+  16 | 0.893198
+  17 | 0.893198
+  18 | 0.893198
+  19 | 0.893198
+  20 | 0.893198
+  21 | 0.893198
+  22 | 0.893198
+  23 | 0.893198
+  24 | 0.893198
+  25 | 0.893198
+  26 | 0.893198
+  27 | 0.893198
+  28 | 0.893198
+  29 | 0.893198
+  30 | 0.893198
+  31 | 0.893198
+  32 | 0.893198
+   7 |  0.89172
+   6 | 0.888957
+   5 | 0.884652
+   4 | 0.881917
+  50 | 0.663459
+  51 | 0.663459
+  52 | 0.663459
+  53 | 0.663459
+  54 | 0.663459
+  55 | 0.663459
+  56 | 0.663459
+  57 | 0.663459
+  58 | 0.663459
+  59 | 0.663459
+  60 | 0.663459
+  61 | 0.663459
+  62 | 0.663459
+  63 | 0.663459
+  64 | 0.663459
+  65 | 0.663459
+  66 | 0.663459
+  67 | 0.663459
+  68 | 0.663459
+  69 | 0.663459
+  70 | 0.663459
+  71 | 0.663459
+  72 | 0.663459
+  73 | 0.663459
+  74 | 0.663459
+  75 | 0.663459
+  76 | 0.663459
+  77 | 0.663459
+  78 | 0.663459
+  79 | 0.663459
+  80 | 0.663459
+  81 | 0.663459
+  82 | 0.663459
+  83 | 0.663459
+  84 | 0.663459
+  85 | 0.663459
+  86 | 0.663459
+  87 | 0.663459
+  88 | 0.663459
+  89 | 0.663459
+  90 | 0.663459
+  91 | 0.663459
+  92 | 0.663459
+  93 | 0.663459
+  94 | 0.663459
+  95 | 0.663459
+  96 | 0.663459
+  97 | 0.663459
+  98 | 0.663459
+  99 | 0.663459
+ 100 | 0.663459
+ 101 | 0.663459
+ 102 | 0.663459
+ 103 | 0.663459
+ 104 | 0.663459
+ 105 | 0.663459
+ 106 | 0.663459
+ 107 | 0.663459
+ 108 | 0.663459
+ 109 | 0.663459
+ 110 | 0.663459
+ 111 | 0.663459
+ 112 | 0.663459
+ 113 | 0.663459
+ 114 | 0.663459
+ 115 | 0.663459
+ 116 | 0.663459
+ 117 | 0.663459
+ 118 | 0.663459
+ 119 | 0.663459
+ 120 | 0.663459
+ 121 | 0.663459
+ 122 | 0.663459
+ 123 | 0.663459
+ 124 | 0.663459
+ 125 | 0.663459
+ 126 | 0.663459
+ 127 | 0.663459
+ 128 | 0.663459
+ 129 | 0.663459
+ 130 | 0.663459
+ 131 | 0.663459
+ 132 | 0.663459
+ 133 | 0.663459
+ 134 | 0.663459
+ 135 | 0.663459
+ 136 | 0.663459
+ 137 | 0.663459
+ 138 | 0.663459
+ 139 | 0.663459
+ 140 | 0.663459
+ 141 | 0.663459
+ 142 | 0.663459
+ 143 | 0.663459
+ 144 | 0.663459
+ 145 | 0.663459
+ 146 | 0.663459
+ 147 | 0.663459
+ 148 | 0.663459
+ 149 | 0.663459
+ 150 | 0.663459
+ 151 | 0.663459
+ 152 | 0.663459
+ 153 | 0.663459
+ 154 | 0.663459
+ 155 | 0.663459
+ 156 | 0.663459
+ 157 | 0.663459
+ 158 | 0.663459
+ 159 | 0.663459
+ 160 | 0.663459
+ 161 | 0.663459
+ 162 | 0.663459
+ 163 | 0.663459
+ 164 | 0.663459
+ 165 | 0.663459
+ 166 | 0.663459
+ 167 | 0.663459
+ 168 | 0.663459
+ 169 | 0.663459
+ 170 | 0.663459
+ 171 | 0.663459
+ 172 | 0.663459
+ 173 | 0.663459
+ 174 | 0.663459
+ 175 | 0.663459
+ 176 | 0.663459
+ 177 | 0.663459
+ 178 | 0.663459
+ 179 | 0.663459
+ 180 | 0.663459
+ 181 | 0.663459
+ 182 | 0.663459
+ 183 | 0.663459
+ 184 | 0.663459
+ 185 | 0.663459
+ 186 | 0.663459
+ 187 | 0.663459
+ 188 | 0.663459
+ 189 | 0.663459
+ 190 | 0.663459
+ 191 | 0.663459
+ 192 | 0.663459
+ 193 | 0.663459
+ 194 | 0.663459
+ 195 | 0.663459
+ 196 | 0.663459
+ 197 | 0.663459
+ 198 | 0.663459
+ 199 | 0.663459
+ 200 | 0.663459
+  33 | 0.651203
+  34 | 0.651203
+  35 | 0.651203
+  36 | 0.651203
+  37 | 0.651203
+  38 | 0.651203
+  39 | 0.651203
+  40 | 0.651203
+  41 | 0.651203
+  42 | 0.651203
+  43 | 0.651203
+  44 | 0.651203
+  45 | 0.651203
+  46 | 0.651203
+  47 | 0.651203
+  48 | 0.651203
+  49 | 0.631477
+(200 rows)
+
diff --git a/expected/date.out b/expected/date.out
new file mode 100644 (file)
index 0000000..10b7fe3
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       epoch2timestamp(v)::date
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_date
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_date ON test_date USING gist (v _date_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_date;
+CREATE INDEX idx_test_date ON test_date USING gin (v _date_sml_ops);
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/float4.out b/expected/float4.out
new file mode 100644 (file)
index 0000000..70eb507
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::float4
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_float4
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_float4 ON test_float4 USING gist (v _float4_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_float4;
+CREATE INDEX idx_test_float4 ON test_float4 USING gin (v _float4_sml_ops);
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/float8.out b/expected/float8.out
new file mode 100644 (file)
index 0000000..4a9286f
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::float8
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_float8
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_float8 ON test_float8 USING gist (v _float8_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_float8;
+CREATE INDEX idx_test_float8 ON test_float8 USING gin (v _float8_sml_ops);
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/inet.out b/expected/inet.out
new file mode 100644 (file)
index 0000000..7bde3d8
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       ( '192.168.1.' || (v % 256) )::inet
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_inet
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_inet ON test_inet USING gist (v _inet_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_inet;
+CREATE INDEX idx_test_inet ON test_inet USING gin (v _inet_sml_ops);
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/int2.out b/expected/int2.out
new file mode 100644 (file)
index 0000000..8c43891
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::int2
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_int2
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int2 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int2 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_int2 ON test_int2 USING gist (v _int2_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int2 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int2 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_int2;
+CREATE INDEX idx_test_int2 ON test_int2 USING gin (v _int2_sml_ops);
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int2 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int2 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/int4.out b/expected/int4.out
new file mode 100644 (file)
index 0000000..1f69657
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::int4
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_int4
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_int4 ON test_int4 USING gist (v _int4_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_int4;
+CREATE INDEX idx_test_int4 ON test_int4 USING gin (v _int4_sml_ops);
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/int4g.out b/expected/int4g.out
new file mode 100644 (file)
index 0000000..dfa75f6
--- /dev/null
@@ -0,0 +1,1633 @@
+SELECT set_smlar_limit(0.3);
+ set_smlar_limit 
+-----------------
+             0.3
+(1 row)
+
+SET smlar.type = "tfidf";
+SET smlar.stattable = "int4_stat";
+UPDATE test_int4 SET v = v || '{50,50,50}'::int4[] WHERE t >=50 AND t < 60;
+INSERT INTO test_int4 VALUES(201, '{50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50}'); 
+CREATE TABLE int4_stat (
+    value   int4 UNIQUE,
+       ndoc    int4 NOT NULL CHECK (ndoc>0)
+);
+NOTICE:  CREATE TABLE / UNIQUE will create implicit index "int4_stat_value_key" for table "int4_stat"
+INSERT INTO int4_stat (
+    SELECT
+               q.w,
+               count(*)
+       FROM
+               (SELECT array_to_col(v) AS w FROM test_int4 WHERE v IS NOT NULL)  AS q
+       GROUP BY w
+);
+INSERT INTO int4_stat VALUES (NULL, (SELECT count(*) FROM test_int4));
+DROP INDEX idx_test_int4;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306753
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.398379
+ 51 | 0.394635
+ 52 | 0.390962
+ 53 | 0.387358
+ 54 |  0.38382
+ 55 | 0.380346
+ 56 | 0.376933
+ 57 | 0.373581
+ 58 | 0.370286
+ 60 | 0.369012
+ 59 | 0.367048
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  50 | 0.510326
+  51 |  0.50553
+  52 | 0.500825
+  18 | 0.496591
+  53 | 0.496208
+  54 | 0.491676
+  55 | 0.487225
+  56 | 0.482854
+  19 | 0.482412
+  57 |  0.47856
+  58 |  0.47434
+  59 | 0.470191
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306662
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 50 | 0.419425
+ 49 | 0.417358
+ 51 |  0.41482
+ 52 | 0.410324
+ 53 | 0.405932
+ 54 |  0.40164
+ 55 | 0.397443
+ 56 | 0.393339
+ 57 | 0.389323
+ 58 | 0.385391
+ 59 | 0.381541
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  50 | 0.481241
+  51 | 0.475957
+  52 | 0.470799
+  20 | 0.469285
+  53 | 0.465759
+  54 | 0.460835
+  21 | 0.457083
+  55 |  0.45602
+   4 |  0.45545
+  56 |  0.45131
+  57 | 0.446702
+  22 |   0.4457
+  58 | 0.442191
+  59 | 0.437774
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+CREATE INDEX idx_test_int4 ON test_int4 USING gist (v _int4_sml_ops);
+SET enable_seqscan = off;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306753
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.398379
+ 51 | 0.394635
+ 52 | 0.390962
+ 53 | 0.387358
+ 54 |  0.38382
+ 55 | 0.380346
+ 56 | 0.376933
+ 57 | 0.373581
+ 58 | 0.370286
+ 60 | 0.369012
+ 59 | 0.367048
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  50 | 0.510326
+  51 |  0.50553
+  52 | 0.500825
+  18 | 0.496591
+  53 | 0.496208
+  54 | 0.491676
+  55 | 0.487225
+  56 | 0.482854
+  19 | 0.482412
+  57 |  0.47856
+  58 |  0.47434
+  59 | 0.470191
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306662
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 50 | 0.419425
+ 49 | 0.417358
+ 51 |  0.41482
+ 52 | 0.410324
+ 53 | 0.405932
+ 54 |  0.40164
+ 55 | 0.397443
+ 56 | 0.393339
+ 57 | 0.389323
+ 58 | 0.385391
+ 59 | 0.381541
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  50 | 0.481241
+  51 | 0.475957
+  52 | 0.470799
+  20 | 0.469285
+  53 | 0.465759
+  54 | 0.460835
+  21 | 0.457083
+  55 |  0.45602
+   4 |  0.45545
+  56 |  0.45131
+  57 | 0.446702
+  22 |   0.4457
+  58 | 0.442191
+  59 | 0.437774
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+DROP INDEX idx_test_int4;
+CREATE INDEX idx_test_int4 ON test_int4 USING gin (v _int4_sml_ops);
+SET enable_seqscan = off;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+RESET enable_seqscan;
diff --git a/expected/int4i.out b/expected/int4i.out
new file mode 100644 (file)
index 0000000..81e8284
--- /dev/null
@@ -0,0 +1,41 @@
+SELECT set_smlar_limit(5.0);
+ set_smlar_limit 
+-----------------
+               5
+(1 row)
+
+SET smlar.type='overlap';
+DROP INDEX idx_test_int4;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+ smlar 
+-------
+     2
+(1 row)
+
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_int4 WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+  t  | s  
+-----+----
+ 199 | 10
+ 200 | 10
+ 198 |  9
+ 197 |  8
+ 196 |  7
+ 195 |  6
+ 194 |  5
+(7 rows)
+
+CREATE INDEX idx_test_int4 ON test_int4 USING gin (v _int4_sml_ops);
+SET enable_seqscan = off;
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_int4 WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+  t  | s  
+-----+----
+ 199 | 10
+ 200 | 10
+ 198 |  9
+ 197 |  8
+ 196 |  7
+ 195 |  6
+ 194 |  5
+(7 rows)
+
+RESET enable_seqscan;
diff --git a/expected/int8.out b/expected/int8.out
new file mode 100644 (file)
index 0000000..ee943d2
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::int8
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_int8
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_int8 ON test_int8 USING gist (v _int8_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_int8;
+CREATE INDEX idx_test_int8 ON test_int8 USING gin (v _int8_sml_ops);
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/int8g.out b/expected/int8g.out
new file mode 100644 (file)
index 0000000..c77879d
--- /dev/null
@@ -0,0 +1,1633 @@
+SELECT set_smlar_limit(0.3);
+ set_smlar_limit 
+-----------------
+             0.3
+(1 row)
+
+SET smlar.type = "tfidf";
+SET smlar.stattable = "int8_stat";
+UPDATE test_int8 SET v = v || '{50,50,50}'::int8[] WHERE t >=50 AND t < 60;
+INSERT INTO test_int8 VALUES(201, '{50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50}'); 
+CREATE TABLE int8_stat (
+    value   int8 UNIQUE,
+       ndoc    int4 NOT NULL CHECK (ndoc>0)
+);
+NOTICE:  CREATE TABLE / UNIQUE will create implicit index "int8_stat_value_key" for table "int8_stat"
+INSERT INTO int8_stat (
+    SELECT
+               q.w,
+               count(*)
+       FROM
+               (SELECT array_to_col(v) AS w FROM test_int8 WHERE v IS NOT NULL)  AS q
+       GROUP BY w
+);
+INSERT INTO int8_stat VALUES (NULL, (SELECT count(*) FROM test_int8));
+DROP INDEX idx_test_int8;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306753
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.398379
+ 51 | 0.394635
+ 52 | 0.390962
+ 53 | 0.387358
+ 54 |  0.38382
+ 55 | 0.380346
+ 56 | 0.376933
+ 57 | 0.373581
+ 58 | 0.370286
+ 60 | 0.369012
+ 59 | 0.367048
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  50 | 0.510326
+  51 |  0.50553
+  52 | 0.500825
+  18 | 0.496591
+  53 | 0.496208
+  54 | 0.491676
+  55 | 0.487225
+  56 | 0.482854
+  19 | 0.482412
+  57 |  0.47856
+  58 |  0.47434
+  59 | 0.470191
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306662
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 50 | 0.419425
+ 49 | 0.417358
+ 51 |  0.41482
+ 52 | 0.410324
+ 53 | 0.405932
+ 54 |  0.40164
+ 55 | 0.397443
+ 56 | 0.393339
+ 57 | 0.389323
+ 58 | 0.385391
+ 59 | 0.381541
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  50 | 0.481241
+  51 | 0.475957
+  52 | 0.470799
+  20 | 0.469285
+  53 | 0.465759
+  54 | 0.460835
+  21 | 0.457083
+  55 |  0.45602
+   4 |  0.45545
+  56 |  0.45131
+  57 | 0.446702
+  22 |   0.4457
+  58 | 0.442191
+  59 | 0.437774
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+CREATE INDEX idx_test_int8 ON test_int8 USING gist (v _int8_sml_ops);
+SET enable_seqscan = off;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306753
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.398379
+ 51 | 0.394635
+ 52 | 0.390962
+ 53 | 0.387358
+ 54 |  0.38382
+ 55 | 0.380346
+ 56 | 0.376933
+ 57 | 0.373581
+ 58 | 0.370286
+ 60 | 0.369012
+ 59 | 0.367048
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  50 | 0.510326
+  51 |  0.50553
+  52 | 0.500825
+  18 | 0.496591
+  53 | 0.496208
+  54 | 0.491676
+  55 | 0.487225
+  56 | 0.482854
+  19 | 0.482412
+  57 |  0.47856
+  58 |  0.47434
+  59 | 0.470191
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306662
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 50 | 0.419425
+ 49 | 0.417358
+ 51 |  0.41482
+ 52 | 0.410324
+ 53 | 0.405932
+ 54 |  0.40164
+ 55 | 0.397443
+ 56 | 0.393339
+ 57 | 0.389323
+ 58 | 0.385391
+ 59 | 0.381541
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  50 | 0.481241
+  51 | 0.475957
+  52 | 0.470799
+  20 | 0.469285
+  53 | 0.465759
+  54 | 0.460835
+  21 | 0.457083
+  55 |  0.45602
+   4 |  0.45545
+  56 |  0.45131
+  57 | 0.446702
+  22 |   0.4457
+  58 | 0.442191
+  59 | 0.437774
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+DROP INDEX idx_test_int8;
+CREATE INDEX idx_test_int8 ON test_int8 USING gin (v _int8_sml_ops);
+SET enable_seqscan = off;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+RESET enable_seqscan;
diff --git a/expected/int8i.out b/expected/int8i.out
new file mode 100644 (file)
index 0000000..9ffcc4d
--- /dev/null
@@ -0,0 +1,41 @@
+SELECT set_smlar_limit(5.0);
+ set_smlar_limit 
+-----------------
+               5
+(1 row)
+
+SET smlar.type='overlap';
+DROP INDEX idx_test_int8;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+ smlar 
+-------
+     2
+(1 row)
+
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_int8 WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+  t  | s  
+-----+----
+ 199 | 10
+ 200 | 10
+ 198 |  9
+ 197 |  8
+ 196 |  7
+ 195 |  6
+ 194 |  5
+(7 rows)
+
+CREATE INDEX idx_test_int8 ON test_int8 USING gin (v _int8_sml_ops);
+SET enable_seqscan = off;
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_int8 WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+  t  | s  
+-----+----
+ 199 | 10
+ 200 | 10
+ 198 |  9
+ 197 |  8
+ 196 |  7
+ 195 |  6
+ 194 |  5
+(7 rows)
+
+RESET enable_seqscan;
diff --git a/expected/interval.out b/expected/interval.out
new file mode 100644 (file)
index 0000000..a8bd2bd
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::text::interval
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_interval
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_interval ON test_interval USING gist (v _interval_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_interval;
+CREATE INDEX idx_test_interval ON test_interval USING gin (v _interval_sml_ops);
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/intervalg.out b/expected/intervalg.out
new file mode 100644 (file)
index 0000000..9b963de
--- /dev/null
@@ -0,0 +1,1633 @@
+SELECT set_smlar_limit(0.3);
+ set_smlar_limit 
+-----------------
+             0.3
+(1 row)
+
+SET smlar.type = "tfidf";
+SET smlar.stattable = "interval_stat";
+UPDATE test_interval SET v = v || '{50,50,50}'::interval[] WHERE t >=50 AND t < 60;
+INSERT INTO test_interval VALUES(201, '{50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50}'); 
+CREATE TABLE interval_stat (
+    value   interval UNIQUE,
+       ndoc    int4 NOT NULL CHECK (ndoc>0)
+);
+NOTICE:  CREATE TABLE / UNIQUE will create implicit index "interval_stat_value_key" for table "interval_stat"
+INSERT INTO interval_stat (
+    SELECT
+               q.w,
+               count(*)
+       FROM
+               (SELECT array_to_col(v) AS w FROM test_interval WHERE v IS NOT NULL)  AS q
+       GROUP BY w
+);
+INSERT INTO interval_stat VALUES (NULL, (SELECT count(*) FROM test_interval));
+DROP INDEX idx_test_interval;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306753
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.398379
+ 51 | 0.394635
+ 52 | 0.390962
+ 53 | 0.387358
+ 54 |  0.38382
+ 55 | 0.380346
+ 56 | 0.376933
+ 57 | 0.373581
+ 58 | 0.370286
+ 60 | 0.369012
+ 59 | 0.367048
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  50 | 0.510326
+  51 |  0.50553
+  52 | 0.500825
+  18 | 0.496591
+  53 | 0.496208
+  54 | 0.491676
+  55 | 0.487225
+  56 | 0.482854
+  19 | 0.482412
+  57 |  0.47856
+  58 |  0.47434
+  59 | 0.470191
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306662
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 50 | 0.419425
+ 49 | 0.417358
+ 51 |  0.41482
+ 52 | 0.410324
+ 53 | 0.405932
+ 54 |  0.40164
+ 55 | 0.397443
+ 56 | 0.393339
+ 57 | 0.389323
+ 58 | 0.385391
+ 59 | 0.381541
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  50 | 0.481241
+  51 | 0.475957
+  52 | 0.470799
+  20 | 0.469285
+  53 | 0.465759
+  54 | 0.460835
+  21 | 0.457083
+  55 |  0.45602
+   4 |  0.45545
+  56 |  0.45131
+  57 | 0.446702
+  22 |   0.4457
+  58 | 0.442191
+  59 | 0.437774
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+CREATE INDEX idx_test_interval ON test_interval USING gist (v _interval_sml_ops);
+SET enable_seqscan = off;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306753
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.398379
+ 51 | 0.394635
+ 52 | 0.390962
+ 53 | 0.387358
+ 54 |  0.38382
+ 55 | 0.380346
+ 56 | 0.376933
+ 57 | 0.373581
+ 58 | 0.370286
+ 60 | 0.369012
+ 59 | 0.367048
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  50 | 0.510326
+  51 |  0.50553
+  52 | 0.500825
+  18 | 0.496591
+  53 | 0.496208
+  54 | 0.491676
+  55 | 0.487225
+  56 | 0.482854
+  19 | 0.482412
+  57 |  0.47856
+  58 |  0.47434
+  59 | 0.470191
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306662
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 50 | 0.419425
+ 49 | 0.417358
+ 51 |  0.41482
+ 52 | 0.410324
+ 53 | 0.405932
+ 54 |  0.40164
+ 55 | 0.397443
+ 56 | 0.393339
+ 57 | 0.389323
+ 58 | 0.385391
+ 59 | 0.381541
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  50 | 0.481241
+  51 | 0.475957
+  52 | 0.470799
+  20 | 0.469285
+  53 | 0.465759
+  54 | 0.460835
+  21 | 0.457083
+  55 |  0.45602
+   4 |  0.45545
+  56 |  0.45131
+  57 | 0.446702
+  22 |   0.4457
+  58 | 0.442191
+  59 | 0.437774
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+DROP INDEX idx_test_interval;
+CREATE INDEX idx_test_interval ON test_interval USING gin (v _interval_sml_ops);
+SET enable_seqscan = off;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+RESET enable_seqscan;
diff --git a/expected/intervali.out b/expected/intervali.out
new file mode 100644 (file)
index 0000000..9d34998
--- /dev/null
@@ -0,0 +1,41 @@
+SELECT set_smlar_limit(5.0);
+ set_smlar_limit 
+-----------------
+               5
+(1 row)
+
+SET smlar.type='overlap';
+DROP INDEX idx_test_interval;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+ smlar 
+-------
+     2
+(1 row)
+
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_interval WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+  t  | s  
+-----+----
+ 199 | 10
+ 200 | 10
+ 198 |  9
+ 197 |  8
+ 196 |  7
+ 195 |  6
+ 194 |  5
+(7 rows)
+
+CREATE INDEX idx_test_interval ON test_interval USING gin (v _interval_sml_ops);
+SET enable_seqscan = off;
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_interval WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+  t  | s  
+-----+----
+ 199 | 10
+ 200 | 10
+ 198 |  9
+ 197 |  8
+ 196 |  7
+ 195 |  6
+ 194 |  5
+(7 rows)
+
+RESET enable_seqscan;
diff --git a/expected/macaddr.out b/expected/macaddr.out
new file mode 100644 (file)
index 0000000..9397042
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       ('01:01:01:01:01:' || (v % 100))::macaddr
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_macaddr
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_macaddr ON test_macaddr USING gist (v _macaddr_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_macaddr;
+CREATE INDEX idx_test_macaddr ON test_macaddr USING gin (v _macaddr_sml_ops);
+SELECT t, smlar(v, '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/money.out b/expected/money.out
new file mode 100644 (file)
index 0000000..c04d690
--- /dev/null
@@ -0,0 +1,104 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::text::money
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_money
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_money WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_money WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_money ON test_money USING gin (v _money_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_money WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_money WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/numeric.out b/expected/numeric.out
new file mode 100644 (file)
index 0000000..84eb7ee
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::numeric
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_numeric
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_numeric WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_numeric WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_numeric ON test_numeric USING gist (v _numeric_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_numeric WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_numeric WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_numeric;
+CREATE INDEX idx_test_numeric ON test_numeric USING gin (v _numeric_sml_ops);
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_numeric WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_numeric WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/oid.out b/expected/oid.out
new file mode 100644 (file)
index 0000000..c76ce6f
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::oid
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_oid
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_oid WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_oid WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_oid ON test_oid USING gist (v _oid_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_oid WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_oid WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_oid;
+CREATE INDEX idx_test_oid ON test_oid USING gin (v _oid_sml_ops);
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_oid WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_oid WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/smlar.out b/expected/smlar.out
new file mode 100644 (file)
index 0000000..2a34641
--- /dev/null
@@ -0,0 +1,354 @@
+CREATE EXTENSION smlar;
+--sanity check
+SELECT 
+       opc.opcname, 
+       t.typname, 
+       opc.opcdefault  
+FROM 
+       pg_opclass opc, 
+       pg_am am, 
+       pg_type t, 
+       pg_type k 
+WHERE 
+       opc.opcmethod = am.oid AND 
+       am.amname='gist' AND 
+       opc.opcintype = t.oid AND 
+       opc.opckeytype = k.oid AND 
+       k.typname='gsmlsign'
+ORDER BY opc.opcname;
+       opcname        |   typname    | opcdefault 
+----------------------+--------------+------------
+ _bytea_sml_ops       | _bytea       | f
+ _char_sml_ops        | _char        | f
+ _cidr_sml_ops        | _cidr        | f
+ _date_sml_ops        | _date        | f
+ _float4_sml_ops      | _float4      | f
+ _float8_sml_ops      | _float8      | f
+ _inet_sml_ops        | _inet        | f
+ _int2_sml_ops        | _int2        | f
+ _int4_sml_ops        | _int4        | f
+ _int8_sml_ops        | _int8        | f
+ _interval_sml_ops    | _interval    | f
+ _macaddr_sml_ops     | _macaddr     | f
+ _numeric_sml_ops     | _numeric     | f
+ _oid_sml_ops         | _oid         | f
+ _text_sml_ops        | _text        | f
+ _time_sml_ops        | _time        | f
+ _timestamp_sml_ops   | _timestamp   | f
+ _timestamptz_sml_ops | _timestamptz | f
+ _timetz_sml_ops      | _timetz      | f
+ _varchar_sml_ops     | _varchar     | f
+(20 rows)
+
+SELECT 
+       opc.opcname, 
+       t.typname, 
+       opc.opcdefault  
+FROM 
+       pg_opclass opc, 
+       pg_am am, 
+       pg_type t
+WHERE 
+       opc.opcmethod = am.oid AND 
+       am.amname='gin' AND 
+       opc.opcintype = t.oid AND 
+       opc.opcname ~ '_sml_ops$'
+ORDER BY opc.opcname;
+       opcname        |   typname    | opcdefault 
+----------------------+--------------+------------
+ _bit_sml_ops         | _bit         | f
+ _bytea_sml_ops       | _bytea       | f
+ _char_sml_ops        | _char        | f
+ _cidr_sml_ops        | _cidr        | f
+ _date_sml_ops        | _date        | f
+ _float4_sml_ops      | _float4      | f
+ _float8_sml_ops      | _float8      | f
+ _inet_sml_ops        | _inet        | f
+ _int2_sml_ops        | _int2        | f
+ _int4_sml_ops        | _int4        | f
+ _int8_sml_ops        | _int8        | f
+ _interval_sml_ops    | _interval    | f
+ _macaddr_sml_ops     | _macaddr     | f
+ _money_sml_ops       | _money       | f
+ _numeric_sml_ops     | _numeric     | f
+ _oid_sml_ops         | _oid         | f
+ _text_sml_ops        | _text        | f
+ _time_sml_ops        | _time        | f
+ _timestamp_sml_ops   | _timestamp   | f
+ _timestamptz_sml_ops | _timestamptz | f
+ _timetz_sml_ops      | _timetz      | f
+ _varbit_sml_ops      | _varbit      | f
+ _varchar_sml_ops     | _varchar     | f
+(23 rows)
+
+SELECT 
+    trim( leading '_'  from t.typname ) || '[]' AS "Array Type",
+    gin.opcname AS "GIN operator class",
+    gist.opcname AS "GiST operator class"
+FROM
+    (
+        SELECT *
+        FROM
+            pg_catalog.pg_opclass,
+            pg_catalog.pg_am
+        WHERE
+            pg_opclass.opcmethod = pg_am.oid AND
+            pg_am.amname = 'gin' AND
+            pg_opclass.opcname ~ '_sml_ops$'
+    ) AS gin
+    FULL OUTER JOIN
+        (
+            SELECT *
+            FROM
+                pg_catalog.pg_opclass,
+                pg_catalog.pg_am
+            WHERE
+                pg_opclass.opcmethod = pg_am.oid AND
+                pg_am.amname = 'gist' AND
+                pg_opclass.opcname ~ '_sml_ops$'
+        ) AS gist
+        ON (
+            gist.opcname = gin.opcname AND 
+            gist.opcintype = gin.opcintype 
+        ),
+    pg_catalog.pg_type t
+WHERE
+    t.oid = COALESCE(gist.opcintype, gin.opcintype) AND
+    t.typarray = 0
+ORDER BY
+    "Array Type" ASC 
+;
+  Array Type   |  GIN operator class  | GiST operator class  
+---------------+----------------------+----------------------
+ bit[]         | _bit_sml_ops         | 
+ bytea[]       | _bytea_sml_ops       | _bytea_sml_ops
+ char[]        | _char_sml_ops        | _char_sml_ops
+ cidr[]        | _cidr_sml_ops        | _cidr_sml_ops
+ date[]        | _date_sml_ops        | _date_sml_ops
+ float4[]      | _float4_sml_ops      | _float4_sml_ops
+ float8[]      | _float8_sml_ops      | _float8_sml_ops
+ inet[]        | _inet_sml_ops        | _inet_sml_ops
+ int2[]        | _int2_sml_ops        | _int2_sml_ops
+ int4[]        | _int4_sml_ops        | _int4_sml_ops
+ int8[]        | _int8_sml_ops        | _int8_sml_ops
+ interval[]    | _interval_sml_ops    | _interval_sml_ops
+ macaddr[]     | _macaddr_sml_ops     | _macaddr_sml_ops
+ money[]       | _money_sml_ops       | 
+ numeric[]     | _numeric_sml_ops     | _numeric_sml_ops
+ oid[]         | _oid_sml_ops         | _oid_sml_ops
+ text[]        | _text_sml_ops        | _text_sml_ops
+ time[]        | _time_sml_ops        | _time_sml_ops
+ timestamp[]   | _timestamp_sml_ops   | _timestamp_sml_ops
+ timestamptz[] | _timestamptz_sml_ops | _timestamptz_sml_ops
+ timetz[]      | _timetz_sml_ops      | _timetz_sml_ops
+ varbit[]      | _varbit_sml_ops      | 
+ varchar[]     | _varchar_sml_ops     | _varchar_sml_ops
+(23 rows)
+
+SELECT set_smlar_limit(0.1);
+ set_smlar_limit 
+-----------------
+             0.1
+(1 row)
+
+SET smlar.threshold = 0.6;
+--First checks
+SELECT smlar('{3,2}'::int[], '{3,2,1}');
+  smlar   
+----------
+ 0.816497
+(1 row)
+
+SELECT smlar('{2,1}'::int[], '{3,2,1}');
+  smlar   
+----------
+ 0.816497
+(1 row)
+
+SELECT smlar('{}'::int[], '{3,2,1}');
+ smlar 
+-------
+     0
+(1 row)
+
+SELECT smlar('{12,10}'::int[], '{3,2,1}');
+ smlar 
+-------
+     0
+(1 row)
+
+SELECT smlar('{123}'::int[], '{}');
+ smlar 
+-------
+     0
+(1 row)
+
+SELECT smlar('{1,4,6}'::int[], '{1,4,6}');
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT smlar('{1,4,6}'::int[], '{6,4,1}');
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT smlar('{1,4,6}'::int[], '{5,4,6}');
+  smlar   
+----------
+ 0.666667
+(1 row)
+
+SELECT smlar('{1,4,6}'::int[], '{5,4,6}');
+  smlar   
+----------
+ 0.666667
+(1 row)
+
+SELECT smlar('{1,2}'::int[], '{2,2,2,2,2,1}');
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT smlar('{1,2}'::int[], '{1,2,2,2,2,2}');
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT smlar('{}'::int[], '{3}');
+ smlar 
+-------
+     0
+(1 row)
+
+SELECT smlar('{3}'::int[], '{3}');
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT smlar('{2}'::int[], '{3}');
+ smlar 
+-------
+     0
+(1 row)
+
+SELECT smlar('{1,4,6}'::int[], '{5,4,6}', 'N.i / (N.a + N.b)' );
+  smlar   
+----------
+ 0.333333
+(1 row)
+
+SELECT smlar('{1,4,6}'::int[], '{5,4,6}', 'N.i / sqrt(N.a * N.b)' );
+  smlar   
+----------
+ 0.666667
+(1 row)
+
+SELECT tsvector2textarray('qwe:12 asd:45');
+ tsvector2textarray 
+--------------------
+ {asd,qwe}
+(1 row)
+
+SELECT array_unique('{12,12,1,4,1,16}'::int4[]);
+ array_unique 
+--------------
+ {1,4,12,16}
+(1 row)
+
+SELECT array_unique('{12,12,1,4,1,16}'::bigint[]);
+ array_unique 
+--------------
+ {1,4,12,16}
+(1 row)
+
+SELECT array_unique('{12,12,1,4,1,16}'::smallint[]);
+ array_unique 
+--------------
+ {1,4,12,16}
+(1 row)
+
+SELECT array_unique('{12,12,1,4,1,16}'::text[]);
+ array_unique 
+--------------
+ {1,12,16,4}
+(1 row)
+
+SELECT array_unique('{12,12,1,4,1,16}'::varchar[]);
+ array_unique 
+--------------
+ {1,12,16,4}
+(1 row)
+
+SELECT inarray('{12,12,1,4,1,16}'::int[], 13::int);
+ inarray 
+---------
+       0
+(1 row)
+
+SELECT inarray('{12,12,1,4,1,16}'::int[], 12::int);
+ inarray 
+---------
+       1
+(1 row)
+
+SELECT inarray('{12,12,1,4,1,16}'::text[], 13::text);
+ inarray 
+---------
+       0
+(1 row)
+
+SELECT inarray('{12,12,1,4,1,16}'::text[], 12::text);
+ inarray 
+---------
+       1
+(1 row)
+
+SELECT inarray('{12,12,1,4,1,16}'::int[], 13::int, 0.9, 0.1);
+ inarray 
+---------
+     0.1
+(1 row)
+
+SELECT inarray('{12,12,1,4,1,16}'::int[], 12::int, 0.9, 0.1);
+ inarray 
+---------
+     0.9
+(1 row)
+
+SELECT inarray('{12,12,1,4,1,16}'::text[], 13::text, 0.9, 0.1);
+ inarray 
+---------
+     0.1
+(1 row)
+
+SELECT inarray('{12,12,1,4,1,16}'::text[], 12::text, 0.9, 0.1);
+ inarray 
+---------
+     0.9
+(1 row)
+
+--testing function
+CREATE OR REPLACE FUNCTION epoch2timestamp(int4)
+RETURNS timestamp AS $$
+    SELECT ('1970-01-01 00:00:00'::timestamp +   ( ($1*3600*24 + $1) ::text || ' seconds' )::interval)::timestamp;
+       $$ LANGUAGE SQL RETURNS NULL ON NULL INPUT IMMUTABLE;
+CREATE OR REPLACE FUNCTION to_tsp_array(_int4)
+RETURNS _timestamp AS $$
+       SELECT ARRAY( 
+               SELECT 
+                       epoch2timestamp( $1[n] )
+               FROM
+                       generate_series( 1, array_upper( $1, 1) - array_lower( $1, 1 ) + 1 ) AS n
+       );
+       $$ LANGUAGE SQL RETURNS NULL ON NULL INPUT IMMUTABLE;
+CREATE OR REPLACE FUNCTION array_to_col(anyarray)
+RETURNS SETOF anyelement AS
+$$
+    SELECT $1[n] FROM generate_series( 1, array_upper( $1, 1) - array_lower( $1, 1 ) + 1 ) AS n;
+$$ LANGUAGE SQL RETURNS NULL ON NULL INPUT IMMUTABLE;
diff --git a/expected/text.out b/expected/text.out
new file mode 100644 (file)
index 0000000..622a89e
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::text
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_text
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_text ON test_text USING gist (v _text_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_text;
+CREATE INDEX idx_test_text ON test_text USING gin (v _text_sml_ops);
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/textg.out b/expected/textg.out
new file mode 100644 (file)
index 0000000..3b94270
--- /dev/null
@@ -0,0 +1,1633 @@
+SELECT set_smlar_limit(0.3);
+ set_smlar_limit 
+-----------------
+             0.3
+(1 row)
+
+SET smlar.type = "tfidf";
+SET smlar.stattable = "text_stat";
+UPDATE test_text SET v = v || '{50,50,50}'::text[] WHERE t >=50 AND t < 60;
+INSERT INTO test_text VALUES(201, '{50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50}'); 
+CREATE TABLE text_stat (
+    value   text UNIQUE,
+       ndoc    int4 NOT NULL CHECK (ndoc>0)
+);
+NOTICE:  CREATE TABLE / UNIQUE will create implicit index "text_stat_value_key" for table "text_stat"
+INSERT INTO text_stat (
+    SELECT
+               q.w,
+               count(*)
+       FROM
+               (SELECT array_to_col(v) AS w FROM test_text WHERE v IS NOT NULL)  AS q
+       GROUP BY w
+);
+INSERT INTO text_stat VALUES (NULL, (SELECT count(*) FROM test_text));
+DROP INDEX idx_test_text;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306753
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.398379
+ 51 | 0.394635
+ 52 | 0.390962
+ 53 | 0.387358
+ 54 |  0.38382
+ 55 | 0.380346
+ 56 | 0.376933
+ 57 | 0.373581
+ 58 | 0.370286
+ 60 | 0.369012
+ 59 | 0.367048
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  50 | 0.510326
+  51 |  0.50553
+  52 | 0.500825
+  18 | 0.496591
+  53 | 0.496208
+  54 | 0.491676
+  55 | 0.487225
+  56 | 0.482854
+  19 | 0.482412
+  57 |  0.47856
+  58 |  0.47434
+  59 | 0.470191
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306662
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 50 | 0.419425
+ 49 | 0.417358
+ 51 |  0.41482
+ 52 | 0.410324
+ 53 | 0.405932
+ 54 |  0.40164
+ 55 | 0.397443
+ 56 | 0.393339
+ 57 | 0.389323
+ 58 | 0.385391
+ 59 | 0.381541
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  50 | 0.481241
+  51 | 0.475957
+  52 | 0.470799
+  20 | 0.469285
+  53 | 0.465759
+  54 | 0.460835
+  21 | 0.457083
+  55 |  0.45602
+   4 |  0.45545
+  56 |  0.45131
+  57 | 0.446702
+  22 |   0.4457
+  58 | 0.442191
+  59 | 0.437774
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+CREATE INDEX idx_test_text ON test_text USING gist (v _text_sml_ops);
+SET enable_seqscan = off;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306753
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.398379
+ 51 | 0.394635
+ 52 | 0.390962
+ 53 | 0.387358
+ 54 |  0.38382
+ 55 | 0.380346
+ 56 | 0.376933
+ 57 | 0.373581
+ 58 | 0.370286
+ 60 | 0.369012
+ 59 | 0.367048
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  50 | 0.510326
+  51 |  0.50553
+  52 | 0.500825
+  18 | 0.496591
+  53 | 0.496208
+  54 | 0.491676
+  55 | 0.487225
+  56 | 0.482854
+  19 | 0.482412
+  57 |  0.47856
+  58 |  0.47434
+  59 | 0.470191
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306662
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 50 | 0.419425
+ 49 | 0.417358
+ 51 |  0.41482
+ 52 | 0.410324
+ 53 | 0.405932
+ 54 |  0.40164
+ 55 | 0.397443
+ 56 | 0.393339
+ 57 | 0.389323
+ 58 | 0.385391
+ 59 | 0.381541
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  50 | 0.481241
+  51 | 0.475957
+  52 | 0.470799
+  20 | 0.469285
+  53 | 0.465759
+  54 | 0.460835
+  21 | 0.457083
+  55 |  0.45602
+   4 |  0.45545
+  56 |  0.45131
+  57 | 0.446702
+  22 |   0.4457
+  58 | 0.442191
+  59 | 0.437774
+  23 | 0.435047
+   2 | 0.428355
+  24 | 0.425047
+  33 | 0.419273
+  25 | 0.415635
+  34 |  0.41221
+  26 | 0.406753
+  35 | 0.405439
+  36 | 0.398938
+  27 | 0.398352
+  37 | 0.392689
+  28 | 0.390389
+  49 | 0.390116
+  38 | 0.386675
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+DROP INDEX idx_test_text;
+CREATE INDEX idx_test_text ON test_text USING gin (v _text_sml_ops);
+SET enable_seqscan = off;
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+  smlar   
+----------
+ 0.997241
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+  smlar   
+----------
+ 0.999075
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ERROR:  GIN supports only smlar.tf_method = "const"
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.870583
+  9 | 0.858716
+ 12 | 0.766621
+  8 | 0.725108
+ 13 | 0.681623
+ 14 | 0.611081
+  7 | 0.599535
+ 15 | 0.551777
+ 16 | 0.501358
+  6 | 0.482432
+ 17 | 0.458069
+ 18 | 0.420577
+ 19 | 0.387851
+  5 | 0.374337
+ 20 | 0.359086
+ 21 | 0.333644
+ 22 | 0.311011
+(18 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 50 | 0.306545
+ 49 | 0.306482
+(2 rows)
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     1
+(1 row)
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.951679
+  9 | 0.946916
+ 12 | 0.909452
+  8 | 0.891104
+ 13 | 0.872126
+ 14 |  0.83881
+  7 |  0.83201
+ 15 | 0.808827
+ 16 | 0.781649
+  6 | 0.768873
+ 17 | 0.756858
+ 18 | 0.734118
+ 19 | 0.713158
+  5 | 0.700594
+ 20 | 0.693752
+ 21 | 0.675714
+ 22 | 0.658886
+ 23 | 0.643138
+ 24 | 0.628355
+  4 | 0.625485
+ 25 |  0.61444
+ 26 |  0.60131
+ 27 |  0.58889
+ 28 | 0.577119
+ 29 | 0.565939
+ 30 |   0.5553
+ 31 |  0.54516
+  3 |   0.5407
+ 32 | 0.535479
+ 33 | 0.526223
+ 34 | 0.517359
+ 35 |  0.50886
+ 36 |   0.5007
+ 37 | 0.492857
+ 38 |  0.48531
+ 39 | 0.478039
+ 40 | 0.471027
+ 41 | 0.464259
+ 42 |  0.45772
+ 43 | 0.451396
+ 44 | 0.445276
+  2 | 0.440679
+ 45 | 0.439348
+ 46 | 0.433601
+ 47 | 0.428026
+ 48 | 0.422615
+ 49 | 0.417358
+ 50 | 0.413885
+ 51 | 0.408856
+ 52 | 0.403962
+ 53 | 0.399199
+ 54 | 0.394558
+ 55 | 0.390035
+ 56 | 0.385625
+ 57 | 0.381322
+ 58 | 0.377121
+ 59 | 0.373019
+ 60 | 0.369012
+ 61 | 0.365094
+ 62 | 0.361263
+ 63 | 0.357515
+ 64 | 0.353847
+ 65 | 0.350256
+ 66 | 0.346738
+ 67 | 0.343291
+ 68 | 0.339913
+ 69 | 0.336601
+ 70 | 0.333351
+ 71 | 0.330163
+ 72 | 0.327034
+ 73 | 0.323962
+ 74 | 0.320945
+ 75 | 0.317981
+ 76 | 0.315068
+ 77 | 0.312205
+  1 | 0.311044
+ 78 |  0.30939
+ 79 | 0.306621
+ 80 | 0.303897
+ 81 | 0.301217
+(81 rows)
+
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+  t  |    s     
+-----+----------
+   8 | 0.759109
+   9 | 0.714367
+   7 | 0.694063
+  10 | 0.676445
+  11 | 0.643758
+   6 | 0.623275
+  12 | 0.615194
+  13 | 0.589945
+  14 | 0.567409
+  15 | 0.547127
+   5 | 0.544812
+  16 | 0.528742
+  17 | 0.511973
+  18 | 0.496591
+  19 | 0.482412
+  20 | 0.469285
+  21 | 0.457083
+   4 |  0.45545
+  22 |   0.4457
+  23 | 0.435047
+   2 | 0.428355
+  50 | 0.425793
+  24 | 0.425047
+  51 | 0.420619
+  33 | 0.419273
+  25 | 0.415635
+  52 | 0.415585
+  34 |  0.41221
+  53 | 0.410684
+  26 | 0.406753
+  54 |  0.40591
+  35 | 0.405439
+  55 | 0.401257
+  36 | 0.398938
+  27 | 0.398352
+  56 |  0.39672
+  37 | 0.392689
+  57 | 0.392293
+  28 | 0.390389
+  49 | 0.390116
+  58 | 0.387972
+  38 | 0.386675
+  59 | 0.383752
+  29 | 0.382826
+  39 | 0.380882
+  60 | 0.379628
+  30 |  0.37563
+  61 | 0.375598
+  40 | 0.375295
+  62 | 0.371657
+  41 | 0.369903
+  31 | 0.368771
+  63 | 0.367801
+  42 | 0.364692
+  64 | 0.364028
+  32 | 0.362222
+  65 | 0.360333
+  43 | 0.359654
+  66 | 0.356714
+  44 | 0.354778
+  67 | 0.353168
+  45 | 0.350054
+  68 | 0.349693
+   3 | 0.349116
+  69 | 0.346285
+  46 | 0.345476
+  70 | 0.342942
+  47 | 0.341034
+  71 | 0.339663
+  48 | 0.336722
+  72 | 0.336444
+  73 | 0.333283
+  74 | 0.330179
+  75 |  0.32713
+  76 | 0.324133
+  77 | 0.321188
+  78 | 0.318291
+  79 | 0.315443
+  80 | 0.312641
+  81 | 0.309883
+  82 | 0.307169
+  83 | 0.304497
+   1 | 0.302346
+ 201 | 0.302346
+  84 | 0.301866
+(85 rows)
+
+RESET enable_seqscan;
diff --git a/expected/texti.out b/expected/texti.out
new file mode 100644 (file)
index 0000000..751d140
--- /dev/null
@@ -0,0 +1,41 @@
+SELECT set_smlar_limit(5.0);
+ set_smlar_limit 
+-----------------
+               5
+(1 row)
+
+SET smlar.type='overlap';
+DROP INDEX idx_test_text;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+ smlar 
+-------
+     2
+(1 row)
+
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_text WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+  t  | s  
+-----+----
+ 199 | 10
+ 200 | 10
+ 198 |  9
+ 197 |  8
+ 196 |  7
+ 195 |  6
+ 194 |  5
+(7 rows)
+
+CREATE INDEX idx_test_text ON test_text USING gin (v _text_sml_ops);
+SET enable_seqscan = off;
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_text WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+  t  | s  
+-----+----
+ 199 | 10
+ 200 | 10
+ 198 |  9
+ 197 |  8
+ 196 |  7
+ 195 |  6
+ 194 |  5
+(7 rows)
+
+RESET enable_seqscan;
diff --git a/expected/time.out b/expected/time.out
new file mode 100644 (file)
index 0000000..2fe47ed
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       epoch2timestamp(v)::time
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_time
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_time ON test_time USING gist (v _time_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_time;
+CREATE INDEX idx_test_time ON test_time USING gin (v _time_sml_ops);
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/timestamp.out b/expected/timestamp.out
new file mode 100644 (file)
index 0000000..72ab686
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       epoch2timestamp(v)::timestamp
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_timestamp
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}') ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}') ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_timestamp ON test_timestamp USING gist (v _timestamp_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}') ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}') ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_timestamp;
+CREATE INDEX idx_test_timestamp ON test_timestamp USING gin (v _timestamp_sml_ops);
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}') ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}') ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/timestamptz.out b/expected/timestamptz.out
new file mode 100644 (file)
index 0000000..a73c451
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       epoch2timestamp(v)::timestamptz
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_timestamptz
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_timestamptz ON test_timestamptz USING gist (v _timestamptz_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_timestamptz;
+CREATE INDEX idx_test_timestamptz ON test_timestamptz USING gin (v _timestamptz_sml_ops);
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/timetz.out b/expected/timetz.out
new file mode 100644 (file)
index 0000000..cd5191d
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       epoch2timestamp(v)::timestamptz::timetz
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_timetz
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_timetz ON test_timetz USING gist (v _timetz_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_timetz;
+CREATE INDEX idx_test_timetz ON test_timetz USING gin (v _timetz_sml_ops);
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/varbit.out b/expected/varbit.out
new file mode 100644 (file)
index 0000000..06332ab
--- /dev/null
@@ -0,0 +1,104 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::bit(10)::varbit
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_varbit
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]::varbit[]) AS s FROM test_varbit WHERE v % '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]::varbit[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]::varbit[]) AS s FROM test_varbit WHERE v % '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]::varbit[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_varbit ON test_varbit USING gin (v _varbit_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]::varbit[]) AS s FROM test_varbit WHERE v % '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]::varbit[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]::varbit[]) AS s FROM test_varbit WHERE v % '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]::varbit[] ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/expected/varchar.out b/expected/varchar.out
new file mode 100644 (file)
index 0000000..9fab6c4
--- /dev/null
@@ -0,0 +1,148 @@
+SELECT set_smlar_limit(0.6);
+ set_smlar_limit 
+-----------------
+             0.6
+(1 row)
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::varchar
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_varchar
+FROM
+       generate_series(1, 200) as t;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_varchar WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_varchar WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+CREATE INDEX idx_test_varchar ON test_varchar USING gist (v _varchar_sml_ops);
+SET enable_seqscan=off;
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_varchar WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_varchar WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+DROP INDEX idx_test_varchar;
+CREATE INDEX idx_test_varchar ON test_varchar USING gin (v _varchar_sml_ops);
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_varchar WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+ 10 |        1
+ 11 | 0.953463
+  9 | 0.948683
+ 12 | 0.912871
+  8 | 0.894427
+ 13 | 0.877058
+ 14 | 0.845154
+  7 |  0.83666
+ 15 | 0.816497
+ 16 | 0.790569
+  6 | 0.774597
+ 17 | 0.766965
+ 18 | 0.745356
+ 19 | 0.725476
+  5 | 0.707107
+ 20 | 0.707107
+ 21 | 0.690066
+ 22 |   0.6742
+ 23 |  0.65938
+ 24 | 0.645497
+  4 | 0.632456
+ 25 | 0.632456
+ 26 | 0.620174
+ 27 | 0.608581
+(24 rows)
+
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_varchar WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+ t  |    s     
+----+----------
+  8 | 0.782624
+  9 | 0.737865
+  7 | 0.717137
+ 10 |      0.7
+ 11 | 0.667424
+  6 | 0.645497
+ 12 |  0.63901
+ 13 | 0.613941
+(8 rows)
+
+SET enable_seqscan=on;
diff --git a/smlar--1.0.sql b/smlar--1.0.sql
new file mode 100644 (file)
index 0000000..db361c0
--- /dev/null
@@ -0,0 +1,714 @@
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION smlar" to load this file. \quit
+
+CREATE OR REPLACE FUNCTION smlar(anyarray, anyarray)
+       RETURNS float4
+       AS      'MODULE_PATHNAME', 'arraysml'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION smlar(anyarray, anyarray, bool)
+       RETURNS float4
+       AS      'MODULE_PATHNAME', 'arraysmlw'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION smlar(anyarray, anyarray, text)
+    RETURNS float4
+       AS  'MODULE_PATHNAME', 'arraysml_func'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION set_smlar_limit(float4)
+       RETURNS float4
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION show_smlar_limit()
+       RETURNS float4
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C STRICT STABLE;
+
+CREATE OR REPLACE FUNCTION smlar_op(anyarray,anyarray)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'arraysml_op'
+       LANGUAGE C STRICT STABLE;
+
+CREATE OPERATOR % (
+       LEFTARG = anyarray,
+       RIGHTARG = anyarray,
+       PROCEDURE = smlar_op,
+       COMMUTATOR = '%',
+       RESTRICT = contsel,
+       JOIN = contjoinsel
+);
+
+--
+
+CREATE OR REPLACE FUNCTION tsvector2textarray(tsvector)
+       RETURNS _text
+       AS 'MODULE_PATHNAME', 'tsvector2textarray'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION array_unique(anyarray)
+       RETURNS anyarray
+       AS      'MODULE_PATHNAME', 'array_unique'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION inarray(anyarray, anyelement)
+       RETURNS float4
+       AS      'MODULE_PATHNAME', 'inarray'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION inarray(anyarray, anyelement, float4, float4)
+       RETURNS float4
+       AS      'MODULE_PATHNAME', 'inarray'
+       LANGUAGE C STRICT IMMUTABLE;
+
+--gist key
+
+CREATE OR REPLACE FUNCTION gsmlsign_in(cstring)
+       RETURNS gsmlsign
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C STRICT;
+
+CREATE OR REPLACE FUNCTION gsmlsign_out(gsmlsign)
+       RETURNS cstring
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C STRICT;
+
+CREATE TYPE gsmlsign (
+       INTERNALLENGTH = -1,
+       INPUT = gsmlsign_in,
+       OUTPUT = gsmlsign_out
+);
+
+-- support functions for gist
+CREATE OR REPLACE FUNCTION gsmlsign_consistent(gsmlsign,internal,int4)
+       RETURNS bool
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_compress(internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_decompress(internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_penalty(internal,internal,internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_picksplit(internal, internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_union(bytea, internal)
+       RETURNS _int4
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_same(gsmlsign, gsmlsign, internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+--create the operator classes for gist
+
+CREATE OPERATOR CLASS _int2_sml_ops
+FOR TYPE _int2 USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _int4_sml_ops
+FOR TYPE _int4 USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _int8_sml_ops
+FOR TYPE _int8 USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _float4_sml_ops
+FOR TYPE _float4 USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _float8_sml_ops
+FOR TYPE _float8 USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+-- money type hasn't hash support
+--CREATE OPERATOR CLASS _money_sml_ops
+--FOR TYPE _money USING gist
+--AS
+--     OPERATOR        1       && (anyarray, anyarray),
+--     OPERATOR        2       % (anyarray, anyarray),
+--     FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+--     FUNCTION        2       gsmlsign_union (bytea, internal),
+--     FUNCTION        3       gsmlsign_compress (internal),
+--     FUNCTION        4       gsmlsign_decompress (internal),
+--     FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+--     FUNCTION        6       gsmlsign_picksplit (internal, internal),
+--     FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+--STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _oid_sml_ops
+FOR TYPE _oid USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _timestamp_sml_ops
+FOR TYPE _timestamp USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _timestamptz_sml_ops
+FOR TYPE _timestamptz USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _time_sml_ops
+FOR TYPE _time USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _timetz_sml_ops
+FOR TYPE _timetz USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _date_sml_ops
+FOR TYPE _date USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _interval_sml_ops
+FOR TYPE _interval USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _macaddr_sml_ops
+FOR TYPE _macaddr USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _inet_sml_ops
+FOR TYPE _inet USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _cidr_sml_ops
+FOR TYPE _cidr USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _text_sml_ops
+FOR TYPE _text USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _varchar_sml_ops
+FOR TYPE _varchar USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _char_sml_ops
+FOR TYPE _char USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _bytea_sml_ops
+FOR TYPE _bytea USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+--no hash 
+--CREATE OPERATOR CLASS _bit_sml_ops
+--FOR TYPE _bit USING gist
+--AS
+--     OPERATOR        1       && (anyarray, anyarray),
+--     OPERATOR        2       % (anyarray, anyarray),
+--     FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+--     FUNCTION        2       gsmlsign_union (bytea, internal),
+--     FUNCTION        3       gsmlsign_compress (internal),
+--     FUNCTION        4       gsmlsign_decompress (internal),
+--     FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+--     FUNCTION        6       gsmlsign_picksplit (internal, internal),
+--     FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+--STORAGE         gsmlsign;
+
+--CREATE OPERATOR CLASS _varbit_sml_ops
+--FOR TYPE _varbit USING gist
+--AS
+--     OPERATOR        1       && (anyarray, anyarray),
+--     OPERATOR        2       % (anyarray, anyarray),
+--     FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+--     FUNCTION        2       gsmlsign_union (bytea, internal),
+--     FUNCTION        3       gsmlsign_compress (internal),
+--     FUNCTION        4       gsmlsign_decompress (internal),
+--     FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+--     FUNCTION        6       gsmlsign_picksplit (internal, internal),
+--     FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+--STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _numeric_sml_ops
+FOR TYPE _numeric USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+--gin support functions
+CREATE OR REPLACE FUNCTION smlararrayextract(anyarray, internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION smlarqueryarrayextract(anyarray, internal, internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION smlararrayconsistent(internal, internal, anyarray)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+--gin opclasses
+
+CREATE OPERATOR CLASS _int2_sml_ops
+FOR TYPE _int2 USING gin
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       %  (anyarray, anyarray),
+       FUNCTION        1       btint2cmp(int2,int2),
+       FUNCTION        2       smlararrayextract(anyarray, internal),
+       FUNCTION        3       smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION        4       smlararrayconsistent(internal, internal, anyarray),
+       STORAGE         int2;
+CREATE OPERATOR CLASS _int4_sml_ops
+FOR TYPE _int4  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btint4cmp(int4,int4),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     int4;
+
+CREATE OPERATOR CLASS _int8_sml_ops
+FOR TYPE _int8  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btint8cmp(int8,int8),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     int8;
+
+CREATE OPERATOR CLASS _float4_sml_ops
+FOR TYPE _float4  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btfloat4cmp(float4,float4),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     float4;
+
+CREATE OPERATOR CLASS _float8_sml_ops
+FOR TYPE _float8  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btfloat8cmp(float8,float8),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     float8;
+
+CREATE OPERATOR CLASS _money_sml_ops
+FOR TYPE _money  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   cash_cmp(money,money),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     money;
+
+CREATE OPERATOR CLASS _oid_sml_ops
+FOR TYPE _oid  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btoidcmp(oid,oid),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     oid;
+
+CREATE OPERATOR CLASS _timestamp_sml_ops
+FOR TYPE _timestamp  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   timestamp_cmp(timestamp,timestamp),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     timestamp;
+
+CREATE OPERATOR CLASS _timestamptz_sml_ops
+FOR TYPE _timestamptz  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   timestamptz_cmp(timestamptz,timestamptz),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     timestamptz;
+
+CREATE OPERATOR CLASS _time_sml_ops
+FOR TYPE _time  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   time_cmp(time,time),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     time;
+
+CREATE OPERATOR CLASS _timetz_sml_ops
+FOR TYPE _timetz  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   timetz_cmp(timetz,timetz),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     timetz;
+
+CREATE OPERATOR CLASS _date_sml_ops
+FOR TYPE _date  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   date_cmp(date,date),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     date;
+
+CREATE OPERATOR CLASS _interval_sml_ops
+FOR TYPE _interval  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   interval_cmp(interval,interval),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     interval;
+
+CREATE OPERATOR CLASS _macaddr_sml_ops
+FOR TYPE _macaddr  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   macaddr_cmp(macaddr,macaddr),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     macaddr;
+
+CREATE OPERATOR CLASS _inet_sml_ops
+FOR TYPE _inet  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   network_cmp(inet,inet),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     inet;
+
+CREATE OPERATOR CLASS _cidr_sml_ops
+FOR TYPE _cidr  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   network_cmp(inet,inet),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     cidr;
+
+CREATE OPERATOR CLASS _text_sml_ops
+FOR TYPE _text  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   bttextcmp(text,text),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     text;
+
+CREATE OPERATOR CLASS _varchar_sml_ops
+FOR TYPE _varchar  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   bttextcmp(text,text),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     varchar;
+
+CREATE OPERATOR CLASS _char_sml_ops
+FOR TYPE "_char"  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btcharcmp("char","char"),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     "char";
+
+CREATE OPERATOR CLASS _bytea_sml_ops
+FOR TYPE _bytea  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   byteacmp(bytea,bytea),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     bytea;
+
+CREATE OPERATOR CLASS _bit_sml_ops
+FOR TYPE _bit  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   bitcmp(bit,bit),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     bit;
+
+CREATE OPERATOR CLASS _varbit_sml_ops
+FOR TYPE _varbit  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   varbitcmp(varbit,varbit),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     varbit;
+
+CREATE OPERATOR CLASS _numeric_sml_ops
+FOR TYPE _numeric  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   numeric_cmp(numeric,numeric),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     numeric;
+
diff --git a/smlar--unpackaged--1.0.sql b/smlar--unpackaged--1.0.sql
new file mode 100644 (file)
index 0000000..36f8720
--- /dev/null
@@ -0,0 +1,125 @@
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION extension_name" to load this file. \quit
+
+ALTER EXTENSION smlar ADD FUNCTION tsvector2textarray(tsvector);
+ALTER EXTENSION smlar ADD FUNCTION array_unique(anyarray);
+ALTER EXTENSION smlar ADD FUNCTION inarray(anyarray, anyelement);
+ALTER EXTENSION smlar ADD FUNCTION inarray(anyarray, anyelement, float4, float4);
+
+ALTER EXTENSION smlar ADD FUNCTION smlar(anyarray, anyarray);
+ALTER EXTENSION smlar ADD FUNCTION smlar(anyarray, anyarray, bool);
+ALTER EXTENSION smlar ADD FUNCTION smlar(anyarray, anyarray, text);
+ALTER EXTENSION smlar ADD FUNCTION set_smlar_limit(float4);
+ALTER EXTENSION smlar ADD FUNCTION show_smlar_limit();
+ALTER EXTENSION smlar ADD FUNCTION smlar_op(anyarray,anyarray);
+ALTER EXTENSION smlar ADD OPERATOR % (anyarray,anyarray);
+
+ALTER EXTENSION smlar ADD FUNCTION gsmlsign_out(gsmlsign);
+ALTER EXTENSION smlar ADD FUNCTION gsmlsign_in(cstring);
+ALTER EXTENSION smlar ADD TYPE gsmlsign;
+
+ALTER EXTENSION smlar ADD FUNCTION gsmlsign_consistent(gsmlsign,internal,int4);
+ALTER EXTENSION smlar ADD FUNCTION gsmlsign_compress(internal);
+ALTER EXTENSION smlar ADD FUNCTION gsmlsign_decompress(internal);
+ALTER EXTENSION smlar ADD FUNCTION gsmlsign_penalty(internal,internal,internal);
+ALTER EXTENSION smlar ADD FUNCTION gsmlsign_picksplit(internal, internal);
+ALTER EXTENSION smlar ADD FUNCTION gsmlsign_union(bytea, internal);
+ALTER EXTENSION smlar ADD FUNCTION gsmlsign_same(gsmlsign, gsmlsign, internal);
+
+ALTER EXTENSION smlar ADD FUNCTION smlararrayextract(anyarray, internal);
+ALTER EXTENSION smlar ADD FUNCTION smlarqueryarrayextract(anyarray, internal, internal);
+ALTER EXTENSION smlar ADD FUNCTION smlararrayconsistent(internal, internal, anyarray);
+
+ALTER EXTENSION smlar ADD OPERATOR CLASS _int2_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _int4_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _int8_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _float4_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _float8_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _money_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _oid_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _timestamp_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _timestamptz_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _time_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _timetz_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _date_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _interval_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _macaddr_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _inet_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _cidr_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _text_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _varchar_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _char_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _bytea_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _bit_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _varbit_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _numeric_sml_ops USING gin;
+
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _int2_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _int4_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _int8_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _float4_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _float8_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _money_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _oid_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _timestamp_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _timestamptz_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _time_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _timetz_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _date_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _interval_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _macaddr_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _inet_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _cidr_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _text_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _varchar_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _char_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _bytea_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _bit_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _varbit_sml_ops USING gin;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _numeric_sml_ops USING gin;
+
+ALTER EXTENSION smlar ADD OPERATOR CLASS _int2_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _int4_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _int8_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _float4_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _float8_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _oid_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _timestamp_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _timestamptz_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _time_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _timetz_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _date_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _interval_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _macaddr_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _inet_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _cidr_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _text_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _varchar_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _char_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _bytea_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR CLASS _numeric_sml_ops USING gist;
+
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _int2_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _int4_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _int8_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _float4_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _float8_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _oid_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _timestamp_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _timestamptz_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _time_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _timetz_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _date_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _interval_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _macaddr_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _inet_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _cidr_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _text_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _varchar_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _char_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _bytea_sml_ops USING gist;
+ALTER EXTENSION smlar ADD OPERATOR FAMILY _numeric_sml_ops USING gist;
+
+
+
+
diff --git a/smlar.c b/smlar.c
new file mode 100644 (file)
index 0000000..84fc344
--- /dev/null
+++ b/smlar.c
@@ -0,0 +1,992 @@
+#include "smlar.h"
+
+#include "fmgr.h"
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/nbtree.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_amproc.h"
+#include "catalog/pg_cast.h"
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_type.h"
+#include "executor/spi.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/tqual.h"
+#include "utils/syscache.h"
+#include "utils/typcache.h"
+
+PG_MODULE_MAGIC;
+
+static Oid
+getDefaultOpclass(Oid amoid, Oid typid) 
+{
+       ScanKeyData     skey;
+       SysScanDesc     scan;
+       HeapTuple       tuple;
+       Relation        heapRel;
+       Oid                     opclassOid = InvalidOid;
+
+       heapRel = heap_open(OperatorClassRelationId, AccessShareLock);  
+
+       ScanKeyInit(&skey,
+                               Anum_pg_opclass_opcmethod,
+                               BTEqualStrategyNumber,  F_OIDEQ,
+                               ObjectIdGetDatum(amoid));
+
+       scan = systable_beginscan(heapRel, 
+                                                               OpclassAmNameNspIndexId, true, 
+                                                               SnapshotNow, 1, &skey);
+
+       while (HeapTupleIsValid((tuple = systable_getnext(scan))))
+       {
+               Form_pg_opclass opclass = (Form_pg_opclass)GETSTRUCT(tuple);
+
+               if ( opclass->opcintype == typid && opclass->opcdefault )
+               {
+                       if ( OidIsValid(opclassOid) )
+                               elog(ERROR, "Ambiguous opclass for type %u (access method %u)", typid, amoid); 
+                       opclassOid = HeapTupleGetOid(tuple);
+               }
+       }
+
+       systable_endscan(scan);
+       heap_close(heapRel, AccessShareLock);
+
+       return opclassOid;
+}
+
+static Oid
+getAMProc(Oid amoid, Oid typid) 
+{
+       Oid             opclassOid = getDefaultOpclass(amoid, typid);
+       Oid             procOid = InvalidOid;
+       Oid             opfamilyOid;
+       ScanKeyData     skey[4];
+       SysScanDesc     scan;
+       HeapTuple       tuple;
+       Relation        heapRel;
+
+       if ( !OidIsValid(opclassOid) )
+       {
+               typid = getBaseType(typid);
+               opclassOid = getDefaultOpclass(amoid, typid);
+       }
+
+       if ( !OidIsValid(opclassOid) )
+       {
+               CatCList        *catlist;
+               int                     i;
+
+               /*
+                * Search binary-coercible type
+                */
+               catlist = SearchSysCacheList(CASTSOURCETARGET, 1,
+                                                                               ObjectIdGetDatum(typid),
+                                                                               0, 0, 0);
+
+               for (i = 0; i < catlist->n_members; i++)
+               {
+                       HeapTuple       tuple = &catlist->members[i]->tuple;
+                       Form_pg_cast    castForm = (Form_pg_cast)GETSTRUCT(tuple);
+
+                       if ( castForm->castfunc == InvalidOid && castForm->castcontext == COERCION_CODE_IMPLICIT )
+                       {
+                               typid = castForm->casttarget;
+                               opclassOid = getDefaultOpclass(amoid, typid);
+                               if( OidIsValid(opclassOid) )
+                                       break;
+                       }
+               }
+
+               ReleaseSysCacheList(catlist);
+       }
+       
+       if ( !OidIsValid(opclassOid) )
+               return InvalidOid;
+
+       opfamilyOid = get_opclass_family(opclassOid);
+
+       heapRel = heap_open(AccessMethodProcedureRelationId, AccessShareLock);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_amproc_amprocfamily,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(opfamilyOid));
+       ScanKeyInit(&skey[1],
+                               Anum_pg_amproc_amproclefttype,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(typid));
+       ScanKeyInit(&skey[2],
+                               Anum_pg_amproc_amprocrighttype,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(typid));
+#if PG_VERSION_NUM >= 90200
+       ScanKeyInit(&skey[3],
+                               Anum_pg_amproc_amprocnum,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               Int32GetDatum(BTORDER_PROC));
+#endif
+
+       scan = systable_beginscan(heapRel, AccessMethodProcedureIndexId, true,
+                                                               SnapshotNow, 
+#if PG_VERSION_NUM >= 90200
+                                                               4,
+#else
+                                                               3,
+#endif
+                                                               skey);
+       while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+       {
+               Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(tuple);
+
+               switch(amoid)
+               {
+                       case BTREE_AM_OID:
+                       case HASH_AM_OID:
+                               if ( OidIsValid(procOid) )
+                                       elog(ERROR,"Ambiguous support function for type %u (opclass %u)", typid, opfamilyOid);
+                               procOid = amprocform->amproc;
+                               break;
+                       default:
+                               elog(ERROR,"Unsupported access method");
+               }
+       }
+
+       systable_endscan(scan);
+       heap_close(heapRel, AccessShareLock);
+
+       return procOid;
+}
+
+static ProcTypeInfo *cacheProcs = NULL;
+static int nCacheProcs = 0;
+
+static ProcTypeInfo
+fillProcs(Oid typid)
+{
+       ProcTypeInfo    info = malloc(sizeof(ProcTypeInfoData));
+
+       if (!info)
+               elog(ERROR, "Can't allocate %u memory", (uint32)sizeof(ProcTypeInfoData));
+
+       info->typid = typid;
+       info->typtype = get_typtype(typid);
+
+       if (info->typtype == 'c')
+       {
+               /* composite type */
+               TupleDesc               tupdesc;
+               MemoryContext   oldcontext;
+
+               tupdesc = lookup_rowtype_tupdesc(typid, -1);
+
+               if (tupdesc->natts != 2)
+                       elog(ERROR,"Composite type has wrong number of fields");
+               if (tupdesc->attrs[1]->atttypid != FLOAT4OID)
+                       elog(ERROR,"Second field of composite type is not float4");
+
+               oldcontext = MemoryContextSwitchTo(TopMemoryContext);
+               info->tupDesc = CreateTupleDescCopyConstr(tupdesc);
+               MemoryContextSwitchTo(oldcontext);
+
+               ReleaseTupleDesc(tupdesc);
+
+               info->cmpFuncOid = getAMProc(BTREE_AM_OID, info->tupDesc->attrs[0]->atttypid);
+               info->hashFuncOid = getAMProc(HASH_AM_OID, info->tupDesc->attrs[0]->atttypid);
+       } 
+       else 
+       {
+               info->tupDesc = NULL;
+
+               /* plain type */
+               info->cmpFuncOid = getAMProc(BTREE_AM_OID, typid);
+               info->hashFuncOid = getAMProc(HASH_AM_OID, typid);
+       }
+
+       get_typlenbyvalalign(typid, &info->typlen, &info->typbyval, &info->typalign);
+       info->hashFuncInited = info->cmpFuncInited = false;
+
+
+       return info;
+}
+
+void
+getFmgrInfoCmp(ProcTypeInfo info)
+{
+       if ( info->cmpFuncInited == false )
+       {
+               if ( !OidIsValid(info->cmpFuncOid) )
+                       elog(ERROR, "Could not find cmp function for type %u", info->typid);
+
+               fmgr_info_cxt( info->cmpFuncOid, &info->cmpFunc, TopMemoryContext );
+               info->cmpFuncInited = true;
+       }
+}
+
+void
+getFmgrInfoHash(ProcTypeInfo info)
+{
+       if ( info->hashFuncInited == false )
+       {
+               if ( !OidIsValid(info->hashFuncOid) )
+                       elog(ERROR, "Could not find hash function for type %u", info->typid);
+
+               fmgr_info_cxt( info->hashFuncOid, &info->hashFunc, TopMemoryContext );
+               info->hashFuncInited = true;
+       }
+}
+
+static int
+cmpProcTypeInfo(const void *a, const void *b)
+{
+       ProcTypeInfo av = *(ProcTypeInfo*)a;
+       ProcTypeInfo bv = *(ProcTypeInfo*)b;
+
+       Assert( av->typid != bv->typid );
+
+       return ( av->typid > bv->typid ) ? 1 : -1; 
+}
+
+ProcTypeInfo
+findProcs(Oid typid)
+{
+       ProcTypeInfo    info = NULL;
+
+       if ( nCacheProcs == 1 )
+       {
+               if ( cacheProcs[0]->typid == typid ) 
+               {
+                       /*cacheProcs[0]->hashFuncInited = cacheProcs[0]->cmpFuncInited = false;*/
+                       return cacheProcs[0];
+               }
+       }
+       else if ( nCacheProcs > 1 )
+       {
+               ProcTypeInfo    *StopMiddle;
+               ProcTypeInfo    *StopLow = cacheProcs, 
+                                               *StopHigh = cacheProcs + nCacheProcs;
+
+               while (StopLow < StopHigh) {
+                       StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
+                       info = *StopMiddle;
+
+                       if ( info->typid == typid )
+                       {
+                               /* info->hashFuncInited = info->cmpFuncInited = false; */
+                               return info;
+                       }
+                       else if ( info->typid < typid )
+                               StopLow = StopMiddle + 1;
+                       else
+                               StopHigh = StopMiddle;
+               }
+
+               /* not found */
+       } 
+
+       info = fillProcs(typid);
+       if ( nCacheProcs == 0 ) 
+       {
+               cacheProcs = malloc(sizeof(ProcTypeInfo));
+
+               if (!cacheProcs)
+                       elog(ERROR, "Can't allocate %u memory", (uint32)sizeof(ProcTypeInfo));
+               else
+               {
+                       nCacheProcs = 1;
+                       cacheProcs[0] = info;
+               }
+       }
+       else
+       {
+               ProcTypeInfo    *cacheProcsTmp = realloc(cacheProcs, (nCacheProcs+1) * sizeof(ProcTypeInfo));
+
+               if (!cacheProcsTmp)
+                       elog(ERROR, "Can't allocate %u memory", (uint32)sizeof(ProcTypeInfo) * (nCacheProcs+1));
+               else
+               {
+                       cacheProcs = cacheProcsTmp;
+                       cacheProcs[ nCacheProcs ] = info;
+                       nCacheProcs++;
+                       qsort(cacheProcs, nCacheProcs, sizeof(ProcTypeInfo), cmpProcTypeInfo);
+               }
+       }
+
+       /* info->hashFuncInited = info->cmpFuncInited = false; */
+
+       return info;
+}
+
+/*
+ * WARNING. Array2SimpleArray* doesn't copy Datum!
+ */
+SimpleArray * 
+Array2SimpleArray(ProcTypeInfo info, ArrayType *a)
+{
+       SimpleArray     *s = palloc(sizeof(SimpleArray));
+
+       CHECKARRVALID(a);
+
+       if ( info == NULL )
+               info = findProcs(ARR_ELEMTYPE(a));
+
+       s->info = info;
+       s->df = NULL;
+       s->hash = NULL;
+
+       deconstruct_array(a, info->typid,
+                                               info->typlen, info->typbyval, info->typalign,
+                                               &s->elems, NULL, &s->nelems);
+
+       return s;
+}
+
+static Datum
+deconstructCompositeType(ProcTypeInfo info, Datum in, double *weight)
+{
+       HeapTupleHeader rec = DatumGetHeapTupleHeader(in);
+       HeapTupleData   tuple;
+       Datum                   values[2];
+       bool                    nulls[2];
+
+       /* Build a temporary HeapTuple control structure */
+       tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
+       ItemPointerSetInvalid(&(tuple.t_self));
+       tuple.t_tableOid = InvalidOid;
+       tuple.t_data = rec;
+
+       heap_deform_tuple(&tuple, info->tupDesc, values, nulls);
+       if (nulls[0] || nulls[1])
+               elog(ERROR, "Both fields in composite type could not be NULL");
+
+       if (weight)
+               *weight = DatumGetFloat4(values[1]);
+       return values[0];
+}
+
+static int
+cmpArrayElem(const void *a, const void *b, void *arg)
+{
+       ProcTypeInfo    info = (ProcTypeInfo)arg;
+
+       if (info->tupDesc) 
+               /* composite type */
+               return DatumGetInt32( FCall2( &info->cmpFunc,
+                                                                                       deconstructCompositeType(info, *(Datum*)a, NULL),
+                                                                                       deconstructCompositeType(info, *(Datum*)b, NULL) ) );
+
+       return DatumGetInt32( FCall2( &info->cmpFunc,
+                                                       *(Datum*)a, *(Datum*)b ) );
+}
+
+SimpleArray *
+Array2SimpleArrayS(ProcTypeInfo info, ArrayType *a)
+{
+       SimpleArray     *s = Array2SimpleArray(info, a);
+
+       if ( s->nelems > 1 )
+       {
+               getFmgrInfoCmp(s->info);
+
+               qsort_arg(s->elems, s->nelems, sizeof(Datum), cmpArrayElem, s->info);
+       }
+
+       return s;
+}
+
+typedef struct cmpArrayElemData {
+       ProcTypeInfo    info;
+       bool                    hasDuplicate;
+
+} cmpArrayElemData;
+
+static int
+cmpArrayElemArg(const void *a, const void *b, void *arg)
+{
+    cmpArrayElemData    *data = (cmpArrayElemData*)arg;
+       int res;
+
+       if (data->info->tupDesc)
+               res =  DatumGetInt32( FCall2( &data->info->cmpFunc,
+                                                                                       deconstructCompositeType(data->info, *(Datum*)a, NULL),
+                                                                                       deconstructCompositeType(data->info, *(Datum*)b, NULL) ) );
+       else
+               res = DatumGetInt32( FCall2( &data->info->cmpFunc,
+                                                               *(Datum*)a, *(Datum*)b ) );
+
+       if ( res == 0 )
+               data->hasDuplicate = true;
+
+       return res;
+}
+
+/*
+ * Uniquefy array and calculate TF. Although 
+ * result doesn't depend on normalization, we
+ * normalize TF by length array to have possiblity
+ * to limit estimation for index support.
+ *
+ * Cache signals of needing of TF caclulation
+ */
+
+SimpleArray *
+Array2SimpleArrayU(ProcTypeInfo info, ArrayType *a, void *cache)
+{
+       SimpleArray     *s = Array2SimpleArray(info, a);
+       StatElem        *stat = NULL;
+
+       if ( s->nelems > 0 && cache )
+       {
+               s->df = palloc(sizeof(double) * s->nelems);
+               s->df[0] = 1.0; /* init */
+       }
+
+       if ( s->nelems > 1 )
+       {
+               cmpArrayElemData        data;
+               int                             i;
+
+               getFmgrInfoCmp(s->info);
+               data.info = s->info;
+               data.hasDuplicate = false;
+
+               qsort_arg(s->elems, s->nelems, sizeof(Datum), cmpArrayElemArg, &data);
+
+               if ( data.hasDuplicate )
+               {
+                       Datum   *tmp,
+                                       *dr,
+                                       *data;
+                       int             num = s->nelems,
+                                       cmp;
+
+                       data = tmp = dr = s->elems;
+
+                       while (tmp - data < num)
+                       {
+                               cmp = (tmp == dr) ? 0 : cmpArrayElem(tmp, dr, s->info);
+                               if ( cmp != 0 )
+                               {
+                                       *(++dr) = *tmp++;
+                                       if ( cache ) 
+                                               s->df[ dr - data ] = 1.0;
+                               }
+                               else
+                               {
+                                       if ( cache )
+                                               s->df[ dr - data ] += 1.0;
+                                       tmp++;
+                               }
+                       }
+
+                       s->nelems = dr + 1 - s->elems;
+
+                       if ( cache )
+                       {
+                               int tfm = getTFMethod();
+
+                               for(i=0;i<s->nelems;i++)
+                               {
+                                       stat = fingArrayStat(cache, s->info->typid, s->elems[i], stat);
+                                       if ( stat )
+                                       {
+                                               switch(tfm)
+                                               {
+                                                       case TF_LOG:
+                                                               s->df[i] = (1.0 + log( s->df[i] ));
+                                                       case TF_N:
+                                                               s->df[i] *= stat->idf;
+                                                               break;
+                                                       case TF_CONST:
+                                                               s->df[i] = stat->idf;
+                                                               break;
+                                                       default:
+                                                               elog(ERROR,"Unknown TF method: %d", tfm);
+                                               }       
+                                       }
+                                       else
+                                       {
+                                               s->df[i] = 0.0; /* unknown word */
+                                       }
+                               }       
+                       }
+               }
+               else if ( cache )
+               {
+                       for(i=0;i<s->nelems;i++)
+                       {
+                               stat = fingArrayStat(cache, s->info->typid, s->elems[i], stat);
+                               if ( stat )
+                                       s->df[i] = stat->idf;
+                               else
+                                       s->df[i] = 0.0;
+                       }
+               }
+       }
+       else if (s->nelems > 0 && cache) 
+       {
+               stat = fingArrayStat(cache, s->info->typid, s->elems[0], stat);
+               if ( stat )
+                       s->df[0] = stat->idf;
+               else
+                       s->df[0] = 0.0;
+       }
+
+       return s;
+}
+
+static int
+numOfIntersect(SimpleArray *a, SimpleArray *b)
+{
+       int                             cnt = 0,
+                                       cmp;
+       Datum                   *aptr = a->elems,
+                                       *bptr = b->elems;
+       ProcTypeInfo    info = a->info;
+
+       Assert( a->info->typid == b->info->typid );
+
+       getFmgrInfoCmp(info);
+
+       while( aptr - a->elems < a->nelems && bptr - b->elems < b->nelems )
+       {
+               cmp = cmpArrayElem(aptr, bptr, info);
+               if ( cmp < 0 )
+                       aptr++;
+               else if ( cmp > 0 )
+                       bptr++;
+               else
+               {
+                       cnt++;
+                       aptr++;
+                       bptr++;
+               }
+       }
+
+       return cnt;
+}
+
+static double
+TFIDFSml(SimpleArray *a, SimpleArray *b)
+{
+       int                             cmp;
+       Datum                   *aptr = a->elems,
+                                       *bptr = b->elems;
+       ProcTypeInfo    info = a->info;
+       double                  res = 0.0;
+       double                  suma = 0.0, sumb = 0.0;
+
+       Assert( a->info->typid == b->info->typid );
+       Assert( a->df );
+       Assert( b->df );
+
+       getFmgrInfoCmp(info);
+
+       while( aptr - a->elems < a->nelems && bptr - b->elems < b->nelems )
+       {
+               cmp = cmpArrayElem(aptr, bptr, info);
+               if ( cmp < 0 )
+               {
+                       suma += a->df[ aptr - a->elems ] * a->df[ aptr - a->elems ];
+                       aptr++;
+               }
+               else if ( cmp > 0 )
+               {
+                       sumb += b->df[ bptr - b->elems ] * b->df[ bptr - b->elems ];
+                       bptr++;
+               }
+               else
+               {
+                       res += a->df[ aptr - a->elems ] * b->df[ bptr - b->elems ];
+                       suma += a->df[ aptr - a->elems ] * a->df[ aptr - a->elems ];
+                       sumb += b->df[ bptr - b->elems ] * b->df[ bptr - b->elems ];
+                       aptr++;
+                       bptr++;
+               }
+       }
+
+       /*
+        * Compute last elements
+        */
+       while( aptr - a->elems < a->nelems )
+       {
+               suma += a->df[ aptr - a->elems ] * a->df[ aptr - a->elems ];
+               aptr++;
+       }
+
+       while( bptr - b->elems < b->nelems )
+       {
+               sumb += b->df[ bptr - b->elems ] * b->df[ bptr - b->elems ];
+               bptr++;
+       }
+
+       if ( suma > 0.0 && sumb > 0.0 )
+               res = res / sqrt( suma * sumb );
+       else
+               res = 0.0;
+
+       return res;
+}
+
+
+PG_FUNCTION_INFO_V1(arraysml);
+Datum  arraysml(PG_FUNCTION_ARGS);
+Datum
+arraysml(PG_FUNCTION_ARGS)
+{
+       ArrayType               *a, *b;
+       SimpleArray             *sa, *sb;
+       
+       fcinfo->flinfo->fn_extra = SearchArrayCache( 
+                                                       fcinfo->flinfo->fn_extra,
+                                                       fcinfo->flinfo->fn_mcxt,
+                                                       PG_GETARG_DATUM(0), &a, &sa, NULL);
+       fcinfo->flinfo->fn_extra = SearchArrayCache( 
+                                                       fcinfo->flinfo->fn_extra,
+                                                       fcinfo->flinfo->fn_mcxt,
+                                                       PG_GETARG_DATUM(1), &b, &sb, NULL);
+
+       if ( ARR_ELEMTYPE(a) != ARR_ELEMTYPE(b) )
+               elog(ERROR,"Arguments array are not the same type!");
+
+       if (ARRISVOID(a) || ARRISVOID(b))
+                PG_RETURN_FLOAT4(0.0);
+
+       switch(getSmlType())
+       {
+               case    ST_TFIDF:
+                       PG_RETURN_FLOAT4( TFIDFSml(sa, sb) );
+                       break;
+               case    ST_COSINE:
+                       {
+                               int                             cnt;
+                               double                  power;
+
+                               power = ((double)(sa->nelems)) * ((double)(sb->nelems));
+                               cnt = numOfIntersect(sa, sb);
+
+                               PG_RETURN_FLOAT4(  ((double)cnt) / sqrt( power ) );
+                       }
+                       break;
+               case    ST_OVERLAP:
+                       {
+                               float4 res = (float4)numOfIntersect(sa, sb);
+
+                               PG_RETURN_FLOAT4(res);
+                       }
+                       break;
+               default:
+                       elog(ERROR,"Unsupported formula type of similarity");
+       }
+
+       PG_RETURN_FLOAT4(0.0); /* keep compiler quiet */ 
+}
+
+PG_FUNCTION_INFO_V1(arraysmlw);
+Datum  arraysmlw(PG_FUNCTION_ARGS);
+Datum
+arraysmlw(PG_FUNCTION_ARGS)
+{
+       ArrayType               *a, *b;
+       SimpleArray             *sa, *sb;
+       bool                    useIntersect = PG_GETARG_BOOL(2);
+       double                  numerator = 0.0;
+       double                  denominatorA = 0.0,
+                                       denominatorB = 0.0,
+                                       tmpA, tmpB;
+       int                             cmp;
+       ProcTypeInfo    info;
+       int                             ai = 0, bi = 0;
+
+       
+       fcinfo->flinfo->fn_extra = SearchArrayCache( 
+                                                       fcinfo->flinfo->fn_extra,
+                                                       fcinfo->flinfo->fn_mcxt,
+                                                       PG_GETARG_DATUM(0), &a, &sa, NULL);
+       fcinfo->flinfo->fn_extra = SearchArrayCache( 
+                                                       fcinfo->flinfo->fn_extra,
+                                                       fcinfo->flinfo->fn_mcxt,
+                                                       PG_GETARG_DATUM(1), &b, &sb, NULL);
+
+       if ( ARR_ELEMTYPE(a) != ARR_ELEMTYPE(b) )
+               elog(ERROR,"Arguments array are not the same type!");
+
+       if (ARRISVOID(a) || ARRISVOID(b))
+                PG_RETURN_FLOAT4(0.0);
+
+       info = sa->info;
+       if (info->tupDesc == NULL)
+               elog(ERROR, "Only weigthed (composite) types should be used");
+       getFmgrInfoCmp(info);
+
+       while(ai < sa->nelems && bi < sb->nelems)
+       {
+               Datum   ad = deconstructCompositeType(info, sa->elems[ai], &tmpA),
+                               bd = deconstructCompositeType(info, sb->elems[bi], &tmpB);
+
+               cmp = DatumGetInt32(FCall2(&info->cmpFunc, ad, bd));
+
+               if ( cmp < 0 ) {
+                       if (useIntersect == false)
+                               denominatorA += tmpA * tmpA;
+                       ai++;
+               } else if ( cmp > 0 ) {
+                       if (useIntersect == false)
+                               denominatorB += tmpB * tmpB;
+                       bi++;
+               } else {
+                       denominatorA += tmpA * tmpA;
+                       denominatorB += tmpB * tmpB;
+                       numerator += tmpA * tmpB;
+                       ai++;
+                       bi++;
+               }
+       }
+
+       if (useIntersect == false) {
+               while(ai < sa->nelems) {
+                       deconstructCompositeType(info, sa->elems[ai], &tmpA);
+                       denominatorA += tmpA * tmpA;
+                       ai++;
+               }
+
+               while(bi < sb->nelems) {
+                       deconstructCompositeType(info, sb->elems[bi], &tmpB);
+                       denominatorB += tmpB * tmpB;
+                       bi++;
+               }
+       }
+
+       if (numerator != 0.0) {
+               numerator = numerator / sqrt( denominatorA * denominatorB );
+       }
+
+       PG_RETURN_FLOAT4(numerator);
+}
+
+PG_FUNCTION_INFO_V1(arraysml_op);
+Datum   arraysml_op(PG_FUNCTION_ARGS);
+Datum
+arraysml_op(PG_FUNCTION_ARGS)
+{
+       ArrayType               *a, *b;
+       SimpleArray             *sa, *sb;
+       double                  power = 0.0;
+       
+       fcinfo->flinfo->fn_extra = SearchArrayCache( 
+                                                       fcinfo->flinfo->fn_extra,
+                                                       fcinfo->flinfo->fn_mcxt,
+                                                       PG_GETARG_DATUM(0), &a, &sa, NULL);
+       fcinfo->flinfo->fn_extra = SearchArrayCache( 
+                                                       fcinfo->flinfo->fn_extra,
+                                                       fcinfo->flinfo->fn_mcxt,
+                                                       PG_GETARG_DATUM(1), &b, &sb, NULL);
+
+       if ( ARR_ELEMTYPE(a) != ARR_ELEMTYPE(b) )
+               elog(ERROR,"Arguments array are not the same type!");
+
+       if (ARRISVOID(a) || ARRISVOID(b))
+                PG_RETURN_BOOL(false);
+
+       switch(getSmlType())
+       {
+               case    ST_TFIDF:
+                       power = TFIDFSml(sa, sb);
+                       break;
+               case    ST_COSINE:
+                       {
+                               int                             cnt;
+
+                               power = sqrt( ((double)(sa->nelems)) * ((double)(sb->nelems)) );
+
+                               if (  ((double)Min(sa->nelems, sb->nelems)) / power < GetSmlarLimit()  )
+                                       PG_RETURN_BOOL(false);
+
+                               cnt = numOfIntersect(sa, sb);
+                               power = ((double)cnt) / power;
+                       }
+                       break;
+               case    ST_OVERLAP:
+                       power = (double)numOfIntersect(sa, sb);
+                       break;
+               default:
+                       elog(ERROR,"Unsupported formula type of similarity");
+       }
+
+       PG_RETURN_BOOL(power >= GetSmlarLimit());
+}
+
+#define        QBSIZE          8192
+static char cachedFormula[QBSIZE];
+static int     cachedLen  = 0;
+static void    *cachedPlan = NULL;
+
+PG_FUNCTION_INFO_V1(arraysml_func);
+Datum   arraysml_func(PG_FUNCTION_ARGS);
+Datum
+arraysml_func(PG_FUNCTION_ARGS)
+{
+       ArrayType               *a, *b;
+       SimpleArray             *sa, *sb;
+       int                             cnt;
+       float4                  result = -1.0;
+       Oid                             arg[] = {INT4OID, INT4OID, INT4OID};
+       Datum                   pars[3];
+       bool                    isnull;
+       void                    *plan;
+       int                             stat;
+       text                    *formula = PG_GETARG_TEXT_P(2); 
+       
+       fcinfo->flinfo->fn_extra = SearchArrayCache( 
+                                                       fcinfo->flinfo->fn_extra,
+                                                       fcinfo->flinfo->fn_mcxt,
+                                                       PG_GETARG_DATUM(0), &a, &sa, NULL);
+       fcinfo->flinfo->fn_extra = SearchArrayCache( 
+                                                       fcinfo->flinfo->fn_extra,
+                                                       fcinfo->flinfo->fn_mcxt,
+                                                       PG_GETARG_DATUM(1), &b, &sb, NULL);
+
+       if ( ARR_ELEMTYPE(a) != ARR_ELEMTYPE(b) )
+               elog(ERROR,"Arguments array are not the same type!");
+
+       if (ARRISVOID(a) || ARRISVOID(b))
+                PG_RETURN_BOOL(false);
+
+       cnt = numOfIntersect(sa, sb);
+
+       if ( VARSIZE(formula) - VARHDRSZ > QBSIZE - 1024 )
+               elog(ERROR,"Formula is too long");
+
+       SPI_connect();
+
+       
+       if ( cachedPlan == NULL || cachedLen != VARSIZE(formula) - VARHDRSZ ||
+                               memcmp( cachedFormula, VARDATA(formula), VARSIZE(formula) - VARHDRSZ ) != 0 )
+       {
+               char                    *ptr, buf[QBSIZE];
+
+               *cachedFormula = '\0';
+               if ( cachedPlan )
+                       SPI_freeplan(cachedPlan);
+               cachedPlan = NULL;
+               cachedLen = 0;
+
+               ptr = stpcpy( buf, "SELECT (" );
+               memcpy( ptr, VARDATA(formula), VARSIZE(formula) - VARHDRSZ );
+               ptr += VARSIZE(formula) - VARHDRSZ;
+               ptr = stpcpy( ptr, ")::float4 FROM");
+               ptr = stpcpy( ptr, " (SELECT $1 ::float8 AS i, $2 ::float8 AS a, $3 ::float8 AS b) AS N;");
+               *ptr = '\0';
+
+               plan = SPI_prepare(buf, 3, arg);
+               if (!plan)
+                       elog(ERROR, "SPI_prepare() failed");
+
+               cachedPlan = SPI_saveplan(plan);
+               if (!cachedPlan)
+                       elog(ERROR, "SPI_saveplan() failed");
+
+               SPI_freeplan(plan);
+               cachedLen = VARSIZE(formula) - VARHDRSZ;
+               memcpy( cachedFormula, VARDATA(formula), VARSIZE(formula) - VARHDRSZ ); 
+       }
+
+       plan = cachedPlan;
+
+
+       pars[0] = Int32GetDatum( cnt );
+       pars[1] = Int32GetDatum( sa->nelems );
+       pars[2] = Int32GetDatum( sb->nelems );
+
+       stat = SPI_execute_plan(plan, pars, NULL, true, 3);
+       if (stat < 0)
+               elog(ERROR, "SPI_execute_plan() returns %d", stat);
+
+       if ( SPI_processed > 0)
+               result = DatumGetFloat4(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull));
+
+       SPI_finish();
+
+       PG_RETURN_FLOAT4(result);
+}
+
+PG_FUNCTION_INFO_V1(array_unique);
+Datum  array_unique(PG_FUNCTION_ARGS);
+Datum
+array_unique(PG_FUNCTION_ARGS)
+{
+       ArrayType               *a = PG_GETARG_ARRAYTYPE_P(0);
+       ArrayType               *res;
+       SimpleArray             *sa;
+
+       sa = Array2SimpleArrayU(NULL, a, NULL);
+
+       res = construct_array(  sa->elems, 
+                                                       sa->nelems,
+                                                       sa->info->typid,
+                                                       sa->info->typlen,
+                                                       sa->info->typbyval,
+                                                       sa->info->typalign);
+
+       pfree(sa->elems);
+       pfree(sa);
+       PG_FREE_IF_COPY(a, 0);
+
+       PG_RETURN_ARRAYTYPE_P(res);
+}
+
+PG_FUNCTION_INFO_V1(inarray);
+Datum   inarray(PG_FUNCTION_ARGS);
+Datum
+inarray(PG_FUNCTION_ARGS)
+{
+       ArrayType               *a;
+       SimpleArray             *sa;
+       Datum                   query = PG_GETARG_DATUM(1); 
+       Oid                             queryTypeOid;
+       Datum                   *StopLow,
+                                       *StopHigh,
+                                       *StopMiddle;
+       int                             cmp;
+
+       fcinfo->flinfo->fn_extra = SearchArrayCache( 
+                                                       fcinfo->flinfo->fn_extra,
+                                                       fcinfo->flinfo->fn_mcxt,
+                                                       PG_GETARG_DATUM(0), &a, &sa, NULL);
+
+       queryTypeOid = get_fn_expr_argtype(fcinfo->flinfo, 1);
+
+       if ( queryTypeOid == InvalidOid )
+               elog(ERROR,"inarray: could not determine actual argument type");
+
+       if ( queryTypeOid != sa->info->typid )
+               elog(ERROR,"inarray: Type of array's element and type of argument are not the same");
+
+       getFmgrInfoCmp(sa->info);
+       StopLow = sa->elems;
+       StopHigh = sa->elems + sa->nelems;
+
+       while (StopLow < StopHigh) 
+       {
+               StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
+               cmp = cmpArrayElem(StopMiddle, &query, sa->info);
+
+               if ( cmp == 0 )
+               {
+                       /* found */
+                       if ( PG_NARGS() >= 3 )
+                               PG_RETURN_DATUM(PG_GETARG_DATUM(2));
+                       PG_RETURN_FLOAT4(1.0);
+               }
+               else if (cmp < 0)
+                       StopLow = StopMiddle + 1;
+               else
+                       StopHigh = StopMiddle;
+       }
+
+       if ( PG_NARGS() >= 4 )
+               PG_RETURN_DATUM(PG_GETARG_DATUM(3));
+       PG_RETURN_FLOAT4(0.0);
+}
diff --git a/smlar.control b/smlar.control
new file mode 100644 (file)
index 0000000..e6aa6e9
--- /dev/null
@@ -0,0 +1,5 @@
+comment = 'compute similary of any one-dimensional arrays'
+default_version = '1.0'
+module_pathname = '$libdir/smlar'
+relocatable = true
+
diff --git a/smlar.h b/smlar.h
new file mode 100644 (file)
index 0000000..82a1bcb
--- /dev/null
+++ b/smlar.h
@@ -0,0 +1,142 @@
+#ifndef _SMLAR_H_
+#define        _SMLAR_H_
+
+#include "postgres.h"
+#include "utils/array.h"
+#include "access/tupdesc.h"
+#include "catalog/pg_collation.h"
+
+typedef        struct ProcTypeInfoData *ProcTypeInfo;
+
+typedef struct ProcTypeInfoData {
+       Oid                             typid;
+       Oid                             hashFuncOid;
+       Oid                             cmpFuncOid;
+       int16                   typlen;
+       bool                    typbyval;
+       char                    typalign;
+
+       /* support of composite type */
+       char                    typtype;
+       TupleDesc               tupDesc;
+
+       /*
+        * Following member can become invalid,
+        * so fill it just before using
+        */
+       bool                    hashFuncInited;
+       FmgrInfo                hashFunc;
+       bool                    cmpFuncInited;
+       FmgrInfo                cmpFunc;
+} ProcTypeInfoData;
+
+ProcTypeInfo findProcs(Oid typid);
+void getFmgrInfoHash(ProcTypeInfo info);
+void getFmgrInfoCmp(ProcTypeInfo info);
+
+#define NDIM 1
+/* reject arrays we can't handle; but allow a NULL or empty array */
+#define CHECKARRVALID(x) \
+       do { \
+               if (x) { \
+                       if (ARR_NDIM(x) != NDIM && ARR_NDIM(x) != 0) \
+                               ereport(ERROR, \
+                                               (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), \
+                                                errmsg("array must be one-dimensional"))); \
+                       if (ARR_HASNULL(x)) \
+                               ereport(ERROR, \
+                                               (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
+                                                errmsg("array must not contain nulls"))); \
+               } \
+       } while(0)
+
+#define ARRISVOID(x)  ((x) == NULL || ARRNELEMS(x) == 0)
+#define ARRNELEMS(x)  ArrayGetNItems(ARR_NDIM(x), ARR_DIMS(x))
+
+
+typedef struct SimpleArray {
+       Datum              *elems;
+       double             *df;  /* frequency in current doc */
+       uint32             *hash;
+       int                             nelems;
+       ProcTypeInfo    info;
+} SimpleArray;
+
+SimpleArray    * Array2SimpleArray(ProcTypeInfo info, ArrayType *a);
+SimpleArray    * Array2SimpleArrayS(ProcTypeInfo info, ArrayType *a);
+SimpleArray    * Array2SimpleArrayU(ProcTypeInfo info, ArrayType *a, void *cache);
+void allocateHash(void *cache, SimpleArray *a);
+
+/*
+ * GUC vars
+ */
+double GetSmlarLimit(void);
+const char* GetSmlarTable(void);
+bool GetSmlarUsePersistent(void);
+double getOneAdd(void);
+int getTFMethod(void);
+int getSmlType(void); 
+/*
+ * GiST
+ */
+
+#define SmlarOverlapStrategy        1
+#define SmlarSimilarityStrategy     2
+
+struct SmlSign;
+struct SmlSign* Array2HashedArray(ProcTypeInfo info, ArrayType *a);
+/*
+ * Cache subsystem
+ */
+void*  SearchArrayCache( void *cache, MemoryContext ctx, Datum a, ArrayType **da, SimpleArray **sa,  struct SmlSign  **ss );
+
+typedef struct StatElem {
+    Datum      datum;
+       double          idf; /*  log(d/df) */
+} StatElem;
+
+typedef struct HashedElem {
+       uint32          hash;
+       double          idfMin;
+       double          idfMax;
+} HashedElem;
+
+typedef struct SignedElem {
+       double          idfMin;
+       double          idfMax;
+} SignedElem;
+
+typedef struct StatCache {
+       StatElem        *elems;
+       int             nelems;
+       int64_t         ndoc;
+       HashedElem              *helems;
+       int             nhelems;
+       SignedElem              *selems;
+       ProcTypeInfo    info;
+} StatCache;
+
+StatCache *initStatCache(MemoryContext ctx);
+void getHashStatCache(StatCache *stat, MemoryContext ctx, size_t n);
+
+void   resetStatCache(void);
+StatElem  *findStat(StatCache *stat, Datum query, StatElem *low);
+StatElem  *fingArrayStat(void *cache, Oid typoid, Datum query, StatElem *low);
+StatCache *getStat(void *cache, size_t n);
+
+/*
+ * Formula's type of similarity
+ */
+#define ST_COSINE      1
+#define ST_TFIDF       2
+#define ST_OVERLAP     3
+/*
+ * TF methods
+ */
+#define TF_N           1
+#define TF_LOG         2
+#define        TF_CONST        3
+
+#define FCall2(f, x1, x2)   FunctionCall2Coll((f), C_COLLATION_OID, (x1), (x2))
+
+#endif
diff --git a/smlar.sql.in.in b/smlar.sql.in.in
new file mode 100644 (file)
index 0000000..636a989
--- /dev/null
@@ -0,0 +1,713 @@
+SET search_path = public;
+
+CREATE OR REPLACE FUNCTION smlar(anyarray, anyarray)
+       RETURNS float4
+       AS      'MODULE_PATHNAME', 'arraysml'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION smlar(anyarray, anyarray, bool)
+       RETURNS float4
+       AS      'MODULE_PATHNAME', 'arraysmlw'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION smlar(anyarray, anyarray, text)
+    RETURNS float4
+       AS  'MODULE_PATHNAME', 'arraysml_func'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION set_smlar_limit(float4)
+       RETURNS float4
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION show_smlar_limit()
+       RETURNS float4
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C STRICT STABLE;
+
+CREATE OR REPLACE FUNCTION smlar_op(anyarray,anyarray)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'arraysml_op'
+       LANGUAGE C STRICT STABLE;
+
+CREATE OPERATOR % (
+       LEFTARG = anyarray,
+       RIGHTARG = anyarray,
+       PROCEDURE = smlar_op,
+       COMMUTATOR = '%',
+       RESTRICT = contsel,
+       JOIN = contjoinsel
+);
+
+--
+
+CREATE OR REPLACE FUNCTION tsvector2textarray(tsvector)
+       RETURNS _text
+       AS 'MODULE_PATHNAME', 'tsvector2textarray'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION array_unique(anyarray)
+       RETURNS anyarray
+       AS      'MODULE_PATHNAME', 'array_unique'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION inarray(anyarray, anyelement)
+       RETURNS float4
+       AS      'MODULE_PATHNAME', 'inarray'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION inarray(anyarray, anyelement, float4, float4)
+       RETURNS float4
+       AS      'MODULE_PATHNAME', 'inarray'
+       LANGUAGE C STRICT IMMUTABLE;
+
+--gist key
+
+CREATE OR REPLACE FUNCTION gsmlsign_in(cstring)
+       RETURNS gsmlsign
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C STRICT;
+
+CREATE OR REPLACE FUNCTION gsmlsign_out(gsmlsign)
+       RETURNS cstring
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C STRICT;
+
+CREATE TYPE gsmlsign (
+       INTERNALLENGTH = -1,
+       INPUT = gsmlsign_in,
+       OUTPUT = gsmlsign_out
+);
+
+-- support functions for gist
+CREATE OR REPLACE FUNCTION gsmlsign_consistent(gsmlsign,internal,int4)
+       RETURNS bool
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_compress(internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_decompress(internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_penalty(internal,internal,internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_picksplit(internal, internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_union(bytea, internal)
+       RETURNS _int4
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION gsmlsign_same(gsmlsign, gsmlsign, internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+--create the operator classes for gist
+
+CREATE OPERATOR CLASS _int2_sml_ops
+FOR TYPE _int2 USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _int4_sml_ops
+FOR TYPE _int4 USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _int8_sml_ops
+FOR TYPE _int8 USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _float4_sml_ops
+FOR TYPE _float4 USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _float8_sml_ops
+FOR TYPE _float8 USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+-- money type hasn't hash support
+--CREATE OPERATOR CLASS _money_sml_ops
+--FOR TYPE _money USING gist
+--AS
+--     OPERATOR        1       && (anyarray, anyarray),
+--     OPERATOR        2       % (anyarray, anyarray),
+--     FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+--     FUNCTION        2       gsmlsign_union (bytea, internal),
+--     FUNCTION        3       gsmlsign_compress (internal),
+--     FUNCTION        4       gsmlsign_decompress (internal),
+--     FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+--     FUNCTION        6       gsmlsign_picksplit (internal, internal),
+--     FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+--STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _oid_sml_ops
+FOR TYPE _oid USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _timestamp_sml_ops
+FOR TYPE _timestamp USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _timestamptz_sml_ops
+FOR TYPE _timestamptz USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _time_sml_ops
+FOR TYPE _time USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _timetz_sml_ops
+FOR TYPE _timetz USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _date_sml_ops
+FOR TYPE _date USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _interval_sml_ops
+FOR TYPE _interval USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _macaddr_sml_ops
+FOR TYPE _macaddr USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _inet_sml_ops
+FOR TYPE _inet USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _cidr_sml_ops
+FOR TYPE _cidr USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _text_sml_ops
+FOR TYPE _text USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _varchar_sml_ops
+FOR TYPE _varchar USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _char_sml_ops
+FOR TYPE _char USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _bytea_sml_ops
+FOR TYPE _bytea USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+--no hash 
+--CREATE OPERATOR CLASS _bit_sml_ops
+--FOR TYPE _bit USING gist
+--AS
+--     OPERATOR        1       && (anyarray, anyarray),
+--     OPERATOR        2       % (anyarray, anyarray),
+--     FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+--     FUNCTION        2       gsmlsign_union (bytea, internal),
+--     FUNCTION        3       gsmlsign_compress (internal),
+--     FUNCTION        4       gsmlsign_decompress (internal),
+--     FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+--     FUNCTION        6       gsmlsign_picksplit (internal, internal),
+--     FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+--STORAGE         gsmlsign;
+
+--CREATE OPERATOR CLASS _varbit_sml_ops
+--FOR TYPE _varbit USING gist
+--AS
+--     OPERATOR        1       && (anyarray, anyarray),
+--     OPERATOR        2       % (anyarray, anyarray),
+--     FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+--     FUNCTION        2       gsmlsign_union (bytea, internal),
+--     FUNCTION        3       gsmlsign_compress (internal),
+--     FUNCTION        4       gsmlsign_decompress (internal),
+--     FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+--     FUNCTION        6       gsmlsign_picksplit (internal, internal),
+--     FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+--STORAGE         gsmlsign;
+
+CREATE OPERATOR CLASS _numeric_sml_ops
+FOR TYPE _numeric USING gist
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       % (anyarray, anyarray),
+       FUNCTION        1       gsmlsign_consistent (gsmlsign, internal, int4),
+       FUNCTION        2       gsmlsign_union (bytea, internal),
+       FUNCTION        3       gsmlsign_compress (internal),
+       FUNCTION        4       gsmlsign_decompress (internal),
+       FUNCTION        5       gsmlsign_penalty (internal, internal, internal),
+       FUNCTION        6       gsmlsign_picksplit (internal, internal),
+       FUNCTION        7       gsmlsign_same (gsmlsign, gsmlsign, internal),
+STORAGE         gsmlsign;
+
+--gin support functions
+CREATE OR REPLACE FUNCTION smlararrayextract(anyarray, internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION smlarqueryarrayextract(anyarray, internal, internal)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION smlararrayconsistent(internal, internal, anyarray)
+       RETURNS internal
+       AS 'MODULE_PATHNAME'
+       LANGUAGE C IMMUTABLE;
+
+--gin opclasses
+
+CREATE OPERATOR CLASS _int2_sml_ops
+FOR TYPE _int2 USING gin
+AS
+       OPERATOR        1       && (anyarray, anyarray),
+       OPERATOR        2       %  (anyarray, anyarray),
+       FUNCTION        1       btint2cmp(int2,int2),
+       FUNCTION        2       smlararrayextract(anyarray, internal),
+       FUNCTION        3       smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION        4       smlararrayconsistent(internal, internal, anyarray),
+       STORAGE         int2;
+CREATE OPERATOR CLASS _int4_sml_ops
+FOR TYPE _int4  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btint4cmp(int4,int4),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     int4;
+
+CREATE OPERATOR CLASS _int8_sml_ops
+FOR TYPE _int8  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btint8cmp(int8,int8),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     int8;
+
+CREATE OPERATOR CLASS _float4_sml_ops
+FOR TYPE _float4  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btfloat4cmp(float4,float4),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     float4;
+
+CREATE OPERATOR CLASS _float8_sml_ops
+FOR TYPE _float8  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btfloat8cmp(float8,float8),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     float8;
+
+CREATE OPERATOR CLASS _money_sml_ops
+FOR TYPE _money  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   cash_cmp(money,money),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     money;
+
+CREATE OPERATOR CLASS _oid_sml_ops
+FOR TYPE _oid  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btoidcmp(oid,oid),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     oid;
+
+CREATE OPERATOR CLASS _timestamp_sml_ops
+FOR TYPE _timestamp  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   timestamp_cmp(timestamp,timestamp),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     timestamp;
+
+CREATE OPERATOR CLASS _timestamptz_sml_ops
+FOR TYPE _timestamptz  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   timestamptz_cmp(timestamptz,timestamptz),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     timestamptz;
+
+CREATE OPERATOR CLASS _time_sml_ops
+FOR TYPE _time  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   time_cmp(time,time),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     time;
+
+CREATE OPERATOR CLASS _timetz_sml_ops
+FOR TYPE _timetz  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   timetz_cmp(timetz,timetz),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     timetz;
+
+CREATE OPERATOR CLASS _date_sml_ops
+FOR TYPE _date  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   date_cmp(date,date),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     date;
+
+CREATE OPERATOR CLASS _interval_sml_ops
+FOR TYPE _interval  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   interval_cmp(interval,interval),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     interval;
+
+CREATE OPERATOR CLASS _macaddr_sml_ops
+FOR TYPE _macaddr  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   macaddr_cmp(macaddr,macaddr),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     macaddr;
+
+CREATE OPERATOR CLASS _inet_sml_ops
+FOR TYPE _inet  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   network_cmp(inet,inet),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     inet;
+
+CREATE OPERATOR CLASS _cidr_sml_ops
+FOR TYPE _cidr  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   network_cmp(inet,inet),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     cidr;
+
+CREATE OPERATOR CLASS _text_sml_ops
+FOR TYPE _text  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   bttextcmp(text,text),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     text;
+
+CREATE OPERATOR CLASS _varchar_sml_ops
+FOR TYPE _varchar  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   bttextcmp(text,text),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     varchar;
+
+CREATE OPERATOR CLASS _char_sml_ops
+FOR TYPE "_char"  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   btcharcmp("char","char"),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     "char";
+
+CREATE OPERATOR CLASS _bytea_sml_ops
+FOR TYPE _bytea  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   byteacmp(bytea,bytea),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     bytea;
+
+CREATE OPERATOR CLASS _bit_sml_ops
+FOR TYPE _bit  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   bitcmp(bit,bit),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     bit;
+
+CREATE OPERATOR CLASS _varbit_sml_ops
+FOR TYPE _varbit  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   varbitcmp(varbit,varbit),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     varbit;
+
+CREATE OPERATOR CLASS _numeric_sml_ops
+FOR TYPE _numeric  USING gin
+AS
+    OPERATOR    1   && (anyarray, anyarray),
+       OPERATOR    2   %  (anyarray, anyarray),
+       FUNCTION    1   numeric_cmp(numeric,numeric),
+       FUNCTION    2   smlararrayextract(anyarray, internal),
+       FUNCTION    3   smlarqueryarrayextract(anyarray, internal, internal),
+       FUNCTION    4   smlararrayconsistent(internal, internal, anyarray),
+       STORAGE     numeric;
+
diff --git a/smlar_cache.c b/smlar_cache.c
new file mode 100644 (file)
index 0000000..2d45547
--- /dev/null
@@ -0,0 +1,301 @@
+#include "smlar.h"
+
+#include "fmgr.h"
+#include "utils/array.h"
+#include "utils/memutils.h"
+
+/*
+ * Deconstructed array cache
+ */
+
+typedef struct ArrayCacheEntry {
+       Datum                   toastedArray;
+       ArrayType               *da;
+       SimpleArray             *sa;
+       struct SmlSign  *ss;
+
+       struct ArrayCacheEntry  *prev;
+       struct ArrayCacheEntry  *next;
+} ArrayCacheEntry;
+
+#define NENTRIES       (16)
+
+typedef struct ArrayCache {
+       MemoryContext           ctx;
+       int32                           nentries;
+       ArrayCacheEntry         *head;
+       ArrayCacheEntry         *tail;
+       ArrayCacheEntry*        entries[ NENTRIES ];
+       StatCache                       *DocStat;
+} ArrayCache;
+
+static void 
+moveFirst(ArrayCache *ac, ArrayCacheEntry *entry)
+{
+       /*
+        * delete entry form a list
+        */
+       Assert( entry != ac->head );
+       if ( entry == ac->tail )
+       {
+               Assert( entry->next == NULL );
+               ac->tail = entry->prev;
+               if ( ac->tail )
+                       ac->tail->next = NULL;
+               else
+                       ac->head = NULL;
+       }
+       else
+       {
+               entry->prev->next = entry->next;
+               entry->next->prev = entry->prev;
+       }
+
+       /*
+        * Install into head 
+        */
+
+       Assert( ac->head != NULL );
+       Assert( ac->tail != NULL );
+
+       entry->next = ac->head;
+       entry->prev = NULL;
+       ac->head->prev = entry;
+       ac->head = entry;
+}
+
+#define        DATUMSIZE(d)    VARSIZE_ANY(DatumGetPointer(d)) 
+static int
+cmpDatum(Datum a, Datum b)
+{
+       int32   la = DATUMSIZE(a);
+       int32   lb = DATUMSIZE(b);
+
+       if ( la == lb )
+               return memcmp( DatumGetPointer(a), DatumGetPointer(b), la );
+
+       return (la > lb) ? 1 : -1;
+}
+
+static void
+fetchData(ArrayCache *ac, ArrayCacheEntry *entry, ArrayType **da, SimpleArray **sa,  struct SmlSign  **ss )
+{
+       ProcTypeInfo    info;
+
+       info = findProcs( ARR_ELEMTYPE(entry->da) );
+
+       if ( sa )
+       {
+               if ( entry->sa == NULL )
+               {
+                       MemoryContext   old;
+
+                       getFmgrInfoCmp(info);
+
+                       old = MemoryContextSwitchTo( ac->ctx );
+                       entry->sa = Array2SimpleArrayU(info, entry->da, (getSmlType() == ST_TFIDF) ? ac : NULL);
+                       MemoryContextSwitchTo(old);
+               }
+
+               *sa = entry->sa;
+       }
+
+       if ( ss )
+       {
+               if ( entry->ss == NULL )
+               {
+                       MemoryContext   old;
+
+                       getFmgrInfoHash(info);
+
+                       old = MemoryContextSwitchTo( ac->ctx );
+                       entry->ss = Array2HashedArray(info, entry->da);
+                       MemoryContextSwitchTo(old);
+               }
+
+               *ss = entry->ss;
+       }
+
+       if (da)
+               *da = entry->da;
+}
+
+static void
+cleanupData(ArrayCacheEntry *entry)
+{
+       if ( entry->sa )
+       {
+               if ( entry->sa->elems )
+                       pfree( entry->sa->elems );
+               if ( entry->sa->df )
+                       pfree( entry->sa->df );
+               if ( entry->sa->hash )
+                       pfree( entry->sa->hash );
+               pfree( entry->sa );
+       }
+       entry->sa = NULL;
+
+       if ( entry->ss )
+               pfree(entry->ss);
+       entry->ss = NULL;
+
+       pfree( DatumGetPointer(entry->toastedArray) );
+       pfree( entry->da );
+}
+
+static void
+makeEntry(ArrayCache *ac, ArrayCacheEntry *entry, Datum a)
+{
+       ArrayType *detoastedArray;
+
+       entry->toastedArray = (Datum)MemoryContextAlloc( ac->ctx, DATUMSIZE(a) );
+       memcpy( DatumGetPointer(entry->toastedArray), DatumGetPointer(a), DATUMSIZE(a) );
+
+       detoastedArray = (ArrayType*)PG_DETOAST_DATUM(entry->toastedArray);
+       entry->da = MemoryContextAlloc( ac->ctx, VARSIZE(detoastedArray));
+       memcpy( entry->da, detoastedArray, VARSIZE(detoastedArray));
+}
+
+static int
+cmpEntry(const void *a, const void *b)
+{
+       return cmpDatum( (*(ArrayCacheEntry**)a)->toastedArray, (*(ArrayCacheEntry**)b)->toastedArray ); 
+}
+
+void*
+SearchArrayCache( void *cache, MemoryContext ctx, Datum a, ArrayType **da, SimpleArray **sa,  struct SmlSign  **ss )
+{
+       ArrayCache              *ac;
+       ArrayCacheEntry *entry;
+
+       if ( cache == NULL )
+               cache = MemoryContextAllocZero(ctx, sizeof(ArrayCache));
+
+       ac = (ArrayCache*) cache;
+       ac->ctx = ctx;
+
+       /*
+        * Fast check of resent used value 
+        */
+       if ( ac->head && cmpDatum(ac->head->toastedArray, a) == 0 )
+       {
+               fetchData(ac, ac->head, da, sa, ss);
+               return cache;
+       }
+
+       if ( ac->head == NULL  )
+       {
+               ac->entries[0] = ac->head = ac->tail = MemoryContextAllocZero(ctx, sizeof(ArrayCacheEntry));
+               ac->nentries = 1;
+               makeEntry(ac, ac->head, a);
+               fetchData(ac, ac->head, da, sa, ss);
+               return cache;
+       }
+
+       do {
+               ArrayCacheEntry **StopLow = ac->entries;
+               ArrayCacheEntry **StopHigh = ac->entries + ac->nentries;
+               ArrayCacheEntry **StopMiddle;
+               int cmp;
+
+        while (StopLow < StopHigh) {
+                       StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
+                       entry = *StopMiddle;
+                       cmp = cmpDatum(entry->toastedArray, a); 
+
+                       if ( cmp == 0 )
+                       {
+                               moveFirst(ac, entry);
+                               fetchData(ac, ac->head, da, sa, ss);
+                               return cache;
+                       }
+                       else if ( cmp < 0 )
+                               StopLow = StopMiddle + 1;
+                       else
+                               StopHigh = StopMiddle;
+               }
+       } while(0);
+
+       /*
+        * Not found 
+        */
+
+       if ( ac->nentries < NENTRIES )
+       {
+               entry = ac->entries[ ac->nentries ] = MemoryContextAllocZero(ctx, sizeof(ArrayCacheEntry));
+
+               /* install first */
+               entry->next = ac->head;
+               entry->prev = NULL;
+               ac->head->prev = entry;
+               ac->head = entry;
+
+               ac->nentries ++;
+
+               makeEntry(ac, ac->head, a);
+               fetchData(ac, ac->head, da, sa, ss);
+       } 
+       else
+       {
+               cleanupData( ac->tail );
+               moveFirst(ac, ac->tail );
+               makeEntry(ac, ac->head, a);
+               fetchData(ac, ac->head, da, sa, ss);
+       }
+
+       qsort(ac->entries, ac->nentries, sizeof(ArrayCacheEntry*), cmpEntry);   
+       return cache;
+}
+
+StatElem  *
+fingArrayStat(void *cache, Oid typoid, Datum query, StatElem *low)
+{
+       ArrayCache              *ac;
+
+       if ( cache == NULL )
+               return NULL;
+
+       ac = (ArrayCache*) cache;
+       if ( ac->DocStat == NULL )
+       {
+               ac->DocStat = initStatCache(ac->ctx);
+               low = NULL;
+       }
+
+       if ( typoid != ac->DocStat->info->typid )
+               elog(ERROR,"Types of stat table and actual arguments are different");
+
+       return findStat(ac->DocStat, query, low);       
+}
+
+StatCache *
+getStat(void *cache, size_t n)
+{
+       ArrayCache      *ac;
+
+       if ( cache == NULL )
+               return NULL;
+
+       ac = (ArrayCache*) cache;
+       if ( ac->DocStat == NULL )
+               ac->DocStat = initStatCache(ac->ctx);
+
+       getHashStatCache(ac->DocStat, ac->ctx, n);
+
+       return ac->DocStat;
+}
+
+void
+allocateHash(void *cache, SimpleArray *a)
+{
+       ArrayCache      *ac;
+
+       if ( cache == NULL )
+               return;
+       ac = (ArrayCache*) cache;
+
+       if (a->hash)
+               return;
+
+       a->hash = MemoryContextAlloc( ac->ctx, sizeof(uint32) * a->nelems );
+}
diff --git a/smlar_gin.c b/smlar_gin.c
new file mode 100644 (file)
index 0000000..5ea1570
--- /dev/null
@@ -0,0 +1,146 @@
+#include "smlar.h"
+
+#include "fmgr.h"
+#include "access/gin.h"
+#include "access/skey.h"
+#include "access/tuptoaster.h"
+
+PG_FUNCTION_INFO_V1(smlararrayextract);
+Datum smlararrayextract(PG_FUNCTION_ARGS);
+Datum
+smlararrayextract(PG_FUNCTION_ARGS)
+{
+       ArrayType       *array;
+       int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
+       SimpleArray     *sa;
+
+       /*
+        * we should guarantee that array will not be destroyed during all
+        * operation
+        */
+       array = PG_GETARG_ARRAYTYPE_P_COPY(0);
+
+       CHECKARRVALID(array);
+
+       sa = Array2SimpleArrayU(NULL, array, NULL);
+
+       *nentries = sa->nelems;
+
+       if (sa->nelems == 0 && PG_NARGS() == 3)
+       {
+               switch (PG_GETARG_UINT16(2))    /* StrategyNumber */
+               {
+                       case    SmlarOverlapStrategy:
+                       case    SmlarSimilarityStrategy:
+                               *nentries = -1; /* nobody can be found */
+                               break;
+                       default:
+                               break;
+               }
+       }
+
+       PG_RETURN_POINTER( sa->elems );
+}
+
+PG_FUNCTION_INFO_V1(smlarqueryarrayextract);
+Datum smlarqueryarrayextract(PG_FUNCTION_ARGS);
+Datum
+smlarqueryarrayextract(PG_FUNCTION_ARGS)
+{
+       PG_RETURN_DATUM(DirectFunctionCall3(smlararrayextract,
+                                                                               PG_GETARG_DATUM(0),
+                                                                               PG_GETARG_DATUM(1),
+                                                                               PG_GETARG_DATUM(2)));
+}
+
+PG_FUNCTION_INFO_V1(smlararrayconsistent);
+Datum smlararrayconsistent(PG_FUNCTION_ARGS);
+Datum
+smlararrayconsistent(PG_FUNCTION_ARGS)
+{
+       bool                    *check = (bool *) PG_GETARG_POINTER(0);
+       StrategyNumber  strategy = PG_GETARG_UINT16(1);
+       SimpleArray             *sa;
+       bool                    res = false;
+       int                             i,
+                                       cnt = 0;
+       bool                    *recheck = (bool *) PG_GETARG_POINTER(5);
+
+       *recheck = true;
+
+       switch (strategy)
+       {
+               case SmlarOverlapStrategy:
+                       /* at least one element in check[] is true, so result = true */
+                       res = true;
+                       *recheck = false;
+                       break;
+               case SmlarSimilarityStrategy:
+
+                       fcinfo->flinfo->fn_extra = SearchArrayCache(
+                                                                                               fcinfo->flinfo->fn_extra,
+                                                                                               fcinfo->flinfo->fn_mcxt,
+                                                                                               PG_GETARG_DATUM(2), NULL, &sa, NULL );
+
+                       for(i=0; i<sa->nelems; i++)
+                               cnt += check[i];
+
+                       /*
+                        * cnt is a lower limit of elements's number in indexed array;
+                        */
+
+                       switch(getSmlType())
+                       {
+                               case    ST_TFIDF:
+                                               {
+                                                       double  weight = 0.0, /* exact weight of union */
+                                                                       saSum = 0.0,  /* exact length of query */
+                                                                       siSum = 0.0;  /* lower limit of length of indexed value */ 
+
+                                                       if ( getTFMethod() != TF_CONST )
+                                                               elog(ERROR,"GIN supports only smlar.tf_method = \"const\"" );
+
+                                                       Assert(sa->df);
+
+                                                       for(i=0; i<sa->nelems; i++)
+                                                       {
+                                                               /*
+                                                                * With smlar.tf_method = "const"   sa->df[i] is 
+                                                                * equal to its idf, so lookup of StatElem is not needed
+                                                                */
+                                                               if ( check[i] )
+                                                               {
+                                                                       weight += sa->df[i] * sa->df[i];
+                                                                       siSum += sa->df[i] * sa->df[i];
+                                                               }
+                                                               saSum += sa->df[i] * sa->df[i];
+                                                       }
+
+                                                       if ( saSum > 0.0 && siSum > 0.0 && weight / sqrt(saSum * siSum ) > GetSmlarLimit() )
+                                                               res = true;
+                                               }
+                                               break;
+                               case    ST_COSINE:
+                                               {
+                                                       double                  power;
+
+                                                       power = sqrt( ((double)(sa->nelems)) * ((double)(cnt)) );
+
+                                                       if (  ((double)cnt) / power >= GetSmlarLimit()  )
+                                                               res = true;
+                                               }
+                                               break;
+                               case    ST_OVERLAP:
+                                               if (cnt >= GetSmlarLimit())
+                                                       res = true;
+                                               break;
+                               default:
+                                       elog(ERROR,"GIN doesn't support current formula type of similarity");
+                       }
+                       break;
+               default:
+                       elog(ERROR, "smlararrayconsistent: unknown strategy number: %d", strategy);
+       }
+
+       PG_RETURN_BOOL(res);
+}
diff --git a/smlar_gist.c b/smlar_gist.c
new file mode 100644 (file)
index 0000000..ce9c6d8
--- /dev/null
@@ -0,0 +1,1238 @@
+#include "smlar.h"
+
+#include "fmgr.h"
+#include "access/gist.h"
+#include "access/skey.h"
+#include "access/tuptoaster.h"
+#include "utils/memutils.h"
+
+typedef struct SmlSign {
+       int32   vl_len_; /* varlena header (do not touch directly!) */
+       int32   flag:8,
+                       size:24;
+       int32   maxrepeat;
+       char    data[1];
+} SmlSign;
+
+#define SMLSIGNHDRSZ   (offsetof(SmlSign, data))
+
+#define BITBYTE 8
+#define SIGLENINT  61
+#define SIGLEN  ( sizeof(int)*SIGLENINT )
+#define SIGLENBIT (SIGLEN*BITBYTE - 1)  /* see makesign */
+typedef char BITVEC[SIGLEN];
+typedef char *BITVECP;
+#define LOOPBYTE \
+               for(i=0;i<SIGLEN;i++)
+
+#define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITBYTE ) ) )
+#define GETBITBYTE(x,i) ( ((char)(x)) >> i & 0x01 )
+#define CLRBIT(x,i)   GETBYTE(x,i) &= ~( 0x01 << ( (i) % BITBYTE ) )
+#define SETBIT(x,i)   GETBYTE(x,i) |=  ( 0x01 << ( (i) % BITBYTE ) )
+#define GETBIT(x,i) ( (GETBYTE(x,i) >> ( (i) % BITBYTE )) & 0x01 )
+
+#define HASHVAL(val) (((unsigned int)(val)) % SIGLENBIT)
+#define HASH(sign, val) SETBIT((sign), HASHVAL(val))
+
+#define ARRKEY          0x01
+#define SIGNKEY         0x02
+#define ALLISTRUE       0x04
+
+#define ISARRKEY(x) ( ((SmlSign*)x)->flag & ARRKEY )
+#define ISSIGNKEY(x)    ( ((SmlSign*)x)->flag & SIGNKEY )
+#define ISALLTRUE(x)    ( ((SmlSign*)x)->flag & ALLISTRUE )
+
+#define CALCGTSIZE(flag, len) ( SMLSIGNHDRSZ + ( ( (flag) & ARRKEY ) ? ((len)*sizeof(uint32)) : (((flag) & ALLISTRUE) ? 0 : SIGLEN) ) )
+#define GETSIGN(x)      ( (BITVECP)( (char*)x+SMLSIGNHDRSZ ) )
+#define GETARR(x)       ( (uint32*)( (char*)x+SMLSIGNHDRSZ ) )
+
+#define GETENTRY(vec,pos) ((SmlSign *) DatumGetPointer((vec)->vector[(pos)].key))
+
+/*
+ * Fake IO
+ */
+PG_FUNCTION_INFO_V1(gsmlsign_in);
+Datum       gsmlsign_in(PG_FUNCTION_ARGS);
+Datum
+gsmlsign_in(PG_FUNCTION_ARGS)
+{
+       elog(ERROR, "not implemented");
+       PG_RETURN_DATUM(0);
+}
+
+PG_FUNCTION_INFO_V1(gsmlsign_out);
+Datum       gsmlsign_out(PG_FUNCTION_ARGS);
+Datum
+gsmlsign_out(PG_FUNCTION_ARGS)
+{
+       elog(ERROR, "not implemented");
+       PG_RETURN_DATUM(0);
+}
+
+/*
+ * Compress/decompress
+ */
+
+/* Number of one-bits in an unsigned byte */
+static const uint8 number_of_ones[256] = {
+    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+static int
+compareint(const void *va, const void *vb)
+{
+    uint32        a = *((uint32 *) va);
+       uint32        b = *((uint32 *) vb);
+                                
+       if (a == b)
+               return 0;
+       return (a > b) ? 1 : -1;
+}
+
+/*
+ * Removes duplicates from an array of int4. 'l' is
+ * size of the input array. Returns the new size of the array.
+ */
+static int
+uniqueint(uint32 *a, int4 l, int4 *max)
+{
+       uint32      *ptr,
+                          *res;
+       int4       cnt = 0;
+
+       *max = 1;
+
+       if (l <= 1)
+               return l;
+
+       ptr = res = a;
+
+       qsort((void *) a, l, sizeof(uint32), compareint);
+
+       while (ptr - a < l)
+               if (*ptr != *res)
+               {
+                       cnt = 1;
+                       *(++res) = *ptr++;
+               }
+               else
+               {
+                       cnt++;
+                       if ( cnt > *max )
+                               *max = cnt;
+                       ptr++;
+               }
+
+       if ( cnt > *max )
+               *max = cnt;
+
+       return res + 1 - a;
+}
+
+SmlSign*
+Array2HashedArray(ProcTypeInfo info, ArrayType *a)
+{
+       SimpleArray *s = Array2SimpleArray(info, a);
+       SmlSign         *sign;
+       int4            len, i;
+       uint32          *ptr;
+
+       len = CALCGTSIZE( ARRKEY, s->nelems );
+
+       getFmgrInfoHash(s->info);
+       if (s->info->tupDesc)
+               elog(ERROR, "GiST  doesn't support composite (weighted) type");
+
+       sign = palloc( len );
+       sign->flag = ARRKEY;
+       sign->size = s->nelems;
+
+       ptr = GETARR(sign);
+       for(i=0;i<s->nelems;i++)
+               ptr[i] = DatumGetUInt32( FunctionCall1( &s->info->hashFunc, s->elems[i] ) );
+                               
+       /*
+        * there is a collision of hash-function; len is always equal or less than
+        * s->nelems
+        */
+       sign->size = uniqueint( GETARR(sign), sign->size, &sign->maxrepeat );
+       len = CALCGTSIZE( ARRKEY, sign->size );
+       SET_VARSIZE(sign, len);
+
+       return sign;
+}
+
+static int
+HashedElemCmp(const void *va, const void *vb)
+{
+    uint32        a = ((HashedElem *) va)->hash;
+       uint32        b = ((HashedElem *) vb)->hash;
+                                
+       if (a == b)
+       {
+               double  ma = ((HashedElem *) va)->idfMin;
+               double  mb = ((HashedElem *) va)->idfMin;
+
+               if (ma == mb)
+                       return 0;
+
+               return ( ma > mb ) ? 1 : -1;
+       }
+
+       return (a > b) ? 1 : -1;
+}
+
+static int
+uniqueHashedElem(HashedElem *a, int4 l)
+{
+       HashedElem      *ptr,
+                                         *res;
+
+       if (l <= 1)
+               return l;
+
+       ptr = res = a;
+
+       qsort(a, l, sizeof(HashedElem), HashedElemCmp);
+
+       while (ptr - a < l)
+               if (ptr->hash != res->hash)
+                       *(++res) = *ptr++;
+               else
+               {
+                       res->idfMax = ptr->idfMax;
+                       ptr++;
+               }
+
+       return res + 1 - a;
+}
+
+static StatCache*
+getHashedCache(void *cache)
+{
+       StatCache *stat = getStat(cache, SIGLENBIT);
+
+       if ( stat->nhelems < 0 )
+       {
+               int i;
+               /*
+                * Init
+                */
+
+               if (stat->info->tupDesc)
+                       elog(ERROR, "GiST  doesn't support composite (weighted) type");
+               getFmgrInfoHash(stat->info);
+               for(i=0;i<stat->nelems;i++)
+               {
+                       uint32  hash = DatumGetUInt32( FunctionCall1( &stat->info->hashFunc, stat->elems[i].datum ) );
+                       int             index = HASHVAL(hash);  
+
+                       stat->helems[i].hash = hash;
+                       stat->helems[i].idfMin = stat->helems[i].idfMax = stat->elems[i].idf;   
+                       if ( stat->selems[index].idfMin == 0.0 )
+                               stat->selems[index].idfMin = stat->selems[index].idfMax = stat->elems[i].idf;
+                       else if ( stat->selems[index].idfMin > stat->elems[i].idf )
+                               stat->selems[index].idfMin = stat->elems[i].idf;
+                       else if ( stat->selems[index].idfMax < stat->elems[i].idf )
+                               stat->selems[index].idfMax = stat->elems[i].idf;
+               }
+
+               stat->nhelems = uniqueHashedElem( stat->helems, stat->nelems); 
+       }
+
+       return stat;
+}
+
+static HashedElem*
+getHashedElemIdf(StatCache *stat, uint32 hash, HashedElem *StopLow)
+{
+       HashedElem      *StopMiddle,
+                               *StopHigh = stat->helems + stat->nhelems;
+
+       if ( !StopLow )
+               StopLow = stat->helems;
+
+       while (StopLow < StopHigh) {
+               StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
+
+               if ( StopMiddle->hash == hash )
+                       return StopMiddle;
+               else if ( StopMiddle->hash < hash )
+                       StopLow = StopMiddle + 1;
+               else
+                       StopHigh = StopMiddle;
+       }
+
+       return NULL;
+}
+
+static void
+fillHashVal(void *cache, SimpleArray *a)
+{
+       int i;
+
+       if (a->hash)
+               return;
+
+       allocateHash(cache, a);
+
+       if (a->info->tupDesc)
+               elog(ERROR, "GiST  doesn't support composite (weighted) type");
+       getFmgrInfoHash(a->info);
+
+       for(i=0;i<a->nelems;i++)
+               a->hash[i] = DatumGetUInt32( FunctionCall1( &a->info->hashFunc, a->elems[i] ) );
+}
+
+
+static bool
+hasHashedElem(SmlSign  *a, uint32 h)
+{
+       uint32  *StopLow = GETARR(a),
+                       *StopHigh = GETARR(a) + a->size,
+                       *StopMiddle;
+
+       while (StopLow < StopHigh) {
+               StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
+               
+               if ( *StopMiddle == h )
+                       return true;
+               else if ( *StopMiddle < h )
+                       StopLow = StopMiddle + 1;
+               else
+                       StopHigh = StopMiddle;
+       }
+
+       return false;
+}
+
+static void
+makesign(BITVECP sign, SmlSign *a)
+{
+       int4    i;
+       uint32  *ptr = GETARR(a);
+
+       MemSet((void *) sign, 0, sizeof(BITVEC));
+       SETBIT(sign, SIGLENBIT);    /* set last unused bit */
+
+       for (i = 0; i < a->size; i++)
+               HASH(sign, ptr[i]);
+}
+
+static int4
+sizebitvec(BITVECP sign)
+{
+       int4    size = 0,
+                       i;
+
+       LOOPBYTE
+               size += number_of_ones[(unsigned char) sign[i]];
+
+       return size;
+}
+
+PG_FUNCTION_INFO_V1(gsmlsign_compress);
+Datum gsmlsign_compress(PG_FUNCTION_ARGS);
+Datum
+gsmlsign_compress(PG_FUNCTION_ARGS)
+{
+       GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+       GISTENTRY  *retval = entry;
+
+       if (entry->leafkey) /* new key */
+       {
+               SmlSign         *sign;
+               ArrayType       *a = DatumGetArrayTypeP(entry->key);
+
+               sign = Array2HashedArray(NULL, a);
+
+               if ( VARSIZE(sign) > TOAST_INDEX_TARGET )
+               {       /* make signature due to its big size */ 
+                       SmlSign *tmpsign;
+                       int             len;
+
+                       len = CALCGTSIZE( SIGNKEY, sign->size );
+                       tmpsign = palloc( len );
+                       tmpsign->flag = SIGNKEY;
+                       SET_VARSIZE(tmpsign, len);
+
+                       makesign(GETSIGN(tmpsign), sign);
+                       tmpsign->size = sizebitvec(GETSIGN(tmpsign));
+                       tmpsign->maxrepeat = sign->maxrepeat; 
+                       sign = tmpsign;
+               }
+
+               retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+               gistentryinit(*retval, PointerGetDatum(sign),
+                                               entry->rel, entry->page,
+                                               entry->offset, FALSE);
+       }
+       else if ( ISSIGNKEY(DatumGetPointer(entry->key)) &&
+                               !ISALLTRUE(DatumGetPointer(entry->key)) )
+       {
+               SmlSign *sign = (SmlSign*)DatumGetPointer(entry->key);
+
+               Assert( sign->size == sizebitvec(GETSIGN(sign)) );
+
+               if ( sign->size == SIGLENBIT )
+               {
+                       int4    len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
+                       int4    maxrepeat = sign->maxrepeat;
+
+                       sign = (SmlSign *) palloc(len);
+                       SET_VARSIZE(sign, len);
+                       sign->flag = SIGNKEY | ALLISTRUE;
+                       sign->size = SIGLENBIT;
+                       sign->maxrepeat = maxrepeat;
+
+                       retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+
+                       gistentryinit(*retval, PointerGetDatum(sign),
+                                                       entry->rel, entry->page,
+                                                       entry->offset, FALSE);
+               }
+       }
+               
+       PG_RETURN_POINTER(retval);
+}
+
+PG_FUNCTION_INFO_V1(gsmlsign_decompress);
+Datum gsmlsign_decompress(PG_FUNCTION_ARGS);
+Datum
+gsmlsign_decompress(PG_FUNCTION_ARGS)
+{
+       GISTENTRY       *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+       SmlSign         *key =  (SmlSign*)DatumGetPointer(PG_DETOAST_DATUM(entry->key));
+
+       if (key != (SmlSign *) DatumGetPointer(entry->key))
+       {
+               GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+
+               gistentryinit(*retval, PointerGetDatum(key),
+                                               entry->rel, entry->page,
+                                               entry->offset, FALSE);
+
+               PG_RETURN_POINTER(retval);
+       }
+
+       PG_RETURN_POINTER(entry);
+}
+
+/*
+ * Union method
+ */
+static bool
+unionkey(BITVECP sbase, SmlSign *add)
+{
+       int4    i;
+
+       if (ISSIGNKEY(add))
+       {
+               BITVECP     sadd = GETSIGN(add);
+
+               if (ISALLTRUE(add))
+                       return true;
+
+               LOOPBYTE
+                       sbase[i] |= sadd[i];
+       }
+       else
+       {
+               uint32       *ptr = GETARR(add);
+
+               for (i = 0; i < add->size; i++)
+                       HASH(sbase, ptr[i]);
+       }
+
+       return false;
+}
+
+PG_FUNCTION_INFO_V1(gsmlsign_union);
+Datum gsmlsign_union(PG_FUNCTION_ARGS);
+Datum
+gsmlsign_union(PG_FUNCTION_ARGS)
+{
+       GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+       int        *size = (int *) PG_GETARG_POINTER(1);
+       BITVEC      base;
+       int4            i,
+                               len,
+                               maxrepeat = 1;
+       int4        flag = 0;
+       SmlSign    *result;
+
+       MemSet((void *) base, 0, sizeof(BITVEC));
+       for (i = 0; i < entryvec->n; i++)
+       {
+               if (GETENTRY(entryvec, i)->maxrepeat > maxrepeat)
+                       maxrepeat = GETENTRY(entryvec, i)->maxrepeat;
+               if (unionkey(base, GETENTRY(entryvec, i)))
+               {
+                       flag = ALLISTRUE;
+                       break;
+               }
+       }
+
+       flag |= SIGNKEY;
+       len = CALCGTSIZE(flag, 0);
+       result = (SmlSign *) palloc(len);
+       *size = len;
+       SET_VARSIZE(result, len);
+       result->flag = flag;
+       result->maxrepeat = maxrepeat;
+
+       if (!ISALLTRUE(result)) 
+       {
+               memcpy((void *) GETSIGN(result), (void *) base, sizeof(BITVEC));
+               result->size = sizebitvec(GETSIGN(result));
+       }
+       else
+               result->size = SIGLENBIT; 
+
+       PG_RETURN_POINTER(result);
+}
+
+/*
+ * Same method
+ */
+
+PG_FUNCTION_INFO_V1(gsmlsign_same);
+Datum gsmlsign_same(PG_FUNCTION_ARGS);
+Datum
+gsmlsign_same(PG_FUNCTION_ARGS)
+{
+       SmlSign *a = (SmlSign*)PG_GETARG_POINTER(0);
+       SmlSign *b = (SmlSign*)PG_GETARG_POINTER(1);
+       bool    *result = (bool *) PG_GETARG_POINTER(2);
+
+       if (a->size != b->size)
+       {
+               *result = false;
+       }
+       else if (ISSIGNKEY(a))
+       {       /* then b also ISSIGNKEY */
+               if ( ISALLTRUE(a) )
+               {
+                       /* in this case b is all true too - other cases is catched
+                          upper */
+                       *result = true;
+               }
+               else
+               {
+                       int4    i;
+                       BITVECP sa = GETSIGN(a),
+                                       sb = GETSIGN(b);
+
+                       *result = true;
+
+                       if ( !ISALLTRUE(a) )
+                       {
+                               LOOPBYTE
+                               {
+                                       if (sa[i] != sb[i])
+                                       {
+                                               *result = false;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+       else
+       {
+               uint32  *ptra = GETARR(a),
+                               *ptrb = GETARR(b);
+               int4    i;
+
+               *result = true;
+               for (i = 0; i < a->size; i++)
+               {
+                       if ( ptra[i] != ptrb[i])
+                       {
+                               *result = false;
+                               break;
+                       }
+               }
+       }
+
+       PG_RETURN_POINTER(result);
+}
+
+/*
+ * Penalty method
+ */
+static int
+hemdistsign(BITVECP a, BITVECP b)
+{
+    int         i,
+                               diff,
+                               dist = 0;
+
+       LOOPBYTE
+       {
+               diff = (unsigned char) (a[i] ^ b[i]);
+               dist += number_of_ones[diff];
+       }
+       return dist;
+}
+                                                                                                                                        
+static int
+hemdist(SmlSign *a, SmlSign *b)
+{
+       if (ISALLTRUE(a))
+       {
+               if (ISALLTRUE(b))
+                       return 0;
+               else
+                       return SIGLENBIT - b->size;
+       }
+       else if (ISALLTRUE(b))
+               return SIGLENBIT - b->size;
+
+       return hemdistsign(GETSIGN(a), GETSIGN(b));
+}
+
+PG_FUNCTION_INFO_V1(gsmlsign_penalty);
+Datum gsmlsign_penalty(PG_FUNCTION_ARGS);
+Datum
+gsmlsign_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);
+       SmlSign *origval = (SmlSign *) DatumGetPointer(origentry->key);
+       SmlSign *newval = (SmlSign *) DatumGetPointer(newentry->key);
+       BITVECP     orig = GETSIGN(origval);
+
+       *penalty = 0.0;
+
+       if (ISARRKEY(newval))
+       {
+               BITVEC      sign;
+
+               makesign(sign, newval);
+
+               if (ISALLTRUE(origval))
+                       *penalty = ((float) (SIGLENBIT - sizebitvec(sign))) / (float) (SIGLENBIT + 1);
+               else
+                       *penalty = hemdistsign(sign, orig);
+       }
+       else
+               *penalty = hemdist(origval, newval);
+
+       PG_RETURN_POINTER(penalty);
+}
+
+/*
+ * Picksplit method
+ */
+
+typedef struct
+{
+       bool        allistrue;
+       int32           size;
+       BITVEC      sign;
+} CACHESIGN;
+
+static void
+fillcache(CACHESIGN *item, SmlSign *key)
+{
+    item->allistrue = false;
+       item->size = key->size;
+
+       if (ISARRKEY(key)) 
+       {
+               makesign(item->sign, key);
+               item->size = sizebitvec( item->sign ); 
+       } 
+       else if (ISALLTRUE(key))
+               item->allistrue = true;
+       else
+               memcpy((void *) item->sign, (void *) GETSIGN(key), sizeof(BITVEC));
+}
+
+#define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
+
+typedef struct
+{
+       OffsetNumber pos;
+       int4        cost;
+} SPLITCOST;
+
+static int
+comparecost(const void *va, const void *vb)
+{
+       SPLITCOST  *a = (SPLITCOST *) va;
+       SPLITCOST  *b = (SPLITCOST *) vb;
+
+       if (a->cost == b->cost)
+               return 0;
+       else
+               return (a->cost > b->cost) ? 1 : -1;
+}
+
+static int
+hemdistcache(CACHESIGN *a, CACHESIGN *b)
+{
+       if (a->allistrue)
+       {
+               if (b->allistrue)
+                       return 0;
+               else
+                       return SIGLENBIT - b->size;
+       }
+       else if (b->allistrue)
+               return SIGLENBIT - a->size;
+
+       return hemdistsign(a->sign, b->sign);
+}
+
+PG_FUNCTION_INFO_V1(gsmlsign_picksplit);
+Datum gsmlsign_picksplit(PG_FUNCTION_ARGS);
+Datum
+gsmlsign_picksplit(PG_FUNCTION_ARGS)
+{
+       GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+       GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
+       OffsetNumber k,
+                               j;
+       SmlSign         *datum_l,
+                               *datum_r;
+       BITVECP     union_l,
+                               union_r;
+       int4        size_alpha,
+                               size_beta;
+       int4        size_waste,
+                               waste = -1;
+       int4        nbytes;
+       OffsetNumber seed_1 = 0,
+                               seed_2 = 0;
+       OffsetNumber *left,
+                               *right;
+       OffsetNumber maxoff;
+       BITVECP     ptr;
+       int         i;
+       CACHESIGN  *cache;
+       SPLITCOST  *costvector;
+
+       maxoff = entryvec->n - 2;
+       nbytes = (maxoff + 2) * sizeof(OffsetNumber);
+       v->spl_left = (OffsetNumber *) palloc(nbytes);
+       v->spl_right = (OffsetNumber *) palloc(nbytes);
+
+       cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 2));
+       fillcache(&cache[FirstOffsetNumber], GETENTRY(entryvec, FirstOffsetNumber));
+
+       for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
+       {
+               for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
+               {
+                       if (k == FirstOffsetNumber)
+                               fillcache(&cache[j], GETENTRY(entryvec, j));
+
+                       size_waste = hemdistcache(&(cache[j]), &(cache[k]));
+                       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 .. */
+       if (cache[seed_1].allistrue)
+       {
+               datum_l = (SmlSign *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
+               SET_VARSIZE(datum_l, CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
+               datum_l->flag = SIGNKEY | ALLISTRUE;
+               datum_l->size = SIGLENBIT; 
+       }
+       else
+       {
+               datum_l = (SmlSign *) palloc(CALCGTSIZE(SIGNKEY, 0));
+               SET_VARSIZE(datum_l, CALCGTSIZE(SIGNKEY, 0));
+               datum_l->flag = SIGNKEY;
+               memcpy((void *) GETSIGN(datum_l), (void *) cache[seed_1].sign, sizeof(BITVEC));
+               datum_l->size = cache[seed_1].size;
+       }
+       if (cache[seed_2].allistrue)
+       {
+               datum_r = (SmlSign *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
+               SET_VARSIZE(datum_r, CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
+               datum_r->flag = SIGNKEY | ALLISTRUE;
+               datum_r->size = SIGLENBIT;
+       }
+       else
+       {
+               datum_r = (SmlSign *) palloc(CALCGTSIZE(SIGNKEY, 0));
+               SET_VARSIZE(datum_r, CALCGTSIZE(SIGNKEY, 0));
+               datum_r->flag = SIGNKEY;
+               memcpy((void *) GETSIGN(datum_r), (void *) cache[seed_2].sign, sizeof(BITVEC));
+               datum_r->size = cache[seed_2].size;
+       }
+
+       union_l = GETSIGN(datum_l);
+       union_r = GETSIGN(datum_r);
+       maxoff = OffsetNumberNext(maxoff);
+       fillcache(&cache[maxoff], GETENTRY(entryvec, maxoff));
+       /* sort before ... */
+       costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+       for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
+       {
+               costvector[j - 1].pos = j;
+               size_alpha = hemdistcache(&(cache[seed_1]), &(cache[j]));
+               size_beta = hemdistcache(&(cache[seed_2]), &(cache[j]));
+               costvector[j - 1].cost = Abs(size_alpha - size_beta);
+       }
+       qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
+
+       datum_l->maxrepeat = datum_r->maxrepeat = 1;
+
+       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;
+               }
+
+               if (ISALLTRUE(datum_l) || cache[j].allistrue)
+               {
+                       if (ISALLTRUE(datum_l) && cache[j].allistrue)
+                               size_alpha = 0;
+                       else
+                               size_alpha = SIGLENBIT - (
+                                                                       (cache[j].allistrue) ? datum_l->size : cache[j].size
+                                                       );
+               }
+               else
+                       size_alpha = hemdistsign(cache[j].sign, GETSIGN(datum_l));
+
+               if (ISALLTRUE(datum_r) || cache[j].allistrue)
+               {
+                       if (ISALLTRUE(datum_r) && cache[j].allistrue)
+                               size_beta = 0;
+                       else
+                               size_beta = SIGLENBIT - (
+                                                                       (cache[j].allistrue) ? datum_r->size : cache[j].size
+                                                       );
+               }
+               else
+                       size_beta = hemdistsign(cache[j].sign, GETSIGN(datum_r));
+
+               if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.1))
+               {
+                       if (ISALLTRUE(datum_l) || cache[j].allistrue)
+                       {
+                               if (!ISALLTRUE(datum_l))
+                                       MemSet((void *) GETSIGN(datum_l), 0xff, sizeof(BITVEC));
+                               datum_l->size = SIGLENBIT;
+                       }
+                       else
+                       {
+                               ptr = cache[j].sign;
+                               LOOPBYTE
+                                       union_l[i] |= ptr[i];
+                               datum_l->size = sizebitvec(union_l);
+                       }
+                       *left++ = j;
+                       v->spl_nleft++;
+               }
+               else
+               {
+                       if (ISALLTRUE(datum_r) || cache[j].allistrue)
+                       {
+                               if (!ISALLTRUE(datum_r))
+                                       MemSet((void *) GETSIGN(datum_r), 0xff, sizeof(BITVEC));
+                               datum_r->size = SIGLENBIT;
+                       }
+                       else
+                       {
+                               ptr = cache[j].sign;
+                               LOOPBYTE
+                                       union_r[i] |= ptr[i];
+                               datum_r->size = sizebitvec(union_r);
+                       }
+                       *right++ = j;
+                       v->spl_nright++;
+               }
+       }
+       *right = *left = FirstOffsetNumber;
+       v->spl_ldatum = PointerGetDatum(datum_l);
+       v->spl_rdatum = PointerGetDatum(datum_r);
+
+       Assert( datum_l->size = sizebitvec(GETSIGN(datum_l)) );
+       Assert( datum_r->size = sizebitvec(GETSIGN(datum_r)) );
+
+       PG_RETURN_POINTER(v);
+}
+
+static double
+getIdfMaxLimit(SmlSign *key)
+{
+       switch( getTFMethod() )
+       {
+               case TF_CONST:
+                       return 1.0;
+                       break;
+               case TF_N:
+                       return (double)(key->maxrepeat);
+                       break;
+               case TF_LOG:
+                       return 1.0 + log( (double)(key->maxrepeat) );
+                       break;
+               default:
+                       elog(ERROR,"Unknown TF method: %d", getTFMethod());
+       }
+
+       return 0.0;
+}
+
+/*
+ * Consistent function
+ */
+PG_FUNCTION_INFO_V1(gsmlsign_consistent);
+Datum gsmlsign_consistent(PG_FUNCTION_ARGS);
+Datum
+gsmlsign_consistent(PG_FUNCTION_ARGS)
+{
+       GISTENTRY               *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+       StrategyNumber  strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+       bool                    *recheck = (bool *) PG_GETARG_POINTER(4);
+       ArrayType               *a;
+       SmlSign                 *key = (SmlSign*)DatumGetPointer(entry->key);
+       int                             res = false;
+       SmlSign                 *query;
+       SimpleArray             *s;
+       int4                    i;
+
+       fcinfo->flinfo->fn_extra = SearchArrayCache(
+                                                                       fcinfo->flinfo->fn_extra,
+                                                                       fcinfo->flinfo->fn_mcxt,
+                                                                       PG_GETARG_DATUM(1), &a, &s, &query);
+
+       *recheck = true;
+
+       if ( ARRISVOID(a) )
+               PG_RETURN_BOOL(res);
+
+       if ( strategy == SmlarOverlapStrategy )
+       {
+               if (ISALLTRUE(key))
+               {
+                       res = true;
+               }
+               else if (ISARRKEY(key))
+               {
+                       uint32          *kptr = GETARR(key),
+                                                       *qptr = GETARR(query);
+
+                       while( kptr - GETARR(key) < key->size && qptr - GETARR(query) < query->size )
+                       {
+                               if ( *kptr < *qptr )
+                                       kptr++;
+                               else if ( *kptr > *qptr )
+                                       qptr++;
+                               else
+                               {
+                                       res = true;
+                                       break;
+                               }
+                       }
+                       *recheck = false;
+               }
+               else
+               {
+                       BITVECP sign = GETSIGN(key);
+
+                       fillHashVal(fcinfo->flinfo->fn_extra, s);
+
+                       for(i=0; i<s->nelems; i++)
+                       {
+                               if ( GETBIT(sign, HASHVAL(s->hash[i])) )
+                               {
+                                       res = true;
+                                       break;
+                               }
+                       }
+               }
+       }
+       /*
+        *  SmlarSimilarityStrategy
+        */
+       else if (ISALLTRUE(key))
+       {
+               if ( GIST_LEAF(entry) )
+               {
+                       /*
+                        * With TF/IDF similarity we cannot say anything useful
+                        */
+                       if ( query->size < SIGLENBIT && getSmlType() != ST_TFIDF )
+                       {
+                               double power = ((double)(query->size)) * ((double)(SIGLENBIT));
+
+                               if ( ((double)(query->size)) / sqrt(power) >= GetSmlarLimit() ) 
+                                       res = true;
+                       }
+                       else
+                       {
+                               res = true;     
+                       }
+               }
+               else
+                       res = true;
+       }
+       else if (ISARRKEY(key))
+       {
+               uint32      *kptr = GETARR(key),
+                                       *qptr = GETARR(query);
+
+               Assert( GIST_LEAF(entry) );
+
+               switch(getSmlType())
+               {
+                       case ST_TFIDF:
+                               {
+                                       StatCache       *stat = getHashedCache(fcinfo->flinfo->fn_extra);
+                                       double          sumU = 0.0,
+                                                               sumQ = 0.0,
+                                                               sumK = 0.0;
+                                       double          maxKTF = getIdfMaxLimit(key);
+                                       HashedElem  *h;
+
+                                       Assert( s->df );
+                                       fillHashVal(fcinfo->flinfo->fn_extra, s);
+                                       if ( stat->info != s->info )
+                                               elog(ERROR,"Statistic and actual argument have different type");
+
+                                       for(i=0;i<s->nelems;i++)
+                                       {
+                                               sumQ += s->df[i] * s->df[i];
+
+                                               h = getHashedElemIdf(stat, s->hash[i], NULL);
+                                               if ( h && hasHashedElem(key, s->hash[i]) )
+                                               {
+                                                       sumK += h->idfMin * h->idfMin;
+                                                       sumU += h->idfMax * maxKTF * s->df[i];
+                                               } 
+                                       }
+
+                                       if ( sumK > 0.0 && sumQ > 0.0 && sumU / sqrt( sumK * sumQ ) >= GetSmlarLimit() )
+                                       {
+                                               /* 
+                                                * More precisely calculate sumK
+                                                */
+                                               h = NULL;
+                                               sumK = 0.0;
+
+                                               for(i=0;i<key->size;i++)
+                                               {
+                                                       h = getHashedElemIdf(stat, GETARR(key)[i], h);                                  
+                                                       if (h)
+                                                               sumK += h->idfMin * h->idfMin;
+                                               }
+
+                                               if ( sumK > 0.0 && sumQ > 0.0 && sumU / sqrt( sumK * sumQ ) >= GetSmlarLimit() )
+                                                       res = true;
+                                       }
+                               }
+                               break;
+                       case ST_COSINE:
+                               {
+                                       double                  power;
+                                       power = sqrt( ((double)(key->size)) * ((double)(s->nelems)) );
+
+                                       if (  ((double)Min(key->size, s->nelems)) / power >= GetSmlarLimit() )
+                                       {
+                                               int  cnt = 0;
+
+                                               while( kptr - GETARR(key) < key->size && qptr - GETARR(query) < query->size )
+                                               {
+                                                       if ( *kptr < *qptr )
+                                                               kptr++;
+                                                       else if ( *kptr > *qptr )
+                                                               qptr++;
+                                                       else
+                                                       {
+                                                               cnt++;
+                                                               kptr++;
+                                                               qptr++;
+                                                       }
+                                               }
+                       
+                                               if ( ((double)cnt) / power >= GetSmlarLimit() )
+                                                       res = true;
+                                       }
+                               }
+                               break;
+                       default:
+                               elog(ERROR,"GiST doesn't support current formula type of similarity");
+               }
+       }
+       else
+       {       /* signature */
+               BITVECP sign = GETSIGN(key);
+               int4    count = 0;
+
+               fillHashVal(fcinfo->flinfo->fn_extra, s);
+
+               if ( GIST_LEAF(entry) )
+               {
+                       switch(getSmlType())
+                       {
+                               case ST_TFIDF:
+                                       {
+                                               StatCache       *stat = getHashedCache(fcinfo->flinfo->fn_extra);
+                                               double          sumU = 0.0,
+                                                                       sumQ = 0.0,
+                                                                       sumK = 0.0;
+                                               double          maxKTF = getIdfMaxLimit(key);
+       
+                                               Assert( s->df );
+                                               if ( stat->info != s->info )
+                                                       elog(ERROR,"Statistic and actual argument have different type");
+
+                                               for(i=0;i<s->nelems;i++)
+                                               {
+                                                       int32           hbit = HASHVAL(s->hash[i]);
+
+                                                       sumQ += s->df[i] * s->df[i];
+                                                       if ( GETBIT(sign, hbit) )
+                                                       {
+                                                               sumK += stat->selems[ hbit ].idfMin * stat->selems[ hbit ].idfMin;
+                                                               sumU += stat->selems[ hbit ].idfMax * maxKTF * s->df[i];
+                                                       }
+                                               }
+
+                                               if ( sumK > 0.0 && sumQ > 0.0 && sumU / sqrt( sumK * sumQ ) >= GetSmlarLimit() )
+                                               {
+                                                       /* 
+                                                        * More precisely calculate sumK
+                                                        */
+                                                       sumK = 0.0;
+
+                                                       for(i=0;i<SIGLENBIT;i++)
+                                                               if ( GETBIT(sign,i) )
+                                                                       sumK += stat->selems[ i ].idfMin * stat->selems[ i ].idfMin;
+
+                                                       if ( sumK > 0.0 && sumQ > 0.0 && sumU / sqrt( sumK * sumQ ) >= GetSmlarLimit() )
+                                                               res = true;
+                                               }
+                                       }
+                                       break;
+                               case ST_COSINE:
+                                       {
+                                               double          power;
+
+                                               power = sqrt( ((double)(key->size)) * ((double)(s->nelems)) );
+
+                                               for(i=0; i<s->nelems; i++)
+                                                       count += GETBIT(sign, HASHVAL(s->hash[i]));
+               
+                                               if ( ((double)count) / power >= GetSmlarLimit() )
+                                                       res = true;
+                                       }
+                                       break;
+                               default:
+                                       elog(ERROR,"GiST doesn't support current formula type of similarity");
+                       }
+               }
+               else /* non-leaf page */
+               {
+                       switch(getSmlType())
+                       {
+                               case ST_TFIDF:
+                                       {
+                                               StatCache       *stat = getHashedCache(fcinfo->flinfo->fn_extra);
+                                               double          sumU = 0.0,
+                                                                       sumQ = 0.0,
+                                                                       minK = -1.0;
+                                               double          maxKTF = getIdfMaxLimit(key);
+       
+                                               Assert( s->df );
+                                               if ( stat->info != s->info )
+                                                       elog(ERROR,"Statistic and actual argument have different type");
+
+                                               for(i=0;i<s->nelems;i++)
+                                               {
+                                                       int32           hbit = HASHVAL(s->hash[i]);
+
+                                                       sumQ += s->df[i] * s->df[i];
+                                                       if ( GETBIT(sign, hbit) )
+                                                       {
+                                                               sumU += stat->selems[ hbit ].idfMax * maxKTF * s->df[i];
+                                                               if ( minK > stat->selems[ hbit ].idfMin  || minK < 0.0 )
+                                                                       minK = stat->selems[ hbit ].idfMin;
+                                                       }
+                                               }
+
+                                               if ( sumQ > 0.0 && minK > 0.0 && sumU / sqrt( sumQ * minK ) >= GetSmlarLimit() )
+                                                       res = true;
+                                       }
+                                       break;
+                               case ST_COSINE:
+                                       {
+                                               for(i=0; i<s->nelems; i++)
+                                                       count += GETBIT(sign, HASHVAL(s->hash[i]));
+                               
+                                               if ( s->nelems == count  || ((double)count) / ((double)(s->nelems)) >= GetSmlarLimit() )
+                                                       res = true;
+                                       }
+                                       break;
+                               default:
+                                       elog(ERROR,"GiST doesn't support current formula type of similarity");
+                       }
+               }
+       }
+
+#if 0
+       {
+               static int nnres = 0;
+               static int nres = 0;
+               if ( GIST_LEAF(entry) ) {
+                       if ( res )
+                               nres++;
+                       else
+                               nnres++;
+                       elog(NOTICE,"%s nn:%d n:%d", (ISARRKEY(key)) ? "ARR" : ( (ISALLTRUE(key)) ? "TRUE" : "SIGN" ), nnres, nres  );
+               }
+       }
+#endif
+
+       PG_RETURN_BOOL(res);
+}
diff --git a/smlar_guc.c b/smlar_guc.c
new file mode 100644 (file)
index 0000000..f437774
--- /dev/null
@@ -0,0 +1,225 @@
+#include "smlar.h"
+
+#include "fmgr.h"
+#include "utils/guc.h"
+
+#include "smlar.h"
+
+/*
+ *  Smlar limit
+ */
+static double smlar_limit = 0.6;
+
+/*
+ * Smlar table stores table-wide statistic
+ */
+static char * smlar_table = "";
+
+static bool smlar_use_malloc = false;
+
+/*
+ * State of GUC initialization
+ */
+static bool smlar_guc_inited = false;
+
+static void
+SmlarTableAssign(const char *newval, void *extra)
+{
+       resetStatCache();
+}
+
+static bool smlar_logadd = false;
+
+static void
+SmlarLogAssign(bool newval, void *extra)
+{
+       resetStatCache();
+}
+
+static int smlar_smltype = ST_COSINE;
+
+static const struct config_enum_entry SmlarTypeOptions[] = {
+    {"cosine", ST_COSINE, false},
+       {"tfidf", ST_TFIDF, false},
+       {"overlap", ST_OVERLAP, false},
+       {NULL, 0, false}
+};
+
+static int     smlar_tf_method = TF_N;
+static const struct config_enum_entry SmlarTFOptions[] = {
+    {"n", TF_N, false},
+       {"log", TF_LOG, false},
+       {"const", TF_CONST, false},
+       {NULL, 0, false}
+};
+
+static void
+initSmlarGUC()
+{
+       if (smlar_guc_inited)
+               return;
+
+       DefineCustomRealVariable(
+                       "smlar.threshold",
+                       "Lower threshold of array's similarity",
+                       "Array's with similarity lower than threshold are not similar by % operation",
+                       &smlar_limit,
+                       0.6, 
+                       0.0,
+                       1e10,
+                       PGC_USERSET,
+                       0,
+                       NULL,
+                       NULL,
+                       NULL
+       );
+
+       DefineCustomStringVariable(
+                       "smlar.stattable",
+                       "Name of table stored set-wide statistic",
+                       "Named table stores global frequencies of array's elements",
+                       &smlar_table,
+                       "",
+                       PGC_USERSET,
+                       GUC_IS_NAME,
+                       NULL,
+                       SmlarTableAssign,
+                       NULL
+       );
+
+       DefineCustomEnumVariable(
+                       "smlar.type",
+                       "Type of similarity formula",
+                       "Type of similarity formula: cosine(default), tfidf, overlap",
+                       &smlar_smltype,
+                       smlar_smltype,
+                       SmlarTypeOptions,
+                       PGC_SUSET,
+                       0,
+                       NULL,
+                       NULL,
+                       NULL
+       );
+
+       DefineCustomBoolVariable(
+                       "smlar.persistent_cache",
+                       "Usage of persistent cache of global stat",
+                       "Cache of global stat is stored in transaction-independent memory",
+                       &smlar_use_malloc,
+                       false,
+                       PGC_USERSET,
+                       0,
+                       NULL,
+                       NULL,
+                       NULL
+       );
+
+       DefineCustomBoolVariable(
+                       "smlar.idf_plus_one",
+                       "Calculate idf by log(1+d/df)",
+                       "Calculate idf by log(1+d/df)",
+                       &smlar_logadd,
+                       false,
+                       PGC_USERSET,
+                       0,
+                       NULL,
+                       SmlarLogAssign,
+                       NULL
+       );
+
+       DefineCustomEnumVariable(
+                       "smlar.tf_method",
+                       "Method of TF caclulation",
+                       "TF method: n => number of entries, log => 1+log(n), const => constant value",
+                       &smlar_tf_method,
+                       smlar_tf_method,
+                       SmlarTFOptions,
+                       PGC_SUSET,
+                       0,
+                       NULL,
+                       NULL,
+                       NULL
+       );
+
+       smlar_guc_inited = true;        
+}
+
+double 
+getOneAdd(void)
+{
+       if (!smlar_guc_inited)
+               initSmlarGUC();
+
+       return (smlar_logadd) ? 1.0 : 0.0;
+}
+
+int
+getTFMethod(void)
+{
+       if (!smlar_guc_inited)
+               initSmlarGUC();
+
+       return smlar_tf_method;
+}
+
+double
+GetSmlarLimit(void)
+{
+       if (!smlar_guc_inited)
+               initSmlarGUC();
+
+       return smlar_limit;
+}
+
+const char*
+GetSmlarTable(void)
+{
+       if (!smlar_guc_inited)
+               initSmlarGUC();
+
+       return smlar_table;
+}
+
+int
+getSmlType(void)
+{
+       if (!smlar_guc_inited)
+               initSmlarGUC();
+
+       return smlar_smltype;
+}
+
+bool
+GetSmlarUsePersistent(void)
+{
+       if (!smlar_guc_inited)
+               initSmlarGUC();
+
+       return smlar_use_malloc;
+}
+
+PG_FUNCTION_INFO_V1(set_smlar_limit);
+Datum       set_smlar_limit(PG_FUNCTION_ARGS);
+Datum
+set_smlar_limit(PG_FUNCTION_ARGS)
+{
+       float4      nlimit = PG_GETARG_FLOAT4(0);
+       char            buf[32];
+
+       /* init smlar guc */
+       initSmlarGUC();
+
+       sprintf(buf,"%f", nlimit);      
+       set_config_option("smlar.threshold", buf, 
+                                               PGC_USERSET, PGC_S_SESSION ,GUC_ACTION_SET, true, 0);
+       PG_RETURN_FLOAT4((float4)GetSmlarLimit());
+}
+
+PG_FUNCTION_INFO_V1(show_smlar_limit);
+Datum       show_smlar_limit(PG_FUNCTION_ARGS);
+Datum
+show_smlar_limit(PG_FUNCTION_ARGS)
+{
+       PG_RETURN_FLOAT4((float4)GetSmlarLimit());
+}
+
diff --git a/smlar_stat.c b/smlar_stat.c
new file mode 100644 (file)
index 0000000..1007de8
--- /dev/null
@@ -0,0 +1,206 @@
+#include "smlar.h"
+
+#include "fmgr.h"
+#include "catalog/pg_type.h"
+#include "executor/spi.h"
+#include "utils/array.h"
+#include "utils/datum.h"
+#include "utils/memutils.h"
+
+static StatCache *PersistentDocStat = NULL;
+
+static void*
+cacheAlloc(MemoryContext ctx, size_t size)
+{
+       if ( GetSmlarUsePersistent() )
+       {
+               void *ptr = malloc(size);
+
+               if (!ptr)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_OUT_OF_MEMORY),
+                                       errmsg("out of memory")));
+
+               return ptr;
+       }
+
+       return  MemoryContextAlloc(ctx, size);
+}
+
+static void*
+cacheAllocZero(MemoryContext ctx, size_t size)
+{
+       void *ptr = cacheAlloc(ctx, size);
+       memset(ptr, 0, size);
+       return ptr;
+}
+
+struct StatCache *
+initStatCache(MemoryContext ctx)
+{
+       if (PersistentDocStat && GetSmlarUsePersistent())
+               return PersistentDocStat;
+       else {
+               int             stat;
+               char            buf[1024];
+               const char      *tbl = GetSmlarTable();
+               StatCache       *cache = NULL;
+
+               if ( tbl == NULL || *tbl == '\0' )
+                       elog(ERROR,"smlar.stattable is not defined");
+
+               sprintf(buf,"SELECT * FROM \"%s\" ORDER BY 1;", tbl); 
+               SPI_connect();
+               stat = SPI_execute(buf, true, 0);
+
+               if (stat != SPI_OK_SELECT)
+                       elog(ERROR, "SPI_execute() returns %d", stat);
+
+               if ( SPI_processed == 0 )
+               {
+                       elog(ERROR, "Stat table '%s' is empty", tbl);
+               }
+               else
+               {
+                       int     i;
+                       double  totaldocs = 0.0;
+                       Oid             ndocType = SPI_gettypeid(SPI_tuptable->tupdesc, 2);
+
+                       if ( SPI_tuptable->tupdesc->natts != 2 )
+                               elog(ERROR,"Stat table is not (type, int4)");
+                       if ( !(ndocType == INT4OID || ndocType == INT8OID) )
+                               elog(ERROR,"Stat table is not (type, int4) nor (type, int8)");
+
+                       cache = cacheAllocZero(ctx, sizeof(StatCache));
+                       cache->info = findProcs( SPI_gettypeid(SPI_tuptable->tupdesc, 1) );
+                       if (cache->info->tupDesc)
+                               elog(ERROR, "TF/IDF is not supported for composite (weighted) type");
+                       getFmgrInfoCmp(cache->info);
+                       cache->elems = cacheAlloc(ctx, sizeof(StatElem) * SPI_processed);
+
+                       for(i=0; i<SPI_processed; i++)
+                       {
+                               bool    isnullvalue, isnullndoc;
+                               Datum   datum = SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &isnullvalue);
+                               int64   ndoc;
+
+                               if (ndocType == INT4OID)
+                                       ndoc = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &isnullndoc));
+                               else
+                                       ndoc = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &isnullndoc));
+
+                               if (isnullndoc)
+                                       elog(ERROR,"NULL value in second column of table '%s'", tbl);
+
+                               if (isnullvalue)
+                               {
+                                       /* total number of docs */
+
+                                       if (ndoc <= 0)
+                                               elog(ERROR,"Total number of document should be positive");
+                                       if ( totaldocs > 0 )
+                                               elog(ERROR,"Total number of document is repeated");
+                                       totaldocs = ndoc;
+                               }
+                               else
+                               {
+                                       if ( i>0 && DatumGetInt32( FCall2( &cache->info->cmpFunc, cache->elems[i-1].datum, datum ) ) == 0 )
+                                               elog(ERROR,"Values of first column of table '%s' are not unique", tbl);
+
+                                       if (ndoc <= 0)
+                                               elog(ERROR,"Number of documents with current value should be positive");
+
+                                       if ( cache->info->typbyval )
+                                               cache->elems[i].datum = datum;
+                                       else
+                                       {
+                                               size_t  size = datumGetSize(datum, false, cache->info->typlen);
+                                               
+                                               cache->elems[i].datum = PointerGetDatum(cacheAlloc(ctx, size));
+                                               memcpy(DatumGetPointer(cache->elems[i].datum), DatumGetPointer(datum), size);
+                                       }
+
+                                       cache->elems[i].idf = ndoc;
+                               }
+                       }
+
+                       if ( totaldocs <= 0)
+                               elog(ERROR,"Total number of document is unknown");
+                       cache->nelems = SPI_processed - 1;
+                       
+                       for(i=0;i<cache->nelems;i++)
+                       {
+                               if ( totaldocs < cache->elems[i].idf )
+                                       elog(ERROR,"Inconsitent data in '%s': there is values with frequency > 1", tbl);
+                               cache->elems[i].idf = log( totaldocs / cache->elems[i].idf + getOneAdd() );
+                       }
+               }
+
+               SPI_finish();
+
+               if ( GetSmlarUsePersistent() )
+                       PersistentDocStat = cache;
+
+               return cache;
+       }
+}
+
+void
+resetStatCache(void)
+{
+       if ( PersistentDocStat )
+       {
+
+               if (!PersistentDocStat->info->typbyval)
+               {
+                       int i;
+                       for(i=0;i<PersistentDocStat->nelems;i++)
+                               free( DatumGetPointer(PersistentDocStat->elems[i].datum) );
+               }
+
+               if (PersistentDocStat->helems)
+                       free(PersistentDocStat->helems);
+               free(PersistentDocStat->elems);
+               free(PersistentDocStat);
+       }
+
+       PersistentDocStat = NULL;
+}
+
+StatElem  *
+findStat(StatCache *stat, Datum query, StatElem *low)
+{
+       StatElem        *StopLow = (low) ? low : stat->elems,
+                               *StopHigh = stat->elems + stat->nelems,
+                               *StopMiddle;
+       int                     cmp;
+
+       if (stat->info->tupDesc)
+               elog(ERROR, "TF/IDF is not supported for composite (weighted) type");
+
+       while (StopLow < StopHigh)
+       {
+               StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
+               cmp = DatumGetInt32( FCall2( &stat->info->cmpFunc, StopMiddle->datum, query ) );
+
+               if ( cmp == 0 )
+                       return StopMiddle;
+               else if (cmp < 0)
+                       StopLow = StopMiddle + 1;
+               else
+                       StopHigh = StopMiddle;
+       }
+
+       return NULL;
+}
+
+void
+getHashStatCache(StatCache *stat, MemoryContext ctx, size_t n)
+{
+       if ( !stat->helems )
+       {
+               stat->helems = cacheAlloc(ctx, (stat->nelems +1) * sizeof(HashedElem));
+               stat->selems = cacheAllocZero(ctx, n * sizeof(SignedElem));
+               stat->nhelems = -1;
+       }
+}
diff --git a/sql/bit.sql b/sql/bit.sql
new file mode 100644 (file)
index 0000000..028268a
--- /dev/null
@@ -0,0 +1,28 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::int4::bit(10)
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_bit
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]) AS s FROM test_bit WHERE v % '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[] ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]) AS s FROM test_bit WHERE v % '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[] ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_bit ON test_bit USING gin (v _bit_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]) AS s FROM test_bit WHERE v % '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[] ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]) AS s FROM test_bit WHERE v % '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[] ORDER BY s DESC, t;
+
+
+SET enable_seqscan=on;
+
diff --git a/sql/bytea.sql b/sql/bytea.sql
new file mode 100644 (file)
index 0000000..e86d6cb
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::text::bytea
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_bytea
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_bytea WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_bytea WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_bytea ON test_bytea USING gist (v _bytea_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_bytea WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_bytea WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_bytea;
+CREATE INDEX idx_test_bytea ON test_bytea USING gin (v _bytea_sml_ops);
+
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_bytea WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_bytea WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/char.sql b/sql/char.sql
new file mode 100644 (file)
index 0000000..9a39f66
--- /dev/null
@@ -0,0 +1,30 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::varchar(1)::"char"
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_char
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{3,2,1}') AS s FROM test_char WHERE v % '{3,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_char ON test_char USING gist (v _char_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{3,2,1}') AS s FROM test_char WHERE v % '{3,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_char;
+CREATE INDEX idx_test_char ON test_char USING gin (v _char_sml_ops);
+
+SELECT  t, smlar(v, '{3,2,1}') AS s FROM test_char WHERE v % '{3,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/cidr.sql b/sql/cidr.sql
new file mode 100644 (file)
index 0000000..afe69d4
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       ( '192.168.1.' || (v % 256) )::cidr
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_cidr
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_cidr ON test_cidr USING gist (v _cidr_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_cidr;
+CREATE INDEX idx_test_cidr ON test_cidr USING gin (v _cidr_sml_ops);
+
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_cidr WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/composite_int4.sql b/sql/composite_int4.sql
new file mode 100644 (file)
index 0000000..0ba908f
--- /dev/null
@@ -0,0 +1,45 @@
+SELECT set_smlar_limit(0.6);
+
+CREATE TYPE cint AS (id int, w float4);
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       (ROW(v::int4, v::float4))::cint
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_composite_int4
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[]) AS s 
+       FROM test_composite_int4 
+       WHERE v % '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[] ORDER BY s DESC, t;
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[] AS s 
+       FROM test_composite_int4 
+       WHERE v % '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[]) ORDER BY s DESC, t;
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[]) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[]) > 0.6 ORDER BY s DESC, t;
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[]) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[]) > 0.6 ORDER BY s DESC, t;
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[], false) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[], false) > 0.6 ORDER BY s DESC, t;
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[], false) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[], false) > 0.6 ORDER BY s DESC, t;
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[], true) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::cint[], true) > 0.6 ORDER BY s DESC, t;
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[], true) AS s 
+       FROM test_composite_int4 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::cint[], true) > 0.6 ORDER BY s DESC, t;
+
+
diff --git a/sql/composite_text.sql b/sql/composite_text.sql
new file mode 100644 (file)
index 0000000..6c0b85d
--- /dev/null
@@ -0,0 +1,45 @@
+SELECT set_smlar_limit(0.6);
+
+CREATE TYPE ctext AS (id text, w float4);
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       (ROW(v::text, v::float4))::ctext
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_composite_text
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[]) AS s 
+       FROM test_composite_text 
+       WHERE v % '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[] ORDER BY s DESC, t;
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[]) AS s 
+       FROM test_composite_text 
+       WHERE v % '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[] ORDER BY s DESC, t;
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[]) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[]) > 0.6 ORDER BY s DESC, t;
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[]) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[]) > 0.6 ORDER BY s DESC, t;
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[], false) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[], false) > 0.6 ORDER BY s DESC, t;
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[], false) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[], false) > 0.6 ORDER BY s DESC, t;
+
+SELECT t, smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[], true) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(10,1)", "(9,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(3,1)", "(2,1)", "(1,1)"}'::ctext[], true) > 0.6 ORDER BY s DESC, t;
+SELECT t, smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[], true) AS s 
+       FROM test_composite_text 
+       WHERE smlar(v, '{"(50,1)", "(49,1)", "(8,1)", "(7,1)", "(6,1)", "(5,1)", "(4,1)", "(33,1)", "(2,1)", "(1,1)"}'::ctext[], true) > 0.6 ORDER BY s DESC, t;
+
+
diff --git a/sql/date.sql b/sql/date.sql
new file mode 100644 (file)
index 0000000..8643579
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       epoch2timestamp(v)::date
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_date
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[] ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_date ON test_date USING gist (v _date_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[] ORDER BY s DESC, t;
+
+DROP INDEX idx_test_date;
+CREATE INDEX idx_test_date ON test_date USING gin (v _date_sml_ops);
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::date[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[]) AS s FROM test_date WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::date[] ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/float4.sql b/sql/float4.sql
new file mode 100644 (file)
index 0000000..53668e9
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::float4
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_float4
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_float4 ON test_float4 USING gist (v _float4_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_float4;
+CREATE INDEX idx_test_float4 ON test_float4 USING gin (v _float4_sml_ops);
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/float8.sql b/sql/float8.sql
new file mode 100644 (file)
index 0000000..3841941
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::float8
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_float8
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_float8 ON test_float8 USING gist (v _float8_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_float8;
+CREATE INDEX idx_test_float8 ON test_float8 USING gin (v _float8_sml_ops);
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_float8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_float8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/inet.sql b/sql/inet.sql
new file mode 100644 (file)
index 0000000..22febf6
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       ( '192.168.1.' || (v % 256) )::inet
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_inet
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_inet ON test_inet USING gist (v _inet_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_inet;
+CREATE INDEX idx_test_inet ON test_inet USING gin (v _inet_sml_ops);
+
+SELECT t, smlar(v, '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.10,192.168.1.9,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.3,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}') AS s FROM test_inet WHERE v % '{192.168.1.50,192.168.1.49,192.168.1.8,192.168.1.7,192.168.1.6,192.168.1.5,192.168.1.4,192.168.1.33,192.168.1.2,192.168.1.1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/int2.sql b/sql/int2.sql
new file mode 100644 (file)
index 0000000..c55464d
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::int2
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_int2
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int2 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int2 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_int2 ON test_int2 USING gist (v _int2_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int2 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int2 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_int2;
+CREATE INDEX idx_test_int2 ON test_int2 USING gin (v _int2_sml_ops);
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int2 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int2 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/int4.sql b/sql/int4.sql
new file mode 100644 (file)
index 0000000..2b16272
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::int4
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_int4
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_int4 ON test_int4 USING gist (v _int4_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_int4;
+CREATE INDEX idx_test_int4 ON test_int4 USING gin (v _int4_sml_ops);
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/int4g.sql b/sql/int4g.sql
new file mode 100644 (file)
index 0000000..982ce4d
--- /dev/null
@@ -0,0 +1,142 @@
+SELECT set_smlar_limit(0.3);
+
+SET smlar.type = "tfidf";
+SET smlar.stattable = "int4_stat";
+
+UPDATE test_int4 SET v = v || '{50,50,50}'::int4[] WHERE t >=50 AND t < 60;
+INSERT INTO test_int4 VALUES(201, '{50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50}'); 
+
+CREATE TABLE int4_stat (
+    value   int4 UNIQUE,
+       ndoc    int4 NOT NULL CHECK (ndoc>0)
+);
+
+INSERT INTO int4_stat (
+    SELECT
+               q.w,
+               count(*)
+       FROM
+               (SELECT array_to_col(v) AS w FROM test_int4 WHERE v IS NOT NULL)  AS q
+       GROUP BY w
+);
+
+INSERT INTO int4_stat VALUES (NULL, (SELECT count(*) FROM test_int4));
+
+DROP INDEX idx_test_int4;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_int4 ON test_int4 USING gist (v _int4_sml_ops);
+SET enable_seqscan = off;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_int4;
+CREATE INDEX idx_test_int4 ON test_int4 USING gin (v _int4_sml_ops);
+SET enable_seqscan = off;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int4 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int4 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
diff --git a/sql/int4i.sql b/sql/int4i.sql
new file mode 100644 (file)
index 0000000..58e9b0d
--- /dev/null
@@ -0,0 +1,14 @@
+SELECT set_smlar_limit(5.0);
+SET smlar.type='overlap';
+
+DROP INDEX idx_test_int4;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int4[]);
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_int4 WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_int4 ON test_int4 USING gin (v _int4_sml_ops);
+SET enable_seqscan = off;
+
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_int4 WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
diff --git a/sql/int8.sql b/sql/int8.sql
new file mode 100644 (file)
index 0000000..9b3e2be
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::int8
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_int8
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_int8 ON test_int8 USING gist (v _int8_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_int8;
+CREATE INDEX idx_test_int8 ON test_int8 USING gin (v _int8_sml_ops);
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/int8g.sql b/sql/int8g.sql
new file mode 100644 (file)
index 0000000..4449e32
--- /dev/null
@@ -0,0 +1,142 @@
+SELECT set_smlar_limit(0.3);
+
+SET smlar.type = "tfidf";
+SET smlar.stattable = "int8_stat";
+
+UPDATE test_int8 SET v = v || '{50,50,50}'::int8[] WHERE t >=50 AND t < 60;
+INSERT INTO test_int8 VALUES(201, '{50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50}'); 
+
+CREATE TABLE int8_stat (
+    value   int8 UNIQUE,
+       ndoc    int4 NOT NULL CHECK (ndoc>0)
+);
+
+INSERT INTO int8_stat (
+    SELECT
+               q.w,
+               count(*)
+       FROM
+               (SELECT array_to_col(v) AS w FROM test_int8 WHERE v IS NOT NULL)  AS q
+       GROUP BY w
+);
+
+INSERT INTO int8_stat VALUES (NULL, (SELECT count(*) FROM test_int8));
+
+DROP INDEX idx_test_int8;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_int8 ON test_int8 USING gist (v _int8_sml_ops);
+SET enable_seqscan = off;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_int8;
+CREATE INDEX idx_test_int8 ON test_int8 USING gin (v _int8_sml_ops);
+SET enable_seqscan = off;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
diff --git a/sql/int8i.sql b/sql/int8i.sql
new file mode 100644 (file)
index 0000000..ad458e4
--- /dev/null
@@ -0,0 +1,14 @@
+SELECT set_smlar_limit(5.0);
+SET smlar.type='overlap';
+
+DROP INDEX idx_test_int8;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_int8 WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_int8 ON test_int8 USING gin (v _int8_sml_ops);
+SET enable_seqscan = off;
+
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_int8 WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
diff --git a/sql/int8n.sql b/sql/int8n.sql
new file mode 100644 (file)
index 0000000..81144c9
--- /dev/null
@@ -0,0 +1,26 @@
+SELECT set_smlar_limit(0.8);
+
+DROP INDEX idx_test_int8;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_int8 ON test_int8 USING gist (v _int8_sml_ops);
+SET enable_seqscan = off;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
+DROP INDEX idx_test_int8;
+
+CREATE INDEX idx_test_int8 ON test_int8 USING gin (v _int8_sml_ops);
+SET enable_seqscan = off;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::int8[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_int8 WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_int8 WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
diff --git a/sql/interval.sql b/sql/interval.sql
new file mode 100644 (file)
index 0000000..7b45c95
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::text::interval
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_interval
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_interval ON test_interval USING gist (v _interval_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_interval;
+CREATE INDEX idx_test_interval ON test_interval USING gin (v _interval_sml_ops);
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/intervalg.sql b/sql/intervalg.sql
new file mode 100644 (file)
index 0000000..5bc25ca
--- /dev/null
@@ -0,0 +1,142 @@
+SELECT set_smlar_limit(0.3);
+
+SET smlar.type = "tfidf";
+SET smlar.stattable = "interval_stat";
+
+UPDATE test_interval SET v = v || '{50,50,50}'::interval[] WHERE t >=50 AND t < 60;
+INSERT INTO test_interval VALUES(201, '{50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50}'); 
+
+CREATE TABLE interval_stat (
+    value   interval UNIQUE,
+       ndoc    int4 NOT NULL CHECK (ndoc>0)
+);
+
+INSERT INTO interval_stat (
+    SELECT
+               q.w,
+               count(*)
+       FROM
+               (SELECT array_to_col(v) AS w FROM test_interval WHERE v IS NOT NULL)  AS q
+       GROUP BY w
+);
+
+INSERT INTO interval_stat VALUES (NULL, (SELECT count(*) FROM test_interval));
+
+DROP INDEX idx_test_interval;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_interval ON test_interval USING gist (v _interval_sml_ops);
+SET enable_seqscan = off;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_interval;
+CREATE INDEX idx_test_interval ON test_interval USING gin (v _interval_sml_ops);
+SET enable_seqscan = off;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
diff --git a/sql/intervali.sql b/sql/intervali.sql
new file mode 100644 (file)
index 0000000..2287d1a
--- /dev/null
@@ -0,0 +1,14 @@
+SELECT set_smlar_limit(5.0);
+SET smlar.type='overlap';
+
+DROP INDEX idx_test_interval;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_interval WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_interval ON test_interval USING gin (v _interval_sml_ops);
+SET enable_seqscan = off;
+
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_interval WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
diff --git a/sql/intervaln.sql b/sql/intervaln.sql
new file mode 100644 (file)
index 0000000..f36759d
--- /dev/null
@@ -0,0 +1,26 @@
+SELECT set_smlar_limit(0.8);
+
+DROP INDEX idx_test_interval;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_interval ON test_interval USING gist (v _interval_sml_ops);
+SET enable_seqscan = off;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
+DROP INDEX idx_test_interval;
+
+CREATE INDEX idx_test_interval ON test_interval USING gin (v _interval_sml_ops);
+SET enable_seqscan = off;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::interval[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_interval WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_interval WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
diff --git a/sql/macaddr.sql b/sql/macaddr.sql
new file mode 100644 (file)
index 0000000..92492c8
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       ('01:01:01:01:01:' || (v % 100))::macaddr
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_macaddr
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_macaddr ON test_macaddr USING gist (v _macaddr_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_macaddr;
+CREATE INDEX idx_test_macaddr ON test_macaddr USING gin (v _macaddr_sml_ops);
+
+SELECT t, smlar(v, '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:10,01:01:01:01:01:9,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:3,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}') AS s FROM test_macaddr WHERE v % '{01:01:01:01:01:50,01:01:01:01:01:49,01:01:01:01:01:8,01:01:01:01:01:7,01:01:01:01:01:6,01:01:01:01:01:5,01:01:01:01:01:4,01:01:01:01:01:33,01:01:01:01:01:2,01:01:01:01:01:1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/money.sql b/sql/money.sql
new file mode 100644 (file)
index 0000000..43ea5ae
--- /dev/null
@@ -0,0 +1,27 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::text::money
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_money
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_money WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_money WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_money ON test_money USING gin (v _money_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_money WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_money WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/numeric.sql b/sql/numeric.sql
new file mode 100644 (file)
index 0000000..5b54b2d
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::numeric
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_numeric
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_numeric WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_numeric WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_numeric ON test_numeric USING gist (v _numeric_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_numeric WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_numeric WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_numeric;
+CREATE INDEX idx_test_numeric ON test_numeric USING gin (v _numeric_sml_ops);
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_numeric WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_numeric WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/oid.sql b/sql/oid.sql
new file mode 100644 (file)
index 0000000..2436a32
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::oid
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_oid
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_oid WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_oid WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_oid ON test_oid USING gist (v _oid_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_oid WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_oid WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_oid;
+CREATE INDEX idx_test_oid ON test_oid USING gin (v _oid_sml_ops);
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_oid WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_oid WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/smlar.sql b/sql/smlar.sql
new file mode 100644 (file)
index 0000000..da93dfe
--- /dev/null
@@ -0,0 +1,135 @@
+CREATE EXTENSION smlar;
+
+--sanity check
+SELECT 
+       opc.opcname, 
+       t.typname, 
+       opc.opcdefault  
+FROM 
+       pg_opclass opc, 
+       pg_am am, 
+       pg_type t, 
+       pg_type k 
+WHERE 
+       opc.opcmethod = am.oid AND 
+       am.amname='gist' AND 
+       opc.opcintype = t.oid AND 
+       opc.opckeytype = k.oid AND 
+       k.typname='gsmlsign'
+ORDER BY opc.opcname;
+
+SELECT 
+       opc.opcname, 
+       t.typname, 
+       opc.opcdefault  
+FROM 
+       pg_opclass opc, 
+       pg_am am, 
+       pg_type t
+WHERE 
+       opc.opcmethod = am.oid AND 
+       am.amname='gin' AND 
+       opc.opcintype = t.oid AND 
+       opc.opcname ~ '_sml_ops$'
+ORDER BY opc.opcname;
+
+SELECT 
+    trim( leading '_'  from t.typname ) || '[]' AS "Array Type",
+    gin.opcname AS "GIN operator class",
+    gist.opcname AS "GiST operator class"
+FROM
+    (
+        SELECT *
+        FROM
+            pg_catalog.pg_opclass,
+            pg_catalog.pg_am
+        WHERE
+            pg_opclass.opcmethod = pg_am.oid AND
+            pg_am.amname = 'gin' AND
+            pg_opclass.opcname ~ '_sml_ops$'
+    ) AS gin
+    FULL OUTER JOIN
+        (
+            SELECT *
+            FROM
+                pg_catalog.pg_opclass,
+                pg_catalog.pg_am
+            WHERE
+                pg_opclass.opcmethod = pg_am.oid AND
+                pg_am.amname = 'gist' AND
+                pg_opclass.opcname ~ '_sml_ops$'
+        ) AS gist
+        ON (
+            gist.opcname = gin.opcname AND 
+            gist.opcintype = gin.opcintype 
+        ),
+    pg_catalog.pg_type t
+WHERE
+    t.oid = COALESCE(gist.opcintype, gin.opcintype) AND
+    t.typarray = 0
+ORDER BY
+    "Array Type" ASC 
+;
+
+SELECT set_smlar_limit(0.1);
+SET smlar.threshold = 0.6;
+
+--First checks
+SELECT smlar('{3,2}'::int[], '{3,2,1}');
+SELECT smlar('{2,1}'::int[], '{3,2,1}');
+SELECT smlar('{}'::int[], '{3,2,1}');
+SELECT smlar('{12,10}'::int[], '{3,2,1}');
+SELECT smlar('{123}'::int[], '{}');
+SELECT smlar('{1,4,6}'::int[], '{1,4,6}');
+SELECT smlar('{1,4,6}'::int[], '{6,4,1}');
+SELECT smlar('{1,4,6}'::int[], '{5,4,6}');
+SELECT smlar('{1,4,6}'::int[], '{5,4,6}');
+SELECT smlar('{1,2}'::int[], '{2,2,2,2,2,1}');
+SELECT smlar('{1,2}'::int[], '{1,2,2,2,2,2}');
+SELECT smlar('{}'::int[], '{3}');
+SELECT smlar('{3}'::int[], '{3}');
+SELECT smlar('{2}'::int[], '{3}');
+
+
+SELECT smlar('{1,4,6}'::int[], '{5,4,6}', 'N.i / (N.a + N.b)' );
+SELECT smlar('{1,4,6}'::int[], '{5,4,6}', 'N.i / sqrt(N.a * N.b)' );
+
+SELECT tsvector2textarray('qwe:12 asd:45');
+
+SELECT array_unique('{12,12,1,4,1,16}'::int4[]);
+SELECT array_unique('{12,12,1,4,1,16}'::bigint[]);
+SELECT array_unique('{12,12,1,4,1,16}'::smallint[]);
+SELECT array_unique('{12,12,1,4,1,16}'::text[]);
+SELECT array_unique('{12,12,1,4,1,16}'::varchar[]);
+
+SELECT inarray('{12,12,1,4,1,16}'::int[], 13::int);
+SELECT inarray('{12,12,1,4,1,16}'::int[], 12::int);
+SELECT inarray('{12,12,1,4,1,16}'::text[], 13::text);
+SELECT inarray('{12,12,1,4,1,16}'::text[], 12::text);
+SELECT inarray('{12,12,1,4,1,16}'::int[], 13::int, 0.9, 0.1);
+SELECT inarray('{12,12,1,4,1,16}'::int[], 12::int, 0.9, 0.1);
+SELECT inarray('{12,12,1,4,1,16}'::text[], 13::text, 0.9, 0.1);
+SELECT inarray('{12,12,1,4,1,16}'::text[], 12::text, 0.9, 0.1);
+
+--testing function
+CREATE OR REPLACE FUNCTION epoch2timestamp(int4)
+RETURNS timestamp AS $$
+    SELECT ('1970-01-01 00:00:00'::timestamp +   ( ($1*3600*24 + $1) ::text || ' seconds' )::interval)::timestamp;
+       $$ LANGUAGE SQL RETURNS NULL ON NULL INPUT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION to_tsp_array(_int4)
+RETURNS _timestamp AS $$
+       SELECT ARRAY( 
+               SELECT 
+                       epoch2timestamp( $1[n] )
+               FROM
+                       generate_series( 1, array_upper( $1, 1) - array_lower( $1, 1 ) + 1 ) AS n
+       );
+       $$ LANGUAGE SQL RETURNS NULL ON NULL INPUT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION array_to_col(anyarray)
+RETURNS SETOF anyelement AS
+$$
+    SELECT $1[n] FROM generate_series( 1, array_upper( $1, 1) - array_lower( $1, 1 ) + 1 ) AS n;
+$$ LANGUAGE SQL RETURNS NULL ON NULL INPUT IMMUTABLE;
+
diff --git a/sql/text.sql b/sql/text.sql
new file mode 100644 (file)
index 0000000..98cac43
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::text
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_text
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_text ON test_text USING gist (v _text_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_text;
+CREATE INDEX idx_test_text ON test_text USING gin (v _text_sml_ops);
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/textg.sql b/sql/textg.sql
new file mode 100644 (file)
index 0000000..c937a5b
--- /dev/null
@@ -0,0 +1,142 @@
+SELECT set_smlar_limit(0.3);
+
+SET smlar.type = "tfidf";
+SET smlar.stattable = "text_stat";
+
+UPDATE test_text SET v = v || '{50,50,50}'::text[] WHERE t >=50 AND t < 60;
+INSERT INTO test_text VALUES(201, '{50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50}'); 
+
+CREATE TABLE text_stat (
+    value   text UNIQUE,
+       ndoc    int4 NOT NULL CHECK (ndoc>0)
+);
+
+INSERT INTO text_stat (
+    SELECT
+               q.w,
+               count(*)
+       FROM
+               (SELECT array_to_col(v) AS w FROM test_text WHERE v IS NOT NULL)  AS q
+       GROUP BY w
+);
+
+INSERT INTO text_stat VALUES (NULL, (SELECT count(*) FROM test_text));
+
+DROP INDEX idx_test_text;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_text ON test_text USING gist (v _text_sml_ops);
+SET enable_seqscan = off;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_text;
+CREATE INDEX idx_test_text ON test_text USING gin (v _text_sml_ops);
+SET enable_seqscan = off;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "n";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "log";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = off;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET smlar.tf_method = "const";
+SET smlar.idf_plus_one = on;
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
diff --git a/sql/texti.sql b/sql/texti.sql
new file mode 100644 (file)
index 0000000..ea974b7
--- /dev/null
@@ -0,0 +1,14 @@
+SELECT set_smlar_limit(5.0);
+SET smlar.type='overlap';
+
+DROP INDEX idx_test_text;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_text WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_text ON test_text USING gin (v _text_sml_ops);
+SET enable_seqscan = off;
+
+SELECT  t, smlar(v, '{199,198,197,196,195,194,193,192,191,190}') AS s FROM test_text WHERE v % '{199,198,197,196,195,194,193,192,191,190}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
diff --git a/sql/textn.sql b/sql/textn.sql
new file mode 100644 (file)
index 0000000..dd6e65e
--- /dev/null
@@ -0,0 +1,26 @@
+SELECT set_smlar_limit(0.8);
+
+DROP INDEX idx_test_text;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_text ON test_text USING gist (v _text_sml_ops);
+SET enable_seqscan = off;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
+DROP INDEX idx_test_text;
+
+CREATE INDEX idx_test_text ON test_text USING gin (v _text_sml_ops);
+SET enable_seqscan = off;
+
+SELECT smlar('{199,199,199,199,1}', '{199,1}'::text[]);
+SELECT  t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_text WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT  t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_text WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+RESET enable_seqscan;
diff --git a/sql/time.sql b/sql/time.sql
new file mode 100644 (file)
index 0000000..81360e7
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       epoch2timestamp(v)::time
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_time
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[] ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_time ON test_time USING gist (v _time_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[] ORDER BY s DESC, t;
+
+DROP INDEX idx_test_time;
+CREATE INDEX idx_test_time ON test_time USING gin (v _time_sml_ops);
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::time[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[]) AS s FROM test_time WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::time[] ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/timestamp.sql b/sql/timestamp.sql
new file mode 100644 (file)
index 0000000..f85a310
--- /dev/null
@@ -0,0 +1,34 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       epoch2timestamp(v)::timestamp
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_timestamp
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}') ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}') ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_timestamp ON test_timestamp USING gist (v _timestamp_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}') ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}') ORDER BY s DESC, t;
+
+DROP INDEX idx_test_timestamp;
+CREATE INDEX idx_test_timestamp ON test_timestamp USING gin (v _timestamp_sml_ops);
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}') ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')) AS s FROM test_timestamp WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}') ORDER BY s DESC, t;
+
+
+SET enable_seqscan=on;
+
diff --git a/sql/timestamptz.sql b/sql/timestamptz.sql
new file mode 100644 (file)
index 0000000..8e9081f
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       epoch2timestamp(v)::timestamptz
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_timestamptz
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[] ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_timestamptz ON test_timestamptz USING gist (v _timestamptz_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[] ORDER BY s DESC, t;
+
+DROP INDEX idx_test_timestamptz;
+CREATE INDEX idx_test_timestamptz ON test_timestamptz USING gin (v _timestamptz_sml_ops);
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]) AS s FROM test_timestamptz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[] ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/timetz.sql b/sql/timetz.sql
new file mode 100644 (file)
index 0000000..c3e18f3
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       epoch2timestamp(v)::timestamptz::timetz
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_timetz
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_timetz ON test_timetz USING gist (v _timetz_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+
+DROP INDEX idx_test_timetz;
+CREATE INDEX idx_test_timetz ON test_timetz USING gin (v _timetz_sml_ops);
+
+SELECT t, smlar(v, to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{10,9,8,7,6,5,4,3,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+SELECT t, smlar(v, to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[]) AS s FROM test_timetz WHERE v % to_tsp_array('{50,49,8,7,6,5,4,33,2,1}')::timestamptz[]::timetz[] ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/varbit.sql b/sql/varbit.sql
new file mode 100644 (file)
index 0000000..23c3b5c
--- /dev/null
@@ -0,0 +1,27 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::bit(10)::varbit
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_varbit
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]::varbit[]) AS s FROM test_varbit WHERE v % '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]::varbit[] ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]::varbit[]) AS s FROM test_varbit WHERE v % '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]::varbit[] ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_varbit ON test_varbit USING gin (v _varbit_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]::varbit[]) AS s FROM test_varbit WHERE v % '{10,9,8,7,6,5,4,3,2,1}'::int4[]::bit(10)[]::varbit[] ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]::varbit[]) AS s FROM test_varbit WHERE v % '{50,49,8,7,6,5,4,33,2,1}'::int4[]::bit(10)[]::varbit[] ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/sql/varchar.sql b/sql/varchar.sql
new file mode 100644 (file)
index 0000000..fe6c720
--- /dev/null
@@ -0,0 +1,33 @@
+SELECT set_smlar_limit(0.6);
+
+SELECT 
+       t,
+       ARRAY(
+               SELECT 
+                       v::varchar
+               FROM
+                       generate_series(1, t) as v
+       ) AS v
+       INTO test_varchar
+FROM
+       generate_series(1, 200) as t;
+
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_varchar WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_varchar WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+CREATE INDEX idx_test_varchar ON test_varchar USING gist (v _varchar_sml_ops);
+
+SET enable_seqscan=off;
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_varchar WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_varchar WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+DROP INDEX idx_test_varchar;
+CREATE INDEX idx_test_varchar ON test_varchar USING gin (v _varchar_sml_ops);
+
+SELECT t, smlar(v, '{10,9,8,7,6,5,4,3,2,1}') AS s FROM test_varchar WHERE v % '{10,9,8,7,6,5,4,3,2,1}' ORDER BY s DESC, t;
+SELECT t, smlar(v, '{50,49,8,7,6,5,4,33,2,1}') AS s FROM test_varchar WHERE v % '{50,49,8,7,6,5,4,33,2,1}' ORDER BY s DESC, t;
+
+SET enable_seqscan=on;
+
diff --git a/tsarr.c b/tsarr.c
new file mode 100644 (file)
index 0000000..4a3deb3
--- /dev/null
+++ b/tsarr.c
@@ -0,0 +1,38 @@
+#include "postgres.h"
+
+#include "catalog/pg_type.h"
+#include "tsearch/ts_type.h"
+#include "utils/array.h"
+
+PG_FUNCTION_INFO_V1(tsvector2textarray);
+Datum       tsvector2textarray(PG_FUNCTION_ARGS);
+Datum
+tsvector2textarray(PG_FUNCTION_ARGS)
+{
+       TSVector        ts = PG_GETARG_TSVECTOR(0);
+       ArrayType       *a;
+       Datum           *words;
+       int                     i;
+       WordEntry       *wptr = ARRPTR(ts);
+
+       words = palloc( sizeof(Datum) * (ts->size+1) );
+
+       for(i=0; i<ts->size; i++)
+       {
+               text            *t = palloc(VARHDRSZ + wptr->len);
+
+               SET_VARSIZE(t, VARHDRSZ + wptr->len);
+               memcpy( VARDATA(t), STRPTR(ts) + wptr->pos, wptr->len);
+               words[i] = PointerGetDatum(t);
+       
+               wptr++;
+       }
+
+       a = construct_array( words, ts->size,
+                                                       TEXTOID, -1, false, 'i' );
+
+       PG_FREE_IF_COPY(ts, 0);
+
+       PG_RETURN_ARRAYTYPE_P(a);
+}
+