/*
Copyright (C) 2017 Christoph Berg

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
*/

-- type definition

CREATE TYPE @TYPE@;

CREATE OR REPLACE FUNCTION @TYPE@_in(cstring)
	RETURNS @TYPE@
	AS '$libdir/numeral'
	LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION @TYPE@_out(@TYPE@)
	RETURNS cstring
	AS '$libdir/numeral'
	LANGUAGE C IMMUTABLE STRICT;

CREATE TYPE @TYPE@ (
	internallength = 8,
	input = @TYPE@_in,
	output = @TYPE@_out,
	@PASSEDBYVALUE@
	alignment = double,
	category = 'N'
);

/* @TYPE@ is as good as bigint, make casts */

CREATE CAST (@TYPE@ AS bigint)
	WITHOUT FUNCTION
	AS IMPLICIT;

CREATE CAST (bigint AS @TYPE@)
	WITHOUT FUNCTION;

/* steal bigint's operators */

CREATE FUNCTION @TYPE@eq(@TYPE@, @TYPE@) RETURNS boolean
	AS 'int8eq' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR = (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@eq,
	commutator = =, negator = <>,
	restrict = eqsel, join = eqjoinsel,
	hashes, merges
);

CREATE FUNCTION @TYPE@ne(@TYPE@, @TYPE@) RETURNS boolean
	AS 'int8ne' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR <> (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@ne,
	commutator = <>, negator = =,
	restrict = neqsel, join = neqjoinsel
);

CREATE FUNCTION @TYPE@lt(@TYPE@, @TYPE@) RETURNS boolean
	AS 'int8lt' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR < (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@lt,
	commutator = >, negator = >=,
	restrict = scalarltsel, join = scalarltjoinsel
);

CREATE FUNCTION @TYPE@gt(@TYPE@, @TYPE@) RETURNS boolean
	AS 'int8gt' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR > (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@gt,
	commutator = <, negator = <=,
	restrict = scalargtsel, join = scalargtjoinsel
);

CREATE FUNCTION @TYPE@le(@TYPE@, @TYPE@) RETURNS boolean
	AS 'int8le' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR <= (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@le,
	commutator = >=, negator = >,
	restrict = scalarltsel, join = scalarltjoinsel
);

CREATE FUNCTION @TYPE@ge(@TYPE@, @TYPE@) RETURNS boolean
	AS 'int8ge' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR >= (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@ge,
	commutator = <=, negator = <,
	restrict = scalargtsel, join = scalargtjoinsel
);


CREATE FUNCTION @TYPE@mod(@TYPE@, @TYPE@) RETURNS @TYPE@
	AS 'int8mod' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR % (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@mod
);

CREATE FUNCTION @TYPE@pl(@TYPE@, @TYPE@) RETURNS @TYPE@
	AS 'int8pl' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR + (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@pl,
	commutator = +
);

CREATE FUNCTION @TYPE@mi(@TYPE@, @TYPE@) RETURNS @TYPE@
	AS 'int8mi' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR - (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@mi
);

CREATE FUNCTION @TYPE@mul(@TYPE@, @TYPE@) RETURNS @TYPE@
	AS 'int8mul' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR * (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@mul,
	commutator = *
);

CREATE FUNCTION @TYPE@div(@TYPE@, @TYPE@) RETURNS @TYPE@
	AS 'int8div' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR / (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@div
);

CREATE FUNCTION @TYPE@and(@TYPE@, @TYPE@) RETURNS @TYPE@
	AS 'int8and' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR & (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@and,
	commutator = &
);

CREATE FUNCTION @TYPE@or(@TYPE@, @TYPE@) RETURNS @TYPE@
	AS 'int8or' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR | (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@or,
	commutator = |
);

CREATE FUNCTION @TYPE@xor(@TYPE@, @TYPE@) RETURNS @TYPE@
	AS 'int8xor' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR # (
	leftarg = @TYPE@, rightarg = @TYPE@,
	procedure = @TYPE@xor,
	commutator = #
);


CREATE FUNCTION @TYPE@abs(@TYPE@) RETURNS @TYPE@
	AS 'int8abs' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR @ (
	rightarg = @TYPE@,
	procedure = @TYPE@abs
);

CREATE FUNCTION @TYPE@um(@TYPE@) RETURNS @TYPE@
	AS 'int8um' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR - (
	rightarg = @TYPE@,
	procedure = @TYPE@um
);

CREATE FUNCTION @TYPE@not(@TYPE@) RETURNS @TYPE@
	AS 'int8not' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR ~ (
	rightarg = @TYPE@,
	procedure = @TYPE@not
);

CREATE FUNCTION @TYPE@up(@TYPE@) RETURNS @TYPE@
	AS 'int8up' LANGUAGE internal IMMUTABLE STRICT;

CREATE OPERATOR + (
	rightarg = @TYPE@,
	procedure = @TYPE@up
);

