-- Create the user-defined type for N-dimensional boxes
-- 
BEGIN TRANSACTION;

-- Adjust this setting to control where the objects get created.
SET search_path = public;

CREATE FUNCTION cube_in(cstring)
RETURNS cube
AS 'MODULE_PATHNAME'
LANGUAGE 'c'IMMUTABLE STRICT;

CREATE FUNCTION cube_out(cube)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'c'IMMUTABLE STRICT;

CREATE TYPE cube (
internallength = variable,
input = cube_in,
output = cube_out
);

COMMENT ON TYPE cube IS
'multi-dimensional cube ''(FLOAT-1, FLOAT-2, ..., FLOAT-N), (FLOAT-1, FLOAT-2, ..., FLOAT-N)''';

-- Convert from text to cube

CREATE FUNCTION cube(text)
RETURNS cube
AS 'MODULE_PATHNAME'
LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube(text) IS
'convert text to cube';

--
-- External C-functions for R-tree methods
--

-- Left/Right methods

CREATE FUNCTION cube_over_left(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube_over_left(cube, cube) IS
'is over and left of (NOT IMPLEMENTED)';

CREATE FUNCTION cube_over_right(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube_over_right(cube, cube) IS
'is over and right of (NOT IMPLEMENTED)';

CREATE FUNCTION cube_left(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube_left(cube, cube) IS
'is left of (NOT IMPLEMENTED)';

CREATE FUNCTION cube_right(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube_right(cube, cube) IS
'is right of (NOT IMPLEMENTED)';


-- Comparison methods

CREATE FUNCTION cube_lt(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube_lt(cube, cube) IS
'lower than';

CREATE FUNCTION cube_gt(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube_gt(cube, cube) IS
'greater than';

CREATE FUNCTION cube_contains(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube_contains(cube, cube) IS
'contains';

CREATE FUNCTION cube_contained(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube_contained(cube, cube) IS
'contained in';

CREATE FUNCTION cube_overlap(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube_overlap(cube, cube) IS
'overlaps';

CREATE FUNCTION cube_same(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube_same(cube, cube) IS
'same as';

CREATE FUNCTION cube_different(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

COMMENT ON FUNCTION cube_different(cube, cube) IS
'different';

-- support routines for indexing

CREATE FUNCTION cube_union(cube, cube) RETURNS cube
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

CREATE FUNCTION cube_inter(cube, cube) RETURNS cube
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

CREATE FUNCTION cube_size(cube) RETURNS float8
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;


-- Misc N-dimensional functions

-- proximity routines

CREATE FUNCTION cube_distance(cube, cube) RETURNS float8
	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

-- Extracting elements functions

CREATE FUNCTION cube_dim(cube) RETURNS int4
        AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

CREATE FUNCTION cube_ll_coord(cube, int4) RETURNS float8
        AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

CREATE FUNCTION cube_ur_coord(cube, int4) RETURNS float8
        AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

-- Test if cube is also a point

CREATE FUNCTION cube_is_point(cube) RETURNS bool
        AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

-- Increasing the size of a cube by a radius in at least n dimensions

CREATE FUNCTION cube_enlarge(cube, float8, int4) RETURNS cube
        AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;

--
-- OPERATORS
--

CREATE OPERATOR < (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_lt,
   COMMUTATOR = '>',
   RESTRICT = scalarltsel, JOIN = scalarltjoinsel
);

CREATE OPERATOR > (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_gt,
   COMMUTATOR = '<',
   RESTRICT = scalargtsel, JOIN = scalargtjoinsel
);

CREATE OPERATOR << (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_left,
   COMMUTATOR = '>>',
   RESTRICT = positionsel, JOIN = positionjoinsel
);

CREATE OPERATOR &< (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_over_left,
   COMMUTATOR = '&>',
   RESTRICT = positionsel, JOIN = positionjoinsel
);

CREATE OPERATOR && (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_overlap,
   COMMUTATOR = '&&',
   RESTRICT = positionsel, JOIN = positionjoinsel
);

CREATE OPERATOR &> (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_over_right,
   COMMUTATOR = '&<',
   RESTRICT = positionsel, JOIN = positionjoinsel
);

CREATE OPERATOR >> (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_right,
   COMMUTATOR = '<<',
   RESTRICT = positionsel, JOIN = positionjoinsel
);

CREATE OPERATOR = (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_same,
   COMMUTATOR = '=', NEGATOR = '<>',
   RESTRICT = eqsel, JOIN = eqjoinsel,
   SORT1 = '<', SORT2 = '<'
);

CREATE OPERATOR <> (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_different,
   COMMUTATOR = '<>', NEGATOR = '=',
   RESTRICT = neqsel, JOIN = neqjoinsel
);

CREATE OPERATOR @ (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_contains,
   COMMUTATOR = '~',
   RESTRICT = contsel, JOIN = contjoinsel
);

CREATE OPERATOR ~ (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_contained,
   COMMUTATOR = '@',
   RESTRICT = contsel, JOIN = contjoinsel
);


-- define the GiST support methods
CREATE FUNCTION g_cube_consistent(internal,cube,int4) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c';

CREATE FUNCTION g_cube_compress(internal) RETURNS internal 
	AS 'MODULE_PATHNAME' LANGUAGE 'c';

CREATE FUNCTION g_cube_decompress(internal) RETURNS internal 
	AS 'MODULE_PATHNAME' LANGUAGE 'c';

CREATE FUNCTION g_cube_penalty(internal,internal,internal) RETURNS internal
	AS 'MODULE_PATHNAME' LANGUAGE 'c' STRICT;

CREATE FUNCTION g_cube_picksplit(internal, internal) RETURNS internal
	AS 'MODULE_PATHNAME' LANGUAGE 'c';

CREATE FUNCTION g_cube_union(bytea, internal) RETURNS cube 
	AS 'MODULE_PATHNAME' LANGUAGE 'c';

CREATE FUNCTION g_cube_same(cube, cube, internal) RETURNS internal 
	AS 'MODULE_PATHNAME' LANGUAGE 'c';


-- Create the operator class for indexing

CREATE OPERATOR CLASS gist_cube_ops
    DEFAULT FOR TYPE cube USING gist AS
	OPERATOR	1	<< ,
	OPERATOR	2	&< ,
	OPERATOR	3	&& ,
	OPERATOR	4	&> ,
	OPERATOR	5	>> ,
	OPERATOR	6	= ,
	OPERATOR	7	@ ,
	OPERATOR	8	~ ,
	FUNCTION	1	g_cube_consistent (internal, cube, int4),
	FUNCTION	2	g_cube_union (bytea, internal),
	FUNCTION	3	g_cube_compress (internal),
	FUNCTION	4	g_cube_decompress (internal),
	FUNCTION	5	g_cube_penalty (internal, internal, internal),
	FUNCTION	6	g_cube_picksplit (internal, internal),
	FUNCTION	7	g_cube_same (cube, cube, internal);


END TRANSACTION;
