diff --git a/contrib/seg/Makefile b/contrib/seg/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..65b8eca4d1b71daa8a2fd3531d22f8369ec7ee1e
--- /dev/null
+++ b/contrib/seg/Makefile
@@ -0,0 +1,83 @@
+#
+# $Header: /cvsroot/pgsql/contrib/seg/Makefile,v 1.1 2000/12/11 20:40:33 tgl Exp $
+#
+
+subdir = contrib/seg
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+
+# override libdir to install shlib in contrib not main directory
+libdir := $(libdir)/contrib
+
+# shared library parameters
+NAME= seg
+SO_MAJOR_VERSION= 1
+SO_MINOR_VERSION= 0
+
+override CPPFLAGS += -I$(srcdir)
+
+OBJS= seg.o segparse.o segscan.o buffer.o
+
+all: all-lib $(NAME).sql
+
+# Shared library stuff
+include $(top_srcdir)/src/Makefile.shlib
+
+
+segparse.c segparse.h: segparse.y
+	$(YACC) -d $(YFLAGS) -p seg_yy $<
+	mv -f y.tab.c segparse.c
+	mv -f y.tab.h segparse.h
+
+segscan.c: segscan.l
+ifdef FLEX
+	$(FLEX) $(FLEXFLAGS) -Pseg_yy -o'$@' $<
+else
+	@$(missing) flex $< $@
+endif
+
+$(NAME).sql: $(NAME).sql.in
+	sed -e 's:MODULE_PATHNAME:$(libdir)/$(shlib):g' < $< > $@
+
+.PHONY: submake
+submake:
+	$(MAKE) -C $(top_builddir)/src/test/regress pg_regress
+
+# against installed postmaster
+installcheck: submake
+	$(top_builddir)/src/test/regress/pg_regress seg
+
+# in-tree test doesn't work yet (no way to install my shared library)
+#check: all submake
+#	$(top_builddir)/src/test/regress/pg_regress --temp-install \
+#	  --top-builddir=$(top_builddir) seg
+check:
+	@echo "'make check' is not supported."
+	@echo "Do 'make install', then 'make installcheck' instead."
+
+install: all installdirs install-lib
+	$(INSTALL_DATA) $(srcdir)/README.$(NAME)  $(docdir)/contrib
+	$(INSTALL_DATA) $(NAME).sql $(datadir)/contrib
+
+installdirs:
+	$(mkinstalldirs) $(docdir)/contrib $(datadir)/contrib $(libdir)
+
+uninstall: uninstall-lib
+	rm -f $(docdir)/contrib/README.$(NAME) $(datadir)/contrib/$(NAME).sql
+
+clean distclean maintainer-clean: clean-lib
+	rm -f segparse.c segparse.h segscan.c
+	rm -f y.tab.c y.tab.h $(OBJS) $(NAME).sql
+# things created by various check targets
+	rm -rf results tmp_check log
+	rm -f regression.diffs regression.out regress.out run_check.out
+ifeq ($(PORTNAME), win)
+	rm -f regress.def
+endif
+
+depend dep:
+	$(CC) -MM $(CFLAGS) *.c >depend
+
+ifeq (depend,$(wildcard depend))
+include depend
+endif
diff --git a/contrib/seg/README.seg b/contrib/seg/README.seg
new file mode 100644
index 0000000000000000000000000000000000000000..5c80ebcd5c4a450b01fb3ebef81b14f63eab3e32
--- /dev/null
+++ b/contrib/seg/README.seg
@@ -0,0 +1,326 @@
+This directory contains the code for the user-defined type,
+SEG, representing laboratory measurements as floating point
+intervals. 
+
+RATIONALE
+=========
+
+The geometry of measurements is usually more complex than that of a
+point in a numeric continuum. A measurement is usually a segment of
+that continuum with somewhat fuzzy limits. The measurements come out
+as intervals because of uncertainty and randomness, as well as because
+the value being measured may naturally be an interval indicating some
+condition, such as the temperature range of stability of a protein.
+
+Using just common sense, it appears more convenient to store such data
+as intervals, rather than pairs of numbers. In practice, it even turns
+out more efficient in most applications.
+
+Further along the line of common sense, the fuzziness of the limits
+suggests that the use of traditional numeric data types leads to a
+certain loss of information. Consider this: your instrument reads
+6.50, and you input this reading into the database. What do you get
+when you fetch it? Watch:
+
+test=> select 6.50 as "pH";
+ pH
+---
+6.5
+(1 row)
+
+In the world of measurements, 6.50 is not the same as 6.5. It may
+sometimes be critically different. The experimenters usually write
+down (and publish) the digits they trust. 6.50 is actually a fuzzy
+interval contained within a bigger and even fuzzier interval, 6.5,
+with their center points being (probably) the only common feature they
+share. We definitely do not want such different data items to appear the
+same.
+
+Conclusion? It is nice to have a special data type that can record the
+limits of an interval with arbitrarily variable precision. Variable in
+a sense that each data element records its own precision.
+
+Check this out:
+
+test=> select '6.25 .. 6.50'::seg as "pH";
+          pH
+------------
+6.25 .. 6.50
+(1 row)
+
+
+FILES
+=====
+
+Makefile		building instructions for the shared library
+
+README.seg		the file you are now reading
+
+buffer.c		global variables and buffer access utilities 
+			shared between the parser (segparse.y) and the
+			scanner (segscan.l)
+
+buffer.h		function prototypes for buffer.c
+
+seg.c			the implementation of this data type in c
+
+seg.sql.in		SQL code needed to register this type with postgres
+			(transformed to seg.sql by make)
+
+segdata.h		the data structure used to store the segments
+
+segparse.y		the grammar file for the parser (used by seg_in() in seg.c)
+ 
+segscan.l		scanner rules (used by seg_yyparse() in segparse.y)
+
+seg-validate.pl		a simple input validation script. It is probably a 
+			little stricter than the type itself: for example, 
+			it rejects '22 ' because of the trailing space. Use 
+			as a filter to discard bad values from a single column;
+			redirect to /dev/null to see the offending input
+
+sort-segments.pl	a script to sort the tables having a SEG type column
+
+
+INSTALLATION
+============
+
+To install the type, run
+
+	make
+	make install
+
+For this to work, make sure that:
+
+. the seg source directory is in the postgres contrib directory
+. the user running "make install" has postgres administrative authority
+. this user's environment defines the PGLIB and PGDATA variables and has
+  postgres binaries in the PATH.
+
+This only installs the type implementation and documentation.  To make the
+type available in any particular database, do
+
+	psql -d databasename < seg.sql
+
+If you install the type in the template1 database, all subsequently created
+databases will inherit it.
+
+To test the new type, after "make install" do
+
+	make installcheck
+
+If it fails, examine the file regression.diffs to find out the reason (the
+test code is a direct adaptation of the regression tests from the main
+source tree).
+
+
+SYNTAX
+======
+
+The external representation of an interval is formed using one or two
+floating point numbers joined by the range operator ('..' or '...'). 
+Optional certainty indicators (<, > and ~) are ignored by the internal 
+logics, but are retained in the data.
+
+Grammar
+-------
+
+rule 1    seg -> boundary PLUMIN deviation
+rule 2    seg -> boundary RANGE boundary
+rule 3    seg -> boundary RANGE
+rule 4    seg -> RANGE boundary
+rule 5    seg -> boundary
+rule 6    boundary -> FLOAT
+rule 7    boundary -> EXTENSION FLOAT
+rule 8    deviation -> FLOAT
+
+Tokens
+------
+
+RANGE        (\.\.)(\.)?
+PLUMIN       \'\+\-\'
+integer      [+-]?[0-9]+
+real         [+-]?[0-9]+\.[0-9]+
+FLOAT        ({integer}|{real})([eE]{integer})?
+EXTENSION    [<>~]
+
+
+Examples of valid SEG representations:
+--------------------------------------
+
+Any number	(rules 5,6) -- creates a zero-length segment (a point,
+		if you will)
+
+~5.0		(rules 5,7) -- creates a zero-length segment AND records 
+		'~' in the data. This notation reads 'approximately 5.0', 
+		but its meaning is not recognized by the code. It is ignored 
+		until you get the value back. View it is a short-hand comment.
+
+<5.0		(rules 5,7) -- creates a point at 5.0; '<' is ignored but 
+		is preserved as a comment
+
+>5.0		(rules 5,7) -- creates a point at 5.0; '>' is ignored but
+		is preserved as a comment
+
+5(+-)0.3
+5'+-'0.3	(rules 1,8) -- creates an interval '4.7..5.3'. As of this 
+		writing (02/09/2000), this mechanism isn't completely accurate 
+		in determining the number of significant digits for the 
+		boundaries. For example, it adds an extra digit to the lower
+		boundary if the resulting interval includes a power of ten:
+
+		template1=> select '10(+-)1'::seg as seg;
+		      seg
+		---------
+		9.0 .. 11 -- should be: 9 .. 11
+
+		Also, the (+-) notation is not preserved: 'a(+-)b' will 
+		always be returned as '(a-b) .. (a+b)'. The purpose of this 
+		notation is to allow input from certain data sources without 
+		conversion.
+
+50 .. 		(rule 3) -- everything that is greater than or equal to 50
+
+.. 0		(rule 4) -- everything that is less than or equal to 0
+
+1.5e-2 .. 2E-2 	(rule 2) -- creates an interval (0.015 .. 0.02)
+
+1 ... 2		The same as 1...2, or 1 .. 2, or 1..2 (space is ignored).
+		Because of the widespread use of '...' in the data sources,
+		I decided to stick to is as a range operator. This, and
+		also the fact that the white space around the range operator
+		is ignored, creates a parsing conflict with numeric constants 
+		starting with a	decimal point.
+
+
+Examples of invalid SEG input:
+------------------------------
+
+.1e7		should be: 0.1e7
+.1 .. .2	should be: 0.1 .. 0.2
+2.4 E4		should be: 2.4E4
+
+The following, although it is not a syntax error, is disallowed to improve
+the sanity of the data:
+
+5 .. 2		should be: 2 .. 5
+
+
+PRECISION
+=========
+
+The segments are stored internally as pairs of 32-bit floating point
+numbers. It means that the numbers with more than 7 significant digits
+will be truncated.
+
+The numbers with less than or exactly 7 significant digits retain their
+original precision. That is, if your query returns 0.00, you will be
+sure that the trailing zeroes are not the artifacts of formatting: they
+reflect the precision of the original data. The number of leading
+zeroes does not affect precision: the value 0.0067 is considered to
+have just 2 significant digits.
+
+
+USAGE
+=====
+
+The access method for SEG is a GiST (gist_seg_ops), which is a
+generalization of R-tree. GiSTs allow the postgres implementation of
+R-tree, originally encoded to support 2-D geometric types such as
+boxes and polygons, to be used with any data type whose data domain
+can be partitioned using the concepts of containment, intersection and
+equality. In other words, everything that can intersect or contain
+its own kind can be indexed with a GiST. That includes, among other
+things, all geometric data types, regardless of their dimensionality
+(see also contrib/cube).
+
+The operators supported by the GiST access method include:
+
+
+[a, b] << [c, d]	Is left of
+
+	The left operand, [a, b], occurs entirely to the left of the
+	right operand, [c, d], on the axis (-inf, inf). It means,
+	[a, b] << [c, d] is true if b < c and false otherwise
+
+[a, b] >> [c, d]	Is right of
+
+	[a, b] is occurs entirely to the right of [c, d]. 
+	[a, b] >> [c, d] is true if b > c and false otherwise
+
+[a, b] &< [c, d]	Over left
+
+	The segment [a, b] overlaps the segment [c, d] in such a way
+	that a <= c <= b and b <= d
+
+[a, b] &> [c, d]	Over right
+
+	The segment [a, b] overlaps the segment [c, d] in such a way
+	that a > c and b <= c <= d
+
+[a, b] = [c, d]		Same as
+
+	The segments [a, b] and [c, d] are identical, that is, a == b
+	and c == d
+
+[a, b] @ [c, d]		Contains
+
+	The segment [a, b] contains the segment [c, d], that is, 
+	a <= c and b >= d
+
+[a, b] @ [c, d]		Contained in
+
+	The segment [a, b] is contained in [c, d], that is, 
+	a >= c and b <= d
+
+Although the mnemonics of the following operators is questionable, I
+preserved them to maintain visual consistency with other geometric
+data types defined in Postgres.
+
+Other operators:
+
+[a, b] < [c, d]		Less than
+[a, b] > [c, d]		Greater than
+
+	These operators do not make a lot of sense for any practical
+	purpose but sorting. These operators first compare (a) to (c),
+	and if these are equal, compare (b) to (d). That accounts for
+	reasonably good sorting in most cases, which is useful if
+	you want to use ORDER BY with this type
+
+There are a few other potentially useful functions defined in seg.c 
+that vanished from the schema because I stopped using them. Some of 
+these were meant to support type casting. Let me know if I was wrong: 
+I will then add them back to the schema. I would also appreciate 
+other ideas that would enhance the type and make it more useful.
+
+For examples of usage, see sql/seg.sql
+
+NOTE: The performance of an R-tree index can largely depend on the
+order of input values. It may be very helpful to sort the input table
+on the SEG column (see the script sort-segments.pl for an example)
+
+
+CREDITS
+=======
+
+My thanks are primarily to Prof. Joe Hellerstein
+(http://db.cs.berkeley.edu/~jmh/) for elucidating the gist of the GiST
+(http://gist.cs.berkeley.edu/). I am also grateful to all postgres
+developers, present and past, for enabling myself to create my own
+world and live undisturbed in it. And I would like to acknowledge my
+gratitude to Argonne Lab and to the U.S. Department of Energy for the
+years of faithful support of my database research.
+
+
+------------------------------------------------------------------------
+Gene Selkov, Jr.
+Computational Scientist
+Mathematics and Computer Science Division
+Argonne National Laboratory
+9700 S Cass Ave.
+Building 221
+Argonne, IL 60439-4844
+
+selkovjr@mcs.anl.gov
+
diff --git a/contrib/seg/buffer.c b/contrib/seg/buffer.c
new file mode 100644
index 0000000000000000000000000000000000000000..f4dfc1edcd30d68a2b17e56628e5d62a7ecf3f1f
--- /dev/null
+++ b/contrib/seg/buffer.c
@@ -0,0 +1,79 @@
+/* This module defines the parse buffer and routines for setting/reading it */
+
+#include "postgres.h"
+
+#include "utils/elog.h"
+
+static char *       PARSE_BUFFER;
+static char *       PARSE_BUFFER_PTR; 
+static unsigned int PARSE_BUFFER_SIZE; 
+static unsigned int SCANNER_POS;
+
+void         set_parse_buffer( char* s );
+void         reset_parse_buffer( void );
+int          read_parse_buffer( void );
+char *       parse_buffer( void );
+char *       parse_buffer_ptr( void );
+unsigned int parse_buffer_curr_char( void );
+unsigned int parse_buffer_size( void );
+unsigned int parse_buffer_pos( void );
+
+extern void seg_flush_scanner_buffer(void); /* defined in segscan.l */
+
+void set_parse_buffer( char* s )
+{
+  PARSE_BUFFER = s;
+  PARSE_BUFFER_SIZE = strlen(s);
+  if ( PARSE_BUFFER_SIZE == 0 ) {
+    elog(ERROR, "seg_in: can't parse an empty string");
+  }
+  PARSE_BUFFER_PTR = PARSE_BUFFER;
+  SCANNER_POS = 0;
+}
+
+void reset_parse_buffer( void )
+{
+  PARSE_BUFFER_PTR = PARSE_BUFFER;
+  SCANNER_POS = 0;
+  seg_flush_scanner_buffer();
+}
+
+int read_parse_buffer( void )
+{
+  int c;
+  /*
+  c = *PARSE_BUFFER_PTR++;
+  SCANNER_POS++;
+  */
+  c = PARSE_BUFFER[SCANNER_POS];
+  if(SCANNER_POS < PARSE_BUFFER_SIZE)
+    SCANNER_POS++;
+  return c;
+}
+
+char * parse_buffer( void )
+{
+  return PARSE_BUFFER;
+}
+
+unsigned int parse_buffer_curr_char( void )
+{
+  return PARSE_BUFFER[SCANNER_POS];
+}
+
+char * parse_buffer_ptr( void )
+{
+  return PARSE_BUFFER_PTR;
+}
+
+unsigned int parse_buffer_pos( void )
+{
+  return SCANNER_POS;
+}
+
+unsigned int parse_buffer_size( void )
+{
+  return PARSE_BUFFER_SIZE;
+}
+
+
diff --git a/contrib/seg/buffer.h b/contrib/seg/buffer.h
new file mode 100644
index 0000000000000000000000000000000000000000..fd41a7b69b713e2b4dc23716af8905477ff8a379
--- /dev/null
+++ b/contrib/seg/buffer.h
@@ -0,0 +1,8 @@
+extern void set_parse_buffer( char* s );
+extern void reset_parse_buffer( void );
+extern int read_parse_buffer( void );
+extern char * parse_buffer( void );
+extern char * parse_buffer_ptr( void );
+extern unsigned int parse_buffer_curr_char( void );
+extern unsigned int parse_buffer_pos( void );
+extern unsigned int parse_buffer_size( void );
diff --git a/contrib/seg/data/test_seg.data b/contrib/seg/data/test_seg.data
new file mode 100644
index 0000000000000000000000000000000000000000..dba9ac90452ad72ea165e0e40aa12cb54f858986
--- /dev/null
+++ b/contrib/seg/data/test_seg.data
@@ -0,0 +1,2577 @@
+...10.3
+...10.5
+...3.5
+...3.9
+...4.9
+...40
+...5.6
+...5.8
+...6.0
+...6.6
+...6.7
+...6.75
+...7.0
+...7.2
+...7.3
+...7.5
+...7.6
+...7.8
+...8.0
+...8.5
+...8.6
+...8.8
+...8.9
+...9.0
+...9.2
+...9.3
+...9.5
+...9.6
+...90
+...<3.0
+...<5.8
+...<7
+...<7.0
+...<8.0
+...<8.2
+...<8.9
+...>10
+...>7.2
+...>7.7
+...>8.0
+...>82
+...>9.0
+< 1.0...3.8
+< 1.5...4.1
+< 1.5...4.15
+< 10...>11.6
+< 2...>4
+< 2.0...3.4
+< 2.0...4.2
+< 2.0...>8.0
+< 2.5...4.7
+< 2.5...5.5
+< 2.5...>8.5
+< 3...>5
+< 3.0...
+< 3.0...4.5
+< 3.0...6.0
+< 3.0...6.5
+< 3.0...9.0
+< 3.0...>10
+< 3.0...>11.0
+< 3.0...>8.0
+< 3.0...>9.0
+< 3.0...>9.5
+< 3.5
+< 3.5...4.3
+< 3.5...5.3
+< 3.5...5.6
+< 3.5...6.0
+< 3.5...8.4
+< 3.6...>6.5
+< 3.7...5.4
+< 4...9.5
+< 4...>5
+< 4...>6.0
+< 4.0...
+< 4.0...10.5
+< 4.0...5.3
+< 4.0...5.75
+< 4.0...6.0
+< 4.0...7.3
+< 4.0...7.5
+< 4.0...7.7
+< 4.0...8.5
+< 4.0...>12
+< 4.0...>5.0
+< 4.0...>6.0
+< 4.0...>7.5
+< 4.0...>8.0
+< 4.0...>8.1
+< 4.0...>9.0
+< 4.2...5.2
+< 4.2...5.3
+< 4.2...5.4
+< 4.2...6.2
+< 4.3...>9.0
+< 4.4
+< 4.4...6.0
+< 4.4...<6.0
+< 4.5...6.3
+< 4.5...7.2
+< 4.5...>12
+< 4.5...>5.0
+< 4.5...>5.5
+< 4.5...>6
+< 4.5...>7.5
+< 4.5...>8
+< 4.5...>9.5
+< 4.7...>9.3
+< 4.8...>6.4
+< 5...7.5
+< 5...7.7
+< 5...>7
+< 5...>8
+< 5...>8.0
+< 5.0
+< 5.0...10
+< 5.0...6.3
+< 5.0...7.4
+< 5.0...7.7
+< 5.0...8.1
+< 5.0...8.3
+< 5.0...8.5
+< 5.0...8.8
+< 5.0...9.5
+< 5.0...<9.0
+< 5.0...>10
+< 5.0...>10.0
+< 5.0...>10.5
+< 5.0...>11
+< 5.0...>6.0
+< 5.0...>6.6
+< 5.0...>7.5
+< 5.0...>8.0
+< 5.0...>8.5
+< 5.0...>8.6
+< 5.0...>9.0
+< 5.2...7.3
+< 5.2...8.2
+< 5.2...8.5
+< 5.2...>5.8
+< 5.2...>7.6
+< 5.3
+< 5.3...6.5
+< 5.3...7.5
+< 5.3...7.8
+< 5.4...6.35
+< 5.5...10
+< 5.5...6.3
+< 5.5...7.0
+< 5.5...7.5
+< 5.5...8.4
+< 5.5...8.5
+< 5.5...>10
+< 5.5...>10.0
+< 5.5...>10.5
+< 5.5...>6.5
+< 5.5...>7
+< 5.5...>7.5
+< 5.5...>8
+< 5.5...>8.0
+< 5.5...>8.5
+< 5.5...>8.7
+< 5.5...>8.9
+< 5.5...>9.0
+< 5.6...6.75
+< 5.75...>9.0
+< 5.8...7.8
+< 5.8...>11
+< 5.8...>8.2
+< 5.9...>8.0
+< 6...>10.5
+< 6...>8
+< 6...>9.5
+< 6.0
+< 6.0...6.8
+< 6.0...7.15
+< 6.0...7.6
+< 6.0...7.7
+< 6.0...8.0
+< 6.0...8.2
+< 6.0...8.5
+< 6.0...9.0
+< 6.0...9.5
+< 6.0...>10
+< 6.0...>10.0
+< 6.0...>11
+< 6.0...>7.0
+< 6.0...>8.0
+< 6.0...>8.2
+< 6.0...>8.5
+< 6.0...>8.6
+< 6.0...>9.0
+< 6.0...>9.6
+< 6.3...9.5
+< 6.3...>6.7
+< 6.3...>7.8
+< 6.35...>7.7
+< 6.4...>8.0
+< 6.4...>8.7
+< 6.5...11
+< 6.5...7.25
+< 6.5...8.0
+< 6.5...8.2
+< 6.5...8.4
+< 6.5...8.5
+< 6.5...9.7
+< 6.5...>10.0
+< 6.5...>10.5
+< 6.5...>7.5
+< 6.5...>8.0
+< 6.5...>8.5
+< 6.5...>8.6
+< 6.5...>8.7
+< 6.5...>9.0
+< 6.5...>9.5
+< 6.6...>7.5
+< 6.6...>8.5
+< 6.8...7.8
+< 6.8...9.5
+< 6.8...>7.5
+< 6.8...>8.6
+< 6.8...>9.0
+< 6.9...9.0
+< 7...9.2
+< 7...>11
+< 7...>7.5
+< 7...>9.5
+< 7.0
+< 7.0...10
+< 7.0...10.5
+< 7.0...11.0
+< 7.0...8.2
+< 7.0...8.3
+< 7.0...8.4
+< 7.0...8.55
+< 7.0...8.7
+< 7.0...8.8
+< 7.0...9.0
+< 7.0...<8.0
+< 7.0...>10.5
+< 7.0...>11
+< 7.0...>11.0
+< 7.0...>7.0
+< 7.0...>7.3
+< 7.0...>7.4
+< 7.0...>7.5
+< 7.0...>7.75
+< 7.0...>7.8
+< 7.0...>8.0
+< 7.0...>8.2
+< 7.0...>8.5
+< 7.0...>8.6
+< 7.0...>8.9
+< 7.0...>9.0
+< 7.0...>9.5
+< 7.2...8.3
+< 7.2...>7.5
+< 7.2...>7.8
+< 7.2...>8.0
+< 7.2...>8.2
+< 7.2...>8.6
+< 7.2...>8.8
+< 7.4...>7.8
+< 7.4...>8.0
+< 7.4...>8.1
+< 7.4...>8.6
+< 7.4...>8.8
+< 7.5...9.0
+< 7.5...>10
+< 7.5...>8.0
+< 7.5...>8.5
+< 7.5...>8.7
+< 7.5...>9
+< 7.5...>9.0
+< 7.5...>9.5
+< 7.6...>7.8
+< 7.6...>8.0
+< 7.6...>8.5
+< 7.6...>8.6
+< 7.6...>8.9
+< 7.8...>9.0
+< 7.9...>8.3
+< 8.0
+< 8.0...>10.0
+< 8.0...>8.5
+< 8.0...>9.0
+< 8.0...>9.4
+< 8.0...>9.5
+< 8.2...9.8
+< 8.2...>8.6
+< 8.5...>10.5
+< 8.5...>11
+< 8.5...>9.5
+< 9...10.5
+<1.0...3.5
+<1.0...3.7
+<1.0...4.0
+<1.0...>13.0
+<1.0...>5.5
+<10.5...11.5
+<12.0...12.5
+<2...10
+<2...>4
+<2.0
+<2.0...11
+<2.0...3.5
+<2.0...5.7
+<2.0...6.0
+<2.0...6.8
+<2.0...9.7
+<2.0...>6.5
+<2.0...>9.0
+<2.3...
+<2.3...>11.0
+<2.4...6.8
+<2.5...7.7
+<2.5...>8.0
+<2.8...>8.0
+<3.0...4.6
+<3.0...5.5
+<3.0...6.0
+<3.0...6.3
+<3.0...6.4
+<3.0...6.8
+<3.0...7.0
+<3.0...7.5
+<3.0...8.3
+<3.0...>10.5
+<3.0...>5.0
+<3.0...>7.0
+<3.0...>7.2
+<3.0...>8.5
+<3.0...>8.7
+<3.0...>9.0
+<3.5...6.0
+<3.5...8.0
+<3.5...<7.0
+<3.5...>10.0
+<3.55...5.3
+<3.7...4.9
+<3.7...5.0
+<4...6.5
+<4.0...10.0
+<4.0...10.5
+<4.0...6.1
+<4.0...6.3
+<4.0...6.5
+<4.0...7.7
+<4.0...8.2
+<4.0...<9.0
+<4.0...>10
+<4.0...>10.0
+<4.0...>10.5
+<4.0...>6.0
+<4.0...>8.0
+<4.0...>9.0
+<4.1...>8.0
+<4.3...7.6
+<4.5...6.3
+<4.5...6.5
+<4.5...>6.5
+<4.5...>9.5
+<4.8...>7.4
+<4.9...>9.5
+<5...>6
+<5...>6.0
+<5...>8
+<5.0...10.0
+<5.0...6.0
+<5.0...6.6
+<5.0...6.8
+<5.0...7.0
+<5.0...7.5
+<5.0...8.2
+<5.0...9.5
+<5.0...>11.0
+<5.0...>5.5
+<5.0...>7.0
+<5.0...>8.0
+<5.0...>9.0
+<5.2...7.5
+<5.2...>6.8
+<5.2...>8.0
+<5.3...10.2
+<5.3...>10.5
+<5.4...8.0
+<5.4...8.5
+<5.4...>8.2
+<5.4...>9.1
+<5.5...6.5
+<5.5...7.0
+<5.5...7.5
+<5.5...8.2
+<5.5...8.3
+<5.5...8.5
+<5.5...8.6
+<5.5...>10.0
+<5.5...>7.0
+<5.5...>7.5
+<5.5...>8.0
+<5.5...>8.5
+<5.5...>9.0
+<5.6...7.5
+<5.6...>6.4
+<5.6...>7.4
+<5.6...>8.0
+<5.6...>8.5
+<5.7...>7.1
+<5.8...7.4
+<5.8...>6.7
+<5.8...>6.8
+<5.8...>7.0
+<5.8...>7.8
+<5.8...>8.8
+<5.85...>9.5
+<6...>9
+<6.0...10.0
+<6.0...6.8
+<6.0...7.1
+<6.0...7.2
+<6.0...7.7
+<6.0...8.0
+<6.0...8.2
+<6.0...8.4
+<6.0...8.5
+<6.0...8.6
+<6.0...9.1
+<6.0...9.2
+<6.0...9.3
+<6.0...9.5
+<6.0...>10
+<6.0...>11.0
+<6.0...>7.0
+<6.0...>7.5
+<6.0...>7.6
+<6.0...>7.9
+<6.0...>8.0
+<6.0...>8.3
+<6.0...>8.5
+<6.0...>8.6
+<6.0...>9.0
+<6.0...>9.2
+<6.0...>9.5
+<6.1...8.4
+<6.1...>6.6
+<6.1...>8.1
+<6.2
+<6.2...6.9
+<6.2...8.3
+<6.2...>7.5
+<6.2...>8.5
+<6.2...>8.7
+<6.3...10.0
+<6.3...7.4
+<6.3...9.6
+<6.3...>7.0
+<6.3...>8.0
+<6.4...7.6
+<6.4...8.5
+<6.4...>8.5
+<6.4...>9.0
+<6.5...7.8
+<6.5...8.2
+<6.5...9.2
+<6.5...>7.0
+<6.5...>7.5
+<6.5...>8.0
+<6.5...>8.5
+<6.5...>8.7
+<6.5...>9.0
+<6.5...>9.5
+<6.6
+<6.6...8.0
+<6.8...8.0
+<6.8...8.2
+<6.8...>7.5
+<6.8...>8.5
+<6.8...>9.5
+<7...9
+<7...>10
+<7.0...7.5
+<7.0...9.0
+<7.0...9.0
+<7.0...9.4
+<7.0...9.5
+<7.0...9.5
+<7.0...>10
+<7.0...>10.0
+<7.0...>11.5
+<7.0...>7.5
+<7.0...>8.0
+<7.0...>8.3
+<7.0...>8.4
+<7.0...>8.5
+<7.0...>9.0
+<7.2...8.8
+<7.2...9.0
+<7.2...>8.2
+<7.2...>8.8
+<7.2...>9.5
+<7.3...>8.0
+<7.4...8.8
+<7.4...9.6
+<7.4...>8.5
+<7.4...>8.7
+<7.5...8.5
+<7.5...<9.0
+<7.5...>8.0
+<7.5...>8.5
+<7.5...>9.5
+<7.6...>8.4
+<7.6...>9.4
+<7.8...>10.2
+<7.8...>8.2
+<8.0
+<8.0...10.0
+<8.0...>8.5
+<8.0...>8.8
+<8.0...>9.0
+<8.2...>10.2
+<8.5...9.6
+<8.5...>9.0
+<8.5...>9.5
+<8.6...>10.6
+<9.1...10.3
+<9.2...>11.0
+<9.5...12
+<9.5...>12.2
+> 11.0
+> 3.0...<7.0
+> 4.0...<10.0
+> 4.0...<9.0
+> 4.5...<9.0
+> 5.0
+> 5.0...<10.0
+> 5.0...<11
+> 5.5...
+> 5.6
+> 5.9...<9.5
+> 6.0...8.0
+> 6.0...<11.5
+> 6.0...<8.0
+> 6.0...>10.0
+> 6.2...<7.4
+> 7.0...<10
+> 7.0...>8.5
+> 7.0...>8.6
+> 7.0...>8.7
+> 7.15...
+> 8.0
+> 8.7
+> 9.3
+> 9.5
+>10.5
+>120
+>2.3...
+>3.0...<7.0
+>3.8...<8.0
+>4.0...<10
+>5.0...<7.0
+>5.0...>8.0
+>5.0...>9.2
+>5.25...6.5
+>5.5...>9.3
+>5.6...<8.2
+>6.0...>11.0
+>6.5...>8.0
+>6.6...<7.3
+>6.8...>8.5
+>6.9...>8.0
+>7.0
+>7.0...<9.0
+>7.0...<9.5
+>7.3...
+>7.5...<10.5
+>8.0
+>8.4
+>8.5
+>9.0
+>9.4
+>9.5
+>95
+~10
+~23
+~5.0...>9.0
+~6.0
+~6.4...~8.5
+~6.8
+~7.0
+~7.5
+~8.0
+~8.0...~10.0
+1.0
+1.0...4.0
+1.0...5.0
+1.1
+1.1...3.6
+1.2...3.2
+1.2...3.5
+1.3...12.0
+1.4...2.0
+1.4...8.2
+1.5
+1.5...10.5
+1.5...4.2
+1.5...4.5
+1.6...3.8
+1.6...7.2
+1.7
+1.7...2.4
+1.7...3.2
+1.7...5.0
+1.7...5.7
+1.8
+1.8...3.8
+1.8...>9.0
+1.9...3.6
+2
+2.0
+2.0...10.0
+2.0...11.0
+2.0...11.5
+2.0...2.5
+2.0...3.2
+2.0...3.5
+2.0...4.0
+2.0...4.3
+2.0...4.4
+2.0...4.6
+2.0...4.75
+2.0...4.8
+2.0...5.0
+2.0...5.5
+2.0...6.5
+2.0...7.0
+2.0...7.5
+2.0...8.0
+2.0...9.0
+2.0...>10
+2.0...>4.0
+2.0...>5.5
+2.1
+2.1...11.8
+2.1...4.2
+2.2
+2.2...11.2
+2.2...4.1
+2.2...4.2
+2.2...5.9
+2.2...6.4
+2.2...6.8
+2.3...10.6
+2.3...4.1
+2.3...4.3
+2.3...4.5
+2.3...4.7
+2.3...6.0
+2.4
+2.4...11.3
+2.4...4.5
+2.4...5.6
+2.4...5.7
+2.4...6.3
+2.5
+2.5...11
+2.5...11.2
+2.5...11.5
+2.5...11.8
+2.5...3.0
+2.5...3.7
+2.5...4.1
+2.5...4.5
+2.5...4.6
+2.5...5.0
+2.5...5.1
+2.5...5.5
+2.5...6.0
+2.5...6.3
+2.5...7.0
+2.5...9.0
+2.5...>3.5
+2.5...>4.0
+2.52
+2.56
+2.6...
+2.6...10.0
+2.6...9.3
+2.6...>4.0
+2.6...>9.4
+2.62
+2.7
+2.7...12.0
+2.7...3.7
+2.7...3.8
+2.7...4.5
+2.7...4.7
+2.7...6.0
+2.7...6.4
+2.7...7.0
+2.7...8.0
+2.75...5.25
+2.79
+2.8
+2.8...11.0
+2.8...3.4
+2.8...4.0
+2.8...7.0
+2.8...8.0
+2.8...9.0
+2.8...9.7
+2.9...3.7
+2.9...4.5
+2.9...5.0
+2.9...5.6
+2.9...6.1
+2.9...7.6
+2.9...9.0
+2.97
+3
+3...10.0
+3...10.5
+3...5.5
+3...58
+3...6
+3...8
+3.0
+3.0...10
+3.0...10.0
+3.0...10.5
+3.0...11.0
+3.0...3.5
+3.0...4.0
+3.0...4.5
+3.0...4.9
+3.0...5.0
+3.0...5.4
+3.0...5.6
+3.0...5.65
+3.0...6.0
+3.0...6.3
+3.0...6.5
+3.0...6.7
+3.0...6.9
+3.0...7.0
+3.0...7.2
+3.0...7.5
+3.0...8.0
+3.0...8.5
+3.0...8.7
+3.0...9.0
+3.0...9.7
+3.0...>10
+3.0...>10.0
+3.0...>8.0
+3.00...5.0
+3.1
+3.1...11.5
+3.1...5.2
+3.1...5.8
+3.1...6.8
+3.1...7.8
+3.15...7.25
+3.2
+3.2...10.0
+3.2...4.2
+3.2...4.6
+3.2...5.4
+3.2...5.8
+3.2...6.25
+3.2...6.8
+3.2...8.1
+3.2...>8.0
+3.2...>9.9
+3.22
+3.3
+3.3...4.7
+3.3...5.3
+3.3...5.5
+3.3...5.6
+3.3...6.0
+3.3...6.5
+3.3...6.7
+3.3...7.2
+3.3...7.4
+3.3...7.5
+3.3...7.8
+3.3...9.0
+3.4
+3.4...4.1
+3.4...4.7
+3.4...5.5
+3.4...6.2
+3.4...6.4
+3.4...8.2
+3.4...>8.0
+3.5
+3.5...10
+3.5...10.0
+3.5...10.5
+3.5...10.8
+3.5...11.0
+3.5...11.5
+3.5...12.2
+3.5...4.0
+3.5...4.4
+3.5...4.5
+3.5...5.0
+3.5...5.3
+3.5...5.5
+3.5...5.6
+3.5...6
+3.5...6.0
+3.5...6.3
+3.5...6.4
+3.5...6.5
+3.5...6.6
+3.5...6.7
+3.5...7.0
+3.5...7.2
+3.5...7.3
+3.5...7.5
+3.5...8.5
+3.5...8.6
+3.5...8.7
+3.5...9.0
+3.5...9.5
+3.5...>11.0
+3.5...>5.0
+3.5...>8.5
+3.5...>9.0
+3.6
+3.6...3.8
+3.6...4.55
+3.6...4.6
+3.6...4.8
+3.6...5.4
+3.6...5.5
+3.6...6
+3.6...6.0
+3.6...6.6
+3.6...6.8
+3.6...7.0
+3.6...7.7
+3.6...8.6
+3.6...8.7
+3.6...8.8
+3.7
+3.7...10.0
+3.7...10.6
+3.7...4.6
+3.7...5.3
+3.7...6.2
+3.7...6.3
+3.7...6.5
+3.7...6.7
+3.7...8.2
+3.7...8.3
+3.7...9.1
+3.7...>10
+3.7...>11
+3.75...5.7
+3.8
+3.8...10
+3.8...4.0
+3.8...4.5
+3.8...4.8
+3.8...5.5
+3.8...5.8
+3.8...5.9
+3.8...6.2
+3.8...7.7
+3.8...8.3
+3.8...8.7
+3.9
+3.9...5.5
+3.9...6.8
+3.9...7.8
+3.9...>7.5
+3.9...>8.5
+3.9...>9.0
+3.95
+4
+4...10
+4...11.0
+4...12
+4...5
+4...6.9
+4...7
+4...7.5
+4...8
+4...9
+4...>11
+4...>8
+4.0
+4.0...
+4.0...10
+4.0...10.0
+4.0...10.4
+4.0...10.5
+4.0...11.0
+4.0...11.7
+4.0...12.5
+4.0...13.0
+4.0...4.4
+4.0...4.5
+4.0...4.8
+4.0...5.0
+4.0...5.1
+4.0...5.2
+4.0...5.5
+4.0...5.7
+4.0...5.75
+4.0...5.8
+4.0...6.0
+4.0...6.1
+4.0...6.2
+4.0...6.3
+4.0...6.5
+4.0...60
+4.0...7.0
+4.0...7.2
+4.0...7.3
+4.0...7.5
+4.0...7.7
+4.0...7.9
+4.0...8.0
+4.0...8.1
+4.0...8.2
+4.0...8.3
+4.0...8.5
+4.0...8.8
+4.0...9.0
+4.0...9.4
+4.0...>10
+4.0...>11
+4.0...>9.0
+4.1
+4.1...10.5
+4.1...5.6
+4.1...5.8
+4.1...6.0
+4.1...7.2
+4.1...8.0
+4.1...9.1
+4.15...5.25
+4.15...6.25
+4.15...6.5
+4.2
+4.2...11.0
+4.2...11.5
+4.2...11.7
+4.2...5.0
+4.2...5.3
+4.2...5.35
+4.2...5.4
+4.2...5.6
+4.2...5.7
+4.2...6.0
+4.2...6.3
+4.2...6.4
+4.2...6.7
+4.2...7.1
+4.2...7.2
+4.2...7.3
+4.2...8.0
+4.2...8.4
+4.2...9.5
+4.2...>7.0
+4.2...>7.3
+4.2...>9.0
+4.2...>9.5
+4.25
+4.25...5.00
+4.25...9.75
+4.3
+4.3...10.3
+4.3...5.3
+4.3...5.7
+4.3...5.8
+4.3...6.0
+4.3...6.3
+4.3...6.5
+4.3...6.8
+4.3...7.0
+4.3...7.2
+4.3...7.3
+4.3...7.5
+4.3...7.6
+4.3...8
+4.3...8.2
+4.3...8.5
+4.3...8.6
+4.3...>5.0
+4.3...>6.0
+4.3...>7.0
+4.3...>8.0
+4.35
+4.4
+4.4...10.7
+4.4...4.6
+4.4...4.8
+4.4...6.0
+4.4...6.2
+4.4...6.4
+4.4...6.6
+4.4...6.7
+4.4...7.0
+4.4...7.2
+4.4...7.5
+4.4...7.6
+4.4...8.5
+4.4...9.3
+4.5
+4.5...10
+4.5...10.0
+4.5...10.5
+4.5...11.0
+4.5...11.5
+4.5...115
+4.5...12.5
+4.5...4.8
+4.5...5.0
+4.5...5.2
+4.5...5.5
+4.5...5.7
+4.5...5.8
+4.5...6.0
+4.5...6.2
+4.5...6.4
+4.5...6.5
+4.5...6.8
+4.5...7
+4.5...7.0
+4.5...7.1
+4.5...7.3
+4.5...7.5
+4.5...7.6
+4.5...7.7
+4.5...7.8
+4.5...7.9
+4.5...8.0
+4.5...8.3
+4.5...8.5
+4.5...8.6
+4.5...8.7
+4.5...8.8
+4.5...8.9
+4.5...9.0
+4.5...9.3
+4.5...9.4
+4.5...9.5
+4.5...<12
+4.5...>10
+4.5...>12
+4.5...>6.0
+4.5...>7.0
+4.5...>7.5
+4.5...>8.0
+4.5...>8.5
+4.5...>9.0
+4.6
+4.6 
+4.6...4.8
+4.6...5.0
+4.6...5.2
+4.6...6.3
+4.6...6.4
+4.6...6.5
+4.6...6.6
+4.6...7.0
+4.6...7.2
+4.6...7.4
+4.6...7.5
+4.6...8.2
+4.6...8.5
+4.6...8.6
+4.6...8.7
+4.6...<6.5
+4.6...>10
+4.6...>11
+4.6...>7.4
+4.6...>8.0
+4.6...~7.0
+4.7
+4.7...10.8
+4.7...11
+4.7...11.8
+4.7...5.6
+4.7...6.0
+4.7...6.2
+4.7...6.3
+4.7...6.6
+4.7...6.7
+4.7...7.0
+4.7...7.4
+4.7...7.5
+4.7...7.7
+4.7...7.8
+4.7...8.0
+4.7...8.3
+4.7...8.4
+4.7...8.5
+4.7...9.3
+4.7...9.5
+4.7...9.6
+4.7...9.7
+4.7...>10
+4.7...>10.0
+4.7...>10.5
+4.7...>6.5
+4.7...>8.0
+4.75
+4.8
+4.8...
+4.8...10.3
+4.8...11.5
+4.8...11.6
+4.8...12.5
+4.8...5.2
+4.8...5.9
+4.8...6.0
+4.8...6.2
+4.8...6.3
+4.8...7.0
+4.8...7.3
+4.8...7.4
+4.8...7.5
+4.8...7.6
+4.8...7.7
+4.8...7.75
+4.8...8.0
+4.8...8.2
+4.8...8.4
+4.8...8.6
+4.8...9.0
+4.8...9.3
+4.8...9.7
+4.8...>10.0
+4.8...>8.0
+4.8...>9.0
+4.85
+4.9
+4.9...
+4.9...6.5
+4.9...7.2
+4.9...7.8
+4.9...8.2
+4.9...8.3
+4.9...9.0
+4.9...9.5
+4.9...<6.0
+4.9...>12
+4.9...>7.5
+4.9...>9.5
+5
+5...10.0
+5...10.5
+5...11
+5...11.5
+5...12
+5...30
+5...6
+5...6.6
+5...7
+5...8
+5...8.5
+5...9
+5...9.5
+5.0
+5.0...10
+5.0...10.0
+5.0...10.2
+5.0...10.3
+5.0...10.5
+5.0...11
+5.0...11.0
+5.0...11.2
+5.0...11.4
+5.0...11.5
+5.0...11.6
+5.0...11.7
+5.0...12.0
+5.0...5.5
+5.0...5.7
+5.0...6.0
+5.0...6.1
+5.0...6.2
+5.0...6.4
+5.0...6.5
+5.0...6.6
+5.0...6.8
+5.0...6.9
+5.0...7.0
+5.0...7.2
+5.0...7.3
+5.0...7.4
+5.0...7.5
+5.0...7.6
+5.0...7.7
+5.0...7.8
+5.0...8.0
+5.0...8.2
+5.0...8.3
+5.0...8.4
+5.0...8.5
+5.0...8.6
+5.0...8.7
+5.0...9.0
+5.0...9.0 
+5.0...9.2
+5.0...9.5
+5.0...>10
+5.0...>10.0
+5.0...>11
+5.0...>12
+5.0...>12.0
+5.0...>7.0
+5.0...>8.0
+5.0...>8.4
+5.0...>8.5
+5.0...>9.0
+5.02...6.74
+5.1
+5.1...5.3
+5.1...5.4
+5.1...6.2
+5.1...6.3
+5.1...6.4
+5.1...6.6
+5.1...6.8
+5.1...7.0
+5.1...7.2
+5.1...7.3
+5.1...7.8
+5.1...8.0
+5.1...8.3
+5.1...8.7
+5.1...>7.0
+5.15
+5.2
+5.2...10.0
+5.2...10.8
+5.2...11.5
+5.2...5.3
+5.2...5.5
+5.2...5.7
+5.2...6.0
+5.2...6.2
+5.2...6.4
+5.2...6.7
+5.2...6.8
+5.2...6.9
+5.2...7.0
+5.2...7.3
+5.2...7.4
+5.2...7.5
+5.2...7.6
+5.2...7.7
+5.2...7.9
+5.2...8.0
+5.2...8.2
+5.2...8.4
+5.2...8.5
+5.2...8.7
+5.2...8.8
+5.2...9.0
+5.2...9.5
+5.2...9.6
+5.2...9.7
+5.2...9.9
+5.2...>10.0
+5.2...>11
+5.2...>12
+5.2...>6.5
+5.2...>7.0
+5.2...>7.5
+5.2...>8
+5.2...>8.0
+5.25...7.5
+5.25...8.5
+5.25...>12
+5.3
+5.3...
+5.3...10.0
+5.3...10.1
+5.3...10.2
+5.3...10.5
+5.3...10.6
+5.3...11.5
+5.3...13
+5.3...5.5
+5.3...5.8
+5.3...7.0
+5.3...7.2
+5.3...7.4
+5.3...7.5
+5.3...7.6
+5.3...7.8
+5.3...8.0
+5.3...8.2
+5.3...8.3
+5.3...8.6
+5.3...8.7
+5.3...8.8
+5.3...8.9
+5.3...9.0
+5.3...9.3
+5.3...9.5
+5.3...9.7
+5.3...9.9
+5.3...>7.8
+5.3...>9.0
+5.3...>90
+5.35
+5.4
+5.4...
+5.4...10
+5.4...10.5
+5.4...5.8
+5.4...6.8
+5.4...7.0
+5.4...7.1
+5.4...7.2
+5.4...7.3
+5.4...7.7
+5.4...7.8
+5.4...8.2
+5.4...8.5
+5.4...9.4
+5.4...>10.0
+5.4...>11.0
+5.4...>9.0
+5.45
+5.5
+5.5...
+5.5...10.0
+5.5...10.2
+5.5...10.5
+5.5...11
+5.5...11.5
+5.5...11.7
+5.5...12
+5.5...12.5
+5.5...13.5
+5.5...5.6
+5.5...5.7
+5.5...5.8
+5.5...6
+5.5...6.0
+5.5...6.2
+5.5...6.3
+5.5...6.5
+5.5...6.7
+5.5...6.8
+5.5...7.0
+5.5...7.1
+5.5...7.2
+5.5...7.3
+5.5...7.4
+5.5...7.5
+5.5...7.6
+5.5...7.7
+5.5...7.9
+5.5...8.0
+5.5...8.1
+5.5...8.2
+5.5...8.5
+5.5...8.6
+5.5...8.7
+5.5...9.0
+5.5...9.1
+5.5...9.3
+5.5...9.5
+5.5...9.7
+5.5...<6.8
+5.5...>10
+5.5...>10.0
+5.5...>11
+5.5...>11.0
+5.5...>12
+5.5...>7.0
+5.5...>8.0
+5.5...>9.0
+5.5...>9.5
+5.55
+5.55...7.8
+5.56
+5.6
+5.6...10
+5.6...10.1
+5.6...6.0
+5.6...6.2
+5.6...6.4
+5.6...6.6
+5.6...7.0
+5.6...7.1
+5.6...7.2
+5.6...7.3
+5.6...7.4
+5.6...7.5
+5.6...7.6
+5.6...7.7
+5.6...8.0
+5.6...8.3
+5.6...8.4
+5.6...8.5
+5.6...8.75
+5.6...8.8
+5.6...9
+5.6...9.0
+5.6...9.4
+5.6...9.5
+5.6...9.6
+5.6...>11
+5.6...>7.0
+5.6...>7.5
+5.6...>8.0
+5.6...>9.0
+5.65
+5.7
+5.7...
+5.7...10
+5.7...10.0
+5.7...11
+5.7...6.0
+5.7...6.2
+5.7...6.3
+5.7...6.5
+5.7...6.8
+5.7...7.0
+5.7...7.2
+5.7...7.3
+5.7...7.5
+5.7...7.6
+5.7...7.65
+5.7...7.7
+5.7...7.8
+5.7...7.9
+5.7...8.0
+5.7...8.4
+5.7...8.5
+5.7...8.7
+5.7...8.9
+5.7...9.0
+5.7...9.2
+5.7...9.4
+5.7...9.7
+5.7...>10.0
+5.7...>11
+5.7...>6.6
+5.7...>7.2
+5.7...>8.5
+5.7...>9.0
+5.73
+5.75
+5.75...7.3
+5.8
+5.8...10.0
+5.8...11
+5.8...6.0
+5.8...6.2
+5.8...6.5
+5.8...6.7
+5.8...6.8
+5.8...6.9
+5.8...7.0
+5.8...7.2
+5.8...7.3
+5.8...7.4
+5.8...7.5
+5.8...7.6
+5.8...7.7
+5.8...7.8
+5.8...8.0
+5.8...8.1
+5.8...8.2
+5.8...8.3
+5.8...8.4
+5.8...8.5
+5.8...8.6
+5.8...8.8
+5.8...9.0
+5.8...9.2
+5.8...9.3
+5.8...9.8
+5.8...>10.5
+5.8...>11
+5.8...>6.7
+5.8...>6.8
+5.8...>8.0
+5.8...>9.0
+5.85
+5.87
+5.9
+5.9...
+5.9...10.2
+5.9...6.0
+5.9...6.5
+5.9...7.3
+5.9...7.5
+5.9...7.7
+5.9...8.0
+5.9...8.2
+5.9...8.3
+5.9...8.4
+5.9...8.5
+5.9...8.7
+5.9...9.0
+5.9...>7.0
+5.9...>8.5
+5.92
+5.95...8.0
+6
+6...10
+6...11
+6...11.5
+6...6.5
+6...8
+6...8.0
+6...8.5
+6...9
+6...9.2
+6...9.3
+6...>10
+6...>12
+6...>7.2
+6...>8
+6.0
+6.0 
+6.0...10
+6.0...10.0
+6.0...10.2
+6.0...10.3
+6.0...10.4
+6.0...10.5
+6.0...11
+6.0...11.0
+6.0...11.5
+6.0...13
+6.0...6.2
+6.0...6.3
+6.0...6.4
+6.0...6.5
+6.0...6.6
+6.0...6.7
+6.0...6.8
+6.0...7.0
+6.0...7.2
+6.0...7.3
+6.0...7.4
+6.0...7.5
+6.0...7.6
+6.0...7.7
+6.0...7.8
+6.0...8.0
+6.0...8.1
+6.0...8.2
+6.0...8.3
+6.0...8.4
+6.0...8.5
+6.0...8.5 
+6.0...8.6
+6.0...8.7
+6.0...8.9
+6.0...9.0
+6.0...9.1
+6.0...9.2
+6.0...9.3
+6.0...9.4
+6.0...9.5
+6.0...9.7
+6.0...9.8
+6.0...9.9
+6.0...>10.0
+6.0...>10.5
+6.0...>11
+6.0...>7.0
+6.0...>7.5
+6.0...>8.0
+6.0...>8.2
+6.0...>8.5
+6.0...>8.7
+6.0...>9.0
+6.0...>9.5
+6.01
+6.1
+6.1...
+6.1...10
+6.1...10.8
+6.1...6.2
+6.1...6.6
+6.1...6.8
+6.1...6.9
+6.1...7.0
+6.1...7.2
+6.1...7.5
+6.1...7.6
+6.1...7.7
+6.1...7.8
+6.1...7.9
+6.1...8.0
+6.1...8.2
+6.1...8.5
+6.1...8.7
+6.1...8.9
+6.1...9.0
+6.1...9.3
+6.1...9.4
+6.1...>12
+6.1...>8.0
+6.1...>8.2
+6.1...>8.5
+6.1...>9.0
+6.1...>9.5
+6.15
+6.18
+6.2
+6.2...10
+6.2...10.0
+6.2...10.5
+6.2...11
+6.2...6.4
+6.2...6.5
+6.2...6.8
+6.2...6.9
+6.2...7.0
+6.2...7.2
+6.2...7.4
+6.2...7.5
+6.2...7.6
+6.2...7.7
+6.2...7.8
+6.2...8.0
+6.2...8.1
+6.2...8.2
+6.2...8.3
+6.2...8.4
+6.2...8.5
+6.2...8.6
+6.2...8.7
+6.2...8.8
+6.2...9.0
+6.2...9.1
+6.2...9.2
+6.2...9.5
+6.2...9.7
+6.2...9.8
+6.2...>10.5
+6.2...>11.5
+6.2...>7.1
+6.2...>7.8
+6.2...>8.0
+6.2...>9.0
+6.2...>9.5
+6.23...8.07
+6.24
+6.25
+6.25...7.5
+6.25...>9.0
+6.3
+6.3...
+6.3...10.0
+6.3...10.2
+6.3...10.4
+6.3...10.5
+6.3...6.4
+6.3...6.5
+6.3...6.6
+6.3...6.7
+6.3...6.8
+6.3...7.3
+6.3...7.5
+6.3...7.7
+6.3...7.8
+6.3...7.9
+6.3...8.0
+6.3...8.2
+6.3...8.3
+6.3...8.5
+6.3...8.6
+6.3...8.7
+6.3...8.9
+6.3...9.0
+6.3...9.1
+6.3...9.2
+6.3...9.3
+6.3...9.4
+6.3...9.5
+6.3...9.7
+6.3...9.8
+6.3...>10.0
+6.3...>11
+6.3...>7.5
+6.3...>7.8
+6.3...>8.0
+6.3...>8.1
+6.3...>8.3
+6.3...>8.5
+6.3...>9.0
+6.3...>9.2
+6.35
+6.4
+6.4...7.7
+6.4...10
+6.4...10.8
+6.4...6.7
+6.4...6.8
+6.4...7.0
+6.4...7.2
+6.4...7.4
+6.4...7.5
+6.4...7.6
+6.4...7.7
+6.4...7.8
+6.4...8.0
+6.4...8.1
+6.4...8.2
+6.4...8.3
+6.4...8.4
+6.4...8.6
+6.4...8.7
+6.4...8.8
+6.4...9.0
+6.4...9.3
+6.4...>10
+6.4...>11.0
+6.4...>7.8
+6.4...>8.0
+6.4...>8.5
+6.4...>8.6
+6.4...>9.0
+6.4...>9.1
+6.4...>9.2
+6.4...>9.5
+6.42
+6.5
+6.5 
+6.5...
+6.5...10
+6.5...10.0
+6.5...10.2
+6.5...10.3
+6.5...10.5
+6.5...11
+6.5...11.0
+6.5...11.5
+6.5...12.0
+6.5...6.7
+6.5...6.75
+6.5...6.8
+6.5...6.9
+6.5...7.0
+6.5...7.1
+6.5...7.3
+6.5...7.4
+6.5...7.5
+6.5...7.6
+6.5...7.7
+6.5...7.8
+6.5...7.9
+6.5...8.0
+6.5...8.1
+6.5...8.2
+6.5...8.25
+6.5...8.3
+6.5...8.4
+6.5...8.5
+6.5...8.6
+6.5...8.7
+6.5...8.8
+6.5...8.9
+6.5...9
+6.5...9.0
+6.5...9.2
+6.5...9.3
+6.5...9.5
+6.5...9.7
+6.5...9.8
+6.5...>10
+6.5...>10.0
+6.5...>11
+6.5...>11.0
+6.5...>12.0
+6.5...>7.0
+6.5...>7.9
+6.5...>8.0
+6.5...>8.3
+6.5...>8.5
+6.5...>8.7
+6.5...>8.8
+6.5...>9.0
+6.5...>9.5
+6.51
+6.55
+6.6
+6.6...
+6.6...7.0
+6.6...7.1
+6.6...7.3
+6.6...7.4
+6.6...7.5
+6.6...7.9
+6.6...8.3
+6.6...8.4
+6.6...8.5
+6.6...8.6
+6.6...8.7
+6.6...8.8
+6.6...8.9
+6.6...9.0
+6.6...9.4
+6.6...9.7
+6.6...9.8
+6.6...>10.0
+6.6...>10.3
+6.6...>11
+6.6...>9.0
+6.6...>9.5
+6.65...8.6
+6.67
+6.7
+6.7...
+6.7...10.2
+6.7...11.5
+6.7...6.8
+6.7...6.9
+6.7...7.0
+6.7...7.3
+6.7...7.4
+6.7...7.5
+6.7...7.6
+6.7...7.8
+6.7...8.0
+6.7...8.1
+6.7...8.2
+6.7...8.3
+6.7...8.5
+6.7...8.6
+6.7...8.7
+6.7...8.8
+6.7...8.9
+6.7...9.0
+6.7...9.1
+6.7...9.2
+6.7...9.5
+6.7...9.7
+6.7...9.8
+6.7...>10
+6.7...>7.0
+6.7...>7.5
+6.7...>8.0
+6.7...>8.5
+6.7...>8.6
+6.7...>9
+6.7...>9.0
+6.7...>9.3
+6.74...8.0
+6.75
+6.75...
+6.75...9.5
+6.75...>9
+6.75...>9.0
+6.75...>9.5
+6.76...8.10
+6.8 
+6.8...
+6.8...10
+6.8...10.0
+6.8...10.5
+6.8...6.9
+6.8...7.0
+6.8...7.1
+6.8...7.2
+6.8...7.3
+6.8...7.5
+6.8...7.6
+6.8...7.7
+6.8...7.8
+6.8...7.9
+6.8...8.0
+6.8...8.2
+6.8...8.25
+6.8...8.3
+6.8...8.5
+6.8...8.6
+6.8...8.7
+6.8...8.8
+6.8...8.9
+6.8...9.0
+6.8...9.1
+6.8...9.3
+6.8...9.4
+6.8...9.5
+6.8...9.6
+6.8...9.9
+6.8...>10.0
+6.8...>7.9
+6.8...>8.0
+6.8...>8.1
+6.8...>8.5
+6.8...>9.0
+6.8...>9.1
+6.80...>8.5
+6.81...7.53
+6.85
+6.86
+6.88
+6.9
+6.9...
+6.9...10.4
+6.9...12.2
+6.9...7.0
+6.9...7.1
+6.9...7.3
+6.9...7.6
+6.9...7.9
+6.9...8.0
+6.9...8.2
+6.9...8.4
+6.9...8.5
+6.9...8.6
+6.9...8.7
+6.9...8.8
+6.9...9.0
+6.9...9.1
+6.9...9.2
+6.9...9.5
+6.9...9.7
+6.9...>7.1
+6.9...>8
+6.9...>8.5
+6.9...>9
+6.9...>9.0
+6.9...>9.3
+6.9...>9.5
+6.9...>90
+7
+7...10
+7...10.5
+7...11
+7...7.5
+7...8
+7...8.5
+7...8.8
+7...9
+7...>10
+7...>10.5
+7...>9.5
+7.0
+7.0 
+7.0...
+7.0...10
+7.0...10.0
+7.0...10.2
+7.0...10.3
+7.0...10.5
+7.0...10.7
+7.0...11
+7.0...11.0
+7.0...11.5
+7.0...7.2
+7.0...7.2 
+7.0...7.3
+7.0...7.4
+7.0...7.5
+7.0...7.6
+7.0...7.8
+7.0...7.9
+7.0...8.0
+7.0...8.1
+7.0...8.2
+7.0...8.3
+7.0...8.4
+7.0...8.5
+7.0...8.6
+7.0...8.67
+7.0...8.7
+7.0...8.8
+7.0...8.9
+7.0...9.0
+7.0...9.1
+7.0...9.2
+7.0...9.3
+7.0...9.4
+7.0...9.5
+7.0...9.7
+7.0...9.75
+7.0...9.8
+7.0...9.9
+7.0...<8.0
+7.0...>10
+7.0...>10.0
+7.0...>10.5
+7.0...>11
+7.0...>11.5
+7.0...>7.8
+7.0...>8.5
+7.0...>8.7
+7.0...>9
+7.0...>9.0
+7.0...>9.5
+7.00
+7.01
+7.03
+7.05
+7.07
+7.1
+7.1...10.1
+7.1...10.3
+7.1...7.9
+7.1...8.1
+7.1...8.2
+7.1...8.3
+7.1...8.4
+7.1...8.6
+7.1...8.7
+7.1...8.9
+7.1...9.0
+7.1...9.2
+7.1...9.3
+7.1...9.4
+7.1...9.8
+7.1...>8.3
+7.1...>8.5
+7.1...>9.0
+7.1...>9.5
+7.10
+7.15
+7.15...8.3
+7.2
+7.2...10.0
+7.2...10.2
+7.2...10.5
+7.2...13.5
+7.2...7.3
+7.2...7.4
+7.2...7.5
+7.2...7.6
+7.2...7.8
+7.2...8.0
+7.2...8.2
+7.2...8.3
+7.2...8.6
+7.2...8.7
+7.2...8.8
+7.2...8.9
+7.2...9.0
+7.2...9.1
+7.2...9.2
+7.2...9.3
+7.2...9.5
+7.2...9.6
+7.2...9.7
+7.2...9.8
+7.2...>10
+7.2...>10.0
+7.2...>11
+7.2...>8.0
+7.2...>8.5
+7.2...>8.7
+7.2...>9.0
+7.2...>9.1
+7.2...>9.2
+7.2...>9.5
+7.24
+7.25
+7.25...7.75
+7.25...8.1
+7.25...8.25
+7.25...8.4
+7.25...8.6
+7.25...8.7
+7.25...9.25
+7.25...>10.0
+7.25...>8.0
+7.25...>8.25
+7.25...>9.0
+7.26
+7.3
+7.3...
+7.3...10.2
+7.3...10.5
+7.3...11
+7.3...7.5
+7.3...7.6
+7.3...7.8
+7.3...7.9
+7.3...8.0
+7.3...8.2
+7.3...8.3
+7.3...8.4
+7.3...8.5
+7.3...8.6
+7.3...8.8
+7.3...8.9
+7.3...9.0
+7.3...9.15
+7.3...9.2
+7.3...9.4
+7.3...9.5
+7.3...9.8
+7.3...9.9
+7.3...>10
+7.3...>10.0
+7.3...>10.5
+7.3...>7.8
+7.3...>8.0
+7.3...>8.3
+7.3...>9.0
+7.3...>9.2
+7.3...>9.3
+7.3...>9.5
+7.3...>9.75
+7.3...>90
+7.32
+7.35
+7.4
+7.4...
+7.4...10
+7.4...10.0
+7.4...12.1
+7.4...7.6
+7.4...7.8
+7.4...8.0
+7.4...8.2
+7.4...8.3
+7.4...8.4
+7.4...8.5
+7.4...8.6
+7.4...8.7
+7.4...8.8
+7.4...9.0
+7.4...9.2
+7.4...9.3
+7.4...9.6
+7.4...9.7
+7.4...9.8
+7.4...>10.0
+7.4...>8
+7.4...>8.5
+7.4...>8.6
+7.4...>8.7
+7.4...>9.0
+7.45
+7.5
+7.5 
+7.5...
+7.5...10
+7.5...10.0
+7.5...10.1
+7.5...10.2
+7.5...10.3
+7.5...10.5
+7.5...10.8
+7.5...11
+7.5...11.0
+7.5...11.5
+7.5...12.0
+7.5...7.6
+7.5...7.8
+7.5...8
+7.5...8.0
+7.5...8.1
+7.5...8.2
+7.5...8.4
+7.5...8.5
+7.5...8.6
+7.5...8.7
+7.5...9.0
+7.5...9.1
+7.5...9.2
+7.5...9.3
+7.5...9.4
+7.5...9.5
+7.5...9.6
+7.5...9.7
+7.5...9.8
+7.5...>10
+7.5...>10.0
+7.5...>10.5
+7.5...>11.0
+7.5...>8.3
+7.5...>8.5
+7.5...>8.7
+7.5...>8.75
+7.5...>9
+7.5...>9.0
+7.5...>9.2
+7.5...>9.5
+7.54
+7.55
+7.6
+7.6 
+7.6...10.3
+7.6...10.5
+7.6...7.8
+7.6...7.9
+7.6...8.0
+7.6...8.2
+7.6...8.3
+7.6...8.4
+7.6...8.5
+7.6...8.6
+7.6...8.8
+7.6...9.0
+7.6...9.2
+7.6...9.3
+7.6...9.4
+7.6...9.5
+7.6...9.7
+7.6...>10.0
+7.6...>10.3
+7.6...>10.5
+7.6...>11
+7.6...>8.25
+7.6...>8.8
+7.6...>9.0
+7.6...>9.5
+7.65
+7.7...
+7.7...10
+7.7...10.0
+7.7...10.3
+7.7...10.5
+7.7...11.0
+7.7...11.5
+7.7...7.8
+7.7...8.0
+7.7...8.3
+7.7...8.5
+7.7...8.7
+7.7...9.0
+7.7...9.25
+7.7...9.4
+7.7...9.5
+7.7...9.8
+7.7...>10.5
+7.7...>8.5
+7.7...>8.6
+7.7...>9.0
+7.7...>9.5
+7.72...8.7
+7.75
+7.75...
+7.75...8.1
+7.78
+7.8
+7.8...10.2
+7.8...7.9
+7.8...8.0
+7.8...8.1
+7.8...8.2
+7.8...8.4
+7.8...8.5
+7.8...8.7
+7.8...8.8
+7.8...8.9
+7.8...9.0
+7.8...9.2
+7.8...9.3
+7.8...9.4
+7.8...9.6
+7.8...<9.8
+7.8...>10.0
+7.8...>8.8
+7.8...>8.9
+7.8...>9.0
+7.8...>9.1
+7.8...>9.4
+7.80
+7.85
+7.9
+7.9...10.9
+7.9...8.1
+7.9...8.2
+7.9...8.3
+7.9...8.5
+7.9...8.6
+7.9...8.9
+7.9...9.0
+7.9...9.3
+7.96
+8
+8...10
+8...10.2
+8...10.5
+8...11.0
+8...8.5
+8...9
+8...>10
+8...>11
+8.0
+8.0...10
+8.0...10.0
+8.0...10.2
+8.0...10.3
+8.0...10.5
+8.0...10.8
+8.0...11.0
+8.0...11.2
+8.0...11.7
+8.0...12.0
+8.0...8.5
+8.0...8.12
+8.0...8.2
+8.0...8.4
+8.0...8.5
+8.0...8.6
+8.0...8.7
+8.0...8.8
+8.0...8.9
+8.0...9.0
+8.0...9.2
+8.0...9.4
+8.0...9.5
+8.0...9.7
+8.0...>10
+8.0...>10.0
+8.0...>10.5
+8.0...>11
+8.0...>13.0
+8.0...>8.75
+8.0...>9.0
+8.0...>9.2
+8.0...>9.5
+8.1
+8.1...10.5
+8.1...10.9
+8.1...8.2
+8.1...8.3
+8.1...8.4
+8.1...8.6
+8.1...8.7
+8.1...8.75
+8.1...8.9
+8.1...9.1
+8.1...9.9
+8.1...>9.5
+8.13
+8.15
+8.2
+8.2...
+8.2...10.2
+8.2...10.4
+8.2...8.4
+8.2...8.5
+8.2...8.8
+8.2...8.9
+8.2...9.0
+8.2...9.6
+8.2...9.8
+8.2...>10
+8.2...>10.5
+8.2...>11
+8.2...>11.0
+8.2...>8.8
+8.2...>9.3
+8.20
+8.25
+8.25...10.2
+8.27
+8.27...10
+8.28
+8.3
+8.3...
+8.3...10.2
+8.3...10.3
+8.3...10.8
+8.3...8.4
+8.3...8.5
+8.3...8.6
+8.3...8.8
+8.3...9.6
+8.3...9.9
+8.3...>9.5
+8.3...>9.8
+8.35
+8.4
+8.4...10.1
+8.4...8.5
+8.4...8.6
+8.4...8.7
+8.4...8.8
+8.4...8.9
+8.4...9.0
+8.4...9.2
+8.4...9.5
+8.4...<9.8
+8.4...>10.0
+8.4...>10.5
+8.4...>9.8
+8.48
+8.5
+8.5...
+8.5...10.0
+8.5...10.3
+8.5...10.5
+8.5...10.7
+8.5...10.8
+8.5...11
+8.5...11.0
+8.5...12.5
+8.5...8.6
+8.5...8.8
+8.5...9.0
+8.5...9.1
+8.5...9.2
+8.5...9.3
+8.5...9.4
+8.5...9.5
+8.5...9.9
+8.5...>10
+8.5...>11
+8.5...>11.5
+8.5...>9.5
+8.6
+8.6...10.2
+8.6...10.3
+8.6...11
+8.6...8.7
+8.6...8.8
+8.6...8.9
+8.6...9.4
+8.6...>11
+8.6...>99
+8.65
+8.7
+8.7...10.6
+8.7...11.2
+8.7...11.3
+8.7...11.7
+8.7...8.9
+8.7...9.1
+8.7...9.6
+8.7...9.8
+8.75
+8.8
+8.8...10.3
+8.8...10.7
+8.8...9.0
+8.8...9.2
+8.8...9.8
+8.8...>9.8
+8.9
+8.9...10.3
+8.9...10.4
+8.9...10.9
+8.9...11.5
+8.9...9.2
+9
+9.8
+9...10
+9...11
+9...>12
+9.0
+9.0...
+9.0...10
+9.0...10.0
+9.0...10.5
+9.0...10.7
+9.0...11
+9.0...11.0
+9.0...11.1
+9.0...11.2
+9.0...11.3
+9.0...11.5
+9.0...12
+9.0...9.2
+9.0...9.5
+9.0...>10.7
+9.0...>11.0
+9.1
+9.1...10
+9.1...10.1
+9.1...9.5
+9.15
+9.2
+9.2...10
+9.2...10.8
+9.2...12
+9.2...9.3
+9.2...9.4
+9.2...9.5
+9.2...9.6
+9.25
+9.3
+9.4
+9.4...10
+9.4...12.2
+9.4...9.7
+9.5
+9.5...
+9.5...10
+9.5...10.0
+9.5...10.4
+9.5...10.5
+9.5...10.6
+9.5...11.2
+9.5...9.8
+9.5...>10.2
+9.5...>10.5
+9.55
+9.6
+9.6...10
+9.6...10.2
+9.6...11.5
+9.6...>11.2
+9.63
+9.7
+9.7...11
+9.7...11.5
+9.7...9.8
+9.7...>12
+9.75
+9.76
+9.8
+9.8...10.0
+9.8...10.1
+9.8...>12.5
+9.9
+9.99
+10
+10...10.5
+10...11
+10.0
+10.0...10.4
+10.0...10.5
+10.0...11.25
+10.0...11.5
+10.0...12.5
+10.0...>12.5
+10.2
+10.2...11.8
+10.25
+10.3
+10.32
+10.4
+10.45
+10.5
+10.5...11.0
+10.5...11.5
+10.5...<13.5
+10.6
+10.7
+10.7...12.3
+10.70
+10.75
+10.8
+11
+11 
+11.0
+11.3
+11.5
+11.5...12.5
+11.75
+12
+12.0
+12.2
+14
+15
+16
+16.7
+17
+18
+19
+19.8
+20
+20.0
+22
+22 
+22.9
+23
+23...25
+23.7
+24
+24.0
diff --git a/contrib/seg/expected/seg.out b/contrib/seg/expected/seg.out
new file mode 100644
index 0000000000000000000000000000000000000000..9abfdc2ecb84f2f6632ab694fc62674279f31942
--- /dev/null
+++ b/contrib/seg/expected/seg.out
@@ -0,0 +1,1064 @@
+--
+--  Test seg datatype
+--
+--
+-- first, define the datatype.  Turn off echoing so that expected file
+-- does not depend on contents of seg.sql.
+--
+\set ECHO none
+--
+-- testing the input and output functions
+--
+-- Any number
+SELECT '1'::seg AS seg;
+ seg 
+-----
+ 1
+(1 row)
+
+SELECT '-1'::seg AS seg;
+ seg 
+-----
+ -1
+(1 row)
+
+SELECT '1.0'::seg AS seg;
+ seg 
+-----
+ 1.0
+(1 row)
+
+SELECT '-1.0'::seg AS seg;
+ seg  
+------
+ -1.0
+(1 row)
+
+SELECT '1e7'::seg AS seg;
+  seg  
+-------
+ 1e+07
+(1 row)
+
+SELECT '-1e7'::seg AS seg;
+  seg   
+--------
+ -1e+07
+(1 row)
+
+SELECT '1.0e7'::seg AS seg;
+   seg   
+---------
+ 1.0e+07
+(1 row)
+
+SELECT '-1.0e7'::seg AS seg;
+   seg    
+----------
+ -1.0e+07
+(1 row)
+
+SELECT '1e+7'::seg AS seg;
+  seg  
+-------
+ 1e+07
+(1 row)
+
+SELECT '-1e+7'::seg AS seg;
+  seg   
+--------
+ -1e+07
+(1 row)
+
+SELECT '1.0e+7'::seg AS seg;
+   seg   
+---------
+ 1.0e+07
+(1 row)
+
+SELECT '-1.0e+7'::seg AS seg;
+   seg    
+----------
+ -1.0e+07
+(1 row)
+
+SELECT '1e-7'::seg AS seg;
+  seg  
+-------
+ 1e-07
+(1 row)
+
+SELECT '-1e-7'::seg AS seg;
+  seg   
+--------
+ -1e-07
+(1 row)
+
+SELECT '1.0e-7'::seg AS seg;
+   seg   
+---------
+ 1.0e-07
+(1 row)
+
+SELECT '-1.0e-7'::seg AS seg;
+   seg    
+----------
+ -1.0e-07
+(1 row)
+
+SELECT '2e-6'::seg AS seg;
+  seg  
+-------
+ 2e-06
+(1 row)
+
+SELECT '2e-5'::seg AS seg;
+  seg  
+-------
+ 2e-05
+(1 row)
+
+SELECT '2e-4'::seg AS seg;
+  seg   
+--------
+ 0.0002
+(1 row)
+
+SELECT '2e-3'::seg AS seg;
+  seg  
+-------
+ 0.002
+(1 row)
+
+SELECT '2e-2'::seg AS seg;
+ seg  
+------
+ 0.02
+(1 row)
+
+SELECT '2e-1'::seg AS seg;
+ seg 
+-----
+ 0.2
+(1 row)
+
+SELECT '2e-0'::seg AS seg;
+ seg 
+-----
+ 2
+(1 row)
+
+SELECT '2e+0'::seg AS seg;
+ seg 
+-----
+ 2
+(1 row)
+
+SELECT '2e+1'::seg AS seg;
+ seg 
+-----
+ 2e1
+(1 row)
+
+SELECT '2e+2'::seg AS seg;
+ seg 
+-----
+ 2e2
+(1 row)
+
+SELECT '2e+3'::seg AS seg;
+ seg 
+-----
+ 2e3
+(1 row)
+
+SELECT '2e+4'::seg AS seg;
+ seg 
+-----
+ 2e4
+(1 row)
+
+SELECT '2e+5'::seg AS seg;
+  seg  
+-------
+ 2e+05
+(1 row)
+
+SELECT '2e+6'::seg AS seg;
+  seg  
+-------
+ 2e+06
+(1 row)
+
+-- Significant digits preserved
+SELECT '1'::seg AS seg;
+ seg 
+-----
+ 1
+(1 row)
+
+SELECT '1.0'::seg AS seg;
+ seg 
+-----
+ 1.0
+(1 row)
+
+SELECT '1.00'::seg AS seg;
+ seg  
+------
+ 1.00
+(1 row)
+
+SELECT '1.000'::seg AS seg;
+  seg  
+-------
+ 1.000
+(1 row)
+
+SELECT '1.0000'::seg AS seg;
+  seg   
+--------
+ 1.0000
+(1 row)
+
+SELECT '1.00000'::seg AS seg;
+   seg   
+---------
+ 1.00000
+(1 row)
+
+SELECT '1.000000'::seg AS seg;
+   seg   
+---------
+ 1.00000
+(1 row)
+
+SELECT '0.000000120'::seg AS seg;
+   seg    
+----------
+ 1.20e-07
+(1 row)
+
+SELECT '3.400e5'::seg AS seg;
+    seg    
+-----------
+ 3.400e+05
+(1 row)
+
+-- Digits truncated
+SELECT '12.34567890123456'::seg AS seg;
+   seg   
+---------
+ 12.3457
+(1 row)
+
+-- Numbers with certainty indicators
+SELECT '~6.5'::seg AS seg;
+ seg  
+------
+ ~6.5
+(1 row)
+
+SELECT '<6.5'::seg AS seg;
+ seg  
+------
+ <6.5
+(1 row)
+
+SELECT '>6.5'::seg AS seg;
+ seg  
+------
+ >6.5
+(1 row)
+
+SELECT '~ 6.5'::seg AS seg;
+ seg  
+------
+ ~6.5
+(1 row)
+
+SELECT '< 6.5'::seg AS seg;
+ seg  
+------
+ <6.5
+(1 row)
+
+SELECT '> 6.5'::seg AS seg;
+ seg  
+------
+ >6.5
+(1 row)
+
+-- Open intervals
+SELECT '0..'::seg AS seg;
+ seg  
+------
+ 0 ..
+(1 row)
+
+SELECT '0...'::seg AS seg;
+ seg  
+------
+ 0 ..
+(1 row)
+
+SELECT '0 ..'::seg AS seg;
+ seg  
+------
+ 0 ..
+(1 row)
+
+SELECT '0 ...'::seg AS seg;
+ seg  
+------
+ 0 ..
+(1 row)
+
+SELECT '..0'::seg AS seg;
+ seg  
+------
+ .. 0
+(1 row)
+
+SELECT '...0'::seg AS seg;
+ seg  
+------
+ .. 0
+(1 row)
+
+SELECT '.. 0'::seg AS seg;
+ seg  
+------
+ .. 0
+(1 row)
+
+SELECT '... 0'::seg AS seg;
+ seg  
+------
+ .. 0
+(1 row)
+
+-- Finite intervals
+SELECT '0 .. 1'::seg AS seg;
+  seg   
+--------
+ 0 .. 1
+(1 row)
+
+SELECT '-1 .. 0'::seg AS seg;
+   seg   
+---------
+ -1 .. 0
+(1 row)
+
+SELECT '-1 .. 1'::seg AS seg;
+   seg   
+---------
+ -1 .. 1
+(1 row)
+
+-- (+/-) intervals
+SELECT '0(+-)1'::seg AS seg;
+   seg   
+---------
+ -1 .. 1
+(1 row)
+
+SELECT '0(+-)1.0'::seg AS seg;
+     seg     
+-------------
+ -1.0 .. 1.0
+(1 row)
+
+SELECT '1.0(+-)0.005'::seg AS seg;
+      seg       
+----------------
+ 0.995 .. 1.005
+(1 row)
+
+SELECT '101(+-)1'::seg AS seg;
+       seg        
+------------------
+ 1.00e2 .. 1.02e2
+(1 row)
+
+-- incorrect number of significant digits in 99.0:
+SELECT '100(+-)1'::seg AS seg;
+      seg       
+----------------
+ 99.0 .. 1.01e2
+(1 row)
+
+-- invalid input
+SELECT ''::seg AS seg;
+ERROR:  seg_in: can't parse an empty string
+SELECT 'ABC'::seg AS seg;
+ERROR:  parse error, expecting `FLOAT' or `RANGE' or `EXTENSION' at or near position 1, character ('A', \101), input: 'ABC'
+
+SELECT '1ABC'::seg AS seg;
+ERROR:  expecting end of input at or near position 2, character ('A', \101), input: '1ABC'
+
+SELECT '1.'::seg AS seg;
+ERROR:  expecting end of input at or near position 2, character ('.', \056), input: '1.'
+
+SELECT '1.....'::seg AS seg;
+ERROR:  expecting end of input at or near position 6, character ('.', \056), input: '1.....'
+
+SELECT '.1'::seg AS seg;
+ERROR:  parse error, expecting `FLOAT' or `RANGE' or `EXTENSION' at or near position 2, character ('1', \061), input: '.1'
+
+SELECT '1..2.'::seg AS seg;
+ERROR:  expecting end of input at or near position 5, character ('.', \056), input: '1..2.'
+
+SELECT '1 e7'::seg AS seg;
+ERROR:  expecting end of input at or near position 3, character ('e', \145), input: '1 e7'
+
+SELECT '1e700'::seg AS seg;
+ERROR:  numeric value 1e700 unrepresentable
+--
+-- testing the  operators
+--
+-- equality/inequality:
+--
+SELECT '24 .. 33.20'::seg = '24 .. 33.20'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '24 .. 33.20'::seg = '24 .. 33.21'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '24 .. 33.20'::seg != '24 .. 33.20'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '24 .. 33.20'::seg != '24 .. 33.21'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+-- overlap
+--
+SELECT '1'::seg && '1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '1'::seg && '2'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 ..'::seg && '0 ..'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 1'::seg && '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '..0'::seg && '0..'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '-1 .. 0.1'::seg && '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '-1 .. 0'::seg && '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '-1 .. -0.0001'::seg && '0 .. 1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 ..'::seg && '1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 1'::seg && '1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 1'::seg && '2'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 2'::seg && '1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '1'::seg && '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '2'::seg && '0 .. 1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '1'::seg && '0 .. 2'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+-- overlap on the left
+--
+SELECT '1'::seg &< '0'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '1'::seg &< '1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '1'::seg &< '2'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 1'::seg &< '0'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 1'::seg &< '1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 1'::seg &< '2'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 1'::seg &< '0 .. 0.5'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 1'::seg &< '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 1'::seg &< '0 .. 2'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 1'::seg &< '1 .. 2'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 1'::seg &< '2 .. 3'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+-- overlap on the right
+--
+SELECT '0'::seg &> '1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '1'::seg &> '1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '2'::seg &> '1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0'::seg &> '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '1'::seg &> '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '2'::seg &> '0 .. 1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 0.5'::seg &> '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 1'::seg &> '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 2'::seg &> '0 .. 2'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '1 .. 2'::seg &> '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '2 .. 3'::seg &> '0 .. 1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+-- left
+--
+SELECT '1'::seg << '0'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '1'::seg << '1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '1'::seg << '2'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 1'::seg << '0'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 1'::seg << '1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 1'::seg << '2'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 1'::seg << '0 .. 0.5'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 1'::seg << '0 .. 1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 1'::seg << '0 .. 2'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 1'::seg << '1 .. 2'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 1'::seg << '2 .. 3'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+-- right
+--
+SELECT '0'::seg >> '1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '1'::seg >> '1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '2'::seg >> '1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0'::seg >> '0 .. 1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '1'::seg >> '0 .. 1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '2'::seg >> '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. 0.5'::seg >> '0 .. 1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 1'::seg >> '0 .. 1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0 .. 2'::seg >> '0 .. 2'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '1 .. 2'::seg >> '0 .. 1'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '2 .. 3'::seg >> '0 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+-- "contained in" (the left value belongs within the interval specified in the right value):
+--
+SELECT '0'::seg        ~ '0'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0'::seg        ~ '0 ..'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0'::seg        ~ '.. 0'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0'::seg        ~ '-1 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0'::seg        ~ '-1 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '-1'::seg       ~ '-1 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '1'::seg        ~ '-1 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '-1 .. 1'::seg  ~ '-1 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+-- "contains" (the left value contains the interval specified in the right value):
+--
+SELECT '0'::seg @ '0'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '0 .. '::seg ~ '0'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '.. 0'::seg ~ '0'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '-1 .. 1'::seg ~ '0'::seg AS bool;
+ bool 
+------
+ f
+(1 row)
+
+SELECT '0'::seg ~ '-1 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '-1'::seg ~ '-1 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+SELECT '1'::seg ~ '-1 .. 1'::seg AS bool;
+ bool 
+------
+ t
+(1 row)
+
+-- Load some example data and build the index
+-- 
+CREATE TABLE test_seg (s seg);
+\copy test_seg from 'data/test_seg.data'
+CREATE INDEX test_seg_ix ON test_seg USING gist (s);
+SELECT count(*) FROM test_seg WHERE s @ '11..11.3';
+ count 
+-------
+   143
+(1 row)
+
+-- Test sorting 
+SELECT * FROM test_seg WHERE s @ '11..11.3' GROUP BY s;
+        s        
+-----------------
+ .. 4.0e1
+ .. >8.2e1
+ .. 9.0e1
+ <1.0 .. >13.0
+ 1.3 .. 12.0
+ 2.0 .. 11.5
+ 2.1 .. 11.8
+ <2.3 ..
+ >2.3 ..
+ 2.4 .. 11.3
+ 2.5 .. 11.5
+ 2.5 .. 11.8
+ 2.6 ..
+ 2.7 .. 12.0
+ <3.0 ..
+ 3 .. 5.8e1
+ 3.1 .. 11.5
+ 3.5 .. 11.5
+ 3.5 .. 12.2
+ <4.0 .. >1.2e1
+ <4.0 ..
+ 4 .. 1.2e1
+ 4.0 .. 11.7
+ 4.0 .. 12.5
+ 4.0 .. 13.0
+ 4.0 .. 6.0e1
+ 4.0 ..
+ 4.2 .. 11.5
+ 4.2 .. 11.7
+ <4.5 .. >1.2e1
+ 4.5 .. 11.5
+ 4.5 .. <1.2e1
+ 4.5 .. >1.2e1
+ 4.5 .. 12.5
+ 4.5 .. 1.15e2
+ 4.7 .. 11.8
+ 4.8 .. 11.5
+ 4.8 .. 11.6
+ 4.8 .. 12.5
+ 4.8 ..
+ 4.9 .. >1.2e1
+ 4.9 ..
+ 5 .. 11.5
+ 5 .. 1.2e1
+ 5 .. 3.0e1
+ 5.0 .. 11.4
+ 5.0 .. 11.5
+ 5.0 .. 11.6
+ 5.0 .. 11.7
+ 5.0 .. 12.0
+ 5.0 .. >12.0
+ 5.0 .. >1.2e1
+ 5.2 .. 11.5
+ 5.2 .. >1.2e1
+ 5.25 .. >1.2e1
+ 5.3 .. 11.5
+ 5.3 .. 1.3e1
+ 5.3 .. >9.0e1
+ 5.3 ..
+ 5.4 ..
+ 5.5 .. 11.5
+ 5.5 .. 11.7
+ 5.5 .. 1.2e1
+ 5.5 .. >1.2e1
+ 5.5 .. 12.5
+ 5.5 .. 13.5
+ 5.5 ..
+ >5.5 ..
+ 5.7 ..
+ 5.9 ..
+ 6 .. 11.5
+ 6 .. >1.2e1
+ 6.0 .. 11.5
+ 6.0 .. 1.3e1
+ >6.0 .. <11.5
+ 6.1 .. >1.2e1
+ 6.1 ..
+ 6.2 .. >11.5
+ 6.3 ..
+ 6.5 .. 11.5
+ 6.5 .. 12.0
+ 6.5 .. >12.0
+ 6.5 ..
+ 6.6 ..
+ 6.7 .. 11.5
+ 6.7 ..
+ 6.75 ..
+ 6.8 ..
+ 6.9 .. 12.2
+ 6.9 .. >9.0e1
+ 6.9 ..
+ <7.0 .. >11.5
+ 7.0 .. 11.5
+ 7.0 .. >11.5
+ 7.0 ..
+ >7.15 ..
+ 7.2 .. 13.5
+ 7.3 .. >9.0e1
+ 7.3 ..
+ >7.3 ..
+ 7.4 .. 12.1
+ 7.4 ..
+ 7.5 .. 11.5
+ 7.5 .. 12.0
+ 7.5 ..
+ 7.7 .. 11.5
+ 7.7 ..
+ 7.75 ..
+ 8.0 .. 11.7
+ 8.0 .. 12.0
+ 8.0 .. >13.0
+ 8.2 ..
+ 8.3 ..
+ 8.5 .. >11.5
+ 8.5 .. 12.5
+ 8.5 ..
+ 8.6 .. >9.9e1
+ 8.7 .. 11.3
+ 8.7 .. 11.7
+ 8.9 .. 11.5
+ 9 .. >1.2e1
+ 9.0 .. 11.3
+ 9.0 .. 11.5
+ 9.0 .. 1.2e1
+ 9.0 ..
+ 9.2 .. 1.2e1
+ 9.4 .. 12.2
+ <9.5 .. 1.2e1
+ <9.5 .. >12.2
+ 9.5 ..
+ 9.6 .. 11.5
+ 9.7 .. 11.5
+ 9.7 .. >1.2e1
+ 9.8 .. >12.5
+ <1.0e1 .. >11.6
+ 10.0 .. 11.5
+ 10.0 .. 12.5
+ 10.0 .. >12.5
+ 10.2 .. 11.8
+ <10.5 .. 11.5
+ 10.5 .. 11.5
+ 10.5 .. <13.5
+ 10.7 .. 12.3
+(143 rows)
+
diff --git a/contrib/seg/seg-validate.pl b/contrib/seg/seg-validate.pl
new file mode 100755
index 0000000000000000000000000000000000000000..9272936aef2c0588865eb0655cddf9816e2054f3
--- /dev/null
+++ b/contrib/seg/seg-validate.pl
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+$integer = '[+-]?[0-9]+';
+$real    = '[+-]?[0-9]+\.[0-9]+';
+
+$RANGE   = '(\.\.)(\.)?';
+$PLUMIN  = q(\'\+\-\');
+$FLOAT   = "(($integer)|($real))([eE]($integer))?";
+$EXTENSION = '<|>|~';
+
+$boundary = "($EXTENSION)?$FLOAT";
+$deviation = $FLOAT;
+
+$rule_1 = $boundary . $PLUMIN . $deviation;
+$rule_2 = $boundary . $RANGE . $boundary;
+$rule_3 = $boundary . $RANGE;
+$rule_4 = $RANGE . $boundary;
+$rule_5 = $boundary;
+
+
+print "$rule_5\n";
+while (<>) {
+#  s/ +//g;
+  if ( /^($rule_1)$/ ) {
+    print;
+  }
+  elsif ( /^($rule_2)$/ ) {
+    print;
+  }
+  elsif ( /^($rule_3)$/ ) {
+    print;
+  }
+  elsif ( /^($rule_4)$/ ) {
+    print;
+  }
+  elsif ( /^($rule_5)$/ ) {
+    print;
+  }
+  else {
+    print STDERR "error in $_\n";
+  }
+
+}
diff --git a/contrib/seg/seg.c b/contrib/seg/seg.c
new file mode 100644
index 0000000000000000000000000000000000000000..1609b42b1eaa11c90dba7e8d197ecc6898edece8
--- /dev/null
+++ b/contrib/seg/seg.c
@@ -0,0 +1,1049 @@
+/******************************************************************************
+  This file contains routines that can be bound to a Postgres backend and
+  called by the backend in the process of processing queries.  The calling
+  format for these routines is dictated by Postgres architecture.
+******************************************************************************/
+
+#include "postgres.h"
+
+#include <float.h>
+
+#include "access/gist.h"
+#include "access/rtree.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+#include "utils/builtins.h"
+
+#include "segdata.h"
+
+#define max(a,b)        ((a) >  (b) ? (a) : (b))
+#define min(a,b)        ((a) <= (b) ? (a) : (b))
+#define abs(a)          ((a) <  (0) ? (-a) : (a))
+
+/* 
+#define GIST_DEBUG
+#define GIST_QUERY_DEBUG 
+*/
+
+extern void  set_parse_buffer(char *str);
+extern int   seg_yyparse();
+/*
+extern int   seg_yydebug;
+*/
+
+/*
+** Input/Output routines
+*/
+SEG *        seg_in(char *str);
+char *       seg_out(SEG *seg);
+float32      seg_lower(SEG *seg);
+float32      seg_upper(SEG *seg);
+float32      seg_center(SEG *seg);
+
+/* 
+** GiST support methods
+*/
+bool             gseg_consistent(GISTENTRY *entry, SEG *query, StrategyNumber strategy);
+GISTENTRY *      gseg_compress(GISTENTRY *entry);
+GISTENTRY *      gseg_decompress(GISTENTRY *entry);
+float *          gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result);
+GIST_SPLITVEC *  gseg_picksplit(bytea *entryvec, GIST_SPLITVEC *v);
+bool             gseg_leaf_consistent(SEG *key, SEG *query, StrategyNumber strategy);
+bool             gseg_internal_consistent(SEG *key, SEG *query, StrategyNumber strategy);
+SEG *            gseg_union(bytea *entryvec, int *sizep);
+SEG *            gseg_binary_union(SEG *r1, SEG *r2, int *sizep);
+bool *           gseg_same(SEG *b1, SEG *b2, bool *result);
+
+
+/*
+** R-tree suport functions
+*/
+bool     seg_same(SEG *a, SEG *b);
+bool     seg_contains_int(SEG *a, int *b);
+bool     seg_contains_float4(SEG *a, float4 *b);
+bool     seg_contains_float8(SEG *a, float8 *b);
+bool     seg_contains(SEG *a, SEG *b);
+bool     seg_contained(SEG *a, SEG *b);
+bool     seg_overlap(SEG *a, SEG *b);
+bool     seg_left(SEG *a, SEG *b);
+bool     seg_over_left(SEG *a, SEG *b);
+bool     seg_right(SEG *a, SEG *b);
+bool     seg_over_right(SEG *a, SEG *b);
+SEG *    seg_union(SEG *a, SEG *b);
+SEG *    seg_inter(SEG *a, SEG *b);
+void     rt_seg_size(SEG *a, float* sz);
+float *  seg_size(SEG *a);
+
+/*
+** Various operators
+*/
+int32    seg_cmp(SEG *a, SEG *b);
+bool     seg_lt(SEG *a, SEG *b);
+bool     seg_le(SEG *a, SEG *b);
+bool     seg_gt(SEG *a, SEG *b);
+bool     seg_ge(SEG *a, SEG *b);
+bool     seg_different(SEG *a, SEG *b);
+
+/* 
+** Auxiliary funxtions
+*/
+static int    restore(char *s, float val, int n);
+int    significant_digits (char* s);
+
+
+/*****************************************************************************
+ * Input/Output functions
+ *****************************************************************************/
+
+SEG *
+seg_in(char *str)
+{
+  SEG * result = palloc(sizeof(SEG));
+  set_parse_buffer( str );
+  
+  /*
+  seg_yydebug = 1;
+  */
+  if ( seg_yyparse(result) != 0 ) {
+    pfree ( result );
+    return NULL;
+  }  
+  return ( result );
+}
+
+/*
+ * You might have noticed a slight inconsistency between the following
+ * declaration and the SQL definition:
+ *     CREATE FUNCTION seg_out(opaque) RETURNS opaque ...
+ * The reason is that the argument passed into seg_out is really just a
+ * pointer. POSTGRES thinks all output functions are:
+ *     char *out_func(char *);
+ */
+char *
+seg_out(SEG *seg)
+{
+    char *result;
+    char *p;
+
+    if (seg == NULL) return(NULL);
+
+    p = result = (char *) palloc(40);
+
+    if ( seg->l_ext == '>' || seg->l_ext == '<' || seg->l_ext == '~' ) {
+      p += sprintf(p, "%c", seg->l_ext);
+    }
+      
+    if ( seg->lower == seg->upper && seg->l_ext == seg->u_ext ) {
+      /* indicates that this interval was built by seg_in off a single point */
+      p += restore(p, seg->lower, seg->l_sigd);
+    }
+    else {
+      if ( seg->l_ext != '-' ) {
+	/* print the lower boudary if exists */
+	p += restore(p, seg->lower, seg->l_sigd);
+	p += sprintf(p, " ");
+      }
+      p += sprintf(p, "..");
+      if ( seg->u_ext != '-' ) {
+	/* print the upper boudary if exists */
+	p += sprintf(p, " ");
+	if ( seg->u_ext == '>' || seg->u_ext == '<' || seg->l_ext == '~' ) {
+	  p += sprintf(p, "%c", seg->u_ext);
+	}
+	p += restore(p, seg->upper, seg->u_sigd);
+      }
+    }
+
+    return(result);
+}
+
+float32
+seg_center(SEG *seg)
+{
+        float32 result = (float32) palloc(sizeof(float32data));
+
+        if (!seg)
+                return (float32) NULL;
+
+        *result = ((float)seg->lower + (float)seg->upper)/2.0;
+        return (result);
+}
+
+float32
+seg_lower(SEG *seg)
+{
+        float32 result = (float32) palloc(sizeof(float32data));
+
+        if (!seg)
+                return (float32) NULL;
+
+        *result = (float)seg->lower;
+        return (result);
+}
+
+float32
+seg_upper(SEG *seg)
+{
+        float32 result = (float32) palloc(sizeof(float32data));
+
+        if (!seg)
+                return (float32) NULL;
+
+        *result = (float)seg->upper;
+        return (result);
+}
+
+
+/*****************************************************************************
+ *                         GiST functions
+ *****************************************************************************/
+
+/*
+** The GiST Consistent method for segments
+** Should return false if for all data items x below entry,
+** the predicate x op query == FALSE, where op is the oper
+** corresponding to strategy in the pg_amop table.
+*/
+bool 
+gseg_consistent(GISTENTRY *entry,
+	       SEG *query,
+	       StrategyNumber strategy)
+{
+    /*
+    ** if entry is not leaf, use gseg_internal_consistent,
+    ** else use gseg_leaf_consistent
+    */
+    if (GIST_LEAF(entry))
+      return(gseg_leaf_consistent((SEG *)(entry->pred), query, strategy));
+    else
+      return(gseg_internal_consistent((SEG *)(entry->pred), query, strategy));
+}
+
+/*
+** The GiST Union method for segments
+** returns the minimal bounding seg that encloses all the entries in entryvec
+*/
+SEG *
+gseg_union(bytea *entryvec, int *sizep)
+{
+    int numranges, i;
+    SEG *out = (SEG *)NULL;
+    SEG *tmp;
+
+#ifdef GIST_DEBUG
+    fprintf(stderr, "union\n");
+#endif
+
+    numranges = (VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY); 
+    tmp = (SEG *)(((GISTENTRY *)(VARDATA(entryvec)))[0]).pred;
+    *sizep = sizeof(SEG);
+
+    for (i = 1; i < numranges; i++) {
+	out = gseg_binary_union(tmp, (SEG *)
+				 (((GISTENTRY *)(VARDATA(entryvec)))[i]).pred,
+				 sizep);
+#ifdef GIST_DEBUG
+	/*
+	fprintf(stderr, "\t%s ^ %s -> %s\n", seg_out(tmp), seg_out((SEG *)(((GISTENTRY *)(VARDATA(entryvec)))[i]).pred), seg_out(out));
+	*/
+#endif
+
+	if (i > 1) pfree(tmp);
+	tmp = out;
+    }
+
+    return(out);
+}
+
+/*
+** GiST Compress and Decompress methods for segments
+** do not do anything.
+*/
+GISTENTRY *
+gseg_compress(GISTENTRY *entry)
+{
+    return(entry);
+}
+
+GISTENTRY *
+gseg_decompress(GISTENTRY *entry)
+{
+    return(entry);
+}
+
+/*
+** The GiST Penalty method for segments
+** As in the R-tree paper, we use change in area as our penalty metric
+*/
+float *
+gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
+{
+    Datum ud;
+    float tmp1, tmp2;
+    
+    ud = (Datum)seg_union((SEG *)(origentry->pred), (SEG *)(newentry->pred));
+    rt_seg_size((SEG *)ud, &tmp1);
+    rt_seg_size((SEG *)(origentry->pred), &tmp2);
+    *result = tmp1 - tmp2;
+    pfree((char *)ud);
+
+#ifdef GIST_DEBUG
+    fprintf(stderr, "penalty\n");
+    fprintf(stderr, "\t%g\n", *result);
+#endif
+
+    return(result);
+}
+
+
+
+/*
+** The GiST PickSplit method for segments
+** We use Guttman's poly time split algorithm 
+*/
+GIST_SPLITVEC *
+gseg_picksplit(bytea *entryvec,
+	      GIST_SPLITVEC *v)
+{
+    OffsetNumber i, j;
+    SEG *datum_alpha, *datum_beta;
+    SEG *datum_l, *datum_r;
+    SEG *union_d, *union_dl, *union_dr;
+    SEG *inter_d;
+    bool firsttime;
+    float size_alpha, size_beta, size_union, size_inter;
+    float size_waste, waste;
+    float size_l, size_r;
+    int nbytes;
+    OffsetNumber seed_1 = 0, seed_2 = 0;
+    OffsetNumber *left, *right;
+    OffsetNumber maxoff;
+
+#ifdef GIST_DEBUG
+    fprintf(stderr, "picksplit\n");
+#endif
+
+    maxoff = ((VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY)) - 2;
+    nbytes =  (maxoff + 2) * sizeof(OffsetNumber);
+    v->spl_left = (OffsetNumber *) palloc(nbytes);
+    v->spl_right = (OffsetNumber *) palloc(nbytes);
+    
+    firsttime = true;
+    waste = 0.0;
+    
+    for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i)) {
+	datum_alpha = (SEG *)(((GISTENTRY *)(VARDATA(entryvec)))[i].pred);
+	for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j)) {
+	    datum_beta = (SEG *)(((GISTENTRY *)(VARDATA(entryvec)))[j].pred);
+	    
+	    /* compute the wasted space by unioning these guys */
+	    /* size_waste = size_union - size_inter; */
+	    union_d = (SEG *)seg_union(datum_alpha, datum_beta);
+	    rt_seg_size(union_d, &size_union);
+	    inter_d = (SEG *)seg_inter(datum_alpha, datum_beta);
+	    rt_seg_size(inter_d, &size_inter);
+	    size_waste = size_union - size_inter;
+	    
+	    pfree(union_d);
+	    
+	    if (inter_d != (SEG *) NULL)
+		pfree(inter_d);
+	    
+	    /*
+	     *  are these a more promising split that what we've
+	     *  already seen?
+	     */
+	    
+	    if (size_waste > waste || firsttime) {
+		waste = size_waste;
+		seed_1 = i;
+		seed_2 = j;
+		firsttime = false;
+	    }
+	}
+    }
+    
+    left = v->spl_left;
+    v->spl_nleft = 0;
+    right = v->spl_right;
+    v->spl_nright = 0;
+    
+    datum_alpha = (SEG *)(((GISTENTRY *)(VARDATA(entryvec)))[seed_1].pred);
+    datum_l = (SEG *)seg_union(datum_alpha, datum_alpha);
+    rt_seg_size((SEG *)datum_l, &size_l);
+    datum_beta = (SEG *)(((GISTENTRY *)(VARDATA(entryvec)))[seed_2].pred);;
+    datum_r = (SEG *)seg_union(datum_beta, datum_beta);
+    rt_seg_size((SEG *)datum_r, &size_r);
+    
+    /*
+     *  Now split up the regions between the two seeds.  An important
+     *  property of this split algorithm is that the split vector v
+     *  has the indices of items to be split in order in its left and
+     *  right vectors.  We exploit this property by doing a merge in
+     *  the code that actually splits the page.
+     *
+     *  For efficiency, we also place the new index tuple in this loop.
+     *  This is handled at the very end, when we have placed all the
+     *  existing tuples and i == maxoff + 1.
+     */
+    
+    maxoff = OffsetNumberNext(maxoff);
+    for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
+	
+	/*
+	 *  If we've already decided where to place this item, just
+	 *  put it on the right list.  Otherwise, we need to figure
+	 *  out which page needs the least enlargement in order to
+	 *  store the item.
+	 */
+	
+	if (i == seed_1) {
+	    *left++ = i;
+	    v->spl_nleft++;
+	    continue;
+	} else if (i == seed_2) {
+	    *right++ = i;
+	    v->spl_nright++;
+	    continue;
+	}
+	
+	/* okay, which page needs least enlargement? */ 
+	datum_alpha = (SEG *)(((GISTENTRY *)(VARDATA(entryvec)))[i].pred);
+	union_dl = (SEG *)seg_union(datum_l, datum_alpha);
+	union_dr = (SEG *)seg_union(datum_r, datum_alpha);
+	rt_seg_size((SEG *)union_dl, &size_alpha);
+	rt_seg_size((SEG *)union_dr, &size_beta);
+	
+	/* pick which page to add it to */
+	if (size_alpha - size_l < size_beta - size_r) {
+	    pfree(datum_l);
+	    pfree(union_dr);
+	    datum_l = union_dl;
+	    size_l = size_alpha;
+	    *left++ = i;
+	    v->spl_nleft++;
+	} else {
+	    pfree(datum_r);
+	    pfree(union_dl);
+	    datum_r = union_dr;
+	    size_r = size_alpha;
+	    *right++ = i;
+	    v->spl_nright++;
+	}
+    }
+    *left = *right = FirstOffsetNumber;	/* sentinel value, see dosplit() */
+    
+    v->spl_ldatum = (char *)datum_l;
+    v->spl_rdatum = (char *)datum_r;
+
+    return v;
+}
+
+/*
+** Equality methods
+*/
+bool *
+gseg_same(SEG *b1, SEG *b2, bool *result)
+{
+  if (seg_same(b1, b2))
+    *result = TRUE;
+  else *result = FALSE;
+
+#ifdef GIST_DEBUG
+  fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE" ));
+#endif
+
+  return(result);
+}
+
+/* 
+** SUPPORT ROUTINES
+*/
+bool 
+gseg_leaf_consistent(SEG *key,
+		     SEG *query,
+		     StrategyNumber strategy)
+{
+    bool retval;
+
+#ifdef GIST_QUERY_DEBUG
+  fprintf(stderr, "leaf_consistent, %d\n", strategy);
+#endif
+
+    switch(strategy) {
+    case RTLeftStrategyNumber:
+      retval = (bool)seg_left(key, query);
+      break;
+    case RTOverLeftStrategyNumber:
+      retval = (bool)seg_over_left(key,query);
+      break;
+    case RTOverlapStrategyNumber:
+      retval = (bool)seg_overlap(key, query);
+      break;
+    case RTOverRightStrategyNumber:
+      retval = (bool)seg_over_right(key, query);
+      break;
+    case RTRightStrategyNumber:
+      retval = (bool)seg_right(key, query);
+      break;
+    case RTSameStrategyNumber:
+      retval = (bool)seg_same(key, query);
+      break;
+    case RTContainsStrategyNumber:
+      retval = (bool)seg_contains(key, query);
+      break;
+    case RTContainedByStrategyNumber:
+      retval = (bool)seg_contained(key,query);
+      break;
+    default:
+      retval = FALSE;
+    }
+    return(retval);
+}
+
+bool 
+gseg_internal_consistent(SEG *key,
+			SEG *query,
+			StrategyNumber strategy)
+{
+    bool retval;
+
+#ifdef GIST_QUERY_DEBUG
+  fprintf(stderr, "internal_consistent, %d\n", strategy);
+#endif
+
+    switch(strategy) {
+    case RTLeftStrategyNumber:
+    case RTOverLeftStrategyNumber:
+      retval = (bool)seg_over_left(key,query);
+      break;
+    case RTOverlapStrategyNumber:
+      retval = (bool)seg_overlap(key, query);
+      break;
+    case RTOverRightStrategyNumber:
+    case RTRightStrategyNumber:
+      retval = (bool)seg_right(key, query);
+      break;
+    case RTSameStrategyNumber:
+    case RTContainsStrategyNumber:
+      retval = (bool)seg_contains(key, query);
+      break;
+    case RTContainedByStrategyNumber:
+      retval = (bool)seg_overlap(key, query);
+      break;
+    default:
+      retval = FALSE;
+    }
+    return(retval);
+}
+
+SEG *
+gseg_binary_union(SEG *r1, SEG *r2, int *sizep)
+{
+    SEG *retval;
+
+    retval = seg_union(r1, r2);
+    *sizep = sizeof(SEG);
+
+    return (retval);
+}
+
+
+bool
+seg_contains(SEG *a, SEG *b)
+{
+  return ( (a->lower <= b->lower) && (a->upper >= b->upper) );
+}
+
+bool
+seg_contained(SEG *a, SEG *b)
+{
+  return ( seg_contains(b, a) );
+}
+
+/*****************************************************************************
+ * Operator class for R-tree indexing
+ *****************************************************************************/
+
+bool
+seg_same(SEG *a, SEG *b)
+{
+  return seg_cmp(a, b) == 0;
+}
+
+/*  seg_overlap -- does a overlap b?
+ */
+bool
+seg_overlap(SEG *a, SEG *b)
+{
+  return (
+	  ((a->upper >= b->upper) && (a->lower <= b->upper)) 
+	  ||
+	  ((b->upper >= a->upper) && (b->lower <= a->upper))
+	  );
+}
+
+/*  seg_overleft -- is the right edge of (a) located to the left of the right edge of (b)?
+ */
+bool
+seg_over_left(SEG *a, SEG *b)
+{
+        return ( a->upper <= b->upper && !seg_left(a, b) && !seg_right(a, b));
+}
+
+/*  seg_left -- is (a) entirely on the left of (b)?
+ */
+bool
+seg_left(SEG *a, SEG *b)
+{
+        return ( a->upper < b->lower );
+}
+
+/*  seg_right -- is (a) entirely on the right of (b)?
+ */
+bool
+seg_right(SEG *a, SEG *b)
+{
+        return ( a->lower > b->upper );
+}
+
+/*  seg_overright -- is the left edge of (a) located to the right of the left edge of (b)?
+ */
+bool
+seg_over_right(SEG *a, SEG *b)
+{
+        return (a->lower >= b->lower && !seg_left(a, b) && !seg_right(a, b));
+}
+
+
+SEG *
+seg_union(SEG *a, SEG *b)
+{
+  SEG *n;
+  
+  n = (SEG *) palloc(sizeof(*n));
+
+  /* take max of upper endpoints */
+  if (a->upper > b->upper)
+  {
+	  n->upper = a->upper;
+	  n->u_sigd = a->u_sigd;
+	  n->u_ext = a->u_ext;
+  }
+  else
+  {
+	  n->upper = b->upper;
+	  n->u_sigd = b->u_sigd;
+	  n->u_ext = b->u_ext;
+  }
+
+  /* take min of lower endpoints */
+  if (a->lower < b->lower)
+  {
+	  n->lower = a->lower;
+	  n->l_sigd = a->l_sigd;
+	  n->l_ext = a->l_ext;
+  }
+  else
+  {
+	  n->lower = b->lower;
+	  n->l_sigd = b->l_sigd;
+	  n->l_ext = b->l_ext;
+  }
+
+  return (n);
+}
+
+
+SEG *
+seg_inter(SEG *a, SEG *b)
+{
+  SEG *n;
+  
+  n = (SEG *) palloc(sizeof(*n));
+
+  /* take min of upper endpoints */
+  if (a->upper < b->upper)
+  {
+	  n->upper = a->upper;
+	  n->u_sigd = a->u_sigd;
+	  n->u_ext = a->u_ext;
+  }
+  else
+  {
+	  n->upper = b->upper;
+	  n->u_sigd = b->u_sigd;
+	  n->u_ext = b->u_ext;
+  }
+
+  /* take max of lower endpoints */
+  if (a->lower > b->lower)
+  {
+	  n->lower = a->lower;
+	  n->l_sigd = a->l_sigd;
+	  n->l_ext = a->l_ext;
+  }
+  else
+  {
+	  n->lower = b->lower;
+	  n->l_sigd = b->l_sigd;
+	  n->l_ext = b->l_ext;
+  }
+
+  return (n);
+}
+
+void
+rt_seg_size(SEG *a, float *size)
+{
+  if (a == (SEG *) NULL || a->upper <= a->lower)
+    *size = 0.0;
+  else
+    *size = (float) abs(a->upper - a->lower);
+  
+  return;
+}
+
+float *
+seg_size(SEG *a)
+{
+  float *result;
+
+  result = (float *) palloc(sizeof(float));
+  
+  *result = (float) abs(a->upper - a->lower);
+
+  return(result);
+}
+
+
+/*****************************************************************************
+ *                 Miscellaneous operators
+ *****************************************************************************/
+int32
+seg_cmp(SEG *a, SEG *b)
+{
+	/*
+	 * First compare on lower boundary position
+	 */
+	if ( a->lower < b->lower )
+		return -1;
+	if ( a->lower > b->lower )
+		return 1;
+	/*
+	 * a->lower == b->lower, so consider type of boundary.
+	 *
+	 * A '-' lower bound is < any other kind (this could only be relevant
+	 * if -HUGE is used as a regular data value).
+	 * A '<' lower bound is < any other kind except '-'.
+	 * A '>' lower bound is > any other kind.
+	 */
+	if ( a->l_ext != b->l_ext )
+	{
+		if ( a->l_ext == '-')
+			return -1;
+		if ( b->l_ext == '-')
+			return 1;
+		if ( a->l_ext == '<')
+			return -1;
+		if ( b->l_ext == '<')
+			return 1;
+		if ( a->l_ext == '>')
+			return 1;
+		if ( b->l_ext == '>')
+			return -1;
+	}
+	/*
+	 * For other boundary types, consider # of significant digits first.
+	 */
+	if ( a->l_sigd < b->l_sigd ) /* (a) is blurred and is likely to include (b) */
+		return -1;
+	if ( a->l_sigd > b->l_sigd ) /* (a) is less blurred and is likely to be included in (b) */
+		return 1;
+	/*
+	 * For same # of digits, an approximate boundary is more blurred than
+	 * exact.
+	 */
+	if ( a->l_ext != b->l_ext )
+	{
+		if ( a->l_ext == '~' ) /* (a) is approximate, while (b) is exact */
+			return -1;
+		if ( b->l_ext == '~' )
+			return 1;
+		/* can't get here unless data is corrupt */
+		elog(ERROR, "seg_cmp: bogus lower boundary types %d %d",
+			 (int) a->l_ext, (int) b->l_ext);
+	}
+
+	/* at this point, the lower boundaries are identical */
+
+	/*
+	 * First compare on upper boundary position
+	 */
+	if ( a->upper < b->upper )
+		return -1;
+	if ( a->upper > b->upper )
+		return 1;
+	/*
+	 * a->upper == b->upper, so consider type of boundary.
+	 *
+	 * A '-' upper bound is > any other kind (this could only be relevant
+	 * if HUGE is used as a regular data value).
+	 * A '<' upper bound is < any other kind.
+	 * A '>' upper bound is > any other kind except '-'.
+	 */
+	if ( a->u_ext != b->u_ext )
+	{
+		if ( a->u_ext == '-')
+			return 1;
+		if ( b->u_ext == '-')
+			return -1;
+		if ( a->u_ext == '<')
+			return -1;
+		if ( b->u_ext == '<')
+			return 1;
+		if ( a->u_ext == '>')
+			return 1;
+		if ( b->u_ext == '>')
+			return -1;
+	}
+	/*
+	 * For other boundary types, consider # of significant digits first.
+	 * Note result here is converse of the lower-boundary case.
+	 */
+	if ( a->u_sigd < b->u_sigd ) /* (a) is blurred and is likely to include (b) */
+		return 1;
+	if ( a->u_sigd > b->u_sigd ) /* (a) is less blurred and is likely to be included in (b) */
+		return -1;
+	/*
+	 * For same # of digits, an approximate boundary is more blurred than
+	 * exact.  Again, result is converse of lower-boundary case.
+	 */
+	if ( a->u_ext != b->u_ext )
+	{
+		if ( a->u_ext == '~' ) /* (a) is approximate, while (b) is exact */
+			return 1;
+		if ( b->u_ext == '~' )
+			return -1;
+		/* can't get here unless data is corrupt */
+		elog(ERROR, "seg_cmp: bogus upper boundary types %d %d",
+			 (int) a->u_ext, (int) b->u_ext);
+	}
+
+	return 0;
+}
+
+bool
+seg_lt(SEG *a, SEG *b)
+{
+  return seg_cmp(a, b) < 0;
+}
+
+bool
+seg_le(SEG *a, SEG *b)
+{
+  return seg_cmp(a, b) <= 0;
+}
+
+bool
+seg_gt(SEG *a, SEG *b)
+{
+  return seg_cmp(a, b) > 0;
+}
+
+
+bool
+seg_ge(SEG *a, SEG *b)
+{
+  return seg_cmp(a, b) >= 0;
+}
+
+bool
+seg_different(SEG *a, SEG *b)
+{
+  return seg_cmp(a, b) != 0;
+}
+
+
+
+/*****************************************************************************
+ *                 Auxiliary functions
+ *****************************************************************************/
+
+/* The purpose of this routine is to print the floating point
+ * value with exact number of significant digits. Its behaviour
+ * is similar to %.ng except it prints 8.00 where %.ng would
+ * print 8
+ */
+static int restore ( char * result, float val, int n )
+{
+  static char efmt[8] = {'%', '-', '1', '5', '.', '#', 'e', 0};
+  char buf[25] = {
+    '0', '0', '0', '0', '0',
+    '0', '0', '0', '0', '0',
+    '0', '0', '0', '0', '0',
+    '0', '0', '0', '0', '0',
+    '0', '0', '0', '0', '\0'
+  };
+  char *p;
+  char *mant;
+  int exp;
+  int i, dp, sign;
+ 
+  /* put a cap on the number of siugnificant digits to avoid
+     nonsense in the output */
+  n = min(n, FLT_DIG);
+
+  /* remember the sign */
+  sign = ( val < 0 ? 1 : 0 );
+
+  efmt[5] = '0' + (n-1)%10; /* makes %-15.(n-1)e -- this format guarantees that 
+			     the exponent is always present */
+
+  sprintf(result, efmt, val);
+
+  /* trim the spaces left by the %e */
+  for( p = result; *p != ' '; p++ ); *p = '\0';
+
+  /* get the exponent */
+  mant = (char *)strtok( strdup(result), "e" );
+  exp = atoi(strtok( NULL, "e" ));
+
+  if ( exp == 0 ) {
+    /* use the supplied mantyssa with sign */
+    strcpy((char *)index(result, 'e'), "");
+  }
+  else {
+    if ( abs( exp ) <= 4 ) {
+      /* remove the decimal point from the mantyssa and write the digits to the buf array */
+      for( p = result + sign, i = 10, dp = 0; *p != 'e'; p++, i++ ) {
+	buf[i] = *p;
+	if( *p == '.' ) {
+	  dp = i--; /* skip the decimal point */
+	}
+      }
+      if (dp == 0) dp = i--; /* no decimal point was found in the above for() loop */
+  
+      if ( exp > 0 ) {
+	if ( dp - 10 + exp >= n ) { 
+	  /* 
+	     the decimal point is behind the last significant digit;
+	     the digits in between must be converted to the exponent
+	     and the decimal point placed after the first digit
+	   */
+	  exp = dp - 10 + exp - n;
+	  buf[10+n] = '\0'; 
+	  
+	  /* insert the decimal point */
+	  if ( n > 1 ) {
+	    dp = 11;
+	    for ( i = 23; i > dp; i-- ) {
+	      buf[i] = buf[i-1];
+	    }
+	    buf[dp] = '.';
+	  }
+	  
+	  /* adjust the exponent by the number of digits after the decimal point */
+	  if ( n > 1 ) {
+	    sprintf(&buf[11+n], "e%d", exp + n - 1);
+	  }
+	  else {
+	    sprintf(&buf[11], "e%d", exp + n - 1);
+	  }
+	  
+	  if ( sign ) {
+	    buf[9] = '-'; 
+	    strcpy(result, &buf[9]);
+	  }
+	  else {
+	    strcpy(result, &buf[10]);
+	  }
+	}
+	else { /* insert the decimal point */
+	  dp += exp;
+	  for ( i = 23; i > dp; i-- ) {
+	    buf[i] = buf[i-1];
+	  }
+	  buf[11+n] = '\0';
+	  buf[dp] = '.';
+	  if ( sign ) {
+	    buf[9] = '-';
+	    strcpy(result, &buf[9]);
+	  }
+	  else {
+	    strcpy(result, &buf[10]);
+	  }
+	}
+      }
+      else { /* exp <= 0 */
+	dp += exp - 1;
+	buf[10+n] = '\0'; 
+	buf[dp] = '.'; 
+	if ( sign ) {
+	  buf[dp-2] = '-'; 
+	  strcpy(result, &buf[dp-2]);
+	}
+	else {
+	  strcpy(result, &buf[dp-1]);
+	}   
+      }
+    }
+
+    /* do nothing for abs(exp) > 4; %e must be OK */
+    /* just get rid of zeroes after [eE]- and +zeroes after [Ee]. */
+    
+    /* ... this is not done yet. */
+  }
+  return ( strlen ( result ) );
+}
+
+
+/*
+** Miscellany
+*/
+
+bool
+seg_contains_int(SEG *a, int *b)
+{
+  return ( (a->lower <= *b) && (a->upper >= *b) );
+}
+
+bool
+seg_contains_float4(SEG *a, float4 *b)
+{
+  return ( (a->lower <= *b) && (a->upper >= *b) );
+}
+
+bool
+seg_contains_float8(SEG *a, float8 *b)
+{
+  return ( (a->lower <= *b) && (a->upper >= *b) );
+}
+
+/* find out the number of significant digits in a string representing 
+ * a floating point number
+ */
+int significant_digits ( char* s )
+{
+  char * p = s;
+  int n, c, zeroes;
+
+  zeroes = 1;
+  /* skip leading zeroes and sign */
+  for ( c = *p; (c == '0' || c == '+' || c == '-') && c != 0; c = *(++p) );
+
+  /* skip decimal point and following zeroes */
+  for ( c = *p; (c == '0' || c == '.' ) && c != 0; c = *(++p) ) {
+    if ( c != '.') zeroes++;
+  }
+
+  /* count significant digits (n) */
+  for ( c = *p, n = 0; c != 0; c = *(++p) ) {
+    if ( !( (c >= '0' && c <= '9') || (c == '.') ) ) break;
+    if ( c != '.') n++;
+  }
+
+  if (!n) return ( zeroes );
+
+  return( n );
+}
diff --git a/contrib/seg/seg.sql.in b/contrib/seg/seg.sql.in
new file mode 100644
index 0000000000000000000000000000000000000000..387989f74282a883ed69dc26a2cf4ddf097ac86d
--- /dev/null
+++ b/contrib/seg/seg.sql.in
@@ -0,0 +1,361 @@
+-- Create the user-defined type for 1-D floating point intervals (seg)
+-- 
+BEGIN TRANSACTION;
+
+CREATE FUNCTION seg_in(opaque)
+RETURNS opaque
+AS 'MODULE_PATHNAME'
+LANGUAGE 'c';
+
+CREATE FUNCTION seg_out(opaque)
+RETURNS opaque
+AS 'MODULE_PATHNAME'
+LANGUAGE 'c';
+
+CREATE TYPE seg (
+internallength = 12,
+input = seg_in,
+output = seg_out
+);
+
+COMMENT ON TYPE seg IS
+'floating point interval ''FLOAT .. FLOAT'', ''.. FLOAT'', ''FLOAT ..'' or ''FLOAT''';
+
+--
+-- External C-functions for R-tree methods
+--
+
+-- Left/Right methods
+
+CREATE FUNCTION seg_over_left(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_over_left(seg, seg) IS
+'is over and left of';
+
+CREATE FUNCTION seg_over_right(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_over_right(seg, seg) IS
+'is over and right of';
+
+CREATE FUNCTION seg_left(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_left(seg, seg) IS
+'is left of';
+
+CREATE FUNCTION seg_right(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_right(seg, seg) IS
+'is right of';
+
+
+-- Comparison methods
+
+CREATE FUNCTION seg_lt(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_lt(seg, seg) IS
+'less than';
+
+CREATE FUNCTION seg_le(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_le(seg, seg) IS
+'less than or equal';
+
+CREATE FUNCTION seg_gt(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_gt(seg, seg) IS
+'greater than';
+
+CREATE FUNCTION seg_ge(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_ge(seg, seg) IS
+'greater than or equal';
+
+CREATE FUNCTION seg_contains(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_contains(seg, seg) IS
+'contains';
+
+CREATE FUNCTION seg_contained(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_contained(seg, seg) IS
+'contained in';
+
+CREATE FUNCTION seg_overlap(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_overlap(seg, seg) IS
+'overlaps';
+
+CREATE FUNCTION seg_same(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_same(seg, seg) IS
+'same as';
+
+CREATE FUNCTION seg_different(seg, seg) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+COMMENT ON FUNCTION seg_different(seg, seg) IS
+'different';
+
+-- support routines for indexing
+
+CREATE FUNCTION seg_union(seg, seg) RETURNS seg
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION seg_inter(seg, seg) RETURNS seg
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION seg_size(seg) RETURNS float4
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+-- miscellaneous
+
+CREATE FUNCTION seg_upper(seg) RETURNS float4
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION seg_lower(seg) RETURNS float4
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+
+--
+-- OPERATORS
+--
+
+CREATE OPERATOR < (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_lt,
+   COMMUTATOR = '>', NEGATOR = '>=',
+   RESTRICT = scalarltsel, JOIN = scalarltjoinsel
+);
+
+CREATE OPERATOR <= (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_le,
+   COMMUTATOR = '>=', NEGATOR = '>',
+   RESTRICT = scalarltsel, JOIN = scalarltjoinsel
+);
+
+CREATE OPERATOR > (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_gt,
+   COMMUTATOR = '<', NEGATOR = '<=',
+   RESTRICT = scalargtsel, JOIN = scalargtjoinsel
+);
+
+CREATE OPERATOR >= (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_ge,
+   COMMUTATOR = '<=', NEGATOR = '<',
+   RESTRICT = scalargtsel, JOIN = scalargtjoinsel
+);
+
+CREATE OPERATOR << (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_left,
+   COMMUTATOR = '>>',
+   RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+CREATE OPERATOR &< (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_over_left,
+   COMMUTATOR = '&>',
+   RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+CREATE OPERATOR && (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_overlap,
+   COMMUTATOR = '&&',
+   RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+CREATE OPERATOR &> (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_over_right,
+   COMMUTATOR = '&<',
+   RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+CREATE OPERATOR >> (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_right,
+   COMMUTATOR = '<<',
+   RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+CREATE OPERATOR = (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_same,
+   COMMUTATOR = '=', NEGATOR = '<>',
+   RESTRICT = eqsel, JOIN = eqjoinsel,
+   SORT1 = '<', SORT2 = '<'
+);
+
+CREATE OPERATOR <> (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_different,
+   COMMUTATOR = '<>', NEGATOR = '=',
+   RESTRICT = neqsel, JOIN = neqjoinsel
+);
+
+CREATE OPERATOR @ (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_contains,
+   COMMUTATOR = '~',
+   RESTRICT = contsel, JOIN = contjoinsel
+);
+
+CREATE OPERATOR ~ (
+   LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_contained,
+   COMMUTATOR = '@',
+   RESTRICT = contsel, JOIN = contjoinsel
+);
+
+
+-- define the GiST support methods
+CREATE FUNCTION gseg_consistent(opaque,seg,int4) RETURNS bool
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION gseg_compress(opaque) RETURNS opaque 
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION gseg_decompress(opaque) RETURNS opaque 
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION gseg_penalty(opaque,opaque,opaque) RETURNS opaque
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION gseg_picksplit(opaque, opaque) RETURNS opaque
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION gseg_union(bytea, opaque) RETURNS seg 
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION gseg_same(seg, seg, opaque) RETURNS opaque 
+	AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+
+-- register the default opclass for indexing
+INSERT INTO pg_opclass (opcname, opcdeftype)
+   SELECT 'gist_seg_ops', oid
+   FROM pg_type
+   WHERE typname = 'seg';
+
+
+-- get the comparators for segments and store them in a tmp table
+SELECT o.oid AS opoid, o.oprname
+INTO TABLE seg_ops_tmp
+FROM pg_operator o, pg_type t
+WHERE o.oprleft = t.oid and o.oprright = t.oid
+   and t.typname = 'seg';
+
+-- make sure we have the right operators
+-- SELECT * from seg_ops_tmp;
+
+-- using the tmp table, generate the amop entries 
+
+-- seg_left
+INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
+   SELECT am.oid, opcl.oid, c.opoid, 1
+   FROM pg_am am, pg_opclass opcl, seg_ops_tmp c
+   WHERE amname = 'gist' and opcname = 'gist_seg_ops' 
+      and c.oprname = '<<';
+
+-- seg_overleft
+INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
+   SELECT am.oid, opcl.oid, c.opoid, 2
+   FROM pg_am am, pg_opclass opcl, seg_ops_tmp c
+   WHERE amname = 'gist' and opcname = 'gist_seg_ops' 
+      and c.oprname = '&<';
+
+-- seg_overlap
+INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
+   SELECT am.oid, opcl.oid, c.opoid, 3
+   FROM pg_am am, pg_opclass opcl, seg_ops_tmp c
+   WHERE amname = 'gist' and opcname = 'gist_seg_ops' 
+      and c.oprname = '&&';
+
+-- seg_overright
+INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
+   SELECT am.oid, opcl.oid, c.opoid, 4
+   FROM pg_am am, pg_opclass opcl, seg_ops_tmp c
+   WHERE amname = 'gist' and opcname = 'gist_seg_ops' 
+      and c.oprname = '&>';
+
+-- seg_right
+INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
+   SELECT am.oid, opcl.oid, c.opoid, 5
+   FROM pg_am am, pg_opclass opcl, seg_ops_tmp c
+   WHERE amname = 'gist' and opcname = 'gist_seg_ops' 
+      and c.oprname = '>>';
+
+-- seg_same
+INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
+   SELECT am.oid, opcl.oid, c.opoid, 6
+   FROM pg_am am, pg_opclass opcl, seg_ops_tmp c
+   WHERE amname = 'gist' and opcname = 'gist_seg_ops' 
+      and c.oprname = '=';
+
+-- seg_contains
+INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
+   SELECT am.oid, opcl.oid, c.opoid, 7
+   FROM pg_am am, pg_opclass opcl, seg_ops_tmp c
+   WHERE amname = 'gist' and opcname = 'gist_seg_ops' 
+      and c.oprname = '@';
+
+-- seg_contained
+INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
+   SELECT am.oid, opcl.oid, c.opoid, 8
+   FROM pg_am am, pg_opclass opcl, seg_ops_tmp c
+   WHERE amname = 'gist' and opcname = 'gist_seg_ops' 
+      and c.oprname = '~';
+
+DROP TABLE seg_ops_tmp;
+
+
+-- add the entries to amproc for the support methods
+-- note the amprocnum numbers associated with each are specific!
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 1
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist_seg_ops'
+      and proname = 'gseg_consistent';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 2
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist_seg_ops'
+      and proname = 'gseg_union';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 3
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist_seg_ops'
+      and proname = 'gseg_compress';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 4
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist_seg_ops'
+      and proname = 'gseg_decompress';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 5
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist_seg_ops'
+      and proname = 'gseg_penalty';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 6
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist_seg_ops'
+      and proname = 'gseg_picksplit';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 7
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist_seg_ops'
+      and proname = 'gseg_same';
+
+END TRANSACTION;
diff --git a/contrib/seg/segdata.h b/contrib/seg/segdata.h
new file mode 100644
index 0000000000000000000000000000000000000000..709f576340c0109c2b5cb62c80648e878d21d5e7
--- /dev/null
+++ b/contrib/seg/segdata.h
@@ -0,0 +1,8 @@
+typedef struct SEG {
+  float lower;
+  float upper;
+  char  l_sigd;
+  char  u_sigd;  
+  char  l_ext;
+  char  u_ext;  
+} SEG;
diff --git a/contrib/seg/segparse.y b/contrib/seg/segparse.y
new file mode 100644
index 0000000000000000000000000000000000000000..adce19c517874b61de0d9dc5b3922d91ca99462b
--- /dev/null
+++ b/contrib/seg/segparse.y
@@ -0,0 +1,183 @@
+%{
+#define YYERROR_VERBOSE   
+#define YYPARSE_PARAM result  /* need this to pass a pointer (void *) to yyparse */
+  
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include "segdata.h"
+#include "buffer.h"
+  
+#include "postgres.h"
+#include "utils/elog.h"
+  
+#undef yylex                  /* falure to redefine yylex will result in calling the */
+#define yylex seg_yylex       /* wrong scanner when running inside postgres backend  */
+
+  extern int errno;
+  extern int yylex();           /* defined as seg_yylex in segscan.c */
+  extern int significant_digits( char *str );    /* defined in seg.c */
+  
+  int seg_yyerror( char *msg );
+  int seg_yyparse( void *result );
+
+  float seg_atof( char *value );
+
+#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+#define ABS(X) ((X) < 0 ? (-X) : (X))
+
+  long threshold;
+  char strbuf[25] = {
+    '0', '0', '0', '0', '0',
+    '0', '0', '0', '0', '0',
+    '0', '0', '0', '0', '0',
+    '0', '0', '0', '0', '0',
+    '0', '0', '0', '0', '\0'
+  };
+
+%}
+
+/* BISON Declarations */
+%union {
+  struct BND {
+    float val;
+    char  ext;
+    char  sigd;
+  } bnd;
+  char * text;
+}
+%token <text> FLOAT
+%token <text> RANGE
+%token <text> PLUMIN
+%token <text> EXTENSION
+%type  <bnd>  boundary
+%type  <bnd>  deviation
+%start range
+
+/* Grammar follows */
+%%
+
+
+range:
+          boundary PLUMIN deviation {
+	    ((SEG *)result)->lower = $1.val - $3.val;
+	    ((SEG *)result)->upper = $1.val + $3.val;
+	    sprintf(strbuf, "%g", ((SEG *)result)->lower);
+	    ((SEG *)result)->l_sigd = MAX(MIN(6, significant_digits(strbuf)), MAX($1.sigd, $3.sigd));
+	    sprintf(strbuf, "%g", ((SEG *)result)->upper);
+	    ((SEG *)result)->u_sigd = MAX(MIN(6, significant_digits(strbuf)), MAX($1.sigd, $3.sigd));
+	    ((SEG *)result)->l_ext = '\0';
+	    ((SEG *)result)->u_ext = '\0';
+          }
+      |
+          boundary RANGE boundary {
+	    ((SEG *)result)->lower = $1.val;
+	    ((SEG *)result)->upper = $3.val;
+	    if ( ((SEG *)result)->lower > ((SEG *)result)->upper ) {
+	      reset_parse_buffer();     
+	      elog(ERROR, "swapped boundaries: %g is greater than %g", ((SEG *)result)->lower, ((SEG *)result)->upper );
+	      YYERROR;
+	    }
+	    ((SEG *)result)->l_sigd = $1.sigd;
+	    ((SEG *)result)->u_sigd = $3.sigd;
+	    ((SEG *)result)->l_ext = ( $1.ext ? $1.ext : '\0' );
+	    ((SEG *)result)->u_ext = ( $3.ext ? $3.ext : '\0' );
+          }
+      |
+          boundary RANGE {
+	    ((SEG *)result)->lower = $1.val;
+	    ((SEG *)result)->upper = HUGE;
+	    ((SEG *)result)->l_sigd = $1.sigd;
+	    ((SEG *)result)->u_sigd = 0;
+	    ((SEG *)result)->l_ext = ( $1.ext ? $1.ext : '\0' );
+	    ((SEG *)result)->u_ext = '-';
+          }
+      ;
+      |
+          RANGE boundary {
+	    ((SEG *)result)->lower = -HUGE;
+	    ((SEG *)result)->upper = $2.val;
+	    ((SEG *)result)->l_sigd = 0;
+	    ((SEG *)result)->u_sigd = $2.sigd;
+	    ((SEG *)result)->l_ext = '-';
+	    ((SEG *)result)->u_ext = ( $2.ext ? $2.ext : '\0' );
+          }
+      |
+          boundary {
+	    ((SEG *)result)->lower = ((SEG *)result)->upper = $1.val;
+	    ((SEG *)result)->l_sigd = ((SEG *)result)->u_sigd = $1.sigd;
+	    ((SEG *)result)->l_ext = ((SEG *)result)->u_ext = ( $1.ext ? $1.ext : '\0' );
+          }
+      ;
+
+boundary:
+          FLOAT {
+             $$.ext = '\0';
+	     $$.sigd = significant_digits($1);
+             $$.val = seg_atof($1);
+	  }
+      | 
+	  EXTENSION FLOAT {
+             $$.ext = $1[0];
+	     $$.sigd = significant_digits($2);
+             $$.val = seg_atof($2);
+	  }
+      ;
+
+deviation:
+          FLOAT {
+             $$.ext = '\0';
+	     $$.sigd = significant_digits($1);
+             $$.val = seg_atof($1);
+	  }
+      ;
+
+%%
+
+
+float seg_atof ( char *value ) {
+  float result;
+  char *buf = (char *) palloc(256);
+
+  errno = 0;
+  sscanf(value, "%f", &result);
+
+  if ( errno ) {
+    sprintf(buf, "numeric value %s unrepresentable", value);
+    reset_parse_buffer();     
+    elog(ERROR, buf);
+  }
+
+  return result;
+}
+
+
+int seg_yyerror ( char *msg ) {
+  char *buf = (char *) palloc(256);
+  int position;
+
+  yyclearin;
+
+  if ( !strcmp(msg, "parse error, expecting `$'") ) {
+    msg = "expecting end of input";
+  }
+
+  position = parse_buffer_pos() > parse_buffer_size() ? parse_buffer_pos() - 1 : parse_buffer_pos();
+
+  sprintf(
+	  buf, 
+	  "%s at or near position %d, character ('%c', \\%03o), input: '%s'\n", 
+	  msg,
+	  position,
+	  parse_buffer()[position - 1],
+	  parse_buffer()[position - 1],
+	  parse_buffer()
+	  );
+
+  reset_parse_buffer();     
+  elog(ERROR, buf);
+  return 0;
+}
+
+
diff --git a/contrib/seg/segscan.l b/contrib/seg/segscan.l
new file mode 100644
index 0000000000000000000000000000000000000000..ea9032685a9d990fbeddc1a19131ca8d6fc871db
--- /dev/null
+++ b/contrib/seg/segscan.l
@@ -0,0 +1,53 @@
+%{
+/* 
+** A scanner for EMP-style numeric ranges 
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include "segparse.h"
+#include "buffer.h"
+
+#define YY_NO_UNPUT 1
+#undef  yywrap
+
+/* flex screws a couple symbols when used with the -P otion; fix those */
+#define YY_DECL int seg_yylex YY_PROTO(( void )); \
+int seg_yylex YY_PROTO(( void ))
+#define yylval seg_yylval
+
+/* redefined YY_INPUT reads byte-wise from the memory area defined in buffer.c */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+{ \
+        int c = read_parse_buffer(); \
+        result = (c == '\0') ?  YY_NULL : (buf[0] = c, 1); \
+}
+
+void seg_flush_scanner_buffer(void); 
+%}
+
+range        (\.\.)(\.)?
+plumin       (\'\+\-\')|(\(\+\-)\)
+integer      [+-]?[0-9]+
+real         [+-]?[0-9]+\.[0-9]+
+float        ({integer}|{real})([eE]{integer})?
+
+%%
+
+{range}      yylval.text = yytext; return RANGE;
+{plumin}     yylval.text = yytext; return PLUMIN;
+{float}      yylval.text = yytext; return FLOAT;
+\<           yylval.text = "<"; return EXTENSION;
+\>           yylval.text = ">"; return EXTENSION;
+\~           yylval.text = "~"; return EXTENSION;
+[ ]+         /* discard spaces */
+.            return yytext[0]; /* alert parser of the garbage */
+
+%%
+
+int seg_yylex();
+
+void seg_flush_scanner_buffer(void) {
+  YY_FLUSH_BUFFER;
+}
diff --git a/contrib/seg/sort-segments.pl b/contrib/seg/sort-segments.pl
new file mode 100755
index 0000000000000000000000000000000000000000..1205d3b972275ee909808926267d0b5277fb2654
--- /dev/null
+++ b/contrib/seg/sort-segments.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+
+# this script will sort any table with the segment data type in its last column
+
+while (<>) {
+  chomp;
+  push @rows, $_;
+}
+
+foreach ( sort { 
+  @ar = split("\t", $a);
+  $valA = pop @ar;
+  $valA =~ s/[~<> ]+//g;
+  @ar = split("\t", $b);
+  $valB = pop @ar;
+  $valB =~ s/[~<> ]+//g;
+  $valA <=> $valB
+} @rows ) {
+  print "$_\n";;
+}
diff --git a/contrib/seg/sql/seg.sql b/contrib/seg/sql/seg.sql
new file mode 100644
index 0000000000000000000000000000000000000000..95394c95d04a0935d86f024b7c4741daba0bea52
--- /dev/null
+++ b/contrib/seg/sql/seg.sql
@@ -0,0 +1,223 @@
+--
+--  Test seg datatype
+--
+
+--
+-- first, define the datatype.  Turn off echoing so that expected file
+-- does not depend on contents of seg.sql.
+--
+\set ECHO none
+\i seg.sql
+\set ECHO all
+
+--
+-- testing the input and output functions
+--
+
+-- Any number
+SELECT '1'::seg AS seg;
+SELECT '-1'::seg AS seg;
+SELECT '1.0'::seg AS seg;
+SELECT '-1.0'::seg AS seg;
+SELECT '1e7'::seg AS seg;
+SELECT '-1e7'::seg AS seg;
+SELECT '1.0e7'::seg AS seg;
+SELECT '-1.0e7'::seg AS seg;
+SELECT '1e+7'::seg AS seg;
+SELECT '-1e+7'::seg AS seg;
+SELECT '1.0e+7'::seg AS seg;
+SELECT '-1.0e+7'::seg AS seg;
+SELECT '1e-7'::seg AS seg;
+SELECT '-1e-7'::seg AS seg;
+SELECT '1.0e-7'::seg AS seg;
+SELECT '-1.0e-7'::seg AS seg;
+SELECT '2e-6'::seg AS seg;
+SELECT '2e-5'::seg AS seg;
+SELECT '2e-4'::seg AS seg;
+SELECT '2e-3'::seg AS seg;
+SELECT '2e-2'::seg AS seg;
+SELECT '2e-1'::seg AS seg;
+SELECT '2e-0'::seg AS seg;
+SELECT '2e+0'::seg AS seg;
+SELECT '2e+1'::seg AS seg;
+SELECT '2e+2'::seg AS seg;
+SELECT '2e+3'::seg AS seg;
+SELECT '2e+4'::seg AS seg;
+SELECT '2e+5'::seg AS seg;
+SELECT '2e+6'::seg AS seg;
+
+
+-- Significant digits preserved
+SELECT '1'::seg AS seg;
+SELECT '1.0'::seg AS seg;
+SELECT '1.00'::seg AS seg;
+SELECT '1.000'::seg AS seg;
+SELECT '1.0000'::seg AS seg;
+SELECT '1.00000'::seg AS seg;
+SELECT '1.000000'::seg AS seg;
+SELECT '0.000000120'::seg AS seg;
+SELECT '3.400e5'::seg AS seg;
+
+-- Digits truncated
+SELECT '12.34567890123456'::seg AS seg;
+
+-- Numbers with certainty indicators
+SELECT '~6.5'::seg AS seg;
+SELECT '<6.5'::seg AS seg;
+SELECT '>6.5'::seg AS seg;
+SELECT '~ 6.5'::seg AS seg;
+SELECT '< 6.5'::seg AS seg;
+SELECT '> 6.5'::seg AS seg;
+
+-- Open intervals
+SELECT '0..'::seg AS seg;
+SELECT '0...'::seg AS seg;
+SELECT '0 ..'::seg AS seg;
+SELECT '0 ...'::seg AS seg;
+SELECT '..0'::seg AS seg;
+SELECT '...0'::seg AS seg;
+SELECT '.. 0'::seg AS seg;
+SELECT '... 0'::seg AS seg;
+
+-- Finite intervals
+SELECT '0 .. 1'::seg AS seg;
+SELECT '-1 .. 0'::seg AS seg;
+SELECT '-1 .. 1'::seg AS seg;
+
+-- (+/-) intervals
+SELECT '0(+-)1'::seg AS seg;
+SELECT '0(+-)1.0'::seg AS seg;
+SELECT '1.0(+-)0.005'::seg AS seg;
+SELECT '101(+-)1'::seg AS seg;
+-- incorrect number of significant digits in 99.0:
+SELECT '100(+-)1'::seg AS seg;
+
+-- invalid input
+SELECT ''::seg AS seg;
+SELECT 'ABC'::seg AS seg;
+SELECT '1ABC'::seg AS seg;
+SELECT '1.'::seg AS seg;
+SELECT '1.....'::seg AS seg;
+SELECT '.1'::seg AS seg;
+SELECT '1..2.'::seg AS seg;
+SELECT '1 e7'::seg AS seg;
+SELECT '1e700'::seg AS seg;
+
+--
+-- testing the  operators
+--
+
+-- equality/inequality:
+--
+SELECT '24 .. 33.20'::seg = '24 .. 33.20'::seg AS bool;
+SELECT '24 .. 33.20'::seg = '24 .. 33.21'::seg AS bool;
+SELECT '24 .. 33.20'::seg != '24 .. 33.20'::seg AS bool;
+SELECT '24 .. 33.20'::seg != '24 .. 33.21'::seg AS bool;
+
+-- overlap
+--
+SELECT '1'::seg && '1'::seg AS bool;
+SELECT '1'::seg && '2'::seg AS bool;
+SELECT '0 ..'::seg && '0 ..'::seg AS bool;
+SELECT '0 .. 1'::seg && '0 .. 1'::seg AS bool;
+SELECT '..0'::seg && '0..'::seg AS bool;
+SELECT '-1 .. 0.1'::seg && '0 .. 1'::seg AS bool;
+SELECT '-1 .. 0'::seg && '0 .. 1'::seg AS bool;
+SELECT '-1 .. -0.0001'::seg && '0 .. 1'::seg AS bool;
+SELECT '0 ..'::seg && '1'::seg AS bool;
+SELECT '0 .. 1'::seg && '1'::seg AS bool;
+SELECT '0 .. 1'::seg && '2'::seg AS bool;
+SELECT '0 .. 2'::seg && '1'::seg AS bool;
+SELECT '1'::seg && '0 .. 1'::seg AS bool;
+SELECT '2'::seg && '0 .. 1'::seg AS bool;
+SELECT '1'::seg && '0 .. 2'::seg AS bool;
+
+-- overlap on the left
+--
+SELECT '1'::seg &< '0'::seg AS bool;
+SELECT '1'::seg &< '1'::seg AS bool;
+SELECT '1'::seg &< '2'::seg AS bool;
+SELECT '0 .. 1'::seg &< '0'::seg AS bool;
+SELECT '0 .. 1'::seg &< '1'::seg AS bool;
+SELECT '0 .. 1'::seg &< '2'::seg AS bool;
+SELECT '0 .. 1'::seg &< '0 .. 0.5'::seg AS bool;
+SELECT '0 .. 1'::seg &< '0 .. 1'::seg AS bool;
+SELECT '0 .. 1'::seg &< '0 .. 2'::seg AS bool;
+SELECT '0 .. 1'::seg &< '1 .. 2'::seg AS bool;
+SELECT '0 .. 1'::seg &< '2 .. 3'::seg AS bool;
+
+-- overlap on the right
+--
+SELECT '0'::seg &> '1'::seg AS bool;
+SELECT '1'::seg &> '1'::seg AS bool;
+SELECT '2'::seg &> '1'::seg AS bool;
+SELECT '0'::seg &> '0 .. 1'::seg AS bool;
+SELECT '1'::seg &> '0 .. 1'::seg AS bool;
+SELECT '2'::seg &> '0 .. 1'::seg AS bool;
+SELECT '0 .. 0.5'::seg &> '0 .. 1'::seg AS bool;
+SELECT '0 .. 1'::seg &> '0 .. 1'::seg AS bool;
+SELECT '0 .. 2'::seg &> '0 .. 2'::seg AS bool;
+SELECT '1 .. 2'::seg &> '0 .. 1'::seg AS bool;
+SELECT '2 .. 3'::seg &> '0 .. 1'::seg AS bool;
+
+-- left
+--
+SELECT '1'::seg << '0'::seg AS bool;
+SELECT '1'::seg << '1'::seg AS bool;
+SELECT '1'::seg << '2'::seg AS bool;
+SELECT '0 .. 1'::seg << '0'::seg AS bool;
+SELECT '0 .. 1'::seg << '1'::seg AS bool;
+SELECT '0 .. 1'::seg << '2'::seg AS bool;
+SELECT '0 .. 1'::seg << '0 .. 0.5'::seg AS bool;
+SELECT '0 .. 1'::seg << '0 .. 1'::seg AS bool;
+SELECT '0 .. 1'::seg << '0 .. 2'::seg AS bool;
+SELECT '0 .. 1'::seg << '1 .. 2'::seg AS bool;
+SELECT '0 .. 1'::seg << '2 .. 3'::seg AS bool;
+
+-- right
+--
+SELECT '0'::seg >> '1'::seg AS bool;
+SELECT '1'::seg >> '1'::seg AS bool;
+SELECT '2'::seg >> '1'::seg AS bool;
+SELECT '0'::seg >> '0 .. 1'::seg AS bool;
+SELECT '1'::seg >> '0 .. 1'::seg AS bool;
+SELECT '2'::seg >> '0 .. 1'::seg AS bool;
+SELECT '0 .. 0.5'::seg >> '0 .. 1'::seg AS bool;
+SELECT '0 .. 1'::seg >> '0 .. 1'::seg AS bool;
+SELECT '0 .. 2'::seg >> '0 .. 2'::seg AS bool;
+SELECT '1 .. 2'::seg >> '0 .. 1'::seg AS bool;
+SELECT '2 .. 3'::seg >> '0 .. 1'::seg AS bool;
+
+
+-- "contained in" (the left value belongs within the interval specified in the right value):
+--
+SELECT '0'::seg        ~ '0'::seg AS bool;
+SELECT '0'::seg        ~ '0 ..'::seg AS bool;
+SELECT '0'::seg        ~ '.. 0'::seg AS bool;
+SELECT '0'::seg        ~ '-1 .. 1'::seg AS bool;
+SELECT '0'::seg        ~ '-1 .. 1'::seg AS bool;
+SELECT '-1'::seg       ~ '-1 .. 1'::seg AS bool;
+SELECT '1'::seg        ~ '-1 .. 1'::seg AS bool;
+SELECT '-1 .. 1'::seg  ~ '-1 .. 1'::seg AS bool;
+
+-- "contains" (the left value contains the interval specified in the right value):
+--
+SELECT '0'::seg @ '0'::seg AS bool;
+SELECT '0 .. '::seg ~ '0'::seg AS bool;
+SELECT '.. 0'::seg ~ '0'::seg AS bool;
+SELECT '-1 .. 1'::seg ~ '0'::seg AS bool;
+SELECT '0'::seg ~ '-1 .. 1'::seg AS bool;
+SELECT '-1'::seg ~ '-1 .. 1'::seg AS bool;
+SELECT '1'::seg ~ '-1 .. 1'::seg AS bool;
+
+-- Load some example data and build the index
+-- 
+CREATE TABLE test_seg (s seg);
+
+\copy test_seg from 'data/test_seg.data'
+
+CREATE INDEX test_seg_ix ON test_seg USING gist (s);
+SELECT count(*) FROM test_seg WHERE s @ '11..11.3';
+
+-- Test sorting 
+SELECT * FROM test_seg WHERE s @ '11..11.3' GROUP BY s;