#include <postgres.h> #include <fmgr.h> #include <libpq/pqformat.h> #include <math.h> #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif typedef struct { double x, y, z; } vector3; PG_FUNCTION_INFO_V1(vector3_in); PG_FUNCTION_INFO_V1(vector3_out); PG_FUNCTION_INFO_V1(vector3_recv); PG_FUNCTION_INFO_V1(vector3_send); Datum vector3_in(PG_FUNCTION_ARGS) { char *s = PG_GETARG_CSTRING(0); vector3 *v = (vector3*)palloc(sizeof(vector3)); if (sscanf(s, "(%lf,%lf,%lf)", &(v->x), &(v->y), &(v->z)) != 3) { ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("Invalid input syntax for vector3: \"%s\"", s))); } PG_RETURN_POINTER(v); } Datum vector3_out(PG_FUNCTION_ARGS) { vector3 *v = (vector3*)PG_GETARG_POINTER(0); char *s = (char*)palloc(100); snprintf(s, 100, "(%lf,%lf,%lf)", v->x, v->y, v->z); PG_RETURN_CSTRING(s); } Datum vector3_recv(PG_FUNCTION_ARGS) { StringInfo buffer = (StringInfo)PG_GETARG_POINTER(0); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = pq_getmsgfloat8(buffer); v->y = pq_getmsgfloat8(buffer); v->z = pq_getmsgfloat8(buffer); PG_RETURN_POINTER(v); } Datum vector3_send(PG_FUNCTION_ARGS) { vector3 *v = (vector3*)PG_GETARG_POINTER(0); StringInfoData buffer; pq_begintypsend(&buffer); pq_sendfloat8(&buffer, v->x); pq_sendfloat8(&buffer, v->y); pq_sendfloat8(&buffer, v->z); PG_RETURN_BYTEA_P(pq_endtypsend(&buffer)); }
cc -I/usr/local/pgsql/include/server -fpic -c math3d.c cc -shared -L/usr/local/pgsql/lib -lpq -o math3d.so math3d.o cp math3d.so /usr/local/pgsql/lib/
CREATE TYPE vector3; CREATE OR REPLACE FUNCTION vector3_in ( s cstring ) RETURNS vector3 AS 'math3d', 'vector3_in' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_out ( v vector3 ) RETURNS cstring AS 'math3d', 'vector3_out' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION vector3_recv ( p internal ) RETURNS vector3 AS 'math3d', 'vector3_recv' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION vector3_send ( v vector3 ) RETURNS bytea AS 'math3d', 'vector3_send' LANGUAGE C IMMUTABLE STRICT; CREATE TYPE vector3 ( internallength = 24, input = vector3_in, output = vector3_out, receive = vector3_recv, send = vector3_send );
SELECT '(0.0,1.0,0.0)'::vector3; -- (0.000000,1.000000,0.000000) vector3
PG_FUNCTION_INFO_V1(vector3_minus); // PG_FUNCTION_INFO_V1(vector3_add); // PG_FUNCTION_INFO_V1(vector3_sub); // PG_FUNCTION_INFO_V1(vector3_mul_left); // PG_FUNCTION_INFO_V1(vector3_mul_right); // PG_FUNCTION_INFO_V1(vector3_div_left); // PG_FUNCTION_INFO_V1(vector3_div_right); // PG_FUNCTION_INFO_V1(vector3_equal); // PG_FUNCTION_INFO_V1(vector3_not_equal); // PG_FUNCTION_INFO_V1(vector3_dot); // PG_FUNCTION_INFO_V1(vector3_cross); // PG_FUNCTION_INFO_V1(vector3_length); // PG_FUNCTION_INFO_V1(vector3_normalize); // PG_FUNCTION_INFO_V1(vector3_distance); // Datum vector3_minus(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = -v0->x; v->y = -v0->y; v->z = -v0->z; PG_RETURN_POINTER(v); } Datum vector3_add(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->x + v1->x; v->y = v0->y + v1->y; v->z = v0->z + v1->z; PG_RETURN_POINTER(v); } Datum vector3_sub(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->x - v1->x; v->y = v0->y - v1->y; v->z = v0->z - v1->z; PG_RETURN_POINTER(v); } Datum vector3_mul_left(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); double k = PG_GETARG_FLOAT8(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->x * k; v->y = v0->y * k; v->z = v0->z * k; PG_RETURN_POINTER(v); } Datum vector3_mul_right(PG_FUNCTION_ARGS) { double k = PG_GETARG_FLOAT8(0); vector3 *v0 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = k * v0->x; v->y = k * v0->y; v->z = k * v0->z; PG_RETURN_POINTER(v); } Datum vector3_div_left(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); double k = PG_GETARG_FLOAT8(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->x / k; v->y = v0->y / k; v->z = v0->z / k; PG_RETURN_POINTER(v); } Datum vector3_div_right(PG_FUNCTION_ARGS) { double k = PG_GETARG_FLOAT8(0); vector3 *v0 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = k / v0->x; v->y = k / v0->y; v->z = k / v0->z; PG_RETURN_POINTER(v); } Datum vector3_equal(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); bool equal = true; equal &= v0->x == v1->x; equal &= v0->y == v1->y; equal &= v0->z == v1->z; PG_RETURN_BOOL(equal); } Datum vector3_not_equal(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); bool not_equal = false; not_equal |= v0->x != v1->x; not_equal |= v0->y != v1->y; not_equal |= v0->z != v1->z; PG_RETURN_BOOL(not_equal); } Datum vector3_dot(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); double r = v0->x * v1->x + v0->y * v1->y + v0->z * v1->z; PG_RETURN_FLOAT8(r); } Datum vector3_cross(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->y * v1->z - v0->z * v1->y; v->y = v0->z * v1->x - v0->x * v1->z; v->z = v0->x * v1->y - v0->y * v1->x; PG_RETURN_POINTER(v); } Datum vector3_length(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); double len = sqrt(v0->x * v0->x + v0->y * v0->y + v0->z * v0->z); PG_RETURN_FLOAT8(len); } Datum vector3_normalize(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v = (vector3*)palloc(sizeof(vector3)); double len = sqrt(v0->x * v0->x + v0->y * v0->y + v0->z * v0->z); if (len > 0.000001) { v->x = v0->y / len; v->y = v0->z / len; v->z = v0->x / len; } else { v->x = 0.0; v->y = 0.0; v->z = 0.0; } PG_RETURN_POINTER(v); } Datum vector3_distance(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->x - v1->x; v->y = v0->y - v1->y; v->z = v0->z - v1->z; double len = sqrt(v->x * v->x + v->y * v->y + v->z * v->z); pfree(v); PG_RETURN_FLOAT8(len); }
CREATE OR REPLACE FUNCTION vector3_minus ( v0 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_minus' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_add ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_add' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_sub ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_sub' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_mul_left ( v0 vector3, k double precision ) RETURNS vector3 AS 'math3d', 'vector3_mul_left' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_mul_right ( k double precision, v0 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_mul_right' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_div_left ( v0 vector3, k double precision ) RETURNS vector3 AS 'math3d', 'vector3_div_left' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_div_right ( k double precision, v0 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_div_right' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_equal ( v0 vector3, v1 vector3 ) RETURNS boolean AS 'math3d', 'vector3_equal' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_not_equal ( v0 vector3, v1 vector3 ) RETURNS boolean AS 'math3d', 'vector3_not_equal' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_dot ( v0 vector3, v1 vector3 ) RETURNS double precision AS 'math3d', 'vector3_dot' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_cross ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_cross' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION length ( v0 vector3 ) RETURNS double precision AS 'math3d', 'vector3_length' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION normalize ( v0 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_normalize' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION distance ( v0 vector3, v1 vector3 ) RETURNS double precision AS 'math3d', 'vector3_distance' LANGUAGE C IMMUTABLE STRICT;
SELECT vector3_add ( '(0.0,1.0,0.0)'::vector3, '(0.5,0.5,0.0)'::vector3 ); -- (0.500000,1.500000,0.000000) SELECT vector3_mul_right ( 5.0, '(0.2,0.2,1.33)'::vector3 ); -- (1.000000,1.000000,6.650000) SELECT vector3_cross ( '(1.0,0.0,0.0)'::vector3, '(0.0,1.0,0.0)'::vector3 ); -- (0.000000,0.000000,1.000000) SELECT length ( '(0.705,0.705,0.0)'::vector3 ); -- 0.9970206
-- CREATE OPERATOR - ( rightarg = vector3, procedure = vector3_minus ); -- CREATE OPERATOR + ( leftarg = vector3, rightarg = vector3, procedure = vector3_add, commutator = + ); -- CREATE OPERATOR - ( leftarg = vector3, rightarg = vector3, procedure = vector3_sub ); -- CREATE OPERATOR * ( leftarg = vector3, rightarg = double precision, procedure = vector3_mul_left ); -- CREATE OPERATOR * ( leftarg = double precision, rightarg = vector3, procedure = vector3_mul_right ); -- CREATE OPERATOR / ( leftarg = vector3, rightarg = double precision, procedure = vector3_div_left ); -- CREATE OPERATOR / ( leftarg = double precision, rightarg = vector3, procedure = vector3_div_right ); -- CREATE OPERATOR = ( leftarg = vector3, rightarg = vector3, procedure = vector3_equal ); -- CREATE OPERATOR != ( leftarg = vector3, rightarg = vector3, procedure = vector3_not_equal ); -- CREATE OPERATOR * ( leftarg = vector3, rightarg = vector3, procedure = vector3_dot commutator = ); -- CREATE OPERATOR ** ( leftarg = vector3, rightarg = vector3, procedure = vector3_cross );
SELECT '(0.0,1.0,0.0)'::vector3 + '(0.5,0.5,0.0)'::vector3; -- (0.500000,1.500000,0.000000) SELECT 5.0 * '(0.2,0.2,1.33)'::vector3; -- (1.000000,1.000000,6.650000) SELECT '(1.0,0.5,0.1)'::vector3 * '(0.707,0.707,0.707)'::vector3; -- 1.1312 SELECT '(1.0,0.0,0.0)'::vector3 ** '(0.0,1.0,0.0)'::vector3; -- (0.000000,0.000000,1.000000)
CREATE TYPE vector3c AS ( x double precision, y double precision, z double precision ); CREATE OR REPLACE FUNCTION vector3_cast_vector3c ( v0 vector3 ) RETURNS vector3c AS $BODY$ DECLARE s text[]; v vector3c; BEGIN s := string_to_array ( trim ( BOTH '()' FROM v0::text ), ',' ); vx := s[1]; vy := s[2]; vz := s[3]; RETURN v; END $BODY$ LANGUAGE plpgsql IMMUTABLE; CREATE OR REPLACE FUNCTION vector3c_cast_vector3 ( v0 vector3c ) RETURNS vector3 AS $BODY$ DECLARE v vector3; BEGIN v := v0::text; RETURN v; END $BODY$ LANGUAGE plpgsql IMMUTABLE; CREATE CAST ( vector3 AS vector3c ) WITH FUNCTION vector3_cast_vector3c ( v0 vector3 ) AS IMPLICIT; CREATE CAST ( vector3c AS vector3 ) WITH FUNCTION vector3c_cast_vector3 ( v0 vector3c ) AS IMPLICIT;
SELECT ('(0.1,1.0,0.5)'::vector3)::vector3c; -- (0.1,1,0.5) SELECT ('(0.707,0.0,0.0)'::vector3c)::vector3; -- (0.707000,0.000000,0.000000)
#include <postgres.h> #include <fmgr.h> #include <libpq/pqformat.h> #include <math.h> #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif // types typedef struct { double x, y, z; } vector3; // declarations PG_FUNCTION_INFO_V1(vector3_in); PG_FUNCTION_INFO_V1(vector3_out); PG_FUNCTION_INFO_V1(vector3_recv); PG_FUNCTION_INFO_V1(vector3_send); PG_FUNCTION_INFO_V1(vector3_minus); PG_FUNCTION_INFO_V1(vector3_add); PG_FUNCTION_INFO_V1(vector3_sub); PG_FUNCTION_INFO_V1(vector3_mul_left); PG_FUNCTION_INFO_V1(vector3_mul_right); PG_FUNCTION_INFO_V1(vector3_div_left); PG_FUNCTION_INFO_V1(vector3_div_right); PG_FUNCTION_INFO_V1(vector3_equal); PG_FUNCTION_INFO_V1(vector3_not_equal); PG_FUNCTION_INFO_V1(vector3_dot); PG_FUNCTION_INFO_V1(vector3_cross); PG_FUNCTION_INFO_V1(vector3_length); PG_FUNCTION_INFO_V1(vector3_normalize); PG_FUNCTION_INFO_V1(vector3_distance); // implementation Datum vector3_in(PG_FUNCTION_ARGS) { char *s = PG_GETARG_CSTRING(0); vector3 *v = (vector3*)palloc(sizeof(vector3)); if (sscanf(s, "(%lf,%lf,%lf)", &(v->x), &(v->y), &(v->z)) != 3) { ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("Invalid input syntax for vector3: \"%s\"", s))); } PG_RETURN_POINTER(v); } Datum vector3_out(PG_FUNCTION_ARGS) { vector3 *v = (vector3*)PG_GETARG_POINTER(0); char *s = (char*)palloc(100); snprintf(s, 100, "(%lf,%lf,%lf)", v->x, v->y, v->z); PG_RETURN_CSTRING(s); } Datum vector3_recv(PG_FUNCTION_ARGS) { StringInfo buffer = (StringInfo)PG_GETARG_POINTER(0); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = pq_getmsgfloat8(buffer); v->y = pq_getmsgfloat8(buffer); v->z = pq_getmsgfloat8(buffer); PG_RETURN_POINTER(v); } Datum vector3_send(PG_FUNCTION_ARGS) { vector3 *v = (vector3*)PG_GETARG_POINTER(0); StringInfoData buffer; pq_begintypsend(&buffer); pq_sendfloat8(&buffer, v->x); pq_sendfloat8(&buffer, v->y); pq_sendfloat8(&buffer, v->z); PG_RETURN_BYTEA_P(pq_endtypsend(&buffer)); } Datum vector3_minus(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = -v0->x; v->y = -v0->y; v->z = -v0->z; PG_RETURN_POINTER(v); } Datum vector3_add(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->x + v1->x; v->y = v0->y + v1->y; v->z = v0->z + v1->z; PG_RETURN_POINTER(v); } Datum vector3_sub(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->x - v1->x; v->y = v0->y - v1->y; v->z = v0->z - v1->z; PG_RETURN_POINTER(v); } Datum vector3_mul_left(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); double k = PG_GETARG_FLOAT8(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->x * k; v->y = v0->y * k; v->z = v0->z * k; PG_RETURN_POINTER(v); } Datum vector3_mul_right(PG_FUNCTION_ARGS) { double k = PG_GETARG_FLOAT8(0); vector3 *v0 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = k * v0->x; v->y = k * v0->y; v->z = k * v0->z; PG_RETURN_POINTER(v); } Datum vector3_div_left(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); double k = PG_GETARG_FLOAT8(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->x / k; v->y = v0->y / k; v->z = v0->z / k; PG_RETURN_POINTER(v); } Datum vector3_div_right(PG_FUNCTION_ARGS) { double k = PG_GETARG_FLOAT8(0); vector3 *v0 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = k / v0->x; v->y = k / v0->y; v->z = k / v0->z; PG_RETURN_POINTER(v); } Datum vector3_equal(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); bool equal = true; equal &= v0->x == v1->x; equal &= v0->y == v1->y; equal &= v0->z == v1->z; PG_RETURN_BOOL(equal); } Datum vector3_not_equal(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); bool not_equal = false; not_equal |= v0->x != v1->x; not_equal |= v0->y != v1->y; not_equal |= v0->z != v1->z; PG_RETURN_BOOL(not_equal); } Datum vector3_dot(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); double r = v0->x * v1->x + v0->y * v1->y + v0->z * v1->z; PG_RETURN_FLOAT8(r); } Datum vector3_cross(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->y * v1->z - v0->z * v1->y; v->y = v0->z * v1->x - v0->x * v1->z; v->z = v0->x * v1->y - v0->y * v1->x; PG_RETURN_POINTER(v); } Datum vector3_length(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); double len = sqrt(v0->x * v0->x + v0->y * v0->y + v0->z * v0->z); PG_RETURN_FLOAT8(len); } Datum vector3_normalize(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v = (vector3*)palloc(sizeof(vector3)); double len = sqrt(v0->x * v0->x + v0->y * v0->y + v0->z * v0->z); if (len > 0.000001) { v->x = v0->y / len; v->y = v0->z / len; v->z = v0->x / len; } else { v->x = 0.0; v->y = 0.0; v->z = 0.0; } PG_RETURN_POINTER(v); } Datum vector3_distance(PG_FUNCTION_ARGS) { vector3 *v0 = (vector3*)PG_GETARG_POINTER(0); vector3 *v1 = (vector3*)PG_GETARG_POINTER(1); vector3 *v = (vector3*)palloc(sizeof(vector3)); v->x = v0->x - v1->x; v->y = v0->y - v1->y; v->z = v0->z - v1->z; double len = sqrt(v->x * v->x + v->y * v->y + v->z * v->z); pfree(v); PG_RETURN_FLOAT8(len); }
CREATE TYPE vector3; CREATE OR REPLACE FUNCTION vector3_in ( s cstring ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_in' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_out ( v vector3 ) RETURNS cstring AS 'MODULE_PATHNAME', 'vector3_out' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_recv ( p internal ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_recv' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION vector3_send ( v vector3 ) RETURNS bytea AS 'MODULE_PATHNAME', 'vector3_send' LANGUAGE C IMMUTABLE STRICT; CREATE TYPE vector3 ( internallength = 24, input = vector3_in, output = vector3_out, receive = vector3_recv, send = vector3_send ); CREATE OR REPLACE FUNCTION vector3_minus ( v0 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_minus' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR - ( rightarg = vector3, procedure = vector3_minus ); CREATE OR REPLACE FUNCTION vector3_add ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_add' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR + ( leftarg = vector3, rightarg = vector3, procedure = vector3_add, commutator = + ); CREATE OR REPLACE FUNCTION vector3_sub ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_sub' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR - ( leftarg = vector3, rightarg = vector3, procedure = vector3_sub ); CREATE OR REPLACE FUNCTION vector3_mul_left ( v0 vector3, k double precision ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_mul_left' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR * ( leftarg = vector3, rightarg = double precision, procedure = vector3_mul_left, commutator = * ); CREATE OR REPLACE FUNCTION vector3_mul_right ( k double precision, v0 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_mul_right' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR * ( leftarg = double precision, rightarg = vector3, procedure = vector3_mul_right, commutator = * ); CREATE OR REPLACE FUNCTION vector3_div_left ( v0 vector3, k double precision ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_div_left' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR / ( leftarg = vector3, rightarg = double precision, procedure = vector3_div_left ); CREATE OR REPLACE FUNCTION vector3_div_right ( k double precision, v0 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_div_right' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR / ( leftarg = double precision, rightarg = vector3, procedure = vector3_div_right ); CREATE OR REPLACE FUNCTION vector3_equal ( v0 vector3, v1 vector3 ) RETURNS boolean AS 'MODULE_PATHNAME', 'vector3_equal' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR = ( leftarg = vector3, rightarg = vector3, procedure = vector3_equal ); CREATE OR REPLACE FUNCTION vector3_not_equal ( v0 vector3, v1 vector3 ) RETURNS boolean AS 'MODULE_PATHNAME', 'vector3_not_equal' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR != ( leftarg = vector3, rightarg = vector3, procedure = vector3_not_equal ); CREATE OR REPLACE FUNCTION vector3_dot ( v0 vector3, v1 vector3 ) RETURNS double precision AS 'MODULE_PATHNAME', 'vector3_dot' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR * ( leftarg = vector3, rightarg = vector3, procedure = vector3_dot, commutator = * ); CREATE OR REPLACE FUNCTION vector3_cross ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_cross' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR ** ( leftarg = vector3, rightarg = vector3, procedure = vector3_cross, commutator = ** ); CREATE OR REPLACE FUNCTION length ( v0 vector3 ) RETURNS double precision AS 'MODULE_PATHNAME', 'vector3_length' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION normalize ( v0 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_normalize' LANGUAGE C IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION distance ( v0 vector3, v1 vector3 ) RETURNS double precision AS 'MODULE_PATHNAME', 'vector3_distance' LANGUAGE C IMMUTABLE STRICT; CREATE TYPE vector3c AS ( x double precision, y double precision, z double precision ); CREATE OR REPLACE FUNCTION vector3_cast_vector3c ( v0 vector3 ) RETURNS vector3c AS $BODY$ DECLARE s text[]; v vector3c; BEGIN s := string_to_array ( trim ( BOTH '()' FROM v0::text ), ',' ); vx := s[1]; vy := s[2]; vz := s[3]; RETURN v; END $BODY$ LANGUAGE plpgsql IMMUTABLE; CREATE OR REPLACE FUNCTION vector3c_cast_vector3 ( v0 vector3c ) RETURNS vector3 AS $BODY$ DECLARE v vector3; BEGIN v := v0::text; RETURN v; END $BODY$ LANGUAGE plpgsql IMMUTABLE; CREATE CAST ( vector3 AS vector3c ) WITH FUNCTION vector3_cast_vector3c ( v0 vector3 ) AS IMPLICIT; CREATE CAST ( vector3c AS vector3 ) WITH FUNCTION vector3c_cast_vector3 ( v0 vector3c ) AS IMPLICIT;
# math3d extension comment = '3D mathematics' default_version = '1.0' module_pathname = '$libdir/math3d' relocatable = true
CREATE EXTENSION math3d;
DROP EXTENSION math3d;
CREATE TABLE user_setting ( username text, key text, value text ); SELECT pg_catalog.pg_extension_config_dump ( 'user_setting', '' );
ALTER EXTENSION math3d UPDATE TO '1.1'
ALTER EXTENSION <_> SET SCHEMA < >; -- ALTER EXTENSION <_> ADD <>; -- ALTER EXTENSION <_> DROP <>; --
Source: https://habr.com/ru/post/198332/
All Articles