diff --git a/contrib/btree_gist/btree_cash.c b/contrib/btree_gist/btree_cash.c
index bfda21b058c4933ec90dc6ac7d06bca8de2fd6ad..7938a70f17a120c1e181df0804b558b6608bef22 100644
--- a/contrib/btree_gist/btree_cash.c
+++ b/contrib/btree_gist/btree_cash.c
@@ -18,6 +18,7 @@ PG_FUNCTION_INFO_V1(gbt_cash_compress);
 PG_FUNCTION_INFO_V1(gbt_cash_union);
 PG_FUNCTION_INFO_V1(gbt_cash_picksplit);
 PG_FUNCTION_INFO_V1(gbt_cash_consistent);
+PG_FUNCTION_INFO_V1(gbt_cash_distance);
 PG_FUNCTION_INFO_V1(gbt_cash_penalty);
 PG_FUNCTION_INFO_V1(gbt_cash_same);
 
@@ -25,6 +26,7 @@ Datum		gbt_cash_compress(PG_FUNCTION_ARGS);
 Datum		gbt_cash_union(PG_FUNCTION_ARGS);
 Datum		gbt_cash_picksplit(PG_FUNCTION_ARGS);
 Datum		gbt_cash_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_cash_distance(PG_FUNCTION_ARGS);
 Datum		gbt_cash_penalty(PG_FUNCTION_ARGS);
 Datum		gbt_cash_same(PG_FUNCTION_ARGS);
 
@@ -71,6 +73,12 @@ gbt_cashkey_cmp(const void *a, const void *b)
 	return (ia->lower > ib->lower) ? 1 : -1;
 }
 
+static float8
+gbt_cash_dist(const void *a, const void *b)
+{
+	return GET_FLOAT_DISTANCE(Cash, a, b);
+}
+
 
 static const gbtree_ninfo tinfo =
 {
@@ -81,10 +89,33 @@ static const gbtree_ninfo tinfo =
 	gbt_casheq,
 	gbt_cashle,
 	gbt_cashlt,
-	gbt_cashkey_cmp
+	gbt_cashkey_cmp,
+	gbt_cash_dist
 };
 
 
+PG_FUNCTION_INFO_V1(cash_dist);
+Datum		cash_dist(PG_FUNCTION_ARGS);
+Datum
+cash_dist(PG_FUNCTION_ARGS)
+{
+	Cash		a = PG_GETARG_CASH(0);
+	Cash		b = PG_GETARG_CASH(1);
+	Cash		r;
+	Cash		ra;
+
+	r = a - b;
+	ra = Abs(r);
+
+	/* Overflow check. */
+	if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+				 errmsg("money out of range")));
+
+	PG_RETURN_CASH(ra);
+}
+
 /**************************************************
  * Cash ops
  **************************************************/
@@ -124,6 +155,25 @@ gbt_cash_consistent(PG_FUNCTION_ARGS)
 }
 
 
+Datum
+gbt_cash_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	Cash		query = PG_GETARG_CASH(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	cashKEY    *kkk = (cashKEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+		);
+}
+
+
 Datum
 gbt_cash_union(PG_FUNCTION_ARGS)
 {
diff --git a/contrib/btree_gist/btree_date.c b/contrib/btree_gist/btree_date.c
index 11904af2573f5f05ab416b5efaa0fa0e3424b459..ccd7e2ad3f383a3fef458454b3bbe5a05fb1cca7 100644
--- a/contrib/btree_gist/btree_date.c
+++ b/contrib/btree_gist/btree_date.c
@@ -18,6 +18,7 @@ PG_FUNCTION_INFO_V1(gbt_date_compress);
 PG_FUNCTION_INFO_V1(gbt_date_union);
 PG_FUNCTION_INFO_V1(gbt_date_picksplit);
 PG_FUNCTION_INFO_V1(gbt_date_consistent);
+PG_FUNCTION_INFO_V1(gbt_date_distance);
 PG_FUNCTION_INFO_V1(gbt_date_penalty);
 PG_FUNCTION_INFO_V1(gbt_date_same);
 
@@ -25,6 +26,7 @@ Datum		gbt_date_compress(PG_FUNCTION_ARGS);
 Datum		gbt_date_union(PG_FUNCTION_ARGS);
 Datum		gbt_date_picksplit(PG_FUNCTION_ARGS);
 Datum		gbt_date_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_date_distance(PG_FUNCTION_ARGS);
 Datum		gbt_date_penalty(PG_FUNCTION_ARGS);
 Datum		gbt_date_same(PG_FUNCTION_ARGS);
 
@@ -84,6 +86,17 @@ gbt_datekey_cmp(const void *a, const void *b)
 	return res;
 }
 
+static float8
+gdb_date_dist(const void *a, const void *b)
+{
+	/* we assume the difference can't overflow */
+	Datum diff = DirectFunctionCall2(date_mi,
+									 DateADTGetDatum(*((const DateADT *) a)),
+									 DateADTGetDatum(*((const DateADT *) b)));
+
+	return (float8) Abs(DatumGetInt32(diff));
+}
+
 
 static const gbtree_ninfo tinfo =
 {
@@ -94,10 +107,25 @@ static const gbtree_ninfo tinfo =
 	gbt_dateeq,
 	gbt_datele,
 	gbt_datelt,
-	gbt_datekey_cmp
+	gbt_datekey_cmp,
+	gdb_date_dist
 };
 
 
+PG_FUNCTION_INFO_V1(date_dist);
+Datum       date_dist(PG_FUNCTION_ARGS);
+Datum
+date_dist(PG_FUNCTION_ARGS)
+{
+	/* we assume the difference can't overflow */
+	Datum diff = DirectFunctionCall2(date_mi,
+									 PG_GETARG_DATUM(0),
+									 PG_GETARG_DATUM(1));
+
+	PG_RETURN_INT32(Abs(DatumGetInt32(diff)));
+}
+
+
 /**************************************************
  * date ops
  **************************************************/
@@ -139,6 +167,25 @@ gbt_date_consistent(PG_FUNCTION_ARGS)
 }
 
 
+Datum
+gbt_date_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	DateADT		query = PG_GETARG_DATEADT(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	dateKEY    *kkk = (dateKEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+		);
+}
+
+
 Datum
 gbt_date_union(PG_FUNCTION_ARGS)
 {
diff --git a/contrib/btree_gist/btree_float4.c b/contrib/btree_gist/btree_float4.c
index 4cfeddfc6870e43e88a04fbd90bb60881c4625a6..932a941f889e4b9d3e91fd4f58ad7654221c7187 100644
--- a/contrib/btree_gist/btree_float4.c
+++ b/contrib/btree_gist/btree_float4.c
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_float4_compress);
 PG_FUNCTION_INFO_V1(gbt_float4_union);
 PG_FUNCTION_INFO_V1(gbt_float4_picksplit);
 PG_FUNCTION_INFO_V1(gbt_float4_consistent);
+PG_FUNCTION_INFO_V1(gbt_float4_distance);
 PG_FUNCTION_INFO_V1(gbt_float4_penalty);
 PG_FUNCTION_INFO_V1(gbt_float4_same);
 
@@ -24,6 +25,7 @@ Datum		gbt_float4_compress(PG_FUNCTION_ARGS);
 Datum		gbt_float4_union(PG_FUNCTION_ARGS);
 Datum		gbt_float4_picksplit(PG_FUNCTION_ARGS);
 Datum		gbt_float4_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_float4_distance(PG_FUNCTION_ARGS);
 Datum		gbt_float4_penalty(PG_FUNCTION_ARGS);
 Datum		gbt_float4_same(PG_FUNCTION_ARGS);
 
@@ -70,6 +72,12 @@ gbt_float4key_cmp(const void *a, const void *b)
 	return (ia->lower > ib->lower) ? 1 : -1;
 }
 
+static float8
+gbt_float4_dist(const void *a, const void *b)
+{
+	return GET_FLOAT_DISTANCE(float4, a, b);
+}
+
 
 static const gbtree_ninfo tinfo =
 {
@@ -80,10 +88,27 @@ static const gbtree_ninfo tinfo =
 	gbt_float4eq,
 	gbt_float4le,
 	gbt_float4lt,
-	gbt_float4key_cmp
+	gbt_float4key_cmp,
+	gbt_float4_dist
 };
 
 
+PG_FUNCTION_INFO_V1(float4_dist);
+Datum       float4_dist(PG_FUNCTION_ARGS);
+Datum
+float4_dist(PG_FUNCTION_ARGS)
+{
+    float4		a = PG_GETARG_FLOAT4(0);
+	float4		b = PG_GETARG_FLOAT4(1);
+	float4		r;
+
+	r = a - b;
+	CHECKFLOATVAL(r, isinf(a) || isinf(b), true);
+
+	PG_RETURN_FLOAT4( Abs(r) );
+}
+
+
 /**************************************************
  * float4 ops
  **************************************************/
@@ -123,6 +148,25 @@ gbt_float4_consistent(PG_FUNCTION_ARGS)
 }
 
 
+Datum
+gbt_float4_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	float4		query = PG_GETARG_FLOAT4(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	float4KEY  *kkk = (float4KEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+		);
+}
+
+
 Datum
 gbt_float4_union(PG_FUNCTION_ARGS)
 {
diff --git a/contrib/btree_gist/btree_float8.c b/contrib/btree_gist/btree_float8.c
index 1386983272c6647e01bce75e1241f52a028dfa07..0c39980ba1e0ee456c05a0d7644364b5b11bd8b2 100644
--- a/contrib/btree_gist/btree_float8.c
+++ b/contrib/btree_gist/btree_float8.c
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_float8_compress);
 PG_FUNCTION_INFO_V1(gbt_float8_union);
 PG_FUNCTION_INFO_V1(gbt_float8_picksplit);
 PG_FUNCTION_INFO_V1(gbt_float8_consistent);
+PG_FUNCTION_INFO_V1(gbt_float8_distance);
 PG_FUNCTION_INFO_V1(gbt_float8_penalty);
 PG_FUNCTION_INFO_V1(gbt_float8_same);
 
@@ -24,6 +25,7 @@ Datum		gbt_float8_compress(PG_FUNCTION_ARGS);
 Datum		gbt_float8_union(PG_FUNCTION_ARGS);
 Datum		gbt_float8_picksplit(PG_FUNCTION_ARGS);
 Datum		gbt_float8_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_float8_distance(PG_FUNCTION_ARGS);
 Datum		gbt_float8_penalty(PG_FUNCTION_ARGS);
 Datum		gbt_float8_same(PG_FUNCTION_ARGS);
 
@@ -71,6 +73,19 @@ gbt_float8key_cmp(const void *a, const void *b)
 	return (ia->lower > ib->lower) ? 1 : -1;
 }
 
+static float8
+gbt_float8_dist(const void *a, const void *b)
+{
+	float8		arg1 = *(const float8 *)a;
+	float8		arg2 = *(const float8 *)b;
+	float8		r;
+
+	r = arg1 - arg2;
+	CHECKFLOATVAL(r, isinf(arg1) || isinf(arg2), true);
+
+	return Abs(r);
+}
+
 
 static const gbtree_ninfo tinfo =
 {
@@ -81,10 +96,26 @@ static const gbtree_ninfo tinfo =
 	gbt_float8eq,
 	gbt_float8le,
 	gbt_float8lt,
-	gbt_float8key_cmp
+	gbt_float8key_cmp,
+	gbt_float8_dist
 };
 
 
+PG_FUNCTION_INFO_V1(float8_dist);
+Datum       float8_dist(PG_FUNCTION_ARGS);
+Datum
+float8_dist(PG_FUNCTION_ARGS)
+{
+	float8		a = PG_GETARG_FLOAT8(0);
+	float8		b = PG_GETARG_FLOAT8(1);
+	float8		r;
+
+	r = a - b;
+	CHECKFLOATVAL(r, isinf(a) || isinf(b), true);
+
+	PG_RETURN_FLOAT8( Abs(r) );
+}
+
 /**************************************************
  * float8 ops
  **************************************************/
@@ -124,6 +155,25 @@ gbt_float8_consistent(PG_FUNCTION_ARGS)
 }
 
 
+Datum
+gbt_float8_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	float8		query = PG_GETARG_FLOAT8(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	float8KEY  *kkk = (float8KEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+		);
+}
+
+
 Datum
 gbt_float8_union(PG_FUNCTION_ARGS)
 {
diff --git a/contrib/btree_gist/btree_gist--1.0.sql b/contrib/btree_gist/btree_gist--1.0.sql
index 1ea5fa2db418d06f991f362a956fec07ccfba9e9..dd428995c185a09519ed65433081752b83b71bb7 100644
--- a/contrib/btree_gist/btree_gist--1.0.sql
+++ b/contrib/btree_gist/btree_gist--1.0.sql
@@ -81,6 +81,151 @@ CREATE TYPE gbtreekey_var (
 	STORAGE = EXTENDED
 );
 
+--distance operators
+
+CREATE FUNCTION cash_dist(money, money)
+RETURNS money
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = money,
+	RIGHTARG = money,
+	PROCEDURE = cash_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION date_dist(date, date)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = date,
+	RIGHTARG = date,
+	PROCEDURE = date_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION float4_dist(float4, float4)
+RETURNS float4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = float4,
+	RIGHTARG = float4,
+	PROCEDURE = float4_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION float8_dist(float8, float8)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = float8,
+	RIGHTARG = float8,
+	PROCEDURE = float8_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int2_dist(int2, int2)
+RETURNS int2
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = int2,
+	RIGHTARG = int2,
+	PROCEDURE = int2_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int4_dist(int4, int4)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = int4,
+	RIGHTARG = int4,
+	PROCEDURE = int4_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int8_dist(int8, int8)
+RETURNS int8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = int8,
+	RIGHTARG = int8,
+	PROCEDURE = int8_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION interval_dist(interval, interval)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = interval,
+	RIGHTARG = interval,
+	PROCEDURE = interval_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION oid_dist(oid, oid)
+RETURNS oid
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = oid,
+	RIGHTARG = oid,
+	PROCEDURE = oid_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION time_dist(time, time)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = time,
+	RIGHTARG = time,
+	PROCEDURE = time_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION ts_dist(timestamp, timestamp)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = timestamp,
+	RIGHTARG = timestamp,
+	PROCEDURE = ts_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION tstz_dist(timestamptz, timestamptz)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = timestamptz,
+	RIGHTARG = timestamptz,
+	PROCEDURE = tstz_dist,
+	COMMUTATOR = '<->'
+);
 
 
 --
@@ -96,6 +241,11 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_oid_distance(internal,oid,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_oid_compress(internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
@@ -154,7 +304,9 @@ AS
 -- that's the only state that can be reproduced during an upgrade from 9.0.
 
 ALTER OPERATOR FAMILY gist_oid_ops USING gist ADD
-	OPERATOR	6	<> (oid, oid) ;
+	OPERATOR	6	<> (oid, oid) ,
+	OPERATOR	15	<-> (oid, oid) FOR ORDER BY pg_catalog.oid_ops ,
+	FUNCTION	8 (oid, oid) gbt_oid_distance (internal, oid, int2, oid) ;
 
 
 --
@@ -170,6 +322,11 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_int2_distance(internal,int2,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_int2_compress(internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
@@ -214,7 +371,9 @@ AS
 	STORAGE		gbtreekey4;
 
 ALTER OPERATOR FAMILY gist_int2_ops USING gist ADD
-	OPERATOR	6	<> (int2, int2) ;
+	OPERATOR	6	<> (int2, int2) ,
+	OPERATOR	15	<-> (int2, int2) FOR ORDER BY pg_catalog.integer_ops ,
+	FUNCTION	8 (int2, int2) gbt_int2_distance (internal, int2, int2, oid) ;
 
 
 --
@@ -230,6 +389,11 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_int4_distance(internal,int4,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_int4_compress(internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
@@ -274,7 +438,9 @@ AS
 	STORAGE		gbtreekey8;
 
 ALTER OPERATOR FAMILY gist_int4_ops USING gist ADD
-	OPERATOR	6	<> (int4, int4) ;
+	OPERATOR	6	<> (int4, int4) ,
+	OPERATOR	15	<-> (int4, int4) FOR ORDER BY pg_catalog.integer_ops ,
+	FUNCTION	8 (int4, int4) gbt_int4_distance (internal, int4, int2, oid) ;
 
 
 --
@@ -290,6 +456,11 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_int8_distance(internal,int8,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_int8_compress(internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
@@ -334,7 +505,9 @@ AS
 	STORAGE		gbtreekey16;
 
 ALTER OPERATOR FAMILY gist_int8_ops USING gist ADD
-	OPERATOR	6	<> (int8, int8) ;
+	OPERATOR	6	<> (int8, int8) ,
+	OPERATOR	15	<-> (int8, int8) FOR ORDER BY pg_catalog.integer_ops ,
+	FUNCTION	8 (int8, int8) gbt_int8_distance (internal, int8, int2, oid) ;
 
 
 --
@@ -350,6 +523,11 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_float4_distance(internal,float4,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_float4_compress(internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
@@ -394,7 +572,9 @@ AS
 	STORAGE		gbtreekey8;
 
 ALTER OPERATOR FAMILY gist_float4_ops USING gist ADD
-	OPERATOR	6	<> (float4, float4) ;
+	OPERATOR	6	<> (float4, float4) ,
+	OPERATOR	15	<-> (float4, float4) FOR ORDER BY pg_catalog.float_ops ,
+	FUNCTION	8 (float4, float4) gbt_float4_distance (internal, float4, int2, oid) ;
 
 
 --
@@ -410,6 +590,11 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_float8_distance(internal,float8,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_float8_compress(internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
@@ -454,7 +639,9 @@ AS
 	STORAGE		gbtreekey16;
 
 ALTER OPERATOR FAMILY gist_float8_ops USING gist ADD
-	OPERATOR	6	<> (float8, float8) ;
+	OPERATOR	6	<> (float8, float8) ,
+	OPERATOR	15	<-> (float8, float8) FOR ORDER BY pg_catalog.float_ops ,
+	FUNCTION	8 (float8, float8) gbt_float8_distance (internal, float8, int2, oid) ;
 
 
 --
@@ -470,11 +657,21 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_ts_distance(internal,timestamp,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_tstz_consistent(internal,timestamptz,int2,oid,internal)
 RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_tstz_distance(internal,timestamptz,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_ts_compress(internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
@@ -524,7 +721,9 @@ AS
 	STORAGE		gbtreekey16;
 
 ALTER OPERATOR FAMILY gist_timestamp_ops USING gist ADD
-	OPERATOR	6	<> (timestamp, timestamp) ;
+	OPERATOR	6	<> (timestamp, timestamp) ,
+	OPERATOR	15	<-> (timestamp, timestamp) FOR ORDER BY pg_catalog.interval_ops ,
+	FUNCTION	8 (timestamp, timestamp) gbt_ts_distance (internal, timestamp, int2, oid) ;
 
 
 -- Create the operator class
@@ -546,7 +745,9 @@ AS
 	STORAGE		gbtreekey16;
 
 ALTER OPERATOR FAMILY gist_timestamptz_ops USING gist ADD
-	OPERATOR	6	<> (timestamptz, timestamptz) ;
+	OPERATOR	6	<> (timestamptz, timestamptz) ,
+	OPERATOR	15	<-> (timestamptz, timestamptz) FOR ORDER BY pg_catalog.interval_ops ,
+	FUNCTION	8 (timestamptz, timestamptz) gbt_tstz_distance (internal, timestamptz, int2, oid) ;
 
 
 --
@@ -562,6 +763,11 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_time_distance(internal,time,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_timetz_consistent(internal,timetz,int2,oid,internal)
 RETURNS bool
 AS 'MODULE_PATHNAME'
@@ -616,7 +822,9 @@ AS
 	STORAGE		gbtreekey16;
 
 ALTER OPERATOR FAMILY gist_time_ops USING gist ADD
-	OPERATOR	6	<> (time, time) ;
+	OPERATOR	6	<> (time, time) ,
+	OPERATOR	15	<-> (time, time) FOR ORDER BY pg_catalog.interval_ops ,
+	FUNCTION	8 (time, time) gbt_time_distance (internal, time, int2, oid) ;
 
 
 CREATE OPERATOR CLASS gist_timetz_ops
@@ -653,6 +861,11 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_date_distance(internal,date,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_date_compress(internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
@@ -697,7 +910,9 @@ AS
 	STORAGE		gbtreekey8;
 
 ALTER OPERATOR FAMILY gist_date_ops USING gist ADD
-	OPERATOR	6	<> (date, date) ;
+	OPERATOR	6	<> (date, date) ,
+	OPERATOR	15	<-> (date, date) FOR ORDER BY pg_catalog.integer_ops ,
+	FUNCTION	8 (date, date) gbt_date_distance (internal, date, int2, oid) ;
 
 
 --
@@ -713,6 +928,11 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_intv_distance(internal,interval,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_intv_compress(internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
@@ -762,7 +982,9 @@ AS
 	STORAGE		gbtreekey32;
 
 ALTER OPERATOR FAMILY gist_interval_ops USING gist ADD
-	OPERATOR	6	<> (interval, interval) ;
+	OPERATOR	6	<> (interval, interval) ,
+	OPERATOR	15	<-> (interval, interval) FOR ORDER BY pg_catalog.interval_ops ,
+	FUNCTION	8 (interval, interval) gbt_intv_distance (internal, interval, int2, oid) ;
 
 
 --
@@ -778,6 +1000,11 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION gbt_cash_distance(internal,money,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
 CREATE FUNCTION gbt_cash_compress(internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
@@ -822,7 +1049,9 @@ AS
 	STORAGE		gbtreekey16;
 
 ALTER OPERATOR FAMILY gist_cash_ops USING gist ADD
-	OPERATOR	6	<> (money, money) ;
+	OPERATOR	6	<> (money, money) ,
+	OPERATOR	15	<-> (money, money) FOR ORDER BY pg_catalog.money_ops ,
+	FUNCTION	8 (money, money) gbt_cash_distance (internal, money, int2, oid) ;
 
 
 --
diff --git a/contrib/btree_gist/btree_gist--unpackaged--1.0.sql b/contrib/btree_gist/btree_gist--unpackaged--1.0.sql
index d8631d6bc267e0c4814b95dc2f02bc0ccfec2660..00252bf7c380a999e4f67e3a45c4a53f40d7b20c 100644
--- a/contrib/btree_gist/btree_gist--unpackaged--1.0.sql
+++ b/contrib/btree_gist/btree_gist--unpackaged--1.0.sql
@@ -171,46 +171,282 @@ ALTER EXTENSION btree_gist ADD operator class gist_inet_ops using gist;
 ALTER EXTENSION btree_gist ADD operator family gist_cidr_ops using gist;
 ALTER EXTENSION btree_gist ADD operator class gist_cidr_ops using gist;
 
+
+-- Add functions and operators that are new in 9.1
+
+--distance operators
+
+CREATE FUNCTION cash_dist(money, money)
+RETURNS money
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = money,
+	RIGHTARG = money,
+	PROCEDURE = cash_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION date_dist(date, date)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = date,
+	RIGHTARG = date,
+	PROCEDURE = date_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION float4_dist(float4, float4)
+RETURNS float4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = float4,
+	RIGHTARG = float4,
+	PROCEDURE = float4_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION float8_dist(float8, float8)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = float8,
+	RIGHTARG = float8,
+	PROCEDURE = float8_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int2_dist(int2, int2)
+RETURNS int2
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = int2,
+	RIGHTARG = int2,
+	PROCEDURE = int2_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int4_dist(int4, int4)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = int4,
+	RIGHTARG = int4,
+	PROCEDURE = int4_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int8_dist(int8, int8)
+RETURNS int8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = int8,
+	RIGHTARG = int8,
+	PROCEDURE = int8_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION interval_dist(interval, interval)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = interval,
+	RIGHTARG = interval,
+	PROCEDURE = interval_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION oid_dist(oid, oid)
+RETURNS oid
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = oid,
+	RIGHTARG = oid,
+	PROCEDURE = oid_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION time_dist(time, time)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = time,
+	RIGHTARG = time,
+	PROCEDURE = time_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION ts_dist(timestamp, timestamp)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = timestamp,
+	RIGHTARG = timestamp,
+	PROCEDURE = ts_dist,
+	COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION tstz_dist(timestamptz, timestamptz)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+	LEFTARG = timestamptz,
+	RIGHTARG = timestamptz,
+	PROCEDURE = tstz_dist,
+	COMMUTATOR = '<->'
+);
+
+-- Support functions for distance operators
+
+CREATE FUNCTION gbt_oid_distance(internal,oid,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_int2_distance(internal,int2,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_int4_distance(internal,int4,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_int8_distance(internal,int8,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_float4_distance(internal,float4,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_float8_distance(internal,float8,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_ts_distance(internal,timestamp,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_tstz_distance(internal,timestamptz,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_time_distance(internal,time,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_date_distance(internal,date,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_intv_distance(internal,interval,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_cash_distance(internal,money,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+
 -- Add new-in-9.1 stuff to the operator classes.
 
 ALTER OPERATOR FAMILY gist_oid_ops USING gist ADD
-	OPERATOR	6	<> (oid, oid) ;
+	OPERATOR	6	<> (oid, oid) ,
+	OPERATOR	15	<-> (oid, oid) FOR ORDER BY pg_catalog.oid_ops ,
+	FUNCTION	8 (oid, oid) gbt_oid_distance (internal, oid, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_int2_ops USING gist ADD
-	OPERATOR	6	<> (int2, int2) ;
+	OPERATOR	6	<> (int2, int2) ,
+	OPERATOR	15	<-> (int2, int2) FOR ORDER BY pg_catalog.integer_ops ,
+	FUNCTION	8 (int2, int2) gbt_int2_distance (internal, int2, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_int4_ops USING gist ADD
-	OPERATOR	6	<> (int4, int4) ;
+	OPERATOR	6	<> (int4, int4) ,
+	OPERATOR	15	<-> (int4, int4) FOR ORDER BY pg_catalog.integer_ops ,
+	FUNCTION	8 (int4, int4) gbt_int4_distance (internal, int4, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_int8_ops USING gist ADD
-	OPERATOR	6	<> (int8, int8) ;
+	OPERATOR	6	<> (int8, int8) ,
+	OPERATOR	15	<-> (int8, int8) FOR ORDER BY pg_catalog.integer_ops ,
+	FUNCTION	8 (int8, int8) gbt_int8_distance (internal, int8, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_float4_ops USING gist ADD
-	OPERATOR	6	<> (float4, float4) ;
+	OPERATOR	6	<> (float4, float4) ,
+	OPERATOR	15	<-> (float4, float4) FOR ORDER BY pg_catalog.float_ops ,
+	FUNCTION	8 (float4, float4) gbt_float4_distance (internal, float4, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_float8_ops USING gist ADD
-	OPERATOR	6	<> (float8, float8) ;
+	OPERATOR	6	<> (float8, float8) ,
+	OPERATOR	15	<-> (float8, float8) FOR ORDER BY pg_catalog.float_ops ,
+	FUNCTION	8 (float8, float8) gbt_float8_distance (internal, float8, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_timestamp_ops USING gist ADD
-	OPERATOR	6	<> (timestamp, timestamp) ;
+	OPERATOR	6	<> (timestamp, timestamp) ,
+	OPERATOR	15	<-> (timestamp, timestamp) FOR ORDER BY pg_catalog.interval_ops ,
+	FUNCTION	8 (timestamp, timestamp) gbt_ts_distance (internal, timestamp, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_timestamptz_ops USING gist ADD
-	OPERATOR	6	<> (timestamptz, timestamptz) ;
+	OPERATOR	6	<> (timestamptz, timestamptz) ,
+	OPERATOR	15	<-> (timestamptz, timestamptz) FOR ORDER BY pg_catalog.interval_ops ,
+	FUNCTION	8 (timestamptz, timestamptz) gbt_tstz_distance (internal, timestamptz, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_time_ops USING gist ADD
-	OPERATOR	6	<> (time, time) ;
+	OPERATOR	6	<> (time, time) ,
+	OPERATOR	15	<-> (time, time) FOR ORDER BY pg_catalog.interval_ops ,
+	FUNCTION	8 (time, time) gbt_time_distance (internal, time, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_timetz_ops USING gist ADD
 	OPERATOR	6	<> (timetz, timetz) ;
 
 ALTER OPERATOR FAMILY gist_date_ops USING gist ADD
-	OPERATOR	6	<> (date, date) ;
+	OPERATOR	6	<> (date, date) ,
+	OPERATOR	15	<-> (date, date) FOR ORDER BY pg_catalog.integer_ops ,
+	FUNCTION	8 (date, date) gbt_date_distance (internal, date, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_interval_ops USING gist ADD
-	OPERATOR	6	<> (interval, interval) ;
+	OPERATOR	6	<> (interval, interval) ,
+	OPERATOR	15	<-> (interval, interval) FOR ORDER BY pg_catalog.interval_ops ,
+	FUNCTION	8 (interval, interval) gbt_intv_distance (internal, interval, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_cash_ops USING gist ADD
-	OPERATOR	6	<> (money, money) ;
+	OPERATOR	6	<> (money, money) ,
+	OPERATOR	15	<-> (money, money) FOR ORDER BY pg_catalog.money_ops ,
+	FUNCTION	8 (money, money) gbt_cash_distance (internal, money, int2, oid) ;
 
 ALTER OPERATOR FAMILY gist_macaddr_ops USING gist ADD
 	OPERATOR	6	<> (macaddr, macaddr) ;
diff --git a/contrib/btree_gist/btree_inet.c b/contrib/btree_gist/btree_inet.c
index dcc934d1562c2ebc6951c103758d670107327a83..690a01cbc7a2b6c264608c8dab94398c1a828fa0 100644
--- a/contrib/btree_gist/btree_inet.c
+++ b/contrib/btree_gist/btree_inet.c
@@ -84,7 +84,8 @@ static const gbtree_ninfo tinfo =
 	gbt_ineteq,
 	gbt_inetle,
 	gbt_inetlt,
-	gbt_inetkey_cmp
+	gbt_inetkey_cmp,
+	NULL
 };
 
 
diff --git a/contrib/btree_gist/btree_int2.c b/contrib/btree_gist/btree_int2.c
index 2e981174520c832865d8c2967487dbc4764cbf4f..c06d170a5e1af5c272fff56d0d775bdc47ed5ffc 100644
--- a/contrib/btree_gist/btree_int2.c
+++ b/contrib/btree_gist/btree_int2.c
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_int2_compress);
 PG_FUNCTION_INFO_V1(gbt_int2_union);
 PG_FUNCTION_INFO_V1(gbt_int2_picksplit);
 PG_FUNCTION_INFO_V1(gbt_int2_consistent);
+PG_FUNCTION_INFO_V1(gbt_int2_distance);
 PG_FUNCTION_INFO_V1(gbt_int2_penalty);
 PG_FUNCTION_INFO_V1(gbt_int2_same);
 
@@ -24,6 +25,7 @@ Datum		gbt_int2_compress(PG_FUNCTION_ARGS);
 Datum		gbt_int2_union(PG_FUNCTION_ARGS);
 Datum		gbt_int2_picksplit(PG_FUNCTION_ARGS);
 Datum		gbt_int2_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_int2_distance(PG_FUNCTION_ARGS);
 Datum		gbt_int2_penalty(PG_FUNCTION_ARGS);
 Datum		gbt_int2_same(PG_FUNCTION_ARGS);
 
@@ -70,6 +72,12 @@ gbt_int2key_cmp(const void *a, const void *b)
 	return (ia->lower > ib->lower) ? 1 : -1;
 }
 
+static float8
+gbt_int2_dist(const void *a, const void *b)
+{
+	return GET_FLOAT_DISTANCE(int2, a, b);
+}
+
 
 static const gbtree_ninfo tinfo =
 {
@@ -80,12 +88,32 @@ static const gbtree_ninfo tinfo =
 	gbt_int2eq,
 	gbt_int2le,
 	gbt_int2lt,
-	gbt_int2key_cmp
+	gbt_int2key_cmp,
+	gbt_int2_dist
 };
 
 
+PG_FUNCTION_INFO_V1(int2_dist);
+Datum       int2_dist(PG_FUNCTION_ARGS);
+Datum
+int2_dist(PG_FUNCTION_ARGS)
+{
+	int2        a = PG_GETARG_INT16(0);
+	int2        b = PG_GETARG_INT16(1);
+	int2		r;
+	int2		ra;
+
+	r = a - b;
+	ra = Abs(r);
 
+	/* Overflow check. */
+	if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+				 errmsg("smallint out of range")));
 
+	PG_RETURN_INT16(ra);
+}
 
 
 /**************************************************
@@ -127,6 +155,25 @@ gbt_int2_consistent(PG_FUNCTION_ARGS)
 }
 
 
+Datum
+gbt_int2_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	int16		query = PG_GETARG_INT16(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	int16KEY   *kkk = (int16KEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+		);
+}
+
+
 Datum
 gbt_int2_union(PG_FUNCTION_ARGS)
 {
diff --git a/contrib/btree_gist/btree_int4.c b/contrib/btree_gist/btree_int4.c
index 678d653fd0b399d04a79447ab72ea7c4ef1d35f4..ef7af524e76bdfab212fd332b8bd3b0778237ba6 100644
--- a/contrib/btree_gist/btree_int4.c
+++ b/contrib/btree_gist/btree_int4.c
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_int4_compress);
 PG_FUNCTION_INFO_V1(gbt_int4_union);
 PG_FUNCTION_INFO_V1(gbt_int4_picksplit);
 PG_FUNCTION_INFO_V1(gbt_int4_consistent);
+PG_FUNCTION_INFO_V1(gbt_int4_distance);
 PG_FUNCTION_INFO_V1(gbt_int4_penalty);
 PG_FUNCTION_INFO_V1(gbt_int4_same);
 
@@ -24,6 +25,7 @@ Datum		gbt_int4_compress(PG_FUNCTION_ARGS);
 Datum		gbt_int4_union(PG_FUNCTION_ARGS);
 Datum		gbt_int4_picksplit(PG_FUNCTION_ARGS);
 Datum		gbt_int4_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_int4_distance(PG_FUNCTION_ARGS);
 Datum		gbt_int4_penalty(PG_FUNCTION_ARGS);
 Datum		gbt_int4_same(PG_FUNCTION_ARGS);
 
@@ -71,6 +73,12 @@ gbt_int4key_cmp(const void *a, const void *b)
 	return (ia->lower > ib->lower) ? 1 : -1;
 }
 
+static float8
+gbt_int4_dist(const void *a, const void *b)
+{
+	return GET_FLOAT_DISTANCE(int4, a, b);
+}
+
 
 static const gbtree_ninfo tinfo =
 {
@@ -81,10 +89,34 @@ static const gbtree_ninfo tinfo =
 	gbt_int4eq,
 	gbt_int4le,
 	gbt_int4lt,
-	gbt_int4key_cmp
+	gbt_int4key_cmp,
+	gbt_int4_dist
 };
 
 
+PG_FUNCTION_INFO_V1(int4_dist);
+Datum       int4_dist(PG_FUNCTION_ARGS);
+Datum
+int4_dist(PG_FUNCTION_ARGS)
+{
+	int4        a = PG_GETARG_INT32(0);
+	int4        b = PG_GETARG_INT32(1);
+	int4        r;
+	int4        ra;
+
+	r = a - b;
+	ra = Abs(r);
+
+	/* Overflow check. */
+	if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+						 errmsg("integer out of range")));
+
+	PG_RETURN_INT32(ra);
+}
+
+
 /**************************************************
  * int32 ops
  **************************************************/
@@ -124,6 +156,25 @@ gbt_int4_consistent(PG_FUNCTION_ARGS)
 }
 
 
+Datum
+gbt_int4_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	int32		query = PG_GETARG_INT32(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	int32KEY   *kkk = (int32KEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+		);
+}
+
+
 Datum
 gbt_int4_union(PG_FUNCTION_ARGS)
 {
diff --git a/contrib/btree_gist/btree_int8.c b/contrib/btree_gist/btree_int8.c
index 8afa5b0af24dbcd3a1345785c523b6c81c21fb7c..1f14d82891d8c47cd59487d2fd8a1d41a4054e96 100644
--- a/contrib/btree_gist/btree_int8.c
+++ b/contrib/btree_gist/btree_int8.c
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_int8_compress);
 PG_FUNCTION_INFO_V1(gbt_int8_union);
 PG_FUNCTION_INFO_V1(gbt_int8_picksplit);
 PG_FUNCTION_INFO_V1(gbt_int8_consistent);
+PG_FUNCTION_INFO_V1(gbt_int8_distance);
 PG_FUNCTION_INFO_V1(gbt_int8_penalty);
 PG_FUNCTION_INFO_V1(gbt_int8_same);
 
@@ -24,6 +25,7 @@ Datum		gbt_int8_compress(PG_FUNCTION_ARGS);
 Datum		gbt_int8_union(PG_FUNCTION_ARGS);
 Datum		gbt_int8_picksplit(PG_FUNCTION_ARGS);
 Datum		gbt_int8_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_int8_distance(PG_FUNCTION_ARGS);
 Datum		gbt_int8_penalty(PG_FUNCTION_ARGS);
 Datum		gbt_int8_same(PG_FUNCTION_ARGS);
 
@@ -71,6 +73,12 @@ gbt_int8key_cmp(const void *a, const void *b)
 	return (ia->lower > ib->lower) ? 1 : -1;
 }
 
+static float8
+gbt_int8_dist(const void *a, const void *b)
+{
+	return GET_FLOAT_DISTANCE(int64, a, b);
+}
+
 
 static const gbtree_ninfo tinfo =
 {
@@ -81,10 +89,34 @@ static const gbtree_ninfo tinfo =
 	gbt_int8eq,
 	gbt_int8le,
 	gbt_int8lt,
-	gbt_int8key_cmp
+	gbt_int8key_cmp,
+	gbt_int8_dist
 };
 
 
+PG_FUNCTION_INFO_V1(int8_dist);
+Datum       int8_dist(PG_FUNCTION_ARGS);
+Datum
+int8_dist(PG_FUNCTION_ARGS)
+{
+	int64       a = PG_GETARG_INT64(0);
+	int64       b = PG_GETARG_INT64(1);
+	int64       r;
+	int64       ra;
+
+	r = a - b;
+	ra = Abs(r);
+
+	/* Overflow check. */
+	if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+						 errmsg("bigint out of range")));
+
+	PG_RETURN_INT64(ra);
+}
+
+
 /**************************************************
  * int64 ops
  **************************************************/
@@ -124,6 +156,25 @@ gbt_int8_consistent(PG_FUNCTION_ARGS)
 }
 
 
+Datum
+gbt_int8_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	int64		query = PG_GETARG_INT64(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	int64KEY   *kkk = (int64KEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+		);
+}
+
+
 Datum
 gbt_int8_union(PG_FUNCTION_ARGS)
 {
diff --git a/contrib/btree_gist/btree_interval.c b/contrib/btree_gist/btree_interval.c
index 0715346f234c544099c9c813a0900e31fa3b723e..5195284afa1be65f3a66acf779d7a1a6c99236f6 100644
--- a/contrib/btree_gist/btree_interval.c
+++ b/contrib/btree_gist/btree_interval.c
@@ -20,6 +20,7 @@ PG_FUNCTION_INFO_V1(gbt_intv_decompress);
 PG_FUNCTION_INFO_V1(gbt_intv_union);
 PG_FUNCTION_INFO_V1(gbt_intv_picksplit);
 PG_FUNCTION_INFO_V1(gbt_intv_consistent);
+PG_FUNCTION_INFO_V1(gbt_intv_distance);
 PG_FUNCTION_INFO_V1(gbt_intv_penalty);
 PG_FUNCTION_INFO_V1(gbt_intv_same);
 
@@ -28,6 +29,7 @@ Datum		gbt_intv_decompress(PG_FUNCTION_ARGS);
 Datum		gbt_intv_union(PG_FUNCTION_ARGS);
 Datum		gbt_intv_picksplit(PG_FUNCTION_ARGS);
 Datum		gbt_intv_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_intv_distance(PG_FUNCTION_ARGS);
 Datum		gbt_intv_penalty(PG_FUNCTION_ARGS);
 Datum		gbt_intv_same(PG_FUNCTION_ARGS);
 
@@ -83,6 +85,12 @@ intr2num(const Interval *i)
 	return INTERVAL_TO_SEC(i);
 }
 
+static float8
+gbt_intv_dist(const void *a, const void *b)
+{
+	return (float8)Abs(intr2num((Interval*)a) - intr2num((Interval*)b));
+}
+
 /*
  * INTERVALSIZE should be the actual size-on-disk of an Interval, as shown
  * in pg_type.	This might be less than sizeof(Interval) if the compiler
@@ -99,10 +107,38 @@ static const gbtree_ninfo tinfo =
 	gbt_intveq,
 	gbt_intvle,
 	gbt_intvlt,
-	gbt_intvkey_cmp
+	gbt_intvkey_cmp,
+	gbt_intv_dist
 };
 
 
+Interval *
+abs_interval(Interval *a)
+{
+	static Interval zero = {0, 0, 0};
+
+	if (DatumGetBool(DirectFunctionCall2(interval_lt,
+										 IntervalPGetDatum(a),
+										 IntervalPGetDatum(&zero))))
+		a = DatumGetIntervalP(DirectFunctionCall1(interval_um,
+												  IntervalPGetDatum(a)));
+
+	return a;
+}
+
+PG_FUNCTION_INFO_V1(interval_dist);
+Datum       interval_dist(PG_FUNCTION_ARGS);
+Datum
+interval_dist(PG_FUNCTION_ARGS)
+{
+	Datum		diff = DirectFunctionCall2(interval_mi,
+										   PG_GETARG_DATUM(0),
+										   PG_GETARG_DATUM(1));
+
+	PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
+}
+
+
 /**************************************************
  * interval ops
  **************************************************/
@@ -190,6 +226,25 @@ gbt_intv_consistent(PG_FUNCTION_ARGS)
 }
 
 
+Datum
+gbt_intv_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	Interval   *query = PG_GETARG_INTERVAL_P(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	intvKEY    *kkk = (intvKEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) query, GIST_LEAF(entry), &tinfo)
+		);
+}
+
+
 Datum
 gbt_intv_union(PG_FUNCTION_ARGS)
 {
diff --git a/contrib/btree_gist/btree_macaddr.c b/contrib/btree_gist/btree_macaddr.c
index fb440c3f198fadfa99b1c29feff23495eadd673b..aa150e26a23d244c7b98a6d760da54c54ff33303 100644
--- a/contrib/btree_gist/btree_macaddr.c
+++ b/contrib/btree_gist/btree_macaddr.c
@@ -84,7 +84,8 @@ static const gbtree_ninfo tinfo =
 	gbt_macadeq,
 	gbt_macadle,
 	gbt_macadlt,
-	gbt_macadkey_cmp
+	gbt_macadkey_cmp,
+	NULL
 };
 
 
diff --git a/contrib/btree_gist/btree_oid.c b/contrib/btree_gist/btree_oid.c
index 4927448258fe31e02deab0be790791daac89aacd..c81dd31799eb9a2f61b86ab29d2f05adc8a2db31 100644
--- a/contrib/btree_gist/btree_oid.c
+++ b/contrib/btree_gist/btree_oid.c
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_oid_compress);
 PG_FUNCTION_INFO_V1(gbt_oid_union);
 PG_FUNCTION_INFO_V1(gbt_oid_picksplit);
 PG_FUNCTION_INFO_V1(gbt_oid_consistent);
+PG_FUNCTION_INFO_V1(gbt_oid_distance);
 PG_FUNCTION_INFO_V1(gbt_oid_penalty);
 PG_FUNCTION_INFO_V1(gbt_oid_same);
 
@@ -24,6 +25,7 @@ Datum		gbt_oid_compress(PG_FUNCTION_ARGS);
 Datum		gbt_oid_union(PG_FUNCTION_ARGS);
 Datum		gbt_oid_picksplit(PG_FUNCTION_ARGS);
 Datum		gbt_oid_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_oid_distance(PG_FUNCTION_ARGS);
 Datum		gbt_oid_penalty(PG_FUNCTION_ARGS);
 Datum		gbt_oid_same(PG_FUNCTION_ARGS);
 
@@ -71,6 +73,18 @@ gbt_oidkey_cmp(const void *a, const void *b)
 	return (ia->lower > ib->lower) ? 1 : -1;
 }
 
+static float8
+gbt_oid_dist(const void *a, const void *b)
+{
+	Oid			aa = *(const Oid *) a;
+	Oid			bb = *(const Oid *) b;
+
+	if (aa < bb)
+		return (float8) (bb - aa);
+	else
+		return (float8) (aa - bb);
+}
+
 
 static const gbtree_ninfo tinfo =
 {
@@ -81,10 +95,28 @@ static const gbtree_ninfo tinfo =
 	gbt_oideq,
 	gbt_oidle,
 	gbt_oidlt,
-	gbt_oidkey_cmp
+	gbt_oidkey_cmp,
+	gbt_oid_dist
 };
 
 
+PG_FUNCTION_INFO_V1(oid_dist);
+Datum       oid_dist(PG_FUNCTION_ARGS);
+Datum
+oid_dist(PG_FUNCTION_ARGS)
+{
+    Oid        	a = PG_GETARG_OID(0);
+	Oid        	b = PG_GETARG_OID(1);
+	Oid 		res;
+
+	if (a < b)
+		res = b - a;
+	else
+		res = a - b;
+	PG_RETURN_OID(res);
+}
+
+
 /**************************************************
  * Oid ops
  **************************************************/
@@ -124,6 +156,25 @@ gbt_oid_consistent(PG_FUNCTION_ARGS)
 }
 
 
+Datum
+gbt_oid_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	Oid			query = PG_GETARG_OID(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	oidKEY	   *kkk = (oidKEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+		);
+}
+
+
 Datum
 gbt_oid_union(PG_FUNCTION_ARGS)
 {
diff --git a/contrib/btree_gist/btree_time.c b/contrib/btree_gist/btree_time.c
index 01163e906ad921e53a67da840a0977a27a89c46c..44f6923409f4b6a6fb1682751deae1507f76c5be 100644
--- a/contrib/btree_gist/btree_time.c
+++ b/contrib/btree_gist/btree_time.c
@@ -20,6 +20,7 @@ PG_FUNCTION_INFO_V1(gbt_timetz_compress);
 PG_FUNCTION_INFO_V1(gbt_time_union);
 PG_FUNCTION_INFO_V1(gbt_time_picksplit);
 PG_FUNCTION_INFO_V1(gbt_time_consistent);
+PG_FUNCTION_INFO_V1(gbt_time_distance);
 PG_FUNCTION_INFO_V1(gbt_timetz_consistent);
 PG_FUNCTION_INFO_V1(gbt_time_penalty);
 PG_FUNCTION_INFO_V1(gbt_time_same);
@@ -29,6 +30,7 @@ Datum		gbt_timetz_compress(PG_FUNCTION_ARGS);
 Datum		gbt_time_union(PG_FUNCTION_ARGS);
 Datum		gbt_time_picksplit(PG_FUNCTION_ARGS);
 Datum		gbt_time_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_time_distance(PG_FUNCTION_ARGS);
 Datum		gbt_timetz_consistent(PG_FUNCTION_ARGS);
 Datum		gbt_time_penalty(PG_FUNCTION_ARGS);
 Datum		gbt_time_same(PG_FUNCTION_ARGS);
@@ -112,6 +114,19 @@ gbt_timekey_cmp(const void *a, const void *b)
 	return res;
 }
 
+static float8
+gbt_time_dist(const void *a, const void *b)
+{
+	const TimeADT *aa = (const TimeADT *) a;
+	const TimeADT *bb = (const TimeADT *) b;
+	Interval	  *i;
+
+	i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
+											  TimeADTGetDatumFast(*aa),
+											  TimeADTGetDatumFast(*bb)));
+	return (float8) Abs(INTERVAL_TO_SEC(i));
+}
+
 
 static const gbtree_ninfo tinfo =
 {
@@ -122,10 +137,24 @@ static const gbtree_ninfo tinfo =
 	gbt_timeeq,
 	gbt_timele,
 	gbt_timelt,
-	gbt_timekey_cmp
+	gbt_timekey_cmp,
+	gbt_time_dist
 };
 
 
+PG_FUNCTION_INFO_V1(time_dist);
+Datum       time_dist(PG_FUNCTION_ARGS);
+Datum
+time_dist(PG_FUNCTION_ARGS)
+{
+	Datum		diff = DirectFunctionCall2(time_mi_time,
+										   PG_GETARG_DATUM(0),
+										   PG_GETARG_DATUM(1));
+
+	PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
+}
+
+
 /**************************************************
  * time ops
  **************************************************/
@@ -196,6 +225,24 @@ gbt_time_consistent(PG_FUNCTION_ARGS)
 		);
 }
 
+Datum
+gbt_time_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	TimeADT		query = PG_GETARG_TIMEADT(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+		);
+}
+
 Datum
 gbt_timetz_consistent(PG_FUNCTION_ARGS)
 {
diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c
index 2b13d14ad19f1f804d492f4a6f8b05290f00c391..9a0ec07a1e742bf4003ee5b0a5f1b7ce2ef40d72 100644
--- a/contrib/btree_gist/btree_ts.c
+++ b/contrib/btree_gist/btree_ts.c
@@ -3,6 +3,7 @@
  */
 #include "btree_gist.h"
 #include "btree_utils_num.h"
+#include "utils/builtins.h"
 #include "utils/datetime.h"
 
 typedef struct
@@ -19,7 +20,9 @@ PG_FUNCTION_INFO_V1(gbt_tstz_compress);
 PG_FUNCTION_INFO_V1(gbt_ts_union);
 PG_FUNCTION_INFO_V1(gbt_ts_picksplit);
 PG_FUNCTION_INFO_V1(gbt_ts_consistent);
+PG_FUNCTION_INFO_V1(gbt_ts_distance);
 PG_FUNCTION_INFO_V1(gbt_tstz_consistent);
+PG_FUNCTION_INFO_V1(gbt_tstz_distance);
 PG_FUNCTION_INFO_V1(gbt_ts_penalty);
 PG_FUNCTION_INFO_V1(gbt_ts_same);
 
@@ -28,7 +31,9 @@ Datum		gbt_tstz_compress(PG_FUNCTION_ARGS);
 Datum		gbt_ts_union(PG_FUNCTION_ARGS);
 Datum		gbt_ts_picksplit(PG_FUNCTION_ARGS);
 Datum		gbt_ts_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_ts_distance(PG_FUNCTION_ARGS);
 Datum		gbt_tstz_consistent(PG_FUNCTION_ARGS);
+Datum		gbt_tstz_distance(PG_FUNCTION_ARGS);
 Datum		gbt_ts_penalty(PG_FUNCTION_ARGS);
 Datum		gbt_ts_same(PG_FUNCTION_ARGS);
 
@@ -110,6 +115,22 @@ gbt_tskey_cmp(const void *a, const void *b)
 	return res;
 }
 
+static float8
+gbt_ts_dist(const void *a, const void *b)
+{
+	const Timestamp *aa = (const Timestamp *) a;
+	const Timestamp *bb = (const Timestamp *) b;
+	Interval      *i;
+
+	if (TIMESTAMP_NOT_FINITE(*aa) || TIMESTAMP_NOT_FINITE(*bb))
+		return get_float8_infinity();
+
+	i = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
+											  TimestampGetDatumFast(*aa),
+											  TimestampGetDatumFast(*bb)));
+	return (float8) Abs(INTERVAL_TO_SEC(i));
+}
+
 
 static const gbtree_ninfo tinfo =
 {
@@ -120,10 +141,71 @@ static const gbtree_ninfo tinfo =
 	gbt_tseq,
 	gbt_tsle,
 	gbt_tslt,
-	gbt_tskey_cmp
+	gbt_tskey_cmp,
+	gbt_ts_dist
 };
 
 
+PG_FUNCTION_INFO_V1(ts_dist);
+Datum       ts_dist(PG_FUNCTION_ARGS);
+Datum
+ts_dist(PG_FUNCTION_ARGS)
+{
+	Timestamp	a = PG_GETARG_TIMESTAMP(0);
+	Timestamp	b = PG_GETARG_TIMESTAMP(1);
+    Interval      *r;
+
+	if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
+	{
+		Interval *p = palloc(sizeof(Interval));
+
+		p->day = INT_MAX;
+		p->month = INT_MAX;
+#ifdef HAVE_INT64_TIMESTAMP
+		p->time = INT64CONST(0x7FFFFFFFFFFFFFFF);
+#else
+		p->time = DBL_MAX;
+#endif
+		PG_RETURN_INTERVAL_P(p);
+	}
+	else
+
+	r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
+											  PG_GETARG_DATUM(0),
+											  PG_GETARG_DATUM(1)));
+	PG_RETURN_INTERVAL_P( abs_interval(r) );
+}
+
+PG_FUNCTION_INFO_V1(tstz_dist);
+Datum       tstz_dist(PG_FUNCTION_ARGS);
+Datum
+tstz_dist(PG_FUNCTION_ARGS)
+{
+	TimestampTz	a = PG_GETARG_TIMESTAMPTZ(0);
+	TimestampTz	b = PG_GETARG_TIMESTAMPTZ(1);
+    Interval      *r;
+
+	if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
+	{
+		Interval *p = palloc(sizeof(Interval));
+
+		p->day = INT_MAX;
+		p->month = INT_MAX;
+#ifdef HAVE_INT64_TIMESTAMP
+		p->time = INT64CONST(0x7FFFFFFFFFFFFFFF);
+#else
+		p->time = DBL_MAX;
+#endif
+		PG_RETURN_INTERVAL_P(p);
+	}
+
+	r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
+											  PG_GETARG_DATUM(0),
+											  PG_GETARG_DATUM(1)));
+	PG_RETURN_INTERVAL_P( abs_interval(r) );
+}
+
+
 /**************************************************
  * timestamp ops
  **************************************************/
@@ -213,6 +295,24 @@ gbt_ts_consistent(PG_FUNCTION_ARGS)
 		);
 }
 
+Datum
+gbt_ts_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	Timestamp	query = PG_GETARG_TIMESTAMP(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	tsKEY	   *kkk = (tsKEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+		);
+}
+
 Datum
 gbt_tstz_consistent(PG_FUNCTION_ARGS)
 {
@@ -238,6 +338,26 @@ gbt_tstz_consistent(PG_FUNCTION_ARGS)
 		);
 }
 
+Datum
+gbt_tstz_distance(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	TimestampTz query = PG_GETARG_TIMESTAMPTZ(1);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	char	   *kkk = (char *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+	Timestamp	qqq;
+
+	key.lower = (GBT_NUMKEY *) &kkk[0];
+	key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)];
+	qqq = tstz_to_ts_gmt(query);
+
+	PG_RETURN_FLOAT8(
+				   gbt_num_distance(&key, (void *) &qqq, GIST_LEAF(entry), &tinfo)
+		);
+}
+
 
 Datum
 gbt_ts_union(PG_FUNCTION_ARGS)
diff --git a/contrib/btree_gist/btree_utils_num.c b/contrib/btree_gist/btree_utils_num.c
index 0df22f21338ad62f24831f9cdbc9591bb2e7bac8..17440a191b271a57afe3e445a3f522a3ead39a69 100644
--- a/contrib/btree_gist/btree_utils_num.c
+++ b/contrib/btree_gist/btree_utils_num.c
@@ -188,16 +188,13 @@ gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo)
 */
 
 bool
-gbt_num_consistent(
-				   const GBT_NUMKEY_R *key,
+gbt_num_consistent(const GBT_NUMKEY_R *key,
 				   const void *query,
 				   const StrategyNumber *strategy,
 				   bool is_leaf,
-				   const gbtree_ninfo *tinfo
-)
+				   const gbtree_ninfo *tinfo)
 {
-
-	bool		retval = FALSE;
+	bool		retval;
 
 	switch (*strategy)
 	{
@@ -214,7 +211,7 @@ gbt_num_consistent(
 			if (is_leaf)
 				retval = (*tinfo->f_eq) (query, key->lower);
 			else
-				retval = (*tinfo->f_le) (key->lower, query) && (*tinfo->f_le) (query, key->upper);
+				retval = ((*tinfo->f_le) (key->lower, query) && (*tinfo->f_le) (query, key->upper)) ? true : false;
 			break;
 		case BTGreaterStrategyNumber:
 			if (is_leaf)
@@ -226,17 +223,43 @@ gbt_num_consistent(
 			retval = (*tinfo->f_le) (query, key->upper);
 			break;
 		case BtreeGistNotEqualStrategyNumber:
-			retval = ! ((*tinfo->f_eq) (query, key->lower) &&
-				(*tinfo->f_eq) (query, key->upper));
+			retval = (! ((*tinfo->f_eq) (query, key->lower) &&
+				(*tinfo->f_eq) (query, key->upper)))  ? true : false;
 			break;
 		default:
-			retval = FALSE;
+			retval = false;
 	}
 
 	return (retval);
 }
 
 
+/*
+** The GiST distance method (for KNN-Gist)
+*/
+
+float8
+gbt_num_distance(const GBT_NUMKEY_R *key,
+				 const void *query,
+				 bool is_leaf,
+				 const gbtree_ninfo *tinfo)
+{
+	float8		retval;
+
+	if (tinfo->f_dist == NULL)
+		elog(ERROR, "KNN search is not supported for btree_gist type %d",
+			 (int) tinfo->t);
+	if ( tinfo->f_le(query, key->lower) )
+		retval = tinfo->f_dist(query, key->lower);
+	else if ( tinfo->f_ge(query, key->upper) )
+		retval = tinfo->f_dist(query, key->upper);
+	else
+		retval = 0.0;
+
+	return retval;
+}
+
+
 GIST_SPLITVEC *
 gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
 				  const gbtree_ninfo *tinfo)
diff --git a/contrib/btree_gist/btree_utils_num.h b/contrib/btree_gist/btree_utils_num.h
index 091784bd5a17160f1d7eefb99785b94cfbcce117..243d3b5cb99087a3c166c922c72031c5bc3cac39 100644
--- a/contrib/btree_gist/btree_utils_num.h
+++ b/contrib/btree_gist/btree_utils_num.h
@@ -40,24 +40,25 @@ typedef struct
 
 	/* Methods */
 
-	bool		(*f_gt) (const void *, const void *);	/* greater then */
-	bool		(*f_ge) (const void *, const void *);	/* greater equal */
+	bool		(*f_gt) (const void *, const void *);	/* greater than */
+	bool		(*f_ge) (const void *, const void *);	/* greater or equal */
 	bool		(*f_eq) (const void *, const void *);	/* equal */
-	bool		(*f_le) (const void *, const void *);	/* less equal */
-	bool		(*f_lt) (const void *, const void *);	/* less then */
+	bool		(*f_le) (const void *, const void *);	/* less or equal */
+	bool		(*f_lt) (const void *, const void *);	/* less than */
 	int			(*f_cmp) (const void *, const void *);	/* key compare function */
+	float8		(*f_dist) (const void *, const void *);	/* key distance function */
 } gbtree_ninfo;
 
 
 /*
  *	Numeric btree functions
-*/
+ */
 
 
 
 /*
  * Note: The factor 0.49 in following macro avoids floating point overflows
-*/
+ */
 #define penalty_num(result,olower,oupper,nlower,nupper) do { \
   double	tmp = 0.0F; \
   (*(result))	= 0.0F; \
@@ -91,11 +92,37 @@ typedef struct
 	 (ivp)->month * (30.0 * SECS_PER_DAY))
 #endif
 
+#define GET_FLOAT_DISTANCE(t, arg1, arg2)	Abs( ((float8) *((const t *) (arg1))) - ((float8) *((const t *) (arg2))) )
+
+#define SAMESIGN(a,b)   (((a) < 0) == ((b) < 0))
+
+/*
+ * check to see if a float4/8 val has underflowed or overflowed
+ * borrowed from src/backend/utils/adt/float.c
+ */
+#define CHECKFLOATVAL(val, inf_is_valid, zero_is_valid)			\
+do {															\
+	if (isinf(val) && !(inf_is_valid))							\
+		ereport(ERROR,											\
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),	\
+		  errmsg("value out of range: overflow")));				\
+																\
+	if ((val) == 0.0 && !(zero_is_valid))						\
+		ereport(ERROR,											\
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),	\
+		 errmsg("value out of range: underflow")));				\
+} while(0)
+
+
+extern Interval *abs_interval(Interval *a);
 
 extern bool gbt_num_consistent(const GBT_NUMKEY_R *key, const void *query,
 				   const StrategyNumber *strategy, bool is_leaf,
 				   const gbtree_ninfo *tinfo);
 
+extern float8 gbt_num_distance(const GBT_NUMKEY_R *key, const void *query,
+				   bool is_leaf, const gbtree_ninfo *tinfo);
+
 extern GIST_SPLITVEC *gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
 				  const gbtree_ninfo *tinfo);
 
diff --git a/contrib/btree_gist/expected/cash.out b/contrib/btree_gist/expected/cash.out
index 2beb8cd92dcb98b562fcbe300c5a220ee09e7d1c..a4100d844e74724165fcbebc92bb42eacc5b54af 100644
--- a/contrib/btree_gist/expected/cash.out
+++ b/contrib/btree_gist/expected/cash.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM moneytmp WHERE a >  '22649.64';
    253
 (1 row)
 
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
+     a      | ?column? 
+------------+----------
+ $21,472.79 |    $0.00
+ $21,469.25 |    $3.54
+ $21,915.01 |  $442.22
+(3 rows)
+
 CREATE INDEX moneyidx ON moneytmp USING gist ( a );
 SET enable_seqscan=off;
 SELECT count(*) FROM moneytmp WHERE a <  '22649.64'::money;
@@ -64,3 +72,20 @@ SELECT count(*) FROM moneytmp WHERE a >  '22649.64'::money;
    253
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
+                  QUERY PLAN                   
+-----------------------------------------------
+ Limit
+   ->  Index Scan using moneyidx on moneytmp
+         Order By: (a <-> '$21,472.79'::money)
+(3 rows)
+
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
+     a      | ?column? 
+------------+----------
+ $21,472.79 |    $0.00
+ $21,469.25 |    $3.54
+ $21,915.01 |  $442.22
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/date.out b/contrib/btree_gist/expected/date.out
index f2082cf391afa923af4cbaefa6a46acf0bec377d..4a360bea6d6c66b50c256a2b06673e8d1b35153b 100644
--- a/contrib/btree_gist/expected/date.out
+++ b/contrib/btree_gist/expected/date.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM datetmp WHERE a >  '2001-02-13';
    313
 (1 row)
 
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
+     a      | ?column? 
+------------+----------
+ 02-13-2001 |        0
+ 02-11-2001 |        2
+ 03-24-2001 |       39
+(3 rows)
+
 CREATE INDEX dateidx ON datetmp USING gist ( a );
 SET enable_seqscan=off;
 SELECT count(*) FROM datetmp WHERE a <  '2001-02-13'::date;
@@ -64,3 +72,20 @@ SELECT count(*) FROM datetmp WHERE a >  '2001-02-13'::date;
    313
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
+                  QUERY PLAN                  
+----------------------------------------------
+ Limit
+   ->  Index Scan using dateidx on datetmp
+         Order By: (a <-> '02-13-2001'::date)
+(3 rows)
+
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
+     a      | ?column? 
+------------+----------
+ 02-13-2001 |        0
+ 02-11-2001 |        2
+ 03-24-2001 |       39
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/float4.out b/contrib/btree_gist/expected/float4.out
index c7f65c8d7fc4448004f3a01e1489ab70ffd38b11..1695f7805a0c6dd0dab1bf1d54cfe171682911b1 100644
--- a/contrib/btree_gist/expected/float4.out
+++ b/contrib/btree_gist/expected/float4.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM float4tmp WHERE a >  -179.0;
    302
 (1 row)
 
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
+    a     | ?column? 
+----------+----------
+     -179 |        0
+ -189.024 |  10.0239
+ -158.177 |  20.8226
+(3 rows)
+
 CREATE INDEX float4idx ON float4tmp USING gist ( a );
 SET enable_seqscan=off;
 SELECT count(*) FROM float4tmp WHERE a <  -179.0::float4;
@@ -64,3 +72,20 @@ SELECT count(*) FROM float4tmp WHERE a >  -179.0::float4;
    302
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
+                  QUERY PLAN                   
+-----------------------------------------------
+ Limit
+   ->  Index Scan using float4idx on float4tmp
+         Order By: (a <-> (-179)::real)
+(3 rows)
+
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
+    a     | ?column? 
+----------+----------
+     -179 |        0
+ -189.024 |  10.0239
+ -158.177 |  20.8226
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/float8.out b/contrib/btree_gist/expected/float8.out
index 4598ac87a2c811135727a641fcca69c349daddb7..7d2228b797390d1b1333d09f97a7153f21d09f50 100644
--- a/contrib/btree_gist/expected/float8.out
+++ b/contrib/btree_gist/expected/float8.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM float8tmp WHERE a >  -1890.0;
    306
 (1 row)
 
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
+      a       |  ?column?  
+--------------+------------
+        -1890 |          0
+ -2003.634512 | 113.634512
+  -1769.73634 |  120.26366
+(3 rows)
+
 CREATE INDEX float8idx ON float8tmp USING gist ( a );
 SET enable_seqscan=off;
 SELECT count(*) FROM float8tmp WHERE a <  -1890.0::float8;
@@ -64,3 +72,20 @@ SELECT count(*) FROM float8tmp WHERE a >  -1890.0::float8;
    306
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
+                     QUERY PLAN                      
+-----------------------------------------------------
+ Limit
+   ->  Index Scan using float8idx on float8tmp
+         Order By: (a <-> (-1890)::double precision)
+(3 rows)
+
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
+      a       |  ?column?  
+--------------+------------
+        -1890 |          0
+ -2003.634512 | 113.634512
+  -1769.73634 |  120.26366
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/int2.out b/contrib/btree_gist/expected/int2.out
index a82819c26a19c997f2ede59b1ae8583507507543..b1cc3b14b252c0b89e02b21df8dcc0ead3598a71 100644
--- a/contrib/btree_gist/expected/int2.out
+++ b/contrib/btree_gist/expected/int2.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM int2tmp WHERE a >  237;
    248
 (1 row)
 
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
+  a  | ?column? 
+-----+----------
+ 237 |        0
+ 232 |        5
+ 228 |        9
+(3 rows)
+
 CREATE INDEX int2idx ON int2tmp USING gist ( a );
 SET enable_seqscan=off;
 SELECT count(*) FROM int2tmp WHERE a <  237::int2;
@@ -64,3 +72,20 @@ SELECT count(*) FROM int2tmp WHERE a >  237::int2;
    248
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
+                QUERY PLAN                 
+-------------------------------------------
+ Limit
+   ->  Index Scan using int2idx on int2tmp
+         Order By: (a <-> 237::smallint)
+(3 rows)
+
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
+  a  | ?column? 
+-----+----------
+ 237 |        0
+ 232 |        5
+ 228 |        9
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/int4.out b/contrib/btree_gist/expected/int4.out
index d4ac0e15135fdb7b4c4c77f11ec8663ddc50464c..41bed1f6e348d9b0acd91b25db38d80555b0865d 100644
--- a/contrib/btree_gist/expected/int4.out
+++ b/contrib/btree_gist/expected/int4.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM int4tmp WHERE a >  237;
    248
 (1 row)
 
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
+  a  | ?column? 
+-----+----------
+ 237 |        0
+ 232 |        5
+ 228 |        9
+(3 rows)
+
 CREATE INDEX int4idx ON int4tmp USING gist ( a );
 SET enable_seqscan=off;
 SELECT count(*) FROM int4tmp WHERE a <  237::int4;
@@ -64,3 +72,20 @@ SELECT count(*) FROM int4tmp WHERE a >  237::int4;
    248
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
+                QUERY PLAN                 
+-------------------------------------------
+ Limit
+   ->  Index Scan using int4idx on int4tmp
+         Order By: (a <-> 237)
+(3 rows)
+
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
+  a  | ?column? 
+-----+----------
+ 237 |        0
+ 232 |        5
+ 228 |        9
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/int8.out b/contrib/btree_gist/expected/int8.out
index 1da484525b511e6c8081f80e1479258d10e65e67..ff0af4a5fb8d8f3bbd7e7997b1a887221ba2f656 100644
--- a/contrib/btree_gist/expected/int8.out
+++ b/contrib/btree_gist/expected/int8.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM int8tmp WHERE a >  464571291354841;
    270
 (1 row)
 
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
+        a        |    ?column?    
+-----------------+----------------
+ 464571291354841 |              0
+ 457257666629329 |  7313624725512
+ 478227196042750 | 13655904687909
+(3 rows)
+
 CREATE INDEX int8idx ON int8tmp USING gist ( a );
 SET enable_seqscan=off;
 SELECT count(*) FROM int8tmp WHERE a <  464571291354841::int8;
@@ -64,3 +72,20 @@ SELECT count(*) FROM int8tmp WHERE a >  464571291354841::int8;
    270
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
+                    QUERY PLAN                     
+---------------------------------------------------
+ Limit
+   ->  Index Scan using int8idx on int8tmp
+         Order By: (a <-> 464571291354841::bigint)
+(3 rows)
+
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
+        a        |    ?column?    
+-----------------+----------------
+ 464571291354841 |              0
+ 457257666629329 |  7313624725512
+ 478227196042750 | 13655904687909
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/interval.out b/contrib/btree_gist/expected/interval.out
index 4c78e21346c2ad5239dbddcafa353bb31a19bad3..6955251a0451bac1ec77e41730a630621be2ea59 100644
--- a/contrib/btree_gist/expected/interval.out
+++ b/contrib/btree_gist/expected/interval.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM intervaltmp WHERE a >  '199 days 21:21:23';
    270
 (1 row)
 
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
+                  a                  |               ?column?               
+-------------------------------------+--------------------------------------
+ @ 199 days 21 hours 21 mins 23 secs | @ 0
+ @ 183 days 6 hours 52 mins 48 secs  | @ 16 days 14 hours 28 mins 35 secs
+ @ 220 days 19 hours 5 mins 42 secs  | @ 21 days -2 hours -15 mins -41 secs
+(3 rows)
+
 CREATE INDEX intervalidx ON intervaltmp USING gist ( a );
 SET enable_seqscan=off;
 SELECT count(*) FROM intervaltmp WHERE a <  '199 days 21:21:23'::interval;
@@ -64,3 +72,20 @@ SELECT count(*) FROM intervaltmp WHERE a >  '199 days 21:21:23'::interval;
    270
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
+                                QUERY PLAN                                 
+---------------------------------------------------------------------------
+ Limit
+   ->  Index Scan using intervalidx on intervaltmp
+         Order By: (a <-> '@ 199 days 21 hours 21 mins 23 secs'::interval)
+(3 rows)
+
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
+                  a                  |               ?column?               
+-------------------------------------+--------------------------------------
+ @ 199 days 21 hours 21 mins 23 secs | @ 0
+ @ 183 days 6 hours 52 mins 48 secs  | @ 16 days 14 hours 28 mins 35 secs
+ @ 220 days 19 hours 5 mins 42 secs  | @ 21 days -2 hours -15 mins -41 secs
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/time.out b/contrib/btree_gist/expected/time.out
index 015a67f6a17d7e166117dd53587b78ec3c28554c..1b9da4e192a14cb4d212ff5de046f9de57b3efc7 100644
--- a/contrib/btree_gist/expected/time.out
+++ b/contrib/btree_gist/expected/time.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM timetmp WHERE a >  '10:57:11';
    292
 (1 row)
 
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
+    a     |    ?column?     
+----------+-----------------
+ 10:57:11 | @ 0
+ 10:57:10 | @ 1 sec
+ 10:55:32 | @ 1 min 39 secs
+(3 rows)
+
 CREATE INDEX timeidx ON timetmp USING gist ( a );
 SET enable_seqscan=off;
 SELECT count(*) FROM timetmp WHERE a <  '10:57:11'::time;
@@ -64,3 +72,20 @@ SELECT count(*) FROM timetmp WHERE a >  '10:57:11'::time;
    292
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
+                          QUERY PLAN                          
+--------------------------------------------------------------
+ Limit
+   ->  Index Scan using timeidx on timetmp
+         Order By: (a <-> '10:57:11'::time without time zone)
+(3 rows)
+
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
+    a     |    ?column?     
+----------+-----------------
+ 10:57:11 | @ 0
+ 10:57:10 | @ 1 sec
+ 10:55:32 | @ 1 min 39 secs
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/timestamp.out b/contrib/btree_gist/expected/timestamp.out
index dc53895ca2110e7e998042b35d0d561eb72232a6..cc3624f084320415549a4ba83fa7e2c12f86f9de 100644
--- a/contrib/btree_gist/expected/timestamp.out
+++ b/contrib/btree_gist/expected/timestamp.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM timestamptmp WHERE a >  '2004-10-26 08:55:08';
    289
 (1 row)
 
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
+            a             |              ?column?              
+--------------------------+------------------------------------
+ Tue Oct 26 08:55:08 2004 | @ 0
+ Sun Oct 31 06:35:03 2004 | @ 4 days 21 hours 39 mins 55 secs
+ Mon Nov 29 20:12:43 2004 | @ 34 days 11 hours 17 mins 35 secs
+(3 rows)
+
 CREATE INDEX timestampidx ON timestamptmp USING gist ( a );
 SET enable_seqscan=off;
 SELECT count(*) FROM timestamptmp WHERE a <  '2004-10-26 08:55:08'::timestamp;
@@ -64,3 +72,20 @@ SELECT count(*) FROM timestamptmp WHERE a >  '2004-10-26 08:55:08'::timestamp;
    289
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
+                                    QUERY PLAN                                     
+-----------------------------------------------------------------------------------
+ Limit
+   ->  Index Scan using timestampidx on timestamptmp
+         Order By: (a <-> 'Tue Oct 26 08:55:08 2004'::timestamp without time zone)
+(3 rows)
+
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
+            a             |              ?column?              
+--------------------------+------------------------------------
+ Tue Oct 26 08:55:08 2004 | @ 0
+ Sun Oct 31 06:35:03 2004 | @ 4 days 21 hours 39 mins 55 secs
+ Mon Nov 29 20:12:43 2004 | @ 34 days 11 hours 17 mins 35 secs
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/timestamptz.out b/contrib/btree_gist/expected/timestamptz.out
index 391705f0dbefa970a5c31eed7c8ecf8716333e61..88d2404c44b3b417517bcf189522ff6870948215 100644
--- a/contrib/btree_gist/expected/timestamptz.out
+++ b/contrib/btree_gist/expected/timestamptz.out
@@ -92,6 +92,14 @@ SELECT count(*) FROM timestamptztmp WHERE a >  '2018-12-18 10:59:54 GMT+4';
    157
 (1 row)
 
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
+              a               |             ?column?              
+------------------------------+-----------------------------------
+ Tue Dec 18 05:59:54 2018 PST | @ 1 hour
+ Thu Jan 10 03:01:34 2019 PST | @ 22 days 22 hours 1 min 40 secs
+ Thu Jan 24 12:28:12 2019 PST | @ 37 days 7 hours 28 mins 18 secs
+(3 rows)
+
 CREATE INDEX timestamptzidx ON timestamptztmp USING gist ( a );
 SET enable_seqscan=off;
 SELECT count(*) FROM timestamptztmp WHERE a <  '2018-12-18 10:59:54 GMT+3'::timestamptz;
@@ -184,3 +192,20 @@ SELECT count(*) FROM timestamptztmp WHERE a >  '2018-12-18 10:59:54 GMT+4'::time
    157
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
+                                     QUERY PLAN                                     
+------------------------------------------------------------------------------------
+ Limit
+   ->  Index Scan using timestamptzidx on timestamptztmp
+         Order By: (a <-> 'Tue Dec 18 04:59:54 2018 PST'::timestamp with time zone)
+(3 rows)
+
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
+              a               |             ?column?              
+------------------------------+-----------------------------------
+ Tue Dec 18 05:59:54 2018 PST | @ 1 hour
+ Thu Jan 10 03:01:34 2019 PST | @ 22 days 22 hours 1 min 40 secs
+ Thu Jan 24 12:28:12 2019 PST | @ 37 days 7 hours 28 mins 18 secs
+(3 rows)
+
diff --git a/contrib/btree_gist/sql/cash.sql b/contrib/btree_gist/sql/cash.sql
index 5313e8f69652bdbbc61a8027260c295c53e8f86f..0e037984e1b6a90e00822888110cbfb5aed2beb2 100644
--- a/contrib/btree_gist/sql/cash.sql
+++ b/contrib/btree_gist/sql/cash.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM moneytmp WHERE a >= '22649.64';
 
 SELECT count(*) FROM moneytmp WHERE a >  '22649.64';
 
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
+
 CREATE INDEX moneyidx ON moneytmp USING gist ( a );
 
 SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM moneytmp WHERE a  = '22649.64'::money;
 SELECT count(*) FROM moneytmp WHERE a >= '22649.64'::money;
 
 SELECT count(*) FROM moneytmp WHERE a >  '22649.64'::money;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
diff --git a/contrib/btree_gist/sql/date.sql b/contrib/btree_gist/sql/date.sql
index f3b8166a6f0220ddd58b5e55d8495452c329129e..f969ef0a08cb37aaa7fe9745f9642263db6d95e3 100644
--- a/contrib/btree_gist/sql/date.sql
+++ b/contrib/btree_gist/sql/date.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM datetmp WHERE a >= '2001-02-13';
 
 SELECT count(*) FROM datetmp WHERE a >  '2001-02-13';
 
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
+
 CREATE INDEX dateidx ON datetmp USING gist ( a );
 
 SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM datetmp WHERE a  = '2001-02-13'::date;
 SELECT count(*) FROM datetmp WHERE a >= '2001-02-13'::date;
 
 SELECT count(*) FROM datetmp WHERE a >  '2001-02-13'::date;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
diff --git a/contrib/btree_gist/sql/float4.sql b/contrib/btree_gist/sql/float4.sql
index fb4b726d22301bc2f08ad49bb37f4091ba2f6669..3da1ce953c8d1471d49236d65e4ab88c447c5460 100644
--- a/contrib/btree_gist/sql/float4.sql
+++ b/contrib/btree_gist/sql/float4.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM float4tmp WHERE a >= -179.0;
 
 SELECT count(*) FROM float4tmp WHERE a >  -179.0;
 
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
+
 CREATE INDEX float4idx ON float4tmp USING gist ( a );
 
 SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM float4tmp WHERE a  = -179.0::float4;
 SELECT count(*) FROM float4tmp WHERE a >= -179.0::float4;
 
 SELECT count(*) FROM float4tmp WHERE a >  -179.0::float4;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
diff --git a/contrib/btree_gist/sql/float8.sql b/contrib/btree_gist/sql/float8.sql
index f8bd12efa139a4f274f429c59da699579d0ff050..e1e819b37f98c18c50b6eb1eb00752d6ef5fe695 100644
--- a/contrib/btree_gist/sql/float8.sql
+++ b/contrib/btree_gist/sql/float8.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM float8tmp WHERE a >= -1890.0;
 
 SELECT count(*) FROM float8tmp WHERE a >  -1890.0;
 
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
+
 CREATE INDEX float8idx ON float8tmp USING gist ( a );
 
 SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM float8tmp WHERE a  = -1890.0::float8;
 SELECT count(*) FROM float8tmp WHERE a >= -1890.0::float8;
 
 SELECT count(*) FROM float8tmp WHERE a >  -1890.0::float8;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
diff --git a/contrib/btree_gist/sql/int2.sql b/contrib/btree_gist/sql/int2.sql
index 80ca6ac37cc8d5d9994f07bd9e551f316e65b38e..988518795fc5631c04e82768c6dcc88f275ebcda 100644
--- a/contrib/btree_gist/sql/int2.sql
+++ b/contrib/btree_gist/sql/int2.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM int2tmp WHERE a >= 237;
 
 SELECT count(*) FROM int2tmp WHERE a >  237;
 
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
+
 CREATE INDEX int2idx ON int2tmp USING gist ( a );
 
 SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM int2tmp WHERE a  = 237::int2;
 SELECT count(*) FROM int2tmp WHERE a >= 237::int2;
 
 SELECT count(*) FROM int2tmp WHERE a >  237::int2;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
diff --git a/contrib/btree_gist/sql/int4.sql b/contrib/btree_gist/sql/int4.sql
index 31307d3610dc42ded469b10ef6532702b6cca604..659ab5ee24bbc6d18a5a82d283570d911ca58a1f 100644
--- a/contrib/btree_gist/sql/int4.sql
+++ b/contrib/btree_gist/sql/int4.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM int4tmp WHERE a >= 237;
 
 SELECT count(*) FROM int4tmp WHERE a >  237;
 
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
+
 CREATE INDEX int4idx ON int4tmp USING gist ( a );
 
 SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM int4tmp WHERE a  = 237::int4;
 SELECT count(*) FROM int4tmp WHERE a >= 237::int4;
 
 SELECT count(*) FROM int4tmp WHERE a >  237::int4;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
diff --git a/contrib/btree_gist/sql/int8.sql b/contrib/btree_gist/sql/int8.sql
index 747bdca1ec97f60d786bf8df4786253f3fc580ed..51e55e9c14b87b7c081b69a0f7ec4ba8ebc5757f 100644
--- a/contrib/btree_gist/sql/int8.sql
+++ b/contrib/btree_gist/sql/int8.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM int8tmp WHERE a >= 464571291354841;
 
 SELECT count(*) FROM int8tmp WHERE a >  464571291354841;
 
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
+
 CREATE INDEX int8idx ON int8tmp USING gist ( a );
 
 SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM int8tmp WHERE a  = 464571291354841::int8;
 SELECT count(*) FROM int8tmp WHERE a >= 464571291354841::int8;
 
 SELECT count(*) FROM int8tmp WHERE a >  464571291354841::int8;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
diff --git a/contrib/btree_gist/sql/interval.sql b/contrib/btree_gist/sql/interval.sql
index 561e3d92ff971139cf98cc6dc69cbf2273b27d8d..0f8b03152035e6316c16e690492567bc0dd2a113 100644
--- a/contrib/btree_gist/sql/interval.sql
+++ b/contrib/btree_gist/sql/interval.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM intervaltmp WHERE a >= '199 days 21:21:23';
 
 SELECT count(*) FROM intervaltmp WHERE a >  '199 days 21:21:23';
 
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
+
 CREATE INDEX intervalidx ON intervaltmp USING gist ( a );
 
 SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM intervaltmp WHERE a  = '199 days 21:21:23'::interval;
 SELECT count(*) FROM intervaltmp WHERE a >= '199 days 21:21:23'::interval;
 
 SELECT count(*) FROM intervaltmp WHERE a >  '199 days 21:21:23'::interval;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
diff --git a/contrib/btree_gist/sql/time.sql b/contrib/btree_gist/sql/time.sql
index 3329ee64da33c930bd6224695f7477d8f01c9645..6104e7f61c8e28ca6dfeca1735a916ce456a0f42 100644
--- a/contrib/btree_gist/sql/time.sql
+++ b/contrib/btree_gist/sql/time.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM timetmp WHERE a >= '10:57:11';
 
 SELECT count(*) FROM timetmp WHERE a >  '10:57:11';
 
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
+
 CREATE INDEX timeidx ON timetmp USING gist ( a );
 
 SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM timetmp WHERE a  = '10:57:11'::time;
 SELECT count(*) FROM timetmp WHERE a >= '10:57:11'::time;
 
 SELECT count(*) FROM timetmp WHERE a >  '10:57:11'::time;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
diff --git a/contrib/btree_gist/sql/timestamp.sql b/contrib/btree_gist/sql/timestamp.sql
index 25e942874eb86371d49ca6778c2b94eca829d4b7..95effebfc47a7fbf9d9896d7f2e17c37c2107be2 100644
--- a/contrib/btree_gist/sql/timestamp.sql
+++ b/contrib/btree_gist/sql/timestamp.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM timestamptmp WHERE a >= '2004-10-26 08:55:08';
 
 SELECT count(*) FROM timestamptmp WHERE a >  '2004-10-26 08:55:08';
 
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
+
 CREATE INDEX timestampidx ON timestamptmp USING gist ( a );
 
 SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM timestamptmp WHERE a  = '2004-10-26 08:55:08'::timestamp;
 SELECT count(*) FROM timestamptmp WHERE a >= '2004-10-26 08:55:08'::timestamp;
 
 SELECT count(*) FROM timestamptmp WHERE a >  '2004-10-26 08:55:08'::timestamp;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
diff --git a/contrib/btree_gist/sql/timestamptz.sql b/contrib/btree_gist/sql/timestamptz.sql
index 371233bc53a5704e5d54de31de5c357e149d67f4..f70caa4a6492c19d53572ee38520c9e6bd5a6b2d 100644
--- a/contrib/btree_gist/sql/timestamptz.sql
+++ b/contrib/btree_gist/sql/timestamptz.sql
@@ -37,7 +37,7 @@ SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+4';
 
 SELECT count(*) FROM timestamptztmp WHERE a >  '2018-12-18 10:59:54 GMT+4';
 
-
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
 
 CREATE INDEX timestamptzidx ON timestamptztmp USING gist ( a );
 
@@ -74,3 +74,7 @@ SELECT count(*) FROM timestamptztmp WHERE a  = '2018-12-18 10:59:54 GMT+4'::time
 SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+4'::timestamptz;
 
 SELECT count(*) FROM timestamptztmp WHERE a >  '2018-12-18 10:59:54 GMT+4'::timestamptz;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
diff --git a/doc/src/sgml/btree-gist.sgml b/doc/src/sgml/btree-gist.sgml
index 931acda95f9db9523f3905e732129dc42d2b0735..af3f707bb9c73c6876f12b9772a8fbb25dd0a8db 100644
--- a/doc/src/sgml/btree-gist.sgml
+++ b/doc/src/sgml/btree-gist.sgml
@@ -8,7 +8,7 @@
  </indexterm>
 
  <para>
-  <filename>btree_gist</> provides sample GiST operator classes that
+  <filename>btree_gist</> provides GiST index operator classes that
   implement B-tree equivalent behavior for the data types
   <type>int2</>, <type>int4</>, <type>int8</>, <type>float4</>,
   <type>float8</>, <type>numeric</>, <type>timestamp with time zone</>,
@@ -23,18 +23,34 @@
   In general, these operator classes will not outperform the equivalent
   standard B-tree index methods, and they lack one major feature of the
   standard B-tree code: the ability to enforce uniqueness.  However,
-  they are useful for GiST testing and as a base for developing other
-  GiST operator classes.
+  they provide some other features that are not available with a B-tree
+  index, as described below.  Also, these operator classes are useful
+  when a multi-column GiST index is needed, wherein some of the columns
+  are of data types that are only indexable with GiST but other columns
+  are just simple data types.  Lastly, these operator classes are useful for
+  GiST testing and as a base for developing other GiST operator classes.
  </para>
 
  <para>
-  In addition to the typical btree search operators, btree_gist also
-  provides search operators for <literal>&lt;&gt;</literal> (<quote>not
+  In addition to the typical B-tree search operators, <filename>btree_gist</>
+  also provides index support for <literal>&lt;&gt;</literal> (<quote>not
   equals</quote>). This may be useful in combination with an
   <link linkend="SQL-CREATETABLE-EXCLUDE">exclusion constraint</link>,
   as described below.
  </para>
 
+ <para>
+  Also, for data types for which there is a natural distance metric,
+  <filename>btree_gist</> defines a distance operator <literal>&lt;-&gt;</>,
+  and provides GiST index support for nearest-neighbor searches using
+  this operator.  Distance operators are provided for
+  <type>int2</>, <type>int4</>, <type>int8</>, <type>float4</>,
+  <type>float8</>, <type>timestamp with time zone</>,
+  <type>timestamp without time zone</>,
+  <type>time without time zone</>, <type>date</>, <type>interval</>,
+  <type>oid</>, and <type>money</>.
+ </para>
+
  <sect2>
   <title>Example Usage</title>
 
@@ -48,6 +64,8 @@ CREATE TABLE test (a int4);
 CREATE INDEX testidx ON test USING gist (a);
 -- query
 SELECT * FROM test WHERE a &lt; 10;
+-- nearest-neighbor search: find the ten entries closest to "42"
+SELECT *, a &lt;-&gt; 42 AS dist FROM test ORDER BY a &lt;-&gt; 42 LIMIT 10;
 </programlisting>
 
   <para>