[postgis-commits] svn - r2815 - in trunk: . liblwgeom lwgeom

postgis-commits at postgis.refractions.net postgis-commits at postgis.refractions.net
Sun Jun 29 12:11:50 PDT 2008


Author: mcayland
Date: 2008-06-29 12:11:48 -0700 (Sun, 29 Jun 2008)
New Revision: 2815

Added:
   trunk/liblwgeom/
   trunk/liblwgeom/Makefile.in
   trunk/liblwgeom/box2d.c
   trunk/liblwgeom/lex.yy.c
   trunk/liblwgeom/liblwgeom.h
   trunk/liblwgeom/lwcollection.c
   trunk/liblwgeom/lwcompound.c
   trunk/liblwgeom/lwcurve.c
   trunk/liblwgeom/lwcurvepoly.c
   trunk/liblwgeom/lwgeom.c
   trunk/liblwgeom/lwgeom_api.c
   trunk/liblwgeom/lwgparse.c
   trunk/liblwgeom/lwgunparse.c
   trunk/liblwgeom/lwline.c
   trunk/liblwgeom/lwmcurve.c
   trunk/liblwgeom/lwmline.c
   trunk/liblwgeom/lwmpoint.c
   trunk/liblwgeom/lwmpoly.c
   trunk/liblwgeom/lwmsurface.c
   trunk/liblwgeom/lwpoint.c
   trunk/liblwgeom/lwpoly.c
   trunk/liblwgeom/lwutil.c
   trunk/liblwgeom/measures.c
   trunk/liblwgeom/ptarray.c
   trunk/liblwgeom/vsprintf.c
   trunk/liblwgeom/wktparse.h
   trunk/liblwgeom/wktparse.lex
   trunk/liblwgeom/wktparse.tab.c
   trunk/liblwgeom/wktparse.tab.h
   trunk/liblwgeom/wktparse.y
Removed:
   trunk/lwgeom/box2d.c
   trunk/lwgeom/lex.yy.c
   trunk/lwgeom/liblwgeom.c
   trunk/lwgeom/liblwgeom.h
   trunk/lwgeom/lwcollection.c
   trunk/lwgeom/lwcompound.c
   trunk/lwgeom/lwcurve.c
   trunk/lwgeom/lwcurvepoly.c
   trunk/lwgeom/lwgeom.c
   trunk/lwgeom/lwgeom_api.c
   trunk/lwgeom/lwgparse.c
   trunk/lwgeom/lwline.c
   trunk/lwgeom/lwmcurve.c
   trunk/lwgeom/lwmline.c
   trunk/lwgeom/lwmpoint.c
   trunk/lwgeom/lwmpoly.c
   trunk/lwgeom/lwmsurface.c
   trunk/lwgeom/lwpoint.c
   trunk/lwgeom/lwpoly.c
   trunk/lwgeom/measures.c
   trunk/lwgeom/ptarray.c
   trunk/lwgeom/vsprintf.c
   trunk/lwgeom/wktparse.h
   trunk/lwgeom/wktparse.lex
   trunk/lwgeom/wktparse.tab.c
   trunk/lwgeom/wktparse.tab.h
   trunk/lwgeom/wktparse.y
   trunk/lwgeom/wktunparse.c
Modified:
   trunk/GNUmakefile
   trunk/configure.ac
   trunk/lwgeom/Makefile.in
   trunk/lwgeom/lwgeom_dump.c
   trunk/lwgeom/lwgeom_functions_basic.c
   trunk/lwgeom/lwgeom_geos_c.c
   trunk/lwgeom/lwgeom_gist.c
   trunk/lwgeom/lwgeom_inout.c
   trunk/lwgeom/lwgeom_ogc.c
   trunk/lwgeom/lwgeom_pg.c
   trunk/lwgeom/lwgeom_pg.h
   trunk/lwgeom/lwgeom_sqlmm.c
Log:
Split the basic geometry accessors into a separate static library liblwgeom.a; this potentially allows re-use of the liblwgeom functions from within PostGIS, or could be extended at a later date to include databases other than MySQL. This patch includes a change to the liblwgeom handler functions; instead of sprinkling init_pg_func()s around the source, I have changed the default liblwgeom handlers to make use of a callback to allow linked libraries to set their own handlers the first time any of them are called. I have also tidied up the parser API a little in liblwgeom.h, which means wktparse.h can be removed from all of the headers in the lwgeom/ directory, plus renamed wktunparse.c to lwgunparse.c to keep things similar to lwgparse.c. Finally, I renamed liblwgeom.c to lwutil.c to avoid confusion within the new interface. TODO: the liblwgeom Makefile has some gcc-specific options, but these can be fixed later - it seemed more important to make the warnings visible to developers.

Modified: trunk/GNUmakefile
===================================================================
--- trunk/GNUmakefile	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/GNUmakefile	2008-06-29 19:11:48 UTC (rev 2815)
@@ -4,13 +4,13 @@
 #
 #-----------------------------------------------------
 
-all: liblwgeom loaderdumper utils 
+all: postgis loaderdumper utils 
 
-install: all liblwgeom-install loaderdumper-install 
+install: all postgis-install loaderdumper-install 
 
-uninstall: liblwgeom-uninstall loaderdumper-uninstall docs-uninstall 
+uninstall: postgis-uninstall loaderdumper-uninstall docs-uninstall 
 
-clean: liblwgeom-clean loaderdumper-clean docs-clean test-clean 
+clean: liblwgeom-clean postgis-clean loaderdumper-clean docs-clean test-clean 
 	rm -f lwpostgis.sql lwpostgis_upgrade.sql
 
 distclean: clean
@@ -35,16 +35,24 @@
 test-clean:
 	$(MAKE) -C regress clean
 
-liblwgeom: 
+liblwgeom/liblwgeom.a:
+	$(MAKE) -C liblwgeom 
+
+liblwgeom: liblwgeom/liblwgeom.a 
+
+liblwgeom-clean:
+	$(MAKE) -C liblwgeom clean
+
+postgis: liblwgeom/liblwgeom.a 
 	$(MAKE) -C lwgeom 
 
-liblwgeom-clean:
+postgis-clean:
 	$(MAKE) -C lwgeom clean
 
-liblwgeom-install:
+postgis-install:
 	$(MAKE) -C lwgeom install
 
-liblwgeom-uninstall:
+postgis-uninstall:
 	$(MAKE) -C lwgeom uninstall
 
 loaderdumper:

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/configure.ac	2008-06-29 19:11:48 UTC (rev 2815)
@@ -357,5 +357,5 @@
 dnl AC_MSG_RESULT([SHLIB_LINK: $SHLIB_LINK])
 
 dnl Output the relevant files
-AC_OUTPUT([lwgeom/Makefile lwgeom/sqldefines.h loader/Makefile.pgsql2shp loader/Makefile.shp2pgsql regress/Makefile doc/Makefile])
+AC_OUTPUT([liblwgeom/Makefile lwgeom/Makefile lwgeom/sqldefines.h loader/Makefile.pgsql2shp loader/Makefile.shp2pgsql regress/Makefile doc/Makefile])
 

Added: trunk/liblwgeom/Makefile.in
===================================================================
--- trunk/liblwgeom/Makefile.in	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/Makefile.in	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,51 @@
+# **********************************************************************
+# * $Id: Makefile.in 
+# *
+# * PostGIS - Spatial Types for PostgreSQL
+# * http://postgis.refractions.net
+# * Copyright 2008 Mark Cave-Ayland
+# *
+# * This is free software; you can redistribute and/or modify it under
+# * the terms of the GNU General Public Licence. See the COPYING file.
+# *
+# **********************************************************************
+
+CC=@CC@
+CFLAGS=@CFLAGS@ -Wall -Wmissing-prototypes -fPIC 
+
+# Standalone LWGEOM objects
+SA_OBJS=measures.o \
+	box2d.o \
+	ptarray.o \
+	lwgeom_api.o \
+	lwgeom.o \
+	lwpoint.o \
+	lwline.o \
+	lwpoly.o \
+	lwmpoint.o \
+	lwmline.o \
+	lwmpoly.o \
+	lwcollection.o \
+	lwcurve.o \
+	lwcompound.o \
+	lwcurvepoly.o \
+	lwmcurve.o \
+	lwmsurface.o \
+	lwutil.o \
+	lwgunparse.o \
+	lwgparse.o \
+	wktparse.tab.o \
+	lex.yy.o \
+	vsprintf.o	
+
+all: $(SA_OBJS)
+	ar rs liblwgeom.a $(SA_OBJS) 	
+
+clean:
+	rm -f $(SA_OBJS) 
+	rm -f liblwgeom.a 
+
+# Command to build each of the .o files
+$(SA_OBJS): %.o: %.c
+	$(CC) $(CFLAGS) -c -o $@ $<
+ 

Added: trunk/liblwgeom/box2d.c
===================================================================
--- trunk/liblwgeom/box2d.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/box2d.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "liblwgeom.h"
+
+#ifndef EPSILON
+#define EPSILON        1.0E-06
+#endif
+#ifndef FPeq
+#define FPeq(A,B)     (fabs((A) - (B)) <= EPSILON)
+#endif
+
+
+/* Expand given box of 'd' units in all directions */
+void
+expand_box2d(BOX2DFLOAT4 *box, double d)
+{
+	box->xmin -= d;
+	box->ymin -= d;
+
+	box->xmax += d;
+	box->ymax += d;
+}
+
+
+/*
+ * This has been changed in PostGIS 1.1.2 to
+ * check exact equality of values (rather then using
+ * the FPeq macro taking into account coordinate drifts).
+ */
+char
+box2d_same(BOX2DFLOAT4 *box1, BOX2DFLOAT4 *box2)
+{
+	return(	(box1->xmax==box2->xmax) &&
+		(box1->xmin==box2->xmin) &&
+		(box1->ymax==box2->ymax) &&
+		(box1->ymin==box2->ymin));
+#if 0 
+	return(FPeq(box1->xmax, box2->xmax) &&
+				   FPeq(box1->xmin, box2->xmin) &&
+				   FPeq(box1->ymax, box2->ymax) &&
+				   FPeq(box1->ymin, box2->ymin));
+#endif
+}
+
+BOX2DFLOAT4 *
+box2d_clone(const BOX2DFLOAT4 *in)
+{
+	BOX2DFLOAT4 *ret = lwalloc(sizeof(BOX2DFLOAT4));
+	memcpy(ret, in, sizeof(BOX2DFLOAT4));
+	return ret;
+}

Added: trunk/liblwgeom/lex.yy.c
===================================================================
--- trunk/liblwgeom/lex.yy.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lex.yy.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,4562 @@
+#define yy_create_buffer lwg_parse_yy_create_buffer
+#define yy_delete_buffer lwg_parse_yy_delete_buffer
+#define yy_scan_buffer lwg_parse_yy_scan_buffer
+#define yy_scan_string lwg_parse_yy_scan_string
+#define yy_scan_bytes lwg_parse_yy_scan_bytes
+#define yy_flex_debug lwg_parse_yy_flex_debug
+#define yy_init_buffer lwg_parse_yy_init_buffer
+#define yy_flush_buffer lwg_parse_yy_flush_buffer
+#define yy_load_buffer_state lwg_parse_yy_load_buffer_state
+#define yy_switch_to_buffer lwg_parse_yy_switch_to_buffer
+#define yyin lwg_parse_yyin
+#define yyleng lwg_parse_yyleng
+#define yylex lwg_parse_yylex
+#define yyout lwg_parse_yyout
+#define yyrestart lwg_parse_yyrestart
+#define yytext lwg_parse_yytext
+#define yywrap lwg_parse_yywrap
+
+#line 20 "lex.yy.c"
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+#include <unistd.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ * 	if ( condition_holds )
+ *		yyless( 5 );
+ *	else
+ *		do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		*yy_cp = yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+	};
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+typedef char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+static yyconst short yy_nxt[][128] =
+    {
+    {
+        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,    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,
+        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,    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,
+
+        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,    0,    0,    0
+    },
+
+    {
+        5,    6,    6,    6,    6,    6,    6,    6,    6,    7,
+        8,    6,    6,    7,    6,    6,    6,    6,    6,    6,
+        6,    6,    6,    6,    6,    6,    6,    6,    6,    6,
+        6,    6,    7,    6,    6,    6,    6,    6,    6,    6,
+        9,   10,    6,    6,   11,    6,    6,    6,   12,    6,
+        6,    6,    6,    6,    6,    6,    6,    6,    6,   13,
+        6,   14,    6,    6,    6,    6,    6,   15,    6,   16,
+
+        6,   17,    6,    6,    6,    6,   18,   19,    6,    6,
+       20,    6,    6,   21,    6,    6,    6,    6,    6,    6,
+        6,    6,    6,    6,    6,    6,    6,    6,    6,   15,
+        6,   16,    6,   17,    6,    6,    6,    6,   18,   19,
+        6,    6,   20,    6,    6,   21,    6,    6,    6,    6,
+        6,    6,    6,    6,    6,    6,    6,    6
+    },
+
+    {
+        5,    6,    6,    6,    6,    6,    6,    6,    6,    7,
+        8,    6,    6,    7,    6,    6,    6,    6,    6,    6,
+        6,    6,    6,    6,    6,    6,    6,    6,    6,    6,
+        6,    6,    7,    6,    6,    6,    6,    6,    6,    6,
+
+        9,   10,    6,    6,   11,    6,    6,    6,   12,    6,
+        6,    6,    6,    6,    6,    6,    6,    6,    6,   13,
+        6,   14,    6,    6,    6,    6,    6,   15,    6,   16,
+        6,   17,    6,    6,    6,    6,   18,   19,    6,    6,
+       20,    6,    6,   21,    6,    6,    6,    6,    6,    6,
+        6,    6,    6,    6,    6,    6,    6,    6,    6,   15,
+        6,   16,    6,   17,    6,    6,    6,    6,   18,   19,
+        6,    6,   20,    6,    6,   21,    6,    6,    6,    6,
+        6,    6,    6,    6,    6,    6,    6,    6
+    },
+
+    {
+        5,    6,    6,    6,    6,    6,    6,    6,    6,    7,
+
+        8,    6,    6,    7,    6,    6,    6,    6,    6,    6,
+        6,    6,    6,    6,    6,    6,    6,    6,    6,    6,
+        6,    6,    7,    6,    6,    6,    6,    6,    6,    6,
+        9,   10,    6,   22,   11,   22,   23,    6,   24,   24,
+       24,   24,   24,   24,   24,   24,   24,   24,    6,   13,
+        6,   14,    6,    6,    6,    6,    6,   15,    6,   16,
+        6,   17,    6,    6,    6,    6,   18,   19,    6,    6,
+       20,    6,    6,   21,    6,    6,    6,    6,    6,    6,
+        6,    6,    6,    6,    6,    6,    6,    6,    6,   15,
+        6,   16,    6,   17,    6,    6,    6,    6,   18,   19,
+
+        6,    6,   20,    6,    6,   21,    6,    6,    6,    6,
+        6,    6,    6,    6,   22,    6,    6,    6
+    },
+
+    {
+        5,    6,    6,    6,    6,    6,    6,    6,    6,    7,
+        8,    6,    6,    7,    6,    6,    6,    6,    6,    6,
+        6,    6,    6,    6,    6,    6,    6,    6,    6,    6,
+        6,    6,    7,    6,    6,    6,    6,    6,    6,    6,
+        9,   10,    6,   22,   11,   22,   23,    6,   24,   24,
+       24,   24,   24,   24,   24,   24,   24,   24,    6,   13,
+        6,   14,    6,    6,    6,    6,    6,   15,    6,   16,
+        6,   17,    6,    6,    6,    6,   18,   19,    6,    6,
+
+       20,    6,    6,   21,    6,    6,    6,    6,    6,    6,
+        6,    6,    6,    6,    6,    6,    6,    6,    6,   15,
+        6,   16,    6,   17,    6,    6,    6,    6,   18,   19,
+        6,    6,   20,    6,    6,   21,    6,    6,    6,    6,
+        6,    6,    6,    6,   22,    6,    6,    6
+    },
+
+    {
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
+       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5
+    },
+
+    {
+        5,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
+
+       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6
+    },
+
+    {
+        5,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   25,
+       25,   -7,   -7,   25,   -7,   -7,   -7,   -7,   -7,   -7,
+       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
+       -7,   -7,   25,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
+       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
+       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
+       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
+       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
+       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
+
+       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
+       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
+       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
+       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7
+    },
+
+    {
+        5,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   25,
+       25,   -8,   -8,   25,   -8,   -8,   -8,   -8,   -8,   -8,
+       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
+       -8,   -8,   25,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
+       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
+       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
+
+       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
+       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
+       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
+       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
+       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
+       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
+       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8
+    },
+
+    {
+        5,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9
+
+    },
+
+    {
+        5,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10
+    },
+
+    {
+        5,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11
+    },
+
+    {
+        5,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,   26,   27,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12
+    },
+
+    {
+        5,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13
+    },
+
+    {
+        5,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14
+    },
+
+    {
+        5,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
+      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
+      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
+      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
+      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
+
+      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
+      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
+      -15,  -15,  -15,   28,  -15,  -15,  -15,  -15,  -15,   29,
+      -15,  -15,  -15,  -15,  -15,   30,  -15,  -15,  -15,  -15,
+      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
+      -15,  -15,  -15,  -15,  -15,   28,  -15,  -15,  -15,  -15,
+      -15,   29,  -15,  -15,  -15,  -15,  -15,   30,  -15,  -15,
+      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15
+    },
+
+    {
+        5,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,   31,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,   31,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16
+    },
+
+    {
+        5,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,   32,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,   32,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17
+    },
+
+    {
+        5,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,   33,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,   33,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18
+    },
+
+    {
+        5,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,   34,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,   34,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19
+
+    },
+
+    {
+        5,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,   35,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,   35,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20
+    },
+
+    {
+        5,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,   36,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,   36,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21
+    },
+
+    {
+        5,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+
+      -22,  -22,  -22,  -22,  -22,  -22,   37,  -22,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22
+    },
+
+    {
+        5,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23
+    },
+
+    {
+        5,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,   40,  -24,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,   41,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,   41,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24
+    },
+
+    {
+        5,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,   25,
+       25,  -25,  -25,   25,  -25,  -25,  -25,  -25,  -25,  -25,
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
+      -25,  -25,   25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
+
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25
+    },
+
+    {
+        5,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+
+      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,   42,   42,
+       42,   42,   42,   42,   42,   42,   42,   42,  -26,  -26,
+      -26,  -26,  -26,  -26,  -26,   42,   42,   42,   42,   42,
+       42,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+      -26,  -26,  -26,  -26,  -26,  -26,  -26,   42,   42,   42,
+       42,   42,   42,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+
+      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26
+    },
+
+    {
+        5,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,   43,   43,   43,   43,   43,
+       43,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+
+      -27,  -27,  -27,  -27,  -27,  -27,  -27,   43,   43,   43,
+       43,   43,   43,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27
+    },
+
+    {
+        5,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+
+      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,   44,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,   44,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28
+    },
+
+    {
+        5,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,   45,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,   45,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29
+
+    },
+
+    {
+        5,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,   46,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,   46,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30
+    },
+
+    {
+        5,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+       47,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,   47,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31
+    },
+
+    {
+        5,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,   48,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,   48,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32
+    },
+
+    {
+        5,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,   49,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+
+       49,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33
+    },
+
+    {
+        5,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,   50,  -34,  -34,  -34,
+
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,   50,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34
+    },
+
+    {
+        5,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,   51,  -35,  -35,   52,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,   51,  -35,  -35,   52,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
+    },
+
+    {
+        5,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,   53,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,   53,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
+    },
+
+    {
+        5,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37
+    },
+
+    {
+        5,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,   40,  -38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,  -38,  -38,
+
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,   41,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,   41,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38
+    },
+
+    {
+        5,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,   54,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,   54,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39
+
+    },
+
+    {
+        5,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40
+    },
+
+    {
+        5,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,   56,  -41,   56,  -41,  -41,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41
+    },
+
+    {
+        5,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42,   42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,   42,   42,   42,   42,   42,
+       42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,   42,   42,   42,
+       42,   42,   42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42
+    },
+
+    {
+        5,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,   43,   43,   43,   43,   43,
+       43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,   43,   43,   43,
+       43,   43,   43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43
+    },
+
+    {
+        5,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,   58,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,   58,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44
+    },
+
+    {
+        5,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+       59,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,   59,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45
+    },
+
+    {
+        5,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,   60,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,   60,  -46,
+
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46
+    },
+
+    {
+        5,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,   61,  -47,  -47,  -47,  -47,  -47,
+
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,   61,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47
+    },
+
+    {
+        5,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,   62,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,   62,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48
+    },
+
+    {
+        5,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,   63,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,   63,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49
+
+    },
+
+    {
+        5,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,   64,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,   64,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50
+    },
+
+    {
+        5,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,   65,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+       65,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51
+    },
+
+    {
+        5,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,   66,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,   66,  -52,  -52,  -52,  -52,  -52,  -52
+    },
+
+    {
+        5,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,   67,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+       67,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53
+    },
+
+    {
+        5,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,   68,  -54,   68,  -54,  -54,   69,   69,
+       69,   69,   69,   69,   69,   69,   69,   69,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54
+    },
+
+    {
+        5,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,   55,   55,
+
+       55,   55,   55,   55,   55,   55,   55,   55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,   41,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,   41,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55
+    },
+
+    {
+        5,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56
+    },
+
+    {
+        5,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57
+    },
+
+    {
+        5,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,   70,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,   70,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58
+    },
+
+    {
+        5,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,   71,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,   71,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59
+
+    },
+
+    {
+        5,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,   72,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+
+      -60,   72,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60
+    },
+
+    {
+        5,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,   73,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,   73,  -61,  -61,  -61,  -61,  -61,  -61
+    },
+
+    {
+        5,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,   74,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,   74,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62
+    },
+
+    {
+        5,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,   75,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+
+      -63,  -63,  -63,  -63,  -63,   75,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63
+    },
+
+    {
+        5,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,   76,  -64,  -64,  -64,  -64,  -64,  -64,
+
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,   76,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64
+    },
+
+    {
+        5,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,   77,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,   77,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65
+    },
+
+    {
+        5,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,   78,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,   78,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66
+    },
+
+    {
+        5,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67
+    },
+
+    {
+        5,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,   69,   69,
+       69,   69,   69,   69,   69,   69,   69,   69,  -68,  -68,
+
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68
+    },
+
+    {
+        5,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,   69,   69,
+       69,   69,   69,   69,   69,   69,   69,   69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69
+
+    },
+
+    {
+        5,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,   79,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,   79,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70
+    },
+
+    {
+        5,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,   80,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,   80,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71
+    },
+
+    {
+        5,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+       81,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,   81,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72
+    },
+
+    {
+        5,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73
+    },
+
+    {
+        5,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+
+      -74,  -74,  -74,  -74,   82,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,   82,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74
+    },
+
+    {
+        5,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,   83,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,   83,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75
+    },
+
+    {
+        5,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,   84,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,   85,  -76,  -76,  -76,
+       86,  -76,  -76,   87,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,   84,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,   85,  -76,
+      -76,  -76,   86,  -76,  -76,   87,  -76,  -76,  -76,  -76,
+
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76
+    },
+
+    {
+        5,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,   88,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,   88,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77
+    },
+
+    {
+        5,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,   89,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,   89,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78
+    },
+
+    {
+        5,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,   90,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,   90,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79
+
+    },
+
+    {
+        5,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,   91,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+       91,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
+    },
+
+    {
+        5,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,   92,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,   92,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81
+    },
+
+    {
+        5,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,   93,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,   93,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82
+    },
+
+    {
+        5,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,   94,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+
+      -83,  -83,  -83,  -83,   94,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
+    },
+
+    {
+        5,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+
+      -84,  -84,  -84,  -84,  -84,   95,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,   95,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84
+    },
+
+    {
+        5,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,   96,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,   96,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85
+    },
+
+    {
+        5,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,   97,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,   97,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86
+    },
+
+    {
+        5,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,   98,  -87,  -87,  -87,  -87,
+
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,   98,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87
+    },
+
+    {
+        5,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88
+    },
+
+    {
+        5,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,   99,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+       99,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89
+
+    },
+
+    {
+        5,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  100,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  100,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
+    },
+
+    {
+        5,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  101,  -91,
+
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      101,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91
+    },
+
+    {
+        5,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  102,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  102,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92
+    },
+
+    {
+        5,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  103,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  103,  -93,  -93,  -93,  -93,  -93,  -93
+    },
+
+    {
+        5,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  104,  -94,  -94,  -94,  -94,  -94,  -94,
+
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  104,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94
+    },
+
+    {
+        5,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  105,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  105,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95
+    },
+
+    {
+        5,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  106,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      106,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96
+    },
+
+    {
+        5,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  107,  -97,  -97,  108,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  107,  -97,  -97,  108,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97
+    },
+
+    {
+        5,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  109,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  109,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98
+    },
+
+    {
+        5,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  110,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  110,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99
+
+    },
+
+    {
+        5, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100,  111, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100,  111, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100
+    },
+
+    {
+        5, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101,  112, -101, -101,
+
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101,  112,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101
+    },
+
+    {
+        5, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102,  113,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102,  113, -102, -102, -102, -102, -102, -102
+    },
+
+    {
+        5, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103,  114, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103,  114,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103
+    },
+
+    {
+        5, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104,  115, -104,
+
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+      115, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104
+    },
+
+    {
+        5, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105,  116, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105,  116, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105
+    },
+
+    {
+        5, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106,  117,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106,  117, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+
+     -106, -106, -106, -106, -106, -106, -106, -106
+    },
+
+    {
+        5, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107,  118, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+      118, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107
+    },
+
+    {
+        5, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108,  119,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108,  119, -108, -108, -108, -108, -108, -108
+    },
+
+    {
+        5, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+      120, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109,  120, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109
+
+    },
+
+    {
+        5, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110
+    },
+
+    {
+        5, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111,  121, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111,  121, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111
+    },
+
+    {
+        5, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112,  122, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112,  122, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112
+    },
+
+    {
+        5, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113,  123, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113,  123, -113, -113, -113, -113, -113, -113,
+
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113
+    },
+
+    {
+        5, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114,  124,
+
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114,  124, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114
+    },
+
+    {
+        5, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115,  125, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115,  125, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115
+    },
+
+    {
+        5, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116,  126,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116,  126, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+
+     -116, -116, -116, -116, -116, -116, -116, -116
+    },
+
+    {
+        5, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117,  127, -117, -117, -117, -117, -117, -117,
+
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117,  127, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117
+    },
+
+    {
+        5, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118,  128, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118,  128, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118
+    },
+
+    {
+        5, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119,  129, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119,  129, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119
+
+    },
+
+    {
+        5, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120,  130, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120,  130, -120, -120,
+
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120
+    },
+
+    {
+        5, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121,  131, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121,  131, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121
+    },
+
+    {
+        5, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122,  132, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122,  132, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122
+    },
+
+    {
+        5, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123,  133,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+
+     -123,  133, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123
+    },
+
+    {
+        5, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124,  134, -124, -124, -124,
+
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124,  134, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124
+    },
+
+    {
+        5, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125,  135, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125,  135,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125
+    },
+
+    {
+        5, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126,  136, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126,  136,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+
+     -126, -126, -126, -126, -126, -126, -126, -126
+    },
+
+    {
+        5, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127,  137, -127, -127, -127, -127, -127,
+
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127,  137, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127
+    },
+
+    {
+        5, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128,  138, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128,  138,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128
+    },
+
+    {
+        5, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129,  139,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129,  139, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129
+
+    },
+
+    {
+        5, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130,  140, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130,  140,
+
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130
+    },
+
+    {
+        5, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+
+     -131, -131, -131,  141, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131,  141, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131
+    },
+
+    {
+        5, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132,  142, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132,  142, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132
+    },
+
+    {
+        5, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133,  143, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+
+      143, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133
+    },
+
+    {
+        5, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134,  144, -134, -134, -134,
+
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134,  144, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134
+    },
+
+    {
+        5, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135
+    },
+
+    {
+        5, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+
+     -136, -136, -136, -136, -136, -136, -136, -136
+    },
+
+    {
+        5, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137,  145, -137, -137, -137, -137, -137, -137, -137,
+
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137,  145, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137
+    },
+
+    {
+        5, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138
+    },
+
+    {
+        5, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139,  146, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+      146, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139
+
+    },
+
+    {
+        5, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140,  147,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+
+     -140,  147, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140
+    },
+
+    {
+        5, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+
+     -141, -141, -141, -141, -141, -141, -141, -141,  148, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+      148, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141
+    },
+
+    {
+        5, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142,  149,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142,  149, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142
+    },
+
+    {
+        5, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143,  150, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143,  150,
+
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143
+    },
+
+    {
+        5, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144,  151,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144,  151, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144
+    },
+
+    {
+        5, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145,  152, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145,  152, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145
+    },
+
+    {
+        5, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146,  153, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146,  153,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+
+     -146, -146, -146, -146, -146, -146, -146, -146
+    },
+
+    {
+        5, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147,  154, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147,  154,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147
+    },
+
+    {
+        5, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148,  155, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148,  155, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148
+    },
+
+    {
+        5, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149,  156, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149,  156,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149
+
+    },
+
+    {
+        5, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150
+    },
+
+    {
+        5, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151,  157, -151, -151,
+
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151,  157,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151
+    },
+
+    {
+        5, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152,  158, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+      158, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152
+    },
+
+    {
+        5, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153
+    },
+
+    {
+        5, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154
+    },
+
+    {
+        5, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155,  159, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155,  159,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155
+    },
+
+    {
+        5, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+
+     -156, -156, -156, -156, -156, -156, -156, -156
+    },
+
+    {
+        5, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157,  160, -157, -157, -157, -157, -157,
+
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157,  160, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157
+    },
+
+    {
+        5, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158,  161, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158,  161, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158
+    },
+
+    {
+        5, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+
+     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159
+
+    },
+
+    {
+        5, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160,  162, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+
+     -160, -160, -160, -160, -160,  162, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160
+    },
+
+    {
+        5, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+
+     -161, -161, -161, -161, -161, -161, -161,  163, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161,  163,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161
+    },
+
+    {
+        5, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162,  164,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162,  164, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162
+    },
+
+    {
+        5, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163
+    },
+
+    {
+        5, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164,  165, -164,
+
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+      165, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164
+    },
+
+    {
+        5, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165,  166, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165,  166,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165
+    },
+
+    {
+        5, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+
+     -166, -166, -166, -166, -166, -166, -166, -166
+    },
+
+    } ;
+
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yytext_ptr = yy_bp; \
+	yyleng = (int) (yy_cp - yy_bp); \
+	yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 38
+#define YY_END_OF_BUFFER 39
+static yyconst short int yy_accept[167] =
+    {   0,
+        0,    0,    0,    0,   39,   37,   36,   36,   31,   32,
+       33,   37,   35,   34,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,    1,   36,    3,    4,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    1,    2,    0,
+        0,    3,    4,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    1,    0,    1,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,   29,    0,    2,    0,
+        0,    0,   30,    0,    0,    0,    5,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    6,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   11,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   12,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    7,   21,    0,   17,    0,    0,
+        0,    0,    0,    0,    8,   22,    0,   18,    0,    0,
+        0,    0,   15,    0,    0,   23,   25,    0,   13,   16,
+        0,    0,   24,   26,    9,   14,    0,    0,   10,    0,
+       19,    0,   20,    0,   27,   28
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+static yyconst yy_state_type yy_NUL_trans[167] =
+    {   0,
+        6,    6,    6,    6,    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,    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,    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,    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,    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,    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,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0
+    } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "wktparse.lex"
+#define INITIAL 0
+/*
+ * Written by Ralph Mason ralph.mason<at>telogis.com
+ *
+ * Copyright Telogis 2004
+ * www.telogis.com
+ *
+ */
+#define vals_ok 1
+
+#line 11 "wktparse.lex"
+#include "wktparse.tab.h"
+#include <unistd.h>
+#include <stdlib.h> // need stdlib for atof() definition 
+
+void init_parser(const char *src);
+void close_parser(void);
+int lwg_parse_yywrap(void);
+int lwg_parse_yylex(void);
+
+static YY_BUFFER_STATE buf_state;
+   void init_parser(const char *src) { BEGIN(0);buf_state = lwg_parse_yy_scan_string(src); }
+   void close_parser() { lwg_parse_yy_delete_buffer(buf_state); }
+   int lwg_parse_yywrap(void){ return 1; }
+
+#line 3281 "lex.yy.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
+		YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+YY_DECL
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp = NULL, *yy_bp = NULL;
+	register int yy_act;
+
+#line 27 "wktparse.lex"
+
+
+#line 3422 "lex.yy.c"
+
+	if ( yy_init )
+		{
+		yy_init = 0;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yy_start )
+			yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! yy_current_buffer )
+			yy_current_buffer =
+				yy_create_buffer( yyin, YY_BUF_SIZE );
+
+		yy_load_buffer_state();
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yy_start;
+yy_match:
+		while ( (yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)]) > 0 )
+			{
+			if ( yy_accept[yy_current_state] )
+				{
+				yy_last_accepting_state = yy_current_state;
+				yy_last_accepting_cpos = yy_cp;
+				}
+
+			++yy_cp;
+			}
+
+		yy_current_state = -yy_current_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+
+do_action:	/* This label is used only to access EOF actions. */
+
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yy_hold_char;
+			yy_cp = yy_last_accepting_cpos + 1;
+			yy_current_state = yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 29 "wktparse.lex"
+{ lwg_parse_yylval.value=atof(lwg_parse_yytext); return VALUE; }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 30 "wktparse.lex"
+{ lwg_parse_yylval.value=atof(lwg_parse_yytext); return VALUE; }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 32 "wktparse.lex"
+{  lwg_parse_yylval.wkb=lwg_parse_yytext; return WKB;}
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 33 "wktparse.lex"
+{  lwg_parse_yylval.wkb=lwg_parse_yytext; return WKB;}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 35 "wktparse.lex"
+{ return POINT; }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 36 "wktparse.lex"
+{ return POINTM; }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 37 "wktparse.lex"
+{ return LINESTRING; }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 38 "wktparse.lex"
+{ return LINESTRINGM; }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 39 "wktparse.lex"
+{ return CIRCULARSTRING; }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 40 "wktparse.lex"
+{ return CIRCULARSTRINGM; }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 41 "wktparse.lex"
+{ return POLYGON; }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 42 "wktparse.lex"
+{ return POLYGONM; }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 43 "wktparse.lex"
+{ return COMPOUNDCURVE; }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 44 "wktparse.lex"
+{ return COMPOUNDCURVEM; }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 45 "wktparse.lex"
+{ return CURVEPOLYGON; }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 46 "wktparse.lex"
+{ return CURVEPOLYGONM; }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 47 "wktparse.lex"
+{ return MULTIPOINT; }
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 48 "wktparse.lex"
+{ return MULTIPOINTM; }
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 49 "wktparse.lex"
+{ return MULTILINESTRING; }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 50 "wktparse.lex"
+{ return MULTILINESTRINGM; }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 51 "wktparse.lex"
+{ return MULTICURVE; }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 52 "wktparse.lex"
+{ return MULTICURVEM; }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 53 "wktparse.lex"
+{ return MULTIPOLYGON; }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 54 "wktparse.lex"
+{ return MULTIPOLYGONM; }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 55 "wktparse.lex"
+{ return MULTISURFACE; }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 56 "wktparse.lex"
+{ return MULTISURFACEM; }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 57 "wktparse.lex"
+{ return GEOMETRYCOLLECTION; }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 58 "wktparse.lex"
+{ return GEOMETRYCOLLECTIONM; }
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 59 "wktparse.lex"
+{ BEGIN(vals_ok); return SRID; }
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 60 "wktparse.lex"
+{ return EMPTY; }
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 62 "wktparse.lex"
+{ BEGIN(vals_ok); return LPAREN; }
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 63 "wktparse.lex"
+{ return RPAREN; }
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 64 "wktparse.lex"
+{ return COMMA ; }
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 65 "wktparse.lex"
+{ return EQUALS ; }
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 66 "wktparse.lex"
+{ BEGIN(0); return SEMICOLON; }
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 67 "wktparse.lex"
+/*eat whitespace*/
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 68 "wktparse.lex"
+{ return lwg_parse_yytext[0]; }
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 70 "wktparse.lex"
+ECHO;
+	YY_BREAK
+#line 3683 "lex.yy.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(vals_ok):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between yy_current_buffer and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yy_n_chars = yy_current_buffer->yy_n_chars;
+			yy_current_buffer->yy_input_file = yyin;
+			yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state();
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yy_c_buf_p;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer() )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yy_did_buffer_switch_on_eof = 0;
+
+				if ( yywrap() )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yy_c_buf_p =
+					yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yy_c_buf_p =
+				&yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+	} /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+	{
+	register char *dest = yy_current_buffer->yy_ch_buf;
+	register char *source = yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( yy_current_buffer->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+	else
+		{
+		int num_to_read =
+			yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+			YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = yy_current_buffer;
+
+			int yy_c_buf_p_offset =
+				(int) (yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yy_flex_realloc( (void *) b->yy_ch_buf,
+							 b->yy_buf_size + 2 );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = yy_current_buffer->yy_buf_size -
+						number_to_move - 1;
+#endif
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+			yy_n_chars, num_to_read );
+
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	if ( yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart( yyin );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			yy_current_buffer->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	yy_n_chars += number_to_move;
+	yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+	return ret_val;
+	}
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+
+	yy_current_state = yy_start;
+
+	for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+		{
+		if ( *yy_cp )
+			{
+			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
+			}
+		else
+			yy_current_state = yy_NUL_trans[yy_current_state];
+		if ( yy_accept[yy_current_state] )
+			{
+			yy_last_accepting_state = yy_current_state;
+			yy_last_accepting_cpos = yy_cp;
+			}
+		}
+
+	return yy_current_state;
+	}
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+	{
+	register int yy_is_jam;
+	register char *yy_cp = yy_c_buf_p;
+
+	yy_current_state = yy_NUL_trans[yy_current_state];
+	yy_is_jam = (yy_current_state == 0);
+
+	if ( ! yy_is_jam )
+		{
+		if ( yy_accept[yy_current_state] )
+			{
+			yy_last_accepting_state = yy_current_state;
+			yy_last_accepting_cpos = yy_cp;
+			}
+		}
+
+	return yy_is_jam ? 0 : yy_current_state;
+	}
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+	{
+	register char *yy_cp = yy_c_buf_p;
+
+	/* undo effects of setting up yytext */
+	*yy_cp = yy_hold_char;
+
+	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = yy_n_chars + 2;
+		register char *dest = &yy_current_buffer->yy_ch_buf[
+					yy_current_buffer->yy_buf_size + 2];
+		register char *source =
+				&yy_current_buffer->yy_ch_buf[number_to_move];
+
+		while ( source > yy_current_buffer->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		yy_current_buffer->yy_n_chars =
+			yy_n_chars = yy_current_buffer->yy_buf_size;
+
+		if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+
+	yytext_ptr = yy_bp;
+	yy_hold_char = *yy_cp;
+	yy_c_buf_p = yy_cp;
+	}
+#endif	/* ifndef YY_NO_UNPUT */
+
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+	{
+	int c;
+
+	*yy_c_buf_p = yy_hold_char;
+
+	if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			/* This was really a NUL. */
+			*yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yy_c_buf_p - yytext_ptr;
+			++yy_c_buf_p;
+
+			switch ( yy_get_next_buffer() )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart( yyin );
+
+					/* fall through */
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap() )
+						return EOF;
+
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yy_c_buf_p = yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yy_c_buf_p;	/* cast for 8-bit char's */
+	*yy_c_buf_p = '\0';	/* preserve yytext */
+	yy_hold_char = *++yy_c_buf_p;
+
+
+	return c;
+	}
+#endif /* YY_NO_INPUT */
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+	{
+	if ( ! yy_current_buffer )
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+	yy_init_buffer( yy_current_buffer, input_file );
+	yy_load_buffer_state();
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+	{
+	if ( yy_current_buffer == new_buffer )
+		return;
+
+	if ( yy_current_buffer )
+		{
+		/* Flush out information for old buffer. */
+		*yy_c_buf_p = yy_hold_char;
+		yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	yy_current_buffer = new_buffer;
+	yy_load_buffer_state();
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yy_did_buffer_switch_on_eof = 1;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+	{
+	yy_n_chars = yy_current_buffer->yy_n_chars;
+	yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+	yyin = yy_current_buffer->yy_input_file;
+	yy_hold_char = *yy_c_buf_p;
+	}
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer( b, file );
+
+	return b;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+	{
+	if ( ! b )
+		return;
+
+	if ( b == yy_current_buffer )
+		yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yy_flex_free( (void *) b->yy_ch_buf );
+
+	yy_flex_free( (void *) b );
+	}
+
+
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+	{
+	yy_flush_buffer( b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+	b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+	b->yy_is_interactive = 0;
+#else
+	b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+	{
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == yy_current_buffer )
+		yy_load_buffer_state();
+	}
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer( b );
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+	{
+	int len;
+	for ( len = 0; yy_str[len]; ++len )
+		;
+
+	return yy_scan_bytes( yy_str, len );
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+	{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = len + 2;
+	buf = (char *) yy_flex_alloc( n );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < len; ++i )
+		buf[i] = bytes[i];
+
+	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer( buf, n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+	{
+	if ( yy_start_stack_ptr >= yy_start_stack_depth )
+		{
+		yy_size_t new_size;
+
+		yy_start_stack_depth += YY_START_STACK_INCR;
+		new_size = yy_start_stack_depth * sizeof( int );
+
+		if ( ! yy_start_stack )
+			yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+		else
+			yy_start_stack = (int *) yy_flex_realloc(
+					(void *) yy_start_stack, new_size );
+
+		if ( ! yy_start_stack )
+			YY_FATAL_ERROR(
+			"out of memory expanding start-condition stack" );
+		}
+
+	yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+	BEGIN(new_state);
+	}
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+	{
+	if ( --yy_start_stack_ptr < 0 )
+		YY_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN(yy_start_stack[yy_start_stack_ptr]);
+	}
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+	{
+	return yy_start_stack[yy_start_stack_ptr - 1];
+	}
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+	{
+	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+	}
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		yytext[yyleng] = yy_hold_char; \
+		yy_c_buf_p = yytext + n; \
+		yy_hold_char = *yy_c_buf_p; \
+		*yy_c_buf_p = '\0'; \
+		yyleng = n; \
+		} \
+	while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+	{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+	}
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+	{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+	}
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+	{
+	return (void *) malloc( size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+	{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+	{
+	free( ptr );
+	}
+
+#if YY_MAIN
+int main()
+	{
+	yylex();
+	return 0;
+	}
+#endif
+#line 70 "wktparse.lex"
+
+

Added: trunk/liblwgeom/liblwgeom.h
===================================================================
--- trunk/liblwgeom/liblwgeom.h	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/liblwgeom.h	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,1269 @@
+#ifndef _LIBLWGEOM_H
+#define _LIBLWGEOM_H 1
+
+#include "../postgis_config.h"
+#include <stdio.h>
+/* #include "compat.h" */
+
+#define INTEGRITY_CHECKS 1
+
+/*
+ * Floating point comparitors.
+ */
+#define PGIS_EPSILON 1e-12
+#define FP_MAX(A, B) ((A > B) ? A : B)
+#define FP_MIN(A, B) ((A < B) ? A : B)
+#define FP_LT(A, B) ((A + PGIS_EPSILON) < B)
+#define FP_LTEQ(A, B) ((A - PGIS_EPSILON) <= B)
+#define FP_CONTAINS_TOP(A, X, B) (FP_LT(A, X) && FP_LTEQ(X, B))
+#define FP_CONTAINS_BOTTOM(A, X, B) (FP_LTEQ(A, X) && FP_LT(X, B))
+#define FP_CONTAINS_INCL(A, X, B) (FP_LTEQ(A, X) && FP_LTEQ(X, B))
+#define FP_CONTAINS_EXCL(A, X, B) (FP_LT(A, X) && FP_LT(X, B))
+#define FP_CONTAINS(A, X, B) FP_CONTAINS_EXCL(A, X, B)
+
+/*
+ * Memory management function types
+ */
+extern void lwgeom_init_allocators(void);
+
+typedef void* (*lwallocator)(size_t size);
+typedef void* (*lwreallocator)(void *mem, size_t size);
+typedef void (*lwfreeor)(void* mem);
+typedef void (*lwreporter)(const char* fmt, ...);
+
+#ifndef C_H
+
+typedef unsigned int uint32;
+typedef int int32;
+
+#endif
+
+/*
+ * this will change to NaN when I figure out how to
+ * get NaN in a platform-independent way
+ */
+#define NO_VALUE 0.0
+#define NO_Z_VALUE NO_VALUE
+#define NO_M_VALUE NO_VALUE
+
+
+/* prototypes */
+void *default_allocator(size_t size);
+void *default_reallocator(void *mem, size_t size);
+void default_freeor(void *ptr);
+void default_errorreporter(const char *fmt, ...);
+void default_noticereporter(const char *fmt, ...);
+
+/* globals */
+extern lwreallocator lwrealloc_var;
+extern lwallocator lwalloc_var;
+extern lwfreeor lwfree_var;
+extern lwreporter lwerror;
+extern lwreporter lwnotice;
+
+/* Debug macros */
+#if POSTGIS_DEBUG_LEVEL > 0
+
+/* Display a notice at the given debug level */
+#define LWDEBUG(level, msg) \
+        do { \
+                if (POSTGIS_DEBUG_LEVEL >= level) \
+                        lwnotice("[%s:%s:%d] " msg, __FILE__, __func__, __LINE__); \
+        } while (0);
+
+/* Display a formatted notice at the given debug level (like printf, with variadic arguments) */
+#define LWDEBUGF(level, msg, ...) \
+        do { \
+                if (POSTGIS_DEBUG_LEVEL >= level) \
+                        lwnotice("[%s:%s:%d] " msg, __FILE__, __func__, __LINE__, __VA_ARGS__); \
+        } while (0);
+
+#else
+
+/* Empty prototype that can be optimised away by the compiler for non-debug builds */
+#define LWDEBUG(level, msg) \
+        ((void) 0)
+
+/* Empty prototype that can be optimised away by the compiler for non-debug builds */
+#define LWDEBUGF(level, msg, ...) \
+        ((void) 0)
+
+#endif
+
+/******************************************************************/
+
+typedef unsigned char uchar;
+
+typedef struct
+{
+	float xmin;
+	float ymin;
+	float xmax;
+	float ymax;
+} BOX2DFLOAT4;
+
+typedef struct
+{
+        double xmin, ymin, zmin;
+        double xmax, ymax, zmax;
+} BOX3D;
+
+typedef struct chiptag
+{
+	int size; /* unused (for use by postgresql) */
+
+	int endian_hint; /* the number 1 in the endian of this datastruct */
+
+	BOX3D bvol;
+	int SRID;
+	char future[4];
+	float factor;	/* Usually 1.0.
+			 * Integer values are multiplied by this number
+			 * to get the actual height value
+			 * (for sub-meter accuracy height data).
+			 */
+
+	int datatype;	/* 1 = float32,
+			 * 5 = 24bit integer,
+			 * 6 = 16bit integer (short)
+			 * 7 = 16bit ???
+			 * 8 = 8bit ???
+			 * 101 = float32 (NDR),
+			 * 105 = 24bit integer (NDR),
+			 * 106 = 16bit int (NDR)
+			 * 107 = 16bit ??? (NDR)
+			 * 108 = 8bit ??? (NDR) (this doesn't make sense)
+			 */
+	int height;
+	int width;
+	int compression;	/* 0 = no compression, 1 = differencer
+				 * 0x80 = new value
+				 * 0x7F = nodata
+				 */
+
+	/*
+	 * this is provided for convenience, it should be set to
+	 *  sizeof(chip) bytes into the struct because the serialized form is:
+	 *    <header><data>
+	 * NULL when serialized
+	 */
+	void  *data;	/* data[0] = bottm left,
+			 * data[width] = 1st pixel, 2nd row (uncompressed)
+			 */
+
+} CHIP;
+
+/*
+ * standard definition of an ellipsoid (what wkt calls a spheroid)
+ *    f = (a-b)/a
+ *    e_sq = (a*a - b*b)/(a*a)
+ *    b = a - fa
+ */
+typedef struct
+{
+	double	a;	/* semimajor axis */
+	double	b; 	/* semiminor axis */
+	double	f;	/* flattening     */
+	double	e;	/* eccentricity (first) */
+	double	e_sq;	/* eccentricity (first), squared */
+	char	name[20]; /* name of ellipse */
+} SPHEROID;
+
+
+/*
+ * ALL LWGEOM structures will use POINT3D as an abstract point.
+ * This means a 2d geometry will be stored as (x,y) in its serialized
+ * form, but all functions will work on (x,y,0).  This keeps all the
+ * analysis functions simple.
+ * NOTE: for GEOS integration, we'll probably set z=NaN
+ *        so look out - z might be NaN for 2d geometries!
+ */
+typedef struct { double	x,y,z; } POINT3DZ;
+typedef struct { double	x,y,z; } POINT3D; /* alias for POINT3DZ */
+typedef struct { double	x,y,m; } POINT3DM;
+
+
+/*
+ * type for 2d points.  When you convert this to 3d, the
+ *   z component will be either 0 or NaN.
+ */
+typedef struct
+{
+	 double x;
+	 double y;
+} POINT2D;
+
+typedef struct
+{
+	 double x;
+	 double y;
+	 double z;
+	 double m;
+} POINT4D;
+
+/******************************************************************/
+
+/*
+ * Point array abstracts a lot of the complexity of points and point lists.
+ * It handles miss-alignment in the serialized form, 2d/3d translation
+ *    (2d points converted to 3d will have z=0 or NaN)
+ * DONT MIX 2D and 3D POINTS!  *EVERYTHING* is either one or the other
+ */
+typedef struct
+{
+    /* array of POINT 2D, 3D or 4D. probably missaligned. */
+    uchar *serialized_pointlist;
+
+    /* use TYPE_* macros to handle */
+    uchar  dims;
+
+    uint32 npoints;
+}  POINTARRAY;
+
+
+/*
+ * Use the following to build pointarrays
+ * when number of points in output is not 
+ * known in advance
+ */
+typedef struct {
+	POINTARRAY *pa;
+	size_t ptsize;
+	size_t capacity; /* given in points */
+} DYNPTARRAY;
+
+/* Create a new dynamic pointarray */
+extern DYNPTARRAY *dynptarray_create(size_t initial_capacity, int dims);
+
+/*
+ * Add a POINT4D to the dynamic pointarray.
+ *
+ * The dynamic pointarray may be of any dimension, only
+ * accepted dimensions will be copied.
+ *
+ * If allow_duplicates is set to 0 (false) a check
+ * is performed to see if last point in array is equal to the
+ * provided one. NOTE that the check is 4d based, with missing
+ * ordinates in the pointarray set to NO_Z_VALUE and NO_M_VALUE
+ * respectively.
+ */
+extern int dynptarray_addPoint4d(DYNPTARRAY *dpa, POINT4D *p4d,
+	int allow_duplicates);
+
+/******************************************************************
+ *
+ * LWGEOM (any type)
+ *
+ ******************************************************************/
+
+typedef struct
+{
+	uchar type; 
+	BOX2DFLOAT4 *bbox;
+	uint32 SRID; /* -1 == unneeded */
+	void *data;
+} LWGEOM;
+
+/* POINTYPE */
+typedef struct
+{
+	uchar type; /* POINTTYPE */
+	BOX2DFLOAT4 *bbox;
+   	uint32 SRID;	
+   	POINTARRAY *point;  /* hide 2d/3d (this will be an array of 1 point) */
+}  LWPOINT; /* "light-weight point" */
+
+/* LINETYPE */
+typedef struct
+{
+	uchar type; /* LINETYPE */
+	BOX2DFLOAT4 *bbox;
+   	uint32 SRID;	
+	POINTARRAY    *points; /* array of POINT3D */
+} LWLINE; /* "light-weight line" */
+
+/* POLYGONTYPE */
+typedef struct
+{
+	uchar type; /* POLYGONTYPE */
+	BOX2DFLOAT4 *bbox;
+   	uint32 SRID;	
+	int  nrings;
+	POINTARRAY **rings; /* list of rings (list of points) */
+} LWPOLY; /* "light-weight polygon" */
+
+/* MULTIPOINTTYPE */
+typedef struct
+{
+	uchar type;  
+	BOX2DFLOAT4 *bbox;
+   	uint32 SRID;	
+	int  ngeoms;
+	LWPOINT **geoms;
+} LWMPOINT; 
+
+/* MULTILINETYPE */
+typedef struct
+{  
+	uchar type; 
+	BOX2DFLOAT4 *bbox;
+   	uint32 SRID;	
+	int  ngeoms;
+	LWLINE **geoms;
+} LWMLINE; 
+
+/* MULTIPOLYGONTYPE */
+typedef struct
+{  
+	uchar type; 
+	BOX2DFLOAT4 *bbox;
+   	uint32 SRID;	
+	int  ngeoms;
+	LWPOLY **geoms;
+} LWMPOLY; 
+
+/* COLLECTIONTYPE */
+typedef struct
+{   
+	uchar type; 
+	BOX2DFLOAT4 *bbox;
+   	uint32 SRID;	
+	int  ngeoms;
+	LWGEOM **geoms;
+} LWCOLLECTION; 
+
+/* Casts LWGEOM->LW* (return NULL if cast is illegal) */
+extern LWMPOLY *lwgeom_as_lwmpoly(LWGEOM *lwgeom);
+extern LWMLINE *lwgeom_as_lwmline(LWGEOM *lwgeom);
+extern LWMPOINT *lwgeom_as_lwmpoint(LWGEOM *lwgeom);
+extern LWCOLLECTION *lwgeom_as_lwcollection(LWGEOM *lwgeom);
+extern LWPOLY *lwgeom_as_lwpoly(LWGEOM *lwgeom);
+extern LWLINE *lwgeom_as_lwline(LWGEOM *lwgeom);
+extern LWPOINT *lwgeom_as_lwpoint(LWGEOM *lwgeom);
+
+/* Casts LW*->LWGEOM (always cast) */
+extern LWGEOM *lwmpoly_as_lwgeom(LWMPOLY *obj);
+extern LWGEOM *lwmline_as_lwgeom(LWMLINE *obj);
+extern LWGEOM *lwmpoint_as_lwgeom(LWMPOINT *obj);
+extern LWGEOM *lwcollection_as_lwgeom(LWCOLLECTION *obj);
+extern LWGEOM *lwpoly_as_lwgeom(LWPOLY *obj);
+extern LWGEOM *lwline_as_lwgeom(LWLINE *obj);
+extern LWGEOM *lwpoint_as_lwgeom(LWPOINT *obj);
+
+/*
+ * Call this function everytime LWGEOM coordinates 
+ * change so to invalidate bounding box
+ */
+extern void lwgeom_changed(LWGEOM *lwgeom);
+
+/*
+ * Call this function to drop BBOX and SRID
+ * from LWGEOM. If LWGEOM type is *not* flagged
+ * with the HASBBOX flag and has a bbox, it
+ * will be released.
+ */
+extern void lwgeom_dropBBOX(LWGEOM *lwgeom);
+
+/* Compute a bbox if not already computed */
+extern void lwgeom_addBBOX(LWGEOM *lwgeom);
+
+extern void lwgeom_dropSRID(LWGEOM *lwgeom);
+
+/******************************************************************/
+
+/*
+ * copies a point from the point array into the parameter point
+ * will set point's z=0 (or NaN) if pa is 2d
+ * will set point's m=0 (or NaN) if pa is 3d or 2d
+ * NOTE: point is a real POINT3D *not* a pointer
+ */
+extern POINT4D getPoint4d(const POINTARRAY *pa, int n);
+
+/*
+ * copies a point from the point array into the parameter point
+ * will set point's z=0 (or NaN) if pa is 2d
+ * will set point's m=0 (or NaN) if pa is 3d or 2d
+ * NOTE: this will modify the point4d pointed to by 'point'.
+ */
+extern int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point);
+
+/*
+ * copies a point from the point array into the parameter point
+ * will set point's z=0 (or NaN) if pa is 2d
+ * NOTE: point is a real POINT3D *not* a pointer
+ */
+extern POINT3DZ getPoint3dz(const POINTARRAY *pa, int n);
+extern POINT3DM getPoint3dm(const POINTARRAY *pa, int n);
+
+/*
+ * copies a point from the point array into the parameter point
+ * will set point's z=0 (or NaN) if pa is 2d
+ * NOTE: this will modify the point3d pointed to by 'point'.
+ */
+extern int getPoint3dz_p(const POINTARRAY *pa, int n, POINT3DZ *point);
+extern int getPoint3dm_p(const POINTARRAY *pa, int n, POINT3DM *point);
+
+
+/*
+ * copies a point from the point array into the parameter point
+ * z value (if present is not returned)
+ * NOTE: point is a real POINT3D *not* a pointer
+ */
+extern POINT2D getPoint2d(const POINTARRAY *pa, int n);
+
+/*
+ * copies a point from the point array into the parameter point
+ * z value (if present is not returned)
+ * NOTE: this will modify the point2d pointed to by 'point'.
+ */
+extern int getPoint2d_p(const POINTARRAY *pa, int n, POINT2D *point);
+
+/*
+ * set point N to the given value
+ * NOTE that the pointarray can be of any
+ * dimension, the appropriate ordinate values
+ * will be extracted from it
+ *
+ */
+extern void setPoint4d(POINTARRAY *pa, int n, POINT4D *p4d);
+
+/*
+ * get a pointer to nth point of a POINTARRAY
+ * You'll need to cast it to appropriate dimensioned point.
+ * Note that if you cast to a higher dimensional point you'll
+ * possibly corrupt the POINTARRAY.
+ *
+ * WARNING: Don't cast this to a POINT !
+ * it would not be reliable due to memory alignment constraints 
+ */
+extern uchar *getPoint_internal(const POINTARRAY *pa, int n);
+
+/* --- here is a macro equivalent, for speed... */
+/* #define getPoint(x,n) &( (x)->serialized_pointlist[((x)->ndims*8)*(n)] ) */
+
+
+/*
+ * constructs a POINTARRAY.
+ * NOTE: points is *not* copied, so be careful about modification
+ * (can be aligned/missaligned)
+ * NOTE: hasz and hasm are descriptive - it describes what type of data
+ *	 'points' points to.  No data conversion is done.
+ */
+extern POINTARRAY *pointArray_construct(uchar *points, char hasz, char hasm,
+	uint32 npoints);
+
+/* 
+ * Calculate the (BOX3D) bounding box of a set of points.
+ * Returns an alloced BOX3D or NULL (for empty geom) in the first form.
+ * Write result in user-provided BOX3D in second form (return 0 if untouched).
+ * If pa is 2d, then box3d's zmin/zmax will be set to NO_Z_VALUE
+ */
+extern BOX3D *ptarray_compute_box3d(const POINTARRAY *pa);
+extern int ptarray_compute_box3d_p(const POINTARRAY *pa, BOX3D *out);
+
+/*
+ * size of point represeneted in the POINTARRAY
+ * 16 for 2d, 24 for 3d, 32 for 4d
+ */
+extern int pointArray_ptsize(const POINTARRAY *pa);
+
+
+#define	POINTTYPE	1
+#define	LINETYPE	2
+#define	POLYGONTYPE	3
+#define	MULTIPOINTTYPE	4
+#define	MULTILINETYPE	5
+#define	MULTIPOLYGONTYPE	6
+#define	COLLECTIONTYPE	7
+
+#define WKBZOFFSET 0x80000000
+#define WKBMOFFSET 0x40000000
+#define WKBSRIDFLAG 0x20000000
+#define WKBBBOXFLAG 0x10000000
+
+/* These macros work on PG_LWGEOM.type, LWGEOM.type and all its subclasses */
+
+#define TYPE_SETTYPE(c,t) ((c)=(((c)&0xF0)|(t)))
+#define TYPE_SETZM(t,z,m) ((t)=(((t)&0xCF)|((z)<<5)|((m)<<4)))
+#define TYPE_SETHASBBOX(t,b) ((t)=(((t)&0x7F)|((b)<<7)))
+#define TYPE_SETHASSRID(t,s) ((t)=(((t)&0xBF)|((s)<<6)))
+
+#define TYPE_HASZ(t) ( ((t)&0x20)>>5 )
+#define TYPE_HASM(t) ( ((t)&0x10)>>4 )
+#define TYPE_HASBBOX(t) ( ((t)&0x80)>>7 )
+#define TYPE_HASSRID(t) ( (((t)&0x40))>>6 )
+#define TYPE_NDIMS(t) ((((t)&0x20)>>5)+(((t)&0x10)>>4)+2)
+#define TYPE_GETTYPE(t) ((t)&0x0F)
+
+/* 0x02==Z 0x01==M */
+#define TYPE_GETZM(t) (((t)&0x30)>>4)
+
+extern char lwgeom_hasBBOX(uchar type); /* true iff B bit set     */
+extern int  lwgeom_ndims(uchar type);   /* returns 2,3 or 4       */
+extern int  lwgeom_hasZ(uchar type);    /* has Z ?                */
+extern int  lwgeom_hasM(uchar type);    /* has M ?                */
+extern int  lwgeom_getType(uchar type); /* returns the tttt value */
+
+extern uchar lwgeom_makeType(char hasZ, char hasM, char hasSRID, int type);
+extern uchar lwgeom_makeType_full(char hasZ, char hasM, char hasSRID, int type, char hasBBOX);
+extern char lwgeom_hasSRID(uchar type); /* true iff S bit is set */
+extern char lwgeom_hasBBOX(uchar type); /* true iff B bit set    */
+
+
+
+/*
+ * This is the binary representation of lwgeom compatible
+ * with postgresql varlena struct
+ */
+typedef struct {
+	uint32 size;        /* varlena header (do not touch directly!) */
+	uchar type;         /* encodes ndims, type, bbox presence,
+		                srid presence */
+	uchar data[1];
+} PG_LWGEOM;
+
+/*
+ * Construct a full PG_LWGEOM type (including size header)
+ * from a serialized form.
+ * The constructed PG_LWGEOM object will be allocated using palloc
+ * and the serialized form will be copied.
+ * If you specify a SRID other then -1 it will be set.
+ * If you request bbox (wantbbox=1) it will be extracted or computed
+ * from the serialized form.
+ */
+extern PG_LWGEOM *PG_LWGEOM_construct(uchar *serialized, int SRID,
+	int wantbbox);
+
+/*
+ * Compute bbox of serialized geom
+ */
+extern int compute_serialized_box2d_p(uchar *serialized_form, BOX2DFLOAT4 *box);
+extern BOX3D *compute_serialized_box3d(uchar *serialized_form);
+extern int compute_serialized_box3d_p(uchar *serialized_form, BOX3D *box);
+
+
+/*
+ * Evaluate with an heuristic if the provided PG_LWGEOM is worth
+ * caching a bbox
+ */
+char is_worth_caching_pglwgeom_bbox(const PG_LWGEOM *);
+char is_worth_caching_serialized_bbox(const uchar *);
+char is_worth_caching_lwgeom_bbox(const LWGEOM *);
+
+/*
+ * Use this macro to extract the char * required
+ * by most functions from an PG_LWGEOM struct.
+ * (which is an PG_LWGEOM w/out int32 size casted to char *)
+ */
+#define SERIALIZED_FORM(x) ((uchar *)VARDATA((x)))
+
+/*
+    This structure is a "glue" structure for returning a serialized
+    LWGEOM from the parser, along with its size. By using a separate
+    type, we remove the constraint that the output from the
+    parser must be PG_LWGEOM format (and hence protect ourselves
+    from future varlena changes)
+*/
+typedef struct serialized_lwgeom {
+    uchar *lwgeom;
+    int size;
+} SERIALIZED_LWGEOM;
+
+/*
+ * This function computes the size in bytes
+ * of the serialized geometries.
+ */
+extern size_t lwgeom_size(const uchar *serialized_form);
+extern size_t lwgeom_size_subgeom(const uchar *serialized_form, int geom_number);
+extern size_t lwgeom_size_line(const uchar *serialized_line);
+extern size_t lwgeom_size_curve(const uchar *serialized_curve);
+extern size_t lwgeom_size_point(const uchar *serialized_point);
+extern size_t lwgeom_size_poly(const uchar *serialized_line);
+
+
+/*--------------------------------------------------------
+ * all the base types (point/line/polygon) will have a
+ * basic constructor, basic de-serializer, basic serializer,
+ * bounding box finder and (TODO) serialized form size finder.
+ *--------------------------------------------------------*/
+
+/*
+ * given the LWPOINT serialized form (or a pointer into a muli* one)
+ * construct a proper LWPOINT.
+ * serialized_form should point to the 8bit type format (with type = 1)
+ * Returns NULL if serialized form is not a point.
+ * See serialized form doc
+ */
+extern LWPOINT *lwpoint_deserialize(uchar *serialized_form);
+
+/*
+ * Find size this point would get when serialized (no BBOX)
+ */
+extern size_t lwpoint_serialize_size(LWPOINT *point);
+
+/*
+ * convert this point into its serialize form
+ * result's first char will be the 8bit type. 
+ * See serialized form doc
+ */
+extern uchar *lwpoint_serialize(LWPOINT *point);
+
+/* same as above, writes to buf */
+extern void lwpoint_serialize_buf(LWPOINT *point, uchar *buf, size_t *size);
+
+/*
+ * find bounding box (standard one) 
+ * zmin=zmax=0 if 2d (might change to NaN)
+ */
+extern BOX3D *lwpoint_compute_box3d(LWPOINT *point);
+
+/*
+ * convenience functions to hide the POINTARRAY
+ */
+extern int lwpoint_getPoint2d_p(const LWPOINT *point, POINT2D *out);
+extern int lwpoint_getPoint3dz_p(const LWPOINT *point, POINT3DZ *out);
+extern int lwpoint_getPoint3dm_p(const LWPOINT *point, POINT3DM *out);
+extern int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out);
+
+/******************************************************************
+ * LWLINE functions
+ ******************************************************************/
+
+/*
+ * given the LWGEOM serialized form (or a pointer into a muli* one)
+ * construct a proper LWLINE.
+ * serialized_form should point to the 8bit type format (with type = 2)
+ * See SERIALIZED_FORM doc
+ */
+extern LWLINE *lwline_deserialize(uchar *serialized_form);
+
+/* find the size this line would get when serialized */
+extern size_t lwline_serialize_size(LWLINE *line);
+
+/*
+ * convert this line into its serialize form
+ * result's first char will be the 8bit type.  See serialized form doc
+ * copies data.
+ */
+extern uchar *lwline_serialize(LWLINE *line);
+
+/* same as above, writes to buf */
+extern void lwline_serialize_buf(LWLINE *line, uchar *buf, size_t *size);
+
+/*
+ * find bounding box (standard one)  zmin=zmax=0 if 2d (might change to NaN)
+ */
+extern BOX3D *lwline_compute_box3d(LWLINE *line);
+
+/******************************************************************
+ * LWPOLY functions
+ ******************************************************************/
+
+/*
+ * given the LWPOLY serialized form (or a pointer into a muli* one)
+ * construct a proper LWPOLY.
+ * serialized_form should point to the 8bit type format (with type = 3)
+ * See SERIALIZED_FORM doc
+ */
+extern LWPOLY *lwpoly_deserialize(uchar *serialized_form);
+
+/* find the size this polygon would get when serialized */
+extern size_t lwpoly_serialize_size(LWPOLY *poly);
+
+/*
+ * create the serialized form of the polygon
+ * result's first char will be the 8bit type.  See serialized form doc
+ * points copied
+ */
+extern uchar *lwpoly_serialize(LWPOLY *poly);
+
+/* same as above, writes to buf */
+extern void lwpoly_serialize_buf(LWPOLY *poly, uchar *buf, size_t *size);
+
+/*
+ * find bounding box (standard one)  zmin=zmax=0 if 2d (might change to NaN)
+ */
+extern BOX3D *lwpoly_compute_box3d(LWPOLY *poly);
+
+/******************************************************************
+ * LWGEOM functions
+ ******************************************************************/
+
+extern size_t lwgeom_serialize_size(LWGEOM *geom);
+extern size_t lwcollection_serialize_size(LWCOLLECTION *coll);
+extern void lwgeom_serialize_buf(LWGEOM *geom, uchar *buf, size_t *size);
+extern uchar *lwgeom_serialize(LWGEOM *geom);
+extern void lwcollection_serialize_buf(LWCOLLECTION *mcoll, uchar *buf, size_t *size);
+
+/*
+ * Deserialize an lwgeom serialized form.
+ * The deserialized (recursive) structure will store
+ * pointers to the serialized form (POINTARRAYs).
+ */
+LWGEOM *lwgeom_deserialize(uchar *serializedform);
+
+/*
+ * Release memory associated with LWGEOM.
+ * POINTARRAYs are not released as they are usually
+ * pointers to user-managed memory.
+ * BBOX is released.
+ */
+void lwgeom_release(LWGEOM *lwgeom);
+
+/******************************************************************
+ * LWMULTIx and LWCOLLECTION functions
+ ******************************************************************/
+
+LWMPOINT *lwmpoint_deserialize(uchar *serializedform);
+LWMLINE *lwmline_deserialize(uchar *serializedform);
+LWMPOLY *lwmpoly_deserialize(uchar *serializedform);
+LWCOLLECTION *lwcollection_deserialize(uchar *serializedform);
+LWGEOM *lwcollection_getsubgeom(LWCOLLECTION *, int);
+
+/******************************************************************
+ * SERIALIZED FORM functions
+ ******************************************************************/
+
+
+/******************************************************************
+ * Multi-geometries
+ *
+ * These are all handled equivelently so its easy to write iterator code.
+ *  NOTE NOTE: you can hand in a non-multigeometry to most of these functions
+ *             and get usual behavior (ie. get geometry 0 on a POINT
+ *	       will return the point).
+ *             This makes coding even easier since you dont have to necessarily
+ *             differenciate between the multi* and non-multi geometries.
+ *
+ * NOTE: these usually work directly off the serialized form, so
+ *	they're a little more difficult to handle (and slower)
+ * NOTE NOTE: the get functions maybe slow, so we may want to have an
+ *            "analysed" lwgeom that would just have pointer to the start
+ *            of each sub-geometry.
+ *
+ ******************************************************************/
+
+/* use this version for speed.  READ-ONLY! */
+typedef struct
+{
+	int   SRID;
+	const uchar *serialized_form; /* orginal structure */
+	uchar  type;        /* 8-bit type for the LWGEOM */
+	int ngeometries;    /* number of sub-geometries */
+	uchar **sub_geoms;  /* list of pointers (into serialized_form)
+			       of the sub-geoms */
+} LWGEOM_INSPECTED;
+
+extern int lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected,
+	int geom_number);
+
+/*
+ * note - for a simple type (ie. point), this will have
+ * sub_geom[0] = serialized_form.
+ * for multi-geomtries sub_geom[0] will be a few bytes into the
+ * serialized form.
+ * This function just computes the length of each sub-object and
+ * pre-caches this info.
+ * For a geometry collection of multi* geometries, you can inspect
+ * the sub-components as well.
+ */
+extern LWGEOM_INSPECTED *lwgeom_inspect(const uchar *serialized_form);
+
+
+/*
+ * 1st geometry has geom_number = 0
+ * if the actual sub-geometry isnt a POINT, null is returned (see _gettype()).
+ * if there arent enough geometries, return null.
+ * this is fine to call on a point (with geom_num=0), multipoint
+ * or geometrycollection
+ */
+extern LWPOINT *lwgeom_getpoint(uchar *serialized_form, int geom_number);
+extern LWPOINT *lwgeom_getpoint_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
+
+/*
+ * 1st geometry has geom_number = 0
+ * if the actual geometry isnt a LINE, null is returned (see _gettype()).
+ * if there arent enough geometries, return null.
+ * this is fine to call on a line, multiline or geometrycollection
+ */
+extern LWLINE *lwgeom_getline(uchar *serialized_form, int geom_number);
+extern LWLINE *lwgeom_getline_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
+
+/*
+ * 1st geometry has geom_number = 0
+ * if the actual geometry isnt a POLYGON, null is returned (see _gettype()).
+ * if there arent enough geometries, return null.
+ * this is fine to call on a polygon, multipolygon or geometrycollection
+ */
+extern LWPOLY *lwgeom_getpoly(uchar *serialized_form, int geom_number);
+extern LWPOLY *lwgeom_getpoly_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
+
+extern LWGEOM *lwgeom_getgeom_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
+
+/*
+ * this gets the serialized form of a sub-geometry
+ * 1st geometry has geom_number = 0
+ * if this isnt a multi* geometry, and geom_number ==0 then it returns
+ * itself
+ * returns null on problems.
+ * in the future this is how you would access a muli* portion of a
+ * geometry collection.
+ *    GEOMETRYCOLLECTION(MULTIPOINT(0 0, 1 1), LINESTRING(0 0, 1 1))
+ *   ie. lwgeom_getpoint( lwgeom_getsubgeometry( serialized, 0), 1)
+ *           --> POINT(1 1)
+ * you can inspect the sub-geometry as well if you wish.
+ */
+extern uchar *lwgeom_getsubgeometry(const uchar *serialized_form, int geom_number);
+extern uchar *lwgeom_getsubgeometry_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
+
+
+/*
+ * 1st geometry has geom_number = 0
+ *  use geom_number = -1 to find the actual type of the serialized form.
+ *    ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, -1)
+ *                 --> multipoint
+ *   ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, 0)
+ *                 --> point
+ * gets the 8bit type of the geometry at location geom_number
+ */
+extern uchar lwgeom_getsubtype(uchar *serialized_form, int geom_number);
+extern uchar lwgeom_getsubtype_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
+
+
+/*
+ * how many sub-geometries are there?
+ *  for point,line,polygon will return 1.
+ */
+extern int lwgeom_getnumgeometries(uchar *serialized_form);
+extern int lwgeom_getnumgeometries_inspected(LWGEOM_INSPECTED *inspected);
+
+
+
+/*
+ * set finalType to COLLECTIONTYPE or 0 (0 means choose a best type)
+ *   (ie. give it 2 points and ask it to be a multipoint)
+ *  use SRID=-1 for unknown SRID  (will have 8bit type's S = 0)
+ * all subgeometries must have the same SRID
+ * if you want to construct an inspected, call this then inspect the result...
+ */
+extern uchar *lwgeom_serialized_construct(int SRID, int finalType, char hasz, char hasm, int nsubgeometries, uchar **serialized_subs);
+
+
+/* construct the empty geometry (GEOMETRYCOLLECTION(EMPTY)) */
+extern uchar *lwgeom_constructempty(int SRID, char hasz, char hasm);
+extern void lwgeom_constructempty_buf(int SRID, char hasz, char hasm, uchar *buf, size_t *size);
+size_t lwgeom_empty_length(int SRID);
+
+/*
+ * get the SRID from the LWGEOM
+ * none present => -1
+ */
+extern int lwgeom_getsrid(uchar *serialized);
+
+
+/*------------------------------------------------------
+ * other stuff
+ *
+ * handle the double-to-float conversion.  The results of this
+ * will usually be a slightly bigger box because of the difference
+ * between float8 and float4 representations.
+ */
+
+extern BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box);
+extern int box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *res);
+
+extern BOX3D box2df_to_box3d(BOX2DFLOAT4 *box);
+extern void box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *box3d);
+
+extern BOX3D *box3d_union(BOX3D *b1, BOX3D *b2);
+extern int box3d_union_p(BOX3D *b1, BOX3D *b2, BOX3D *ubox);
+
+/*
+ * Returns a pointer to the BBOX internal to the serialized form.
+ * READ-ONLY!
+ * Or NULL if serialized form does not have a BBOX
+ * OBSOLETED to avoid memory alignment problems.
+ */
+/*extern BOX2DFLOAT4 *getbox2d_internal(uchar *serialized_form);*/
+
+/*
+ * this function writes to 'box' and returns 0 if serialized_form
+ * does not have a bounding box (empty geom)
+ */
+extern int getbox2d_p(uchar *serialized_form, BOX2DFLOAT4 *box);
+
+/* Expand given box of 'd' units in all directions */
+void expand_box2d(BOX2DFLOAT4 *box, double d);
+void expand_box3d(BOX3D *box, double d);
+
+/* Check if to boxes are equal (considering FLOAT approximations) */
+char box2d_same(BOX2DFLOAT4 *box1, BOX2DFLOAT4 *box2);
+
+/****************************************************************
+ * memory management -- these only delete the memory associated
+ *  directly with the structure - NOT the stuff pointing into
+ *  the original de-serialized info
+ ****************************************************************/
+
+
+extern void pfree_inspected(LWGEOM_INSPECTED *inspected);
+extern void pfree_point    (LWPOINT *pt);
+extern void pfree_line     (LWLINE  *line);
+extern void pfree_polygon  (LWPOLY  *poly);
+extern void pfree_POINTARRAY(POINTARRAY *pa);
+
+
+/****************************************************************
+ * utility
+ ****************************************************************/
+
+extern uint32 lw_get_uint32(const uchar *loc);
+extern int32 lw_get_int32(const uchar *loc);
+extern void printBOX3D(BOX3D *b);
+extern void printPA(POINTARRAY *pa);
+extern void printLWPOINT(LWPOINT *point);
+extern void printLWLINE(LWLINE *line);
+extern void printLWPOLY(LWPOLY *poly);
+extern void printBYTES(uchar *a, int n);
+extern void printMULTI(uchar *serialized);
+extern void printType(uchar str);
+
+
+extern float LWGEOM_Minf(float a, float b);
+extern float LWGEOM_Maxf(float a, float b);
+extern double LWGEOM_Mind(double a, double b);
+extern double LWGEOM_Maxd(double a, double b);
+
+extern float  nextDown_f(double d);
+extern float  nextUp_f(double d);
+extern double nextDown_d(float d);
+extern double nextUp_d(float d);
+
+extern float nextafterf_custom(float x, float y);
+
+
+#define LW_MAX(a,b)	((a) >	(b) ? (a) : (b))
+#define LW_MIN(a,b)	((a) <= (b) ? (a) : (b))
+#define LW_ABS(a)	((a) <	(0) ? (-a) : (a))
+
+
+/* general utilities */
+extern double lwgeom_polygon_area(LWPOLY *poly);
+extern double lwgeom_polygon_perimeter(LWPOLY *poly);
+extern double lwgeom_polygon_perimeter2d(LWPOLY *poly);
+extern double lwgeom_pointarray_length2d(POINTARRAY *pts);
+extern double lwgeom_pointarray_length(POINTARRAY *pts);
+extern void lwgeom_force2d_recursive(uchar *serialized, uchar *optr, size_t *retsize);
+extern void lwgeom_force3dz_recursive(uchar *serialized, uchar *optr, size_t *retsize);
+extern void lwgeom_force3dm_recursive(uchar *serialized, uchar *optr, size_t *retsize);
+extern void lwgeom_force4d_recursive(uchar *serialized, uchar *optr, size_t *retsize);
+extern double distance2d_pt_pt(POINT2D *p1, POINT2D *p2);
+extern double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B);
+extern double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D);
+extern double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa);
+extern double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2);
+extern int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring);
+extern int pt_in_poly_2d(POINT2D *p, LWPOLY *poly);
+extern double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly);
+extern double distance2d_point_point(LWPOINT *point1, LWPOINT *point2);
+extern double distance2d_point_line(LWPOINT *point, LWLINE *line);
+extern double distance2d_line_line(LWLINE *line1, LWLINE *line2);
+extern double distance2d_point_poly(LWPOINT *point, LWPOLY *poly);
+extern double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2);
+extern double distance2d_line_poly(LWLINE *line, LWPOLY *poly);
+extern int azimuth_pt_pt(POINT2D *p1, POINT2D *p2, double *ret);
+extern double lwgeom_mindistance2d_recursive(uchar *lw1, uchar *lw2);
+extern double lwgeom_mindistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance);
+extern int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad);
+extern int32 lwgeom_npoints(uchar *serialized);
+extern char ptarray_isccw(const POINTARRAY *pa);
+extern void lwgeom_reverse(LWGEOM *lwgeom);
+extern void lwline_reverse(LWLINE *line);
+extern void lwpoly_reverse(LWPOLY *poly);
+extern void lwpoly_forceRHR(LWPOLY *poly);
+extern void lwgeom_forceRHR(LWGEOM *lwgeom);
+extern char *lwgeom_summary(LWGEOM *lwgeom, int offset);
+extern const char *lwgeom_typename(int type);
+extern int ptarray_compute_box2d_p(const POINTARRAY *pa, BOX2DFLOAT4 *result);
+extern BOX2DFLOAT4 *ptarray_compute_box2d(const POINTARRAY *pa);
+extern int lwpoint_compute_box2d_p(LWPOINT *point, BOX2DFLOAT4 *box);
+extern int lwline_compute_box2d_p(LWLINE *line, BOX2DFLOAT4 *box);
+extern int lwpoly_compute_box2d_p(LWPOLY *poly, BOX2DFLOAT4 *box);
+extern int lwcollection_compute_box2d_p(LWCOLLECTION *col, BOX2DFLOAT4 *box);
+extern BOX2DFLOAT4 *lwgeom_compute_box2d(LWGEOM *lwgeom);
+
+extern void interpolate_point4d(POINT4D *A, POINT4D *B, POINT4D *I, double F);
+
+/* return alloced memory */
+extern BOX2DFLOAT4 *box2d_union(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2);
+
+/* args may overlap ! */
+extern int box2d_union_p(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2, BOX2DFLOAT4 *ubox);
+extern int lwgeom_compute_box2d_p(LWGEOM *lwgeom, BOX2DFLOAT4 *box);
+void lwgeom_longitude_shift(LWGEOM *lwgeom);
+
+/* Is lwgeom1 geometrically equal to lwgeom2 ? */
+char lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2);
+char ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2);
+char lwpoint_same(const LWPOINT *p1, const LWPOINT *p2);
+char lwline_same(const LWLINE *p1, const LWLINE *p2);
+char lwpoly_same(const LWPOLY *p1, const LWPOLY *p2);
+char lwcollection_same(const LWCOLLECTION *p1, const LWCOLLECTION *p2);
+
+/*
+ * Add 'what' to 'to' at position 'where'.
+ * where=0 == prepend
+ * where=-1 == append
+ * Mix of dimensions is not allowed (TODO: allow it?).
+ * Returns a newly allocated LWGEOM (with NO BBOX)
+ */
+extern LWGEOM *lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what);
+
+LWGEOM *lwpoint_add(const LWPOINT *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwline_add(const LWLINE *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwpoly_add(const LWPOLY *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwmpoly_add(const LWMPOLY *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwmline_add(const LWMLINE *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwmpoint_add(const LWMPOINT *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwcollection_add(const LWCOLLECTION *to, uint32 where, const LWGEOM *what);
+
+/*
+ * Clone an LWGEOM
+ * pointarray are not copied.
+ * BBOXes are copied 
+ */
+extern LWGEOM *lwgeom_clone(const LWGEOM *lwgeom);
+extern LWPOINT *lwpoint_clone(const LWPOINT *lwgeom);
+extern LWLINE *lwline_clone(const LWLINE *lwgeom);
+extern LWPOLY *lwpoly_clone(const LWPOLY *lwgeom);
+extern LWCOLLECTION *lwcollection_clone(const LWCOLLECTION *lwgeom);
+extern BOX2DFLOAT4 *box2d_clone(const BOX2DFLOAT4 *lwgeom);
+extern POINTARRAY *ptarray_clone(const POINTARRAY *ptarray);
+
+/*
+ * Geometry constructors
+ * Take ownership of arguments
+ */
+extern LWPOINT  *lwpoint_construct(int SRID, BOX2DFLOAT4 *bbox,
+	POINTARRAY *point);
+extern LWLINE *lwline_construct(int SRID, BOX2DFLOAT4 *bbox,
+	POINTARRAY *points);
+
+/*
+ * Construct a new LWPOLY.  arrays (points/points per ring) will NOT be copied
+ * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
+ */
+extern LWPOLY *lwpoly_construct(int SRID, BOX2DFLOAT4 *bbox,
+	unsigned int nrings, POINTARRAY **points);
+
+extern LWCOLLECTION *lwcollection_construct(unsigned int type, int SRID,
+	BOX2DFLOAT4 *bbox, unsigned int ngeoms, LWGEOM **geoms);
+extern LWCOLLECTION *lwcollection_construct_empty(int SRID,
+	char hasZ, char hasM);
+
+/* Other constructors */
+extern LWPOINT *make_lwpoint2d(int SRID, double x, double y);
+extern LWPOINT *make_lwpoint3dz(int SRID, double x, double y, double z);
+extern LWPOINT *make_lwpoint3dm(int SRID, double x, double y, double m);
+extern LWPOINT *make_lwpoint4d(int SRID, double x, double y, double z, double m);
+extern LWLINE *lwline_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points);
+extern LWLINE *lwline_from_lwmpoint(int SRID, LWMPOINT *mpoint);
+extern LWLINE *lwline_addpoint(LWLINE *line, LWPOINT *point, unsigned int where);
+extern LWLINE *lwline_removepoint(LWLINE *line, unsigned int which);
+extern void lwline_setPoint4d(LWLINE *line, unsigned int which, POINT4D *newpoint);
+extern LWPOLY *lwpoly_from_lwlines(const LWLINE *shell, unsigned int nholes, const LWLINE **holes);
+
+/* Return a char string with ASCII versionf of type flags */
+extern const char *lwgeom_typeflags(uchar type);
+
+/* Construct an empty pointarray */
+extern POINTARRAY *ptarray_construct(char hasz, char hasm,
+	unsigned int npoints);
+
+/*
+ * extern POINTARRAY *ptarray_construct2d(uint32 npoints, const POINT2D *pts);
+ * extern POINTARRAY *ptarray_construct3dz(uint32 npoints, const POINT3DZ *pts);
+ * extern POINTARRAY *ptarray_construct3dm(uint32 npoints, const POINT3DM *pts);
+ * extern POINTARRAY *ptarray_construct4d(uint32 npoints, const POINT4D *pts);
+ */
+
+extern POINTARRAY *ptarray_addPoint(POINTARRAY *pa, uchar *p, size_t pdims,
+	unsigned int where);
+extern POINTARRAY *ptarray_removePoint(POINTARRAY *pa, unsigned int where);
+
+extern int ptarray_isclosed2d(const POINTARRAY *pa);
+
+extern void ptarray_longitude_shift(POINTARRAY *pa);
+
+extern int32 lwgeom_nrings_recursive(uchar *serialized);
+extern void ptarray_reverse(POINTARRAY *pa);
+extern POINTARRAY *ptarray_substring(POINTARRAY *, double, double);
+extern double ptarray_locate_point(POINTARRAY *, POINT2D *);
+extern void closest_point_on_segment(POINT2D *p, POINT2D *A, POINT2D *B, POINT2D *ret);
+
+/*
+ * Ensure every segment is at most 'dist' long.
+ * Returned LWGEOM might is unchanged if a POINT.
+ */
+extern LWGEOM *lwgeom_segmentize2d(LWGEOM *line, double dist);
+extern POINTARRAY *ptarray_segmentize2d(POINTARRAY *ipa, double dist);
+extern LWLINE *lwline_segmentize2d(LWLINE *line, double dist);
+extern LWPOLY *lwpoly_segmentize2d(LWPOLY *line, double dist);
+extern LWCOLLECTION *lwcollection_segmentize2d(LWCOLLECTION *coll, double dist);
+
+extern uchar parse_hex(char *str);
+extern void deparse_hex(uchar str, char *result);
+
+/* Parser access routines */
+extern char *unparse_WKT(uchar* serialized, lwallocator alloc, lwfreeor free);
+extern char *unparse_WKB(uchar* serialized, lwallocator alloc, lwfreeor free, char endian, size_t *outsize, uchar hex);
+
+extern SERIALIZED_LWGEOM *parse_lwgeom_wkt(char *wkt_input);
+extern char *lwgeom_to_ewkt(LWGEOM *lwgeom);
+extern char *lwgeom_to_hexwkb(LWGEOM *lwgeom, unsigned int byteorder);
+extern LWGEOM *lwgeom_from_ewkb(uchar *ewkb, size_t ewkblen);
+extern uchar *lwgeom_to_ewkb(LWGEOM *lwgeom, char byteorder, size_t *ewkblen);
+
+extern void *lwalloc(size_t size);
+extern void *lwrealloc(void *mem, size_t size);
+extern void lwfree(void *mem);
+
+/* Utilities */
+extern void trim_trailing_zeros(char *num);
+
+/* Machine endianness */
+#define XDR 0
+#define NDR 1
+extern char getMachineEndian(void);
+
+void errorIfSRIDMismatch(int srid1, int srid2);
+
+/* CURVETYPE */
+typedef struct
+{
+        uchar type; /* CURVETYPE */
+        BOX2DFLOAT4 *bbox;
+        uint32 SRID;
+        POINTARRAY *points; /* array of POINT(3D/3DM) */
+} LWCURVE; /* "light-weight arcline" */
+
+/* COMPOUNDTYPE */
+typedef struct
+{
+        uchar type; /* COMPOUNDTYPE */
+        BOX2DFLOAT4 *bbox;
+        uint32 SRID;
+        int ngeoms;
+        LWGEOM **geoms;
+} LWCOMPOUND; /* "light-weight compound line" */
+
+/* CURVEPOLYTYPE */
+typedef struct
+{
+        uchar type; /* CURVEPOLYTYPE */
+        BOX2DFLOAT4 *bbox;
+        uint32 SRID;
+        int nrings;
+        LWGEOM **rings; /* list of rings (list of points) */
+} LWCURVEPOLY; /* "light-weight polygon" */
+
+/* MULTICURVE */
+typedef struct
+{
+        uchar type;
+        BOX2DFLOAT4 *bbox;
+        uint32 SRID;
+        int ngeoms;
+        LWGEOM **geoms;
+} LWMCURVE;
+
+/* MULTISURFACETYPE */
+typedef struct
+{
+        uchar type;
+        BOX2DFLOAT4 *bbox;
+        uint32 SRID;
+        int ngeoms;
+        LWGEOM **geoms;
+} LWMSURFACE;
+
+#define CURVETYPE       8
+#define COMPOUNDTYPE    9
+#define CURVEPOLYTYPE   13
+#define MULTICURVETYPE          14
+#define MULTISURFACETYPE        15
+
+/******************************************************************
+ * LWCURVE functions
+ ******************************************************************/
+
+/* Casts LWGEOM->LW* (return NULL if cast is illegal) */
+extern LWCURVE *lwgeom_as_lwcurve(LWGEOM *lwgeom);
+
+
+LWCURVE *lwcurve_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *points);
+
+/*
+ * given the LWGEOM serialized form (or a pointer into a muli* one)
+ * construct a proper LWCURVE.
+ * serialized_form should point to the 8bit type format (with type = 2)
+ * See SERIALIZED_FORM doc
+ */
+extern LWCURVE *lwcurve_deserialize(uchar *serialized_form);
+
+/* find the size this curve would get when serialized */
+extern size_t lwcurve_serialize_size(LWCURVE *curve);
+
+/*
+ * convert this curve into its serialize form
+ * result's first char will be the 8bit type.  See serialized form doc
+ * copies data.
+ */
+extern uchar *lwcurve_serialize(LWCURVE *curve);
+
+/* same as above, writes to buf */
+extern void lwcurve_serialize_buf(LWCURVE *curve, uchar *buf, size_t *size);
+
+/*
+ * find bounding box (standard one)  zmin=zmax=0 if 2d (might change to NaN)
+ */
+extern BOX3D *lwcurve_compute_box3d(LWCURVE *curve);
+
+LWGEOM *lwcurve_add(const LWCURVE *to, uint32 where, const LWGEOM *what);
+extern int lwcurve_compute_box2d_p(LWCURVE *curve, BOX2DFLOAT4 *box);
+extern BOX3D *lwcurve_compute_box3d(LWCURVE *curve);
+extern void pfree_curve(LWCURVE  *curve);
+LWCURVE *lwcurve_clone(const LWCURVE *curve);
+
+/******************************************************************
+ * LWMULTIx and LWCOLLECTION functions
+ ******************************************************************/
+
+LWCOMPOUND *lwcompound_deserialize(uchar *serialized_form);
+
+LWGEOM *lwcompound_add(const LWCOMPOUND *to, uint32 where, const LWGEOM *what);
+
+LWCURVEPOLY *lwcurvepoly_deserialize(uchar *serialized_form);
+
+LWGEOM *lwcurvepoly_add(const LWCURVEPOLY *to, uint32 where, const LWGEOM *what);
+
+LWMCURVE *lwmcurve_deserialize(uchar *serialized_form);
+
+LWGEOM *lwmcurve_add(const LWMCURVE *to, uint32 where, const LWGEOM *what);
+
+LWMSURFACE *lwmsurface_deserialize(uchar *serialized_form);
+
+LWGEOM *lwmsurface_add(const LWMSURFACE *to, uint32 where, const LWGEOM *what);
+
+/*******************************************************************************
+ * SQLMM internal functions
+ ******************************************************************************/
+
+uint32 has_arc(LWGEOM *geom);
+double lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D **result);
+LWGEOM *lwgeom_segmentize(LWGEOM *geom, uint32 perQuad);
+extern double lwgeom_curvepolygon_area(LWCURVEPOLY *curvepoly);
+double lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D **result);
+
+#endif /* !defined _LIBLWGEOM_H  */
+

Added: trunk/liblwgeom/lwcollection.c
===================================================================
--- trunk/liblwgeom/lwcollection.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwcollection.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,356 @@
+/**********************************************************************
+ * $Id: lwcollection.c 2797 2008-05-31 09:56:44Z mcayland $
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "liblwgeom.h"
+
+
+#define CHECK_LWGEOM_ZM 1
+
+LWCOLLECTION *
+lwcollection_construct(unsigned int type, int SRID, BOX2DFLOAT4 *bbox,
+	unsigned int ngeoms, LWGEOM **geoms)
+{
+	LWCOLLECTION *ret;
+	int hasz, hasm;
+#ifdef CHECK_LWGEOM_ZM
+	char zm;
+	unsigned int i;
+#endif
+
+        LWDEBUGF(2, "lwcollection_construct called with %d, %d, %p, %d, %p.", type, SRID, bbox, ngeoms, geoms);
+
+	hasz = 0;
+	hasm = 0;
+	if ( ngeoms > 0 )
+	{
+		hasz = TYPE_HASZ(geoms[0]->type);
+		hasm = TYPE_HASM(geoms[0]->type);
+#ifdef CHECK_LWGEOM_ZM
+		zm = TYPE_GETZM(geoms[0]->type);
+
+                LWDEBUGF(3, "lwcollection_construct type[0]=%d", geoms[0]->type);
+
+		for (i=1; i<ngeoms; i++)
+		{
+                        LWDEBUGF(3, "lwcollection_construct type=[%d]=%d", i, geoms[i]->type);
+
+			if ( zm != TYPE_GETZM(geoms[i]->type) )
+				lwerror("lwcollection_construct: mixed dimension geometries: %d/%d", zm, TYPE_GETZM(geoms[i]->type));
+		}
+#endif
+	}
+
+
+	ret = lwalloc(sizeof(LWCOLLECTION));
+	ret->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1),
+		type, 0);
+	ret->SRID = SRID;
+	ret->ngeoms = ngeoms;
+	ret->geoms = geoms;
+	ret->bbox = bbox;
+
+	return ret;
+}
+
+LWCOLLECTION *
+lwcollection_construct_empty(int SRID, char hasz, char hasm)
+{
+	LWCOLLECTION *ret;
+
+	ret = lwalloc(sizeof(LWCOLLECTION));
+	ret->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1),
+		COLLECTIONTYPE, 0);
+	ret->SRID = SRID;
+	ret->ngeoms = 0;
+	ret->geoms = NULL;
+	ret->bbox = NULL;
+
+	return ret;
+}
+
+
+LWCOLLECTION *
+lwcollection_deserialize(uchar *srl)
+{
+	LWCOLLECTION *result;
+	LWGEOM_INSPECTED *insp;
+	char typefl = srl[0];
+	int type = lwgeom_getType(typefl);
+	int i;
+
+	if ( type != COLLECTIONTYPE ) 
+	{
+		lwerror("lwcollection_deserialize called on NON geometrycollection: %d", type);
+		return NULL;
+	}
+
+	insp = lwgeom_inspect(srl);
+
+	result = lwalloc(sizeof(LWCOLLECTION));
+	result->type = typefl;
+	result->SRID = insp->SRID;
+	result->ngeoms = insp->ngeometries;
+
+	if (lwgeom_hasBBOX(srl[0]))
+	{
+		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+		memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4));
+	}
+	else result->bbox = NULL;
+
+
+	if ( insp->ngeometries )
+	{
+		result->geoms = lwalloc(sizeof(LWGEOM *)*insp->ngeometries);
+		for (i=0; i<insp->ngeometries; i++)
+		{
+			result->geoms[i] =
+				lwgeom_deserialize(insp->sub_geoms[i]);
+		}
+	}
+
+	return result;
+}
+
+LWGEOM *
+lwcollection_getsubgeom(LWCOLLECTION *col, int gnum)
+{
+	return (LWGEOM *)col->geoms[gnum];
+}
+
+/* find serialized size of this collection */
+size_t
+lwcollection_serialize_size(LWCOLLECTION *col)
+{
+	size_t size = 5; /* type + nsubgeoms */
+	int i;
+
+	if ( col->SRID != -1 ) size += 4; /* SRID */
+	if ( col->bbox ) size += sizeof(BOX2DFLOAT4);
+
+	LWDEBUGF(2, "lwcollection_serialize_size[%p]: start size: %d", col, size);
+
+
+	for (i=0; i<col->ngeoms; i++)
+	{
+		size += lwgeom_serialize_size(col->geoms[i]);
+
+		LWDEBUGF(3, "lwcollection_serialize_size[%p]: with geom%d: %d", col, i, size);
+	}
+
+	LWDEBUGF(3, "lwcollection_serialize_size[%p]:  returning %d", col, size);
+
+	return size; 
+}
+
+/*
+ * convert this collectoin into its serialize form writing it into
+ * the given buffer, and returning number of bytes written into
+ * the given int pointer.
+ */
+void
+lwcollection_serialize_buf(LWCOLLECTION *coll, uchar *buf, size_t *retsize)
+{
+	size_t size=1; /* type  */
+	size_t subsize=0;
+	char hasSRID;
+	uchar *loc;
+	int i;
+
+	LWDEBUGF(2, "lwcollection_serialize_buf called (%s with %d elems)",
+		lwgeom_typename(TYPE_GETTYPE(coll->type)), coll->ngeoms);
+
+	hasSRID = (coll->SRID != -1);
+
+	buf[0] = lwgeom_makeType_full(
+		TYPE_HASZ(coll->type), TYPE_HASM(coll->type),
+		hasSRID, TYPE_GETTYPE(coll->type), coll->bbox ? 1 : 0);
+	loc = buf+1;
+
+	/* Add BBOX if requested */
+	if ( coll->bbox )
+	{
+		memcpy(loc, coll->bbox, sizeof(BOX2DFLOAT4));
+		size += sizeof(BOX2DFLOAT4);
+		loc += sizeof(BOX2DFLOAT4);
+	}
+
+	/* Add SRID if requested */
+	if (hasSRID)
+	{
+		memcpy(loc, &coll->SRID, 4);
+		size += 4; 
+		loc += 4;
+	}
+
+	/* Write number of subgeoms */
+	memcpy(loc, &coll->ngeoms, 4);
+	size += 4;
+	loc += 4;
+
+	/* Serialize subgeoms */
+	for (i=0; i<coll->ngeoms; i++)
+	{
+		lwgeom_serialize_buf(coll->geoms[i], loc, &subsize);
+		size += subsize;
+		loc += subsize;
+	}
+
+	if (retsize) *retsize = size;
+
+	LWDEBUG(3, "lwcollection_serialize_buf returning");
+}
+
+int
+lwcollection_compute_box2d_p(LWCOLLECTION *col, BOX2DFLOAT4 *box)
+{
+	BOX2DFLOAT4 boxbuf;
+	uint32 i;
+
+	if ( ! col->ngeoms ) return 0;
+	if ( ! lwgeom_compute_box2d_p(col->geoms[0], box) ) return 0;
+	for (i=1; i<col->ngeoms; i++)
+	{
+		if ( ! lwgeom_compute_box2d_p(col->geoms[i], &boxbuf) )
+			return 0;
+		if ( ! box2d_union_p(box, &boxbuf, box) ) return 0;
+	}
+	return 1;
+}
+
+/*
+ * Clone LWCOLLECTION object. POINTARRAY are not copied.
+ * Bbox is cloned if present in input.
+ */
+LWCOLLECTION *
+lwcollection_clone(const LWCOLLECTION *g)
+{
+	uint32 i;
+	LWCOLLECTION *ret = lwalloc(sizeof(LWCOLLECTION));
+	memcpy(ret, g, sizeof(LWCOLLECTION));
+	if ( g->ngeoms > 0 )
+	{
+		ret->geoms = lwalloc(sizeof(LWGEOM *)*g->ngeoms);
+		for (i=0; i<g->ngeoms; i++)
+		{
+			ret->geoms[i] = lwgeom_clone(g->geoms[i]);
+		}
+		if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
+	}
+	else
+	{
+		ret->bbox = NULL; /* empty collection */
+		ret->geoms = NULL;
+	}
+	return ret;
+}
+
+/*
+ * Add 'what' to this collection at position 'where'.
+ * where=0 == prepend
+ * where=-1 == append
+ * Returns a GEOMETRYCOLLECTION
+ */
+LWGEOM *
+lwcollection_add(const LWCOLLECTION *to, uint32 where, const LWGEOM *what)
+{
+	LWCOLLECTION *col;
+	LWGEOM **geoms;
+	uint32 i;
+
+	if ( where == -1 ) where = to->ngeoms;
+	else if ( where < -1 || where > to->ngeoms )
+	{
+		lwerror("lwcollection_add: add position out of range %d..%d",
+			-1, to->ngeoms);
+		return NULL;
+	}
+
+	/* dimensions compatibility are checked by caller */
+
+	/* Construct geoms array */
+	geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
+	for (i=0; i<where; i++)
+	{
+		geoms[i] = lwgeom_clone(to->geoms[i]);
+		lwgeom_dropSRID(geoms[i]);
+		lwgeom_dropBBOX(geoms[i]);
+	}
+	geoms[where] = lwgeom_clone(what);
+	lwgeom_dropSRID(geoms[where]);
+	lwgeom_dropBBOX(geoms[where]);
+	for (i=where; i<to->ngeoms; i++)
+	{
+		geoms[i+1] = lwgeom_clone(to->geoms[i]);
+		lwgeom_dropSRID(geoms[i+1]);
+		lwgeom_dropBBOX(geoms[i+1]);
+	}
+
+	col = lwcollection_construct(COLLECTIONTYPE,
+		to->SRID, NULL,
+		to->ngeoms+1, geoms);
+	
+	return (LWGEOM *)col;
+
+}
+
+LWCOLLECTION *
+lwcollection_segmentize2d(LWCOLLECTION *col, double dist)
+{
+	unsigned int i;
+	LWGEOM **newgeoms;
+
+	if ( ! col->ngeoms ) return col;
+
+	newgeoms = lwalloc(sizeof(LWGEOM *)*col->ngeoms);
+	for (i=0; i<col->ngeoms; i++)
+		newgeoms[i] = lwgeom_segmentize2d(col->geoms[i], dist);
+
+	return lwcollection_construct(col->type, col->SRID, NULL,
+		col->ngeoms, newgeoms);
+}
+
+/* check for same geometry composition */
+char
+lwcollection_same(const LWCOLLECTION *c1, const LWCOLLECTION *c2)
+{
+	unsigned int i, j;
+	unsigned int *hit;
+
+	LWDEBUG(2, "lwcollection_same called");
+
+	if ( TYPE_GETTYPE(c1->type) != TYPE_GETTYPE(c2->type) ) return 0;
+	if ( c1->ngeoms != c2->ngeoms ) return 0;
+
+	hit = lwalloc(sizeof(unsigned int)*c1->ngeoms);
+	memset(hit, 0, sizeof(unsigned int)*c1->ngeoms);
+
+	for (i=0; i<c1->ngeoms; i++)
+	{
+		char found=0;
+		for (j=0; j<c2->ngeoms; j++)
+		{
+			if ( hit[j] ) continue;
+			if ( lwgeom_same(c1->geoms[i], c2->geoms[j]) )
+			{
+				hit[j] = 1;
+				found=1;
+				break;
+			}
+		}
+		if ( ! found ) return 0;
+	}
+	return 1;
+}

Added: trunk/liblwgeom/lwcompound.c
===================================================================
--- trunk/liblwgeom/lwcompound.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwcompound.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,118 @@
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "liblwgeom.h"
+
+LWCOMPOUND *
+lwcompound_deserialize(uchar *serialized)
+{
+        LWCOMPOUND *result;
+        LWGEOM_INSPECTED *insp;
+        int type = lwgeom_getType(serialized[0]);
+        int i;
+
+        if(type != COMPOUNDTYPE)
+        {
+                lwerror("lwcompound_deserialize called on non compound: %d", type);
+                return NULL;
+        }
+
+        insp = lwgeom_inspect(serialized);
+
+        result = lwalloc(sizeof(LWCOMPOUND));
+        result->type = insp->type;
+        result->SRID = insp->SRID;
+        result->ngeoms = insp->ngeometries;
+        result->geoms = lwalloc(sizeof(LWGEOM *)*insp->ngeometries);
+
+        if(lwgeom_hasBBOX(serialized[0]))
+        {
+                result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+                memcpy(result->bbox, serialized + 1, sizeof(BOX2DFLOAT4));
+        }
+        else result->bbox = NULL;
+
+        for(i = 0; i < insp->ngeometries; i++)
+        {
+                if(lwgeom_getType(insp->sub_geoms[i][0]) == LINETYPE)
+                        result->geoms[i] = (LWGEOM *)lwline_deserialize(insp->sub_geoms[i]);
+                else
+                        result->geoms[i] = (LWGEOM *)lwcurve_deserialize(insp->sub_geoms[i]);
+                if(TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type))
+                {
+                        lwerror("Mixed dimensions (compound:%d, line/curve%d:%d)",
+                            TYPE_NDIMS(result->type), i,
+                            TYPE_NDIMS(result->geoms[i]->type)
+                        );
+                        lwfree(result);
+                        return NULL;
+                }
+        }
+        return result;
+}
+
+/*
+ * Add 'what' to this string at position 'where'
+ * where=0 == prepend
+ * where=-1 == append
+ * Returns a COMPOUND or a GEOMETRYCOLLECTION
+ */
+LWGEOM *
+lwcompound_add(const LWCOMPOUND *to, uint32 where, const LWGEOM *what)
+{
+        LWCOLLECTION *col;
+        LWGEOM **geoms;
+        int newtype;
+
+        LWDEBUG(2, "lwcompound_add called.");
+
+        if(where != -1 && where != 0)
+        {
+                lwerror("lwcompound_add only supports 0 or -1 as a second argument, not %d", where);
+                return NULL;
+        }
+
+        /* dimensions compatibility are checked by caller */
+
+        /* Construct geoms array */
+        geoms = lwalloc(sizeof(LWGEOM *)*2);
+        if(where == -1) /* append */
+        {
+                geoms[0] = lwgeom_clone((LWGEOM *)to);
+                geoms[1] = lwgeom_clone(what);
+        }
+        else /* prepend */
+        {
+                geoms[0] = lwgeom_clone(what);
+                geoms[1] = lwgeom_clone((LWGEOM *)to);
+        }
+
+        /* reset SRID and wantbbox flag from component types */
+        geoms[0]->SRID = geoms[1]->SRID = -1;
+        TYPE_SETHASSRID(geoms[0]->type, 0);
+        TYPE_SETHASSRID(geoms[1]->type, 0);
+        TYPE_SETHASBBOX(geoms[0]->type, 0);
+        TYPE_SETHASBBOX(geoms[1]->type, 0);
+
+        /* Find appropriate geom type */
+        if(TYPE_GETTYPE(what->type) == LINETYPE || TYPE_GETTYPE(what->type) == CURVETYPE) newtype = COMPOUNDTYPE;
+        else newtype = COLLECTIONTYPE;
+
+        col = lwcollection_construct(newtype,
+                to->SRID, NULL, 2, geoms);
+
+        return (LWGEOM *)col;
+}
+

Added: trunk/liblwgeom/lwcurve.c
===================================================================
--- trunk/liblwgeom/lwcurve.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwcurve.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,707 @@
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+/* basic LWCURVE functions */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "liblwgeom.h"
+
+BOX3D *lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3);
+void printLWCURVE(LWCURVE *curve);
+void lwcurve_reverse(LWCURVE *curve);
+LWCURVE *lwcurve_segmentize2d(LWCURVE *curve, double dist);
+char lwcurve_same(const LWCURVE *me, const LWCURVE *you);
+LWCURVE *lwcurve_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points);
+LWCURVE *lwcurve_from_lwmpoint(int SRID, LWMPOINT *mpoint);
+LWCURVE *lwcurve_addpoint(LWCURVE *curve, LWPOINT *point, unsigned int where);
+LWCURVE *lwcurve_removepoint(LWCURVE *curve, unsigned int index);
+void lwcurve_setPoint4d(LWCURVE *curve, unsigned int index, POINT4D *newpoint);
+
+
+
+#ifndef MAXFLOAT
+  #define MAXFLOAT      3.402823466e+38F
+#endif
+
+/*
+ * Construct a new LWCURVE.  points will *NOT* be copied
+ * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
+ */
+LWCURVE *
+lwcurve_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *points)
+{
+        LWCURVE *result;
+        
+	/*
+         * The first arc requires three points.  Each additional
+         * arc requires two more points.  Thus the minimum point count
+         * is three, and the count must be odd.
+         */
+        if(points->npoints % 2 != 1 || points->npoints < 3) 
+        {
+                lwerror("lwcurve_construct: invalid point count %d", points->npoints);
+                return NULL;
+        }
+        
+        result = (LWCURVE*) lwalloc(sizeof(LWCURVE));
+
+        result->type = lwgeom_makeType_full(
+                TYPE_HASZ(points->dims),
+                TYPE_HASM(points->dims),
+                (SRID!=-1), CURVETYPE, 0);
+        result->SRID = SRID;
+        result->points = points;
+        result->bbox = bbox;
+         
+        return result;
+}
+
+/*
+ * given the LWGEOM serialized form (or a point into a multi* one)
+ * construct a propert LWCURVE.
+ * serialized_form should point to the 8bit type format (with type = 8)
+ * See serialized form doc
+ */
+LWCURVE *
+lwcurve_deserialize(uchar *serialized_form)
+{
+        uchar type;
+        LWCURVE *result;
+        uchar *loc=NULL;
+        uint32 npoints;
+        POINTARRAY *pa;
+
+        type = (uchar)serialized_form[0];
+        if(lwgeom_getType(type) != CURVETYPE)
+        {
+                lwerror("lwcurve_deserialize: attempt to deserialize a curve which is really a %s", lwgeom_typename(type));
+                return NULL;
+        }
+
+        result = (LWCURVE*) lwalloc(sizeof(LWCURVE));
+        result->type = type;
+
+        loc = serialized_form + 1;
+
+        if(lwgeom_hasBBOX(type))
+        {
+                LWDEBUG(3, "lwcurve_deserialize: input has bbox");
+
+                result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+                memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
+                loc += sizeof(BOX2DFLOAT4);               
+         }
+         else
+         {
+                LWDEBUG(3, "lwcurve_deserialize: input lacks bbox");           
+               
+                result->bbox = NULL;
+         }
+
+         if(lwgeom_hasSRID(type))
+         {
+                LWDEBUG(3, "lwcurve_deserialize: input has srid");
+
+                result->SRID = lw_get_int32(loc);               
+                loc += 4; /* type + SRID */
+         }
+         else
+         {
+                LWDEBUG(3, "lwcurve_deserialize: input lacks srid");
+
+                result->SRID = -1;                
+         }
+
+         /* we've read the type (1 byte) and SRID (4 bytes, if present) */
+
+         npoints = lw_get_uint32(loc);
+
+         LWDEBUGF(3, "curve npoints = %d", npoints);
+         
+         loc += 4;
+         pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), npoints);
+         result->points = pa;
+         return result;
+}
+
+/*
+ * convert this curve into its serialized form
+ * result's first char will be the 8bit type. See serialized form doc
+ */
+uchar *
+lwcurve_serialize(LWCURVE *curve)
+{
+        size_t size, retsize;
+        uchar * result;
+
+        if(curve == NULL) {
+                lwerror("lwcurve_serialize:: given null curve");
+                return NULL;
+        }
+
+        size = lwcurve_serialize_size(curve);
+        result = lwalloc(size);
+        lwcurve_serialize_buf(curve, result, &retsize);
+        if(retsize != size)
+                lwerror("lwcurve_serialize_size returned %d, ..selialize_buf returned %d", size, retsize);
+        return result;
+}
+
+/*
+ * convert this curve into its serialized form writing it into 
+ * the given buffer, and returning number of bytes written into 
+ * the given int pointer.
+ * result's first char will be the 8bit type.  See serialized form doc
+ */
+void lwcurve_serialize_buf(LWCURVE *curve, uchar *buf, size_t *retsize)
+{
+        char hasSRID;
+        uchar *loc;
+        int ptsize;
+        size_t size;
+
+        LWDEBUGF(2, "lwcurve_serialize_buf(%p, %p, %p) called",
+                curve, buf, retsize);
+
+        if(curve == NULL) 
+        {
+                lwerror("lwcurve_serialize:: given null curve");
+                return;
+        }
+
+        if(TYPE_GETZM(curve->type) != TYPE_GETZM(curve->points->dims))
+        {
+                lwerror("Dimensions mismatch in lwcurve");
+                return;
+        }
+
+        ptsize = pointArray_ptsize(curve->points);
+
+        hasSRID = (curve->SRID != -1);
+
+        buf[0] = (uchar)lwgeom_makeType_full(
+                TYPE_HASZ(curve->type), TYPE_HASM(curve->type),
+                hasSRID, CURVETYPE, curve->bbox ? 1 : 0);
+        loc = buf+1;
+
+        LWDEBUGF(3, "lwcurve_serialize_buf added type (%d)", curve->type);
+
+        if(curve->bbox)
+        {
+                memcpy(loc, curve->bbox, sizeof(BOX2DFLOAT4));
+                loc += sizeof(BOX2DFLOAT4);
+
+                LWDEBUG(3, "lwcurve_serialize_buf added BBOX");
+        }                
+
+        if(hasSRID)
+        {
+                memcpy(loc, &curve->SRID, sizeof(int32));
+                loc += sizeof(int32);
+
+                LWDEBUG(3, "lwcurve_serialize_buf added SRID");
+        }
+
+        memcpy(loc, &curve->points->npoints, sizeof(uint32));
+        loc += sizeof(uint32);
+
+        LWDEBUGF(3, "lwcurve_serialize_buf added npoints (%d)",
+            curve->points->npoints);
+
+        /* copy in points */
+        size = curve->points->npoints * ptsize;
+        memcpy(loc, getPoint_internal(curve->points, 0), size);
+        loc += size;
+
+        LWDEBUGF(3, "lwcurve_serialize_buf copied serialized_pointlist (%d bytes)",
+                ptsize * curve->points->npoints);        
+
+        if(retsize) *retsize = loc-buf;
+
+        LWDEBUGF(3, "lwcurve_serialize_buf returning (loc: %p, size: %d)",
+                loc, loc-buf);
+}
+
+/* find length of this deserialized curve */
+size_t
+lwcurve_serialize_size(LWCURVE *curve)
+{
+        size_t size = 1; /* type */
+
+        LWDEBUG(2, "lwcurve_serialize_size called");        
+
+        if(curve->SRID != -1) size += 4; /* SRID */
+        if(curve->bbox) size += sizeof(BOX2DFLOAT4);
+
+        size += 4; /* npoints */
+        size += pointArray_ptsize(curve->points) * curve->points->npoints;
+
+        LWDEBUGF(3, "lwcurve_serialize_size returning %d", size);
+
+        return size;
+}
+
+BOX3D *
+lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
+{
+        double x1, x2, y1, y2, z1, z2;
+        double angle, radius, sweep;
+        /*
+        double top, left;
+        */
+        double a1, a2, a3;
+        double xe = 0.0, ye = 0.0;
+        POINT4D *center;
+        int i;
+        BOX3D *box;
+
+        LWDEBUG(2, "lwcircle_compute_box3d called.");
+
+        center = lwalloc(sizeof(POINT4D));
+        radius = lwcircle_center(p1, p2, p3, &center);
+        if(radius < 0.0) return NULL;
+
+        /*
+        top = center->y + radius;
+        left = center->x - radius;
+
+        LWDEBUGF(3, "lwcircle_compute_box3d: top=%.16f, left=%.16f", top, left);
+        */
+
+        x1 = MAXFLOAT;
+        x2 = -1 * MAXFLOAT;
+        y1 = MAXFLOAT;
+        y2 = -1 * MAXFLOAT;
+
+        a1 = atan2(p1->y - center->y, p1->x - center->x);
+        a2 = atan2(p2->y - center->y, p2->x - center->x);
+        a3 = atan2(p3->y - center->y, p3->x - center->x);
+
+        /* Determine sweep angle */
+        if(a1 > a2 && a2 > a3) 
+        {
+                sweep = a3 - a1;
+        }
+        /* Counter-clockwise */
+        else if(a1 < a2 && a2 < a3)
+        {
+                sweep = a3 - a1;
+        }
+        /* Clockwise, wrap */
+        else if((a1 < a2 && a1 > a3) || (a2 < a3 && a1 > a3))
+        {
+                sweep = a3 - a1 + 2*M_PI;
+        }
+        /* Counter-clockwise, wrap */
+        else if((a1 > a2 && a1 < a3) || (a2 > a3 && a1 < a3))
+        {
+                sweep = a3 - a1 - 2*M_PI;
+        } 
+        else 
+        {
+                sweep = 0.0;
+        }
+
+        LWDEBUGF(3, "a1 %.16f, a2 %.16f, a3 %.16f, sweep %.16f", a1, a2, a3, sweep);
+
+        angle = 0.0;
+        for(i=0; i < 6; i++)
+        {
+                switch(i) {
+                case 0:
+                        angle = 0.0;
+                        xe = center->x + radius;
+                        ye = center->y;
+                        break;
+                case 1:
+                        angle = M_PI_2;
+                        xe = center->x;
+                        ye = center->y + radius;
+                        break;
+                case 2:
+                        angle = M_PI;
+                        xe = center->x - radius;
+                        ye = center->y;
+                        break;
+                case 3:
+                        angle = -1 * M_PI_2;
+                        xe = center->x;
+                        ye = center->y - radius;
+                        break;
+                case 4:
+                        angle = a1;
+                        xe = p1->x;
+                        ye = p1->y;
+                        break;
+                case 5:
+                        angle = a3;
+                        xe = p3->x;
+                        ye = p3->y;
+                        break;
+                }
+                if(i < 4) 
+                {
+                        if(sweep > 0.0 && (angle > a3 || angle < a1)) continue;
+                        if(sweep < 0.0 && (angle < a3 || angle > a1)) continue;
+                }
+
+                LWDEBUGF(3, "lwcircle_compute_box3d: potential extreame %d (%.16f, %.16f)", i, xe, ye);
+
+                x1 = (x1 < xe) ? x1 : xe;
+                y1 = (y1 < ye) ? y1 : ye;
+                x2 = (x2 > xe) ? x2 : xe;
+                y2 = (y2 > ye) ? y2 : ye;
+        }
+
+        LWDEBUGF(3, "lwcircle_compute_box3d: extreames found (%.16f %.16f, %.16f %.16f)", x1, y1, x2, y2);
+
+        /*
+        x1 = center->x + x1 * radius;
+        x2 = center->x + x2 * radius;
+        y1 = center->y + y1 * radius;
+        y2 = center->y + y2 * radius;
+        */
+        z1 = (p1->z < p2->z) ? p1->z : p2->z;
+        z1 = (z1 < p3->z) ? z1 : p3->z;
+        z2 = (p1->z > p2->z) ? p1->z : p2->z;
+        z2 = (z2 > p3->z) ? z2 : p3->z;
+
+        box = lwalloc(sizeof(BOX3D));
+        box->xmin = x1; box->xmax = x2;
+        box->ymin = y1; box->ymax = y2;
+        box->zmin = z1; box->zmax = z2;
+
+        lwfree(center);
+
+        return box;
+}
+
+/*
+ * Find bounding box (standard one)
+ * zmin=zmax=NO_Z_VALUE if 2d
+ * TODO: This ignores curvature, which should be taken into account.
+ */
+BOX3D *
+lwcurve_compute_box3d(LWCURVE *curve)
+{
+        BOX3D *box, *tmp; 
+        int i;
+        POINT4D *p1 = lwalloc(sizeof(POINT4D));
+        POINT4D *p2 = lwalloc(sizeof(POINT4D));
+        POINT4D *p3 = lwalloc(sizeof(POINT4D));
+
+        LWDEBUG(2, "lwcurve_compute_box3d called.");
+
+        /* initialize box values */
+        box = lwalloc(sizeof(BOX3D));
+        box->xmin = MAXFLOAT; box->xmax = -1 * MAXFLOAT;
+        box->ymin = MAXFLOAT; box->ymax = -1 * MAXFLOAT;
+        box->zmin = MAXFLOAT; box->zmax = -1 * MAXFLOAT;
+        
+        for(i = 2; i < curve->points->npoints; i+=2)
+        {
+                getPoint4d_p(curve->points, i-2, p1);
+                getPoint4d_p(curve->points, i-1, p2);
+                getPoint4d_p(curve->points, i, p3);
+                tmp = lwcircle_compute_box3d(p1, p2, p3);
+                if(tmp == NULL) continue;
+                box->xmin = (box->xmin < tmp->xmin) ? box->xmin : tmp->xmin;
+                box->xmax = (box->xmax > tmp->xmax) ? box->xmax : tmp->xmax;
+                box->ymin = (box->ymin < tmp->ymin) ? box->ymin : tmp->ymin;
+                box->ymax = (box->ymax > tmp->ymax) ? box->ymax : tmp->ymax;
+                box->zmin = (box->zmin < tmp->zmin) ? box->zmin : tmp->zmin;
+                box->zmax = (box->zmax > tmp->zmax) ? box->zmax : tmp->zmax;
+
+                LWDEBUGF(4, "curve %d x=(%.16f,%.16f) y=(%.16f,%.16f) z=(%.16f,%.16f)", i/2, box->xmin, box->xmax, box->ymin, box->ymax, box->zmin, box->zmax);
+        }
+
+        
+        return box;
+}
+
+int
+lwcurve_compute_box2d_p(LWCURVE *curve, BOX2DFLOAT4 *result)
+{
+        BOX3D *box = lwcurve_compute_box3d(curve);
+        LWDEBUG(2, "lwcurve_compute_box2d_p called.");
+
+        if(box == NULL) return 0;
+        box3d_to_box2df_p(box, result);
+        return 1;
+}
+
+void pfree_curve(LWCURVE *curve)
+{
+        lwfree(curve->points);
+        lwfree(curve);
+}
+
+/* find length of this serialized curve */
+size_t
+lwgeom_size_curve(const uchar *serialized_curve)
+{
+        int type = (uchar)serialized_curve[0];
+        uint32 result = 1; /* type */
+        const uchar *loc;
+        uint32 npoints;
+
+        LWDEBUG(2, "lwgeom_size_curve called");
+
+        if(lwgeom_getType(type) != CURVETYPE)
+                lwerror("lwgeom_size_curve::attempt to find the length of a non-curve");
+
+        loc = serialized_curve + 1;
+        if(lwgeom_hasBBOX(type))
+        {
+                loc += sizeof(BOX2DFLOAT4);
+                result += sizeof(BOX2DFLOAT4);
+        }
+
+        if(lwgeom_hasSRID(type))
+        {
+                loc += 4; /* type + SRID */
+                result += 4;
+        }
+
+        /* we've read the type (1 byte) and SRID (4 bytes, if present) */
+        npoints = lw_get_uint32(loc);
+        result += sizeof(uint32); /* npoints */
+
+        result += TYPE_NDIMS(type) * sizeof(double) * npoints;
+
+        LWDEBUGF(3, "lwgeom_size_curve returning %d", result);
+
+        return result;
+}
+
+void printLWCURVE(LWCURVE *curve)
+{
+        lwnotice("LWCURVE {");
+        lwnotice("    ndims = %i", (int)TYPE_NDIMS(curve->type));
+        lwnotice("    SRID = %i", (int)curve->SRID);
+        printPA(curve->points);
+        lwnotice("}");
+}
+
+/* Clone LWCURVE object.  POINTARRAY is not copied. */
+LWCURVE *
+lwcurve_clone(const LWCURVE *g)
+{
+        LWCURVE *ret = lwalloc(sizeof(LWCURVE));
+        memcpy(ret, g, sizeof(LWCURVE));
+        if(g->bbox) ret->bbox = box2d_clone(g->bbox);
+        return ret;
+}
+
+/*
+ * Add 'what' to this curve at position 'where'.
+ * where=0 == prepend
+ * where=-1 == append
+ * Returns a MULTICURVE or a GEOMETRYCOLLECTION
+ */
+LWGEOM *
+lwcurve_add(const LWCURVE *to, uint32 where, const LWGEOM *what)
+{
+        LWCOLLECTION *col;
+        LWGEOM **geoms;
+        int newtype;
+        
+        if(where != -1 && where != 0)
+        {
+                lwerror("lwcurve_add only supports 0 or -1 as second argument %d", where);
+                return NULL;
+        }
+
+        /* dimensions compatibility are checked by caller */
+
+        /* Construct geoms array */
+        geoms = lwalloc(sizeof(LWGEOM *)*2);
+        if(where == -1) /* append */
+        {
+                geoms[0] = lwgeom_clone((LWGEOM *)to);
+                geoms[1] = lwgeom_clone(what);
+        }
+        else /* prepend */
+        {
+                geoms[0] = lwgeom_clone(what);
+                geoms[1] = lwgeom_clone((LWGEOM *)to);
+        }
+        
+        /* reset SRID and wantbbox flag from component types */
+        geoms[0]->SRID = geoms[1]->SRID = -1;
+        TYPE_SETHASSRID(geoms[0]->type, 0);
+        TYPE_SETHASSRID(geoms[1]->type, 0);
+        TYPE_SETHASBBOX(geoms[0]->type, 0);
+        TYPE_SETHASBBOX(geoms[1]->type, 0);
+
+        /* Find appropriate geom type */
+        if(TYPE_GETTYPE(what->type) == CURVETYPE || TYPE_GETTYPE(what->type) == LINETYPE) newtype = MULTICURVETYPE;
+        else newtype = COLLECTIONTYPE;
+
+        col = lwcollection_construct(newtype, 
+                to->SRID, NULL, 
+                2, geoms);
+
+        return (LWGEOM *)col;
+}
+
+void lwcurve_reverse(LWCURVE *curve)
+{
+        ptarray_reverse(curve->points);
+}
+
+/*
+ * TODO: Invalid segmentization.  This should accomodate the curvature.
+ */
+LWCURVE *
+lwcurve_segmentize2d(LWCURVE *curve, double dist)
+{
+        return lwcurve_construct(curve->SRID, NULL,
+                ptarray_segmentize2d(curve->points, dist));
+}
+                    
+/* check coordinate equality */
+char
+lwcurve_same(const LWCURVE *me, const LWCURVE *you)
+{
+        return ptarray_same(me->points, you->points);
+}
+
+/*
+ * Construct a LWCURVE from an array of LWPOINTs
+ * LWCURVE dimensions are large enough to host all input dimensions.
+ */
+LWCURVE *
+lwcurve_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points)
+{
+        int zmflag=0;
+        unsigned int i;
+        POINTARRAY *pa;
+        uchar *newpoints, *ptr;
+        size_t ptsize, size;
+
+        /*
+         * Find output dimensions, check integrity
+         */
+        for(i = 0; i < npoints; i++)
+        {
+                if(TYPE_GETTYPE(points[i]->type) != POINTTYPE)
+                {
+                        lwerror("lwcurve_from_lwpointarray: invalid input type: %s",
+                            lwgeom_typename(TYPE_GETTYPE(points[i]->type)));
+                        return NULL;
+                }
+                if(TYPE_HASZ(points[i]->type)) zmflag |= 2;
+                if(TYPE_HASM(points[i]->type)) zmflag |=1;
+                if(zmflag == 3) break;
+        }
+
+        if(zmflag == 0) ptsize = 2 * sizeof(double);
+        else if(zmflag == 3) ptsize = 4 * sizeof(double);
+        else ptsize = 3 * sizeof(double);
+
+        /*
+         * Allocate output points array
+         */
+        size = ptsize * npoints;
+        newpoints = lwalloc(size);
+        memset(newpoints, 0, size);
+
+        ptr = newpoints;
+        for(i = 0; i < npoints; i++)
+        {
+                size = pointArray_ptsize(points[i]->point);
+                memcpy(ptr, getPoint_internal(points[i]->point, 0), size);
+                ptr += ptsize;
+        }
+        pa = pointArray_construct(newpoints, zmflag&2, zmflag&1, npoints);
+
+        return lwcurve_construct(SRID, NULL, pa);
+}
+
+/*
+ * Construct a LWCURVE from a LWMPOINT
+ */
+LWCURVE *
+lwcurve_from_lwmpoint(int SRID, LWMPOINT *mpoint)
+{
+        unsigned int i;
+        POINTARRAY *pa;
+        char zmflag = TYPE_GETZM(mpoint->type);
+        size_t ptsize, size;
+        uchar *newpoints, *ptr;
+
+        if(zmflag == 0) ptsize = 2 * sizeof(double);
+        else if(zmflag == 3) ptsize = 4 * sizeof(double);
+        else ptsize = 3 * sizeof(double);
+
+        /* Allocate space for output points */
+        size = ptsize * mpoint->ngeoms;
+        newpoints = lwalloc(size);
+        memset(newpoints, 0, size);
+
+        ptr = newpoints;
+        for(i = 0; i < mpoint->ngeoms; i++)
+        {
+                memcpy(ptr,
+                        getPoint_internal(mpoint->geoms[i]->point, 0),
+                        ptsize);
+                ptr += ptsize;
+        }
+
+        pa = pointArray_construct(newpoints, zmflag&2, zmflag&1,
+                mpoint->ngeoms);
+
+        LWDEBUGF(3, "lwcurve_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag);
+        
+        return lwcurve_construct(SRID, NULL, pa);
+}
+
+LWCURVE *
+lwcurve_addpoint(LWCURVE *curve, LWPOINT *point, unsigned int where)
+{
+        POINTARRAY *newpa;
+        LWCURVE *ret;
+
+        newpa = ptarray_addPoint(curve->points, 
+                getPoint_internal(point->point, 0),
+                TYPE_NDIMS(point->type), where);
+        ret = lwcurve_construct(curve->SRID, NULL, newpa);
+
+        return ret;
+}
+
+LWCURVE *
+lwcurve_removepoint(LWCURVE *curve, unsigned int index)
+{
+        POINTARRAY *newpa;
+        LWCURVE *ret;
+
+        newpa = ptarray_removePoint(curve->points, index);
+        ret = lwcurve_construct(curve->SRID, NULL, newpa);
+
+        return ret;
+}
+
+/*
+ * Note: input will be changed, make sure you have permissions for this.
+ * */
+void
+lwcurve_setPoint4d(LWCURVE *curve, unsigned int index, POINT4D *newpoint)
+{
+        setPoint4d(curve->points, index, newpoint);
+}
+
+

Added: trunk/liblwgeom/lwcurvepoly.c
===================================================================
--- trunk/liblwgeom/lwcurvepoly.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwcurvepoly.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,86 @@
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+/* basic LWCURVEPOLY manipulation */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "liblwgeom.h"
+
+
+LWCURVEPOLY *
+lwcurvepoly_deserialize(uchar *srl)
+{
+        LWCURVEPOLY *result;
+        LWGEOM_INSPECTED *insp;
+        int type = lwgeom_getType(srl[0]);
+        int i;
+
+        LWDEBUG(3, "lwcurvepoly_deserialize called.");
+
+        if(type != CURVEPOLYTYPE)
+        {
+                lwerror("lwcurvepoly_deserialize called on NON curvepoly: %d",
+                        type);
+                return NULL;
+        }
+
+        insp = lwgeom_inspect(srl);
+
+        result = lwalloc(sizeof(LWCURVEPOLY));
+        result->type = insp->type;
+        result->SRID = insp->SRID;
+        result->nrings = insp->ngeometries;
+        result->rings = lwalloc(sizeof(LWGEOM *)*insp->ngeometries);
+
+        if(lwgeom_hasBBOX(srl[0]))
+        {
+                result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+                memcpy(result->bbox, srl + 1, sizeof(BOX2DFLOAT4));
+        }
+        else result->bbox = NULL;
+
+        for(i = 0; i < insp->ngeometries; i++)
+        {
+                result->rings[i] = lwgeom_deserialize(insp->sub_geoms[i]);
+                if(lwgeom_getType(result->rings[i]->type) != CURVETYPE 
+                        && lwgeom_getType(result->rings[i]->type) != LINETYPE)
+                {
+                        lwerror("Only Circular curves and Linestrings are currently supported as rings, not %s (%d)", lwgeom_typename(result->rings[i]->type), result->rings[i]->type);
+                        lwfree(result);
+                        lwfree(insp);
+                        return NULL;
+                }
+                if(TYPE_NDIMS(result->rings[i]->type) != TYPE_NDIMS(result->type))
+                {
+                        lwerror("Mixed dimensions (curvepoly %d, ring %d)",
+                                TYPE_NDIMS(result->type), i, 
+                                TYPE_NDIMS(result->rings[i]->type));
+                        lwfree(result);
+                        lwfree(insp);
+                        return NULL;
+                }
+        }
+        return result;
+}
+
+LWGEOM *
+lwcurvepoly_add(const LWCURVEPOLY *to, uint32 where, const LWGEOM *what)
+{
+        /* TODO */
+        lwerror("lwcurvepoly_add not yet implemented.");
+        return NULL;
+}
+
+
+

Added: trunk/liblwgeom/lwgeom.c
===================================================================
--- trunk/liblwgeom/lwgeom.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwgeom.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,696 @@
+/**********************************************************************
+ * $Id: lwgeom.c 2797 2008-05-31 09:56:44Z mcayland $
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+/*#include "lwgeom_pg.h"*/
+#include "liblwgeom.h"
+#include "wktparse.h"
+
+
+LWGEOM *
+lwgeom_deserialize(uchar *srl)
+{
+	int type = lwgeom_getType(srl[0]);
+
+	LWDEBUGF(2, "lwgeom_deserialize got %d - %s", type, lwgeom_typename(type));
+
+	switch (type)
+	{
+		case POINTTYPE:
+			return (LWGEOM *)lwpoint_deserialize(srl);
+		case LINETYPE:
+			return (LWGEOM *)lwline_deserialize(srl);
+                case CURVETYPE:
+                        return (LWGEOM *)lwcurve_deserialize(srl);
+		case POLYGONTYPE:
+			return (LWGEOM *)lwpoly_deserialize(srl);
+		case MULTIPOINTTYPE:
+			return (LWGEOM *)lwmpoint_deserialize(srl);
+		case MULTILINETYPE:
+			return (LWGEOM *)lwmline_deserialize(srl);
+		case MULTIPOLYGONTYPE:
+			return (LWGEOM *)lwmpoly_deserialize(srl);
+		case COLLECTIONTYPE:
+			return (LWGEOM *)lwcollection_deserialize(srl);
+                case COMPOUNDTYPE:
+                        return (LWGEOM *)lwcompound_deserialize(srl);
+                case CURVEPOLYTYPE:
+                        return (LWGEOM *)lwcurvepoly_deserialize(srl);
+                case MULTICURVETYPE:
+                        return (LWGEOM *)lwmcurve_deserialize(srl);
+                case MULTISURFACETYPE:
+                        return (LWGEOM *)lwmsurface_deserialize(srl);
+		default:
+			lwerror("Unknown geometry type: %d", type);
+
+			return NULL;
+	}
+
+}
+
+size_t
+lwgeom_serialize_size(LWGEOM *lwgeom)
+{
+	int type = TYPE_GETTYPE(lwgeom->type);
+
+	LWDEBUGF(2, "lwgeom_serialize_size(%s) called", lwgeom_typename(type));
+
+	switch (type)
+	{
+		case POINTTYPE:
+			return lwpoint_serialize_size((LWPOINT *)lwgeom);
+		case LINETYPE:
+			return lwline_serialize_size((LWLINE *)lwgeom);
+		case POLYGONTYPE:
+			return lwpoly_serialize_size((LWPOLY *)lwgeom);
+                case CURVETYPE:
+                        return lwcurve_serialize_size((LWCURVE *)lwgeom);
+                case CURVEPOLYTYPE:
+                case COMPOUNDTYPE:
+		case MULTIPOINTTYPE:
+		case MULTILINETYPE:
+                case MULTICURVETYPE:
+		case MULTIPOLYGONTYPE:
+                case MULTISURFACETYPE:
+		case COLLECTIONTYPE:
+			return lwcollection_serialize_size((LWCOLLECTION *)lwgeom);
+		default:
+			lwerror("Unknown geometry type: %d", type);
+
+			return 0;
+	}
+}
+
+void
+lwgeom_serialize_buf(LWGEOM *lwgeom, uchar *buf, size_t *retsize)
+{
+	int type = TYPE_GETTYPE(lwgeom->type);
+
+	LWDEBUGF(2, "lwgeom_serialize_buf called with a %s",
+			lwgeom_typename(type));
+
+	switch (type)
+	{
+		case POINTTYPE:
+			lwpoint_serialize_buf((LWPOINT *)lwgeom, buf, retsize);
+			break;
+		case LINETYPE:
+			lwline_serialize_buf((LWLINE *)lwgeom, buf, retsize);
+			break;
+		case POLYGONTYPE:
+			lwpoly_serialize_buf((LWPOLY *)lwgeom, buf, retsize);
+			break;
+                case CURVETYPE:
+                        lwcurve_serialize_buf((LWCURVE *)lwgeom, buf, retsize);
+                        break;
+                case CURVEPOLYTYPE:
+                case COMPOUNDTYPE:
+		case MULTIPOINTTYPE:
+		case MULTILINETYPE:
+                case MULTICURVETYPE:
+		case MULTIPOLYGONTYPE:
+                case MULTISURFACETYPE:
+		case COLLECTIONTYPE:
+			lwcollection_serialize_buf((LWCOLLECTION *)lwgeom, buf,
+				retsize);
+			break;
+		default:
+			lwerror("Unknown geometry type: %d", type);
+			return;
+	}
+	return;
+}
+
+uchar *
+lwgeom_serialize(LWGEOM *lwgeom)
+{
+	size_t size = lwgeom_serialize_size(lwgeom);
+	size_t retsize;
+	uchar *serialized = lwalloc(size);
+
+	lwgeom_serialize_buf(lwgeom, serialized, &retsize);
+
+#if POSTGIS_DEBUG_LEVEL > 0
+	if ( retsize != size )
+	{
+		lwerror("lwgeom_serialize: computed size %d, returned size %d",
+			size, retsize);
+	}
+#endif
+
+	return serialized;
+}
+
+/* Force Right-hand-rule on LWGEOM polygons */
+void
+lwgeom_forceRHR(LWGEOM *lwgeom)
+{
+	LWCOLLECTION *coll;
+	int i;
+
+	switch (TYPE_GETTYPE(lwgeom->type))
+	{
+		case POLYGONTYPE:
+			lwpoly_forceRHR((LWPOLY *)lwgeom);
+			return;
+
+		case MULTIPOLYGONTYPE:
+		case COLLECTIONTYPE:
+			coll = (LWCOLLECTION *)lwgeom;
+			for (i=0; i<coll->ngeoms; i++)
+				lwgeom_forceRHR(coll->geoms[i]);
+			return;
+	}
+}
+
+/* Reverse vertex order of LWGEOM */
+void
+lwgeom_reverse(LWGEOM *lwgeom)
+{
+	int i;
+	LWCOLLECTION *col;
+
+	switch (TYPE_GETTYPE(lwgeom->type))
+	{
+		case LINETYPE:
+			lwline_reverse((LWLINE *)lwgeom);
+			return;
+		case POLYGONTYPE:
+			lwpoly_reverse((LWPOLY *)lwgeom);
+			return;
+		case MULTILINETYPE:
+		case MULTIPOLYGONTYPE:
+		case COLLECTIONTYPE:
+			col = (LWCOLLECTION *)lwgeom;
+			for (i=0; i<col->ngeoms; i++)
+				lwgeom_reverse(col->geoms[i]);
+			return;
+	}
+}
+
+int
+lwgeom_compute_box2d_p(LWGEOM *lwgeom, BOX2DFLOAT4 *buf)
+{
+        LWDEBUGF(2, "lwgeom_compute_box2d_p called of %p of type %d.", lwgeom, TYPE_GETTYPE(lwgeom->type));
+
+	switch(TYPE_GETTYPE(lwgeom->type))
+	{
+		case POINTTYPE:
+			return lwpoint_compute_box2d_p((LWPOINT *)lwgeom, buf);
+		case LINETYPE:
+			return lwline_compute_box2d_p((LWLINE *)lwgeom, buf);
+                case CURVETYPE:
+                        return lwcurve_compute_box2d_p((LWCURVE *)lwgeom, buf);
+		case POLYGONTYPE:
+			return lwpoly_compute_box2d_p((LWPOLY *)lwgeom, buf);
+                case COMPOUNDTYPE:
+                case CURVEPOLYTYPE:
+		case MULTIPOINTTYPE:
+		case MULTILINETYPE:
+                case MULTICURVETYPE:
+		case MULTIPOLYGONTYPE:
+                case MULTISURFACETYPE:
+		case COLLECTIONTYPE:
+			return lwcollection_compute_box2d_p((LWCOLLECTION *)lwgeom, buf);
+	}
+	return 0;
+}
+
+/*
+ * dont forget to lwfree() result
+ */
+BOX2DFLOAT4 *
+lwgeom_compute_box2d(LWGEOM *lwgeom)
+{
+	BOX2DFLOAT4 *result = lwalloc(sizeof(BOX2DFLOAT4));
+	if ( lwgeom_compute_box2d_p(lwgeom, result) ) return result;
+	else  {
+		lwfree(result);
+		return NULL;
+	}
+}
+
+LWPOINT *
+lwgeom_as_lwpoint(LWGEOM *lwgeom)
+{
+	if ( TYPE_GETTYPE(lwgeom->type) == POINTTYPE )
+		return (LWPOINT *)lwgeom;
+	else return NULL;
+}
+
+LWLINE *
+lwgeom_as_lwline(LWGEOM *lwgeom)
+{
+	if ( TYPE_GETTYPE(lwgeom->type) == LINETYPE )
+		return (LWLINE *)lwgeom;
+	else return NULL;
+}
+
+LWCURVE *
+lwgeom_as_lwcurve(LWGEOM *lwgeom)
+{
+        if( TYPE_GETTYPE(lwgeom->type) == CURVETYPE )
+                return (LWCURVE *)lwgeom;
+        else return NULL;
+}
+
+LWPOLY *
+lwgeom_as_lwpoly(LWGEOM *lwgeom)
+{
+	if ( TYPE_GETTYPE(lwgeom->type) == POLYGONTYPE )
+		return (LWPOLY *)lwgeom;
+	else return NULL;
+}
+
+LWCOLLECTION *
+lwgeom_as_lwcollection(LWGEOM *lwgeom)
+{
+	if ( TYPE_GETTYPE(lwgeom->type) >= MULTIPOINTTYPE 
+            && TYPE_GETTYPE(lwgeom->type) <= COLLECTIONTYPE)
+		return (LWCOLLECTION *)lwgeom;
+	else return NULL;
+}
+
+LWMPOINT *
+lwgeom_as_lwmpoint(LWGEOM *lwgeom)
+{
+	if ( TYPE_GETTYPE(lwgeom->type) == MULTIPOINTTYPE )
+		return (LWMPOINT *)lwgeom;
+	else return NULL;
+}
+
+LWMLINE *
+lwgeom_as_lwmline(LWGEOM *lwgeom)
+{
+	if ( TYPE_GETTYPE(lwgeom->type) == MULTILINETYPE )
+		return (LWMLINE *)lwgeom;
+	else return NULL;
+}
+
+LWMPOLY *
+lwgeom_as_lwmpoly(LWGEOM *lwgeom)
+{
+	if ( TYPE_GETTYPE(lwgeom->type) == MULTIPOLYGONTYPE )
+		return (LWMPOLY *)lwgeom;
+	else return NULL;
+}
+
+LWGEOM *lwmpoly_as_lwgeom(LWMPOLY *obj) { return (LWGEOM *)obj; }
+LWGEOM *lwmline_as_lwgeom(LWMLINE *obj) { return (LWGEOM *)obj; }
+LWGEOM *lwmpoint_as_lwgeom(LWMPOINT *obj) { return (LWGEOM *)obj; }
+LWGEOM *lwcollection_as_lwgeom(LWCOLLECTION *obj) { return (LWGEOM *)obj; }
+LWGEOM *lwpoly_as_lwgeom(LWPOLY *obj) { return (LWGEOM *)obj; }
+LWGEOM *lwline_as_lwgeom(LWLINE *obj) { return (LWGEOM *)obj; }
+LWGEOM *lwpoint_as_lwgeom(LWPOINT *obj) { return (LWGEOM *)obj; }
+
+void
+lwgeom_release(LWGEOM *lwgeom)
+{
+	uint32 i;
+	LWCOLLECTION *col;
+
+#ifdef INTEGRITY_CHECKS
+	if ( ! lwgeom )
+		lwerror("lwgeom_release: someone called on 0x0");
+#endif
+
+	/* Drop bounding box (always a copy) */
+	if ( lwgeom->bbox ) {
+                LWDEBUG(3, "lwgeom_release: releasing bbox.");
+
+                lwfree(lwgeom->bbox);
+        }
+
+	/* Collection */
+	if ( (col=lwgeom_as_lwcollection(lwgeom)) )
+	{
+                LWDEBUG(3, "lwgeom_release: Releasing collection.");
+
+		for (i=0; i<col->ngeoms; i++)
+		{
+			lwgeom_release(col->geoms[i]);
+		}
+		lwfree(lwgeom);
+	}
+
+	/* Single element */
+	else lwfree(lwgeom);
+
+}
+
+/* Clone an LWGEOM object. POINTARRAY are not copied. */
+LWGEOM *
+lwgeom_clone(const LWGEOM *lwgeom)
+{
+        LWDEBUGF(2, "lwgeom_clone called with %p, %d", lwgeom, TYPE_GETTYPE(lwgeom->type));
+
+	switch(TYPE_GETTYPE(lwgeom->type))
+	{
+		case POINTTYPE:
+			return (LWGEOM *)lwpoint_clone((LWPOINT *)lwgeom);
+		case LINETYPE:
+			return (LWGEOM *)lwline_clone((LWLINE *)lwgeom);
+                case CURVETYPE:
+                        return (LWGEOM *)lwcurve_clone((LWCURVE *)lwgeom);
+		case POLYGONTYPE:
+			return (LWGEOM *)lwpoly_clone((LWPOLY *)lwgeom);
+                case COMPOUNDTYPE:
+                case CURVEPOLYTYPE:
+		case MULTIPOINTTYPE:
+		case MULTILINETYPE:
+                case MULTICURVETYPE:
+		case MULTIPOLYGONTYPE:
+                case MULTISURFACETYPE:
+		case COLLECTIONTYPE:
+			return (LWGEOM *)lwcollection_clone((LWCOLLECTION *)lwgeom);
+		default:
+			return NULL;
+	}
+}
+
+/*
+ * Add 'what' to 'to' at position 'where'
+ *
+ * where=0 == prepend
+ * where=-1 == append
+ * Appended-to LWGEOM gets a new type based on new condition.
+ * Mix of dimensions is not allowed (TODO: allow it?).
+ */
+LWGEOM *
+lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what)
+{
+	if ( TYPE_NDIMS(what->type) != TYPE_NDIMS(to->type) )
+	{
+		lwerror("lwgeom_add: mixed dimensions not supported");
+		return NULL;
+	}
+
+	LWDEBUGF(2, "lwgeom_add(%s, %d, %s) called",
+		lwgeom_typename(TYPE_GETTYPE(to->type)),
+		where,
+		lwgeom_typename(TYPE_GETTYPE(what->type)));
+
+	switch(TYPE_GETTYPE(to->type))
+	{
+		case POINTTYPE:
+			return (LWGEOM *)lwpoint_add((const LWPOINT *)to, where, what);
+		case LINETYPE:
+			return (LWGEOM *)lwline_add((const LWLINE *)to, where, what);
+
+                case CURVETYPE:
+                        return (LWGEOM *)lwcurve_add((const LWCURVE *)to, where, what);
+
+		case POLYGONTYPE:
+			return (LWGEOM *)lwpoly_add((const LWPOLY *)to, where, what);
+
+                case COMPOUNDTYPE:
+                        return (LWGEOM *)lwcompound_add((const LWCOMPOUND *)to, where, what);
+
+                case CURVEPOLYTYPE:
+                        return (LWGEOM *)lwcurvepoly_add((const LWCURVEPOLY *)to, where, what);
+
+		case MULTIPOINTTYPE:
+			return (LWGEOM *)lwmpoint_add((const LWMPOINT *)to,
+				where, what);
+
+		case MULTILINETYPE:
+			return (LWGEOM *)lwmline_add((const LWMLINE *)to,
+				where, what);
+
+                case MULTICURVETYPE:
+                        return (LWGEOM *)lwmcurve_add((const LWMCURVE *)to,
+                                where, what);
+
+		case MULTIPOLYGONTYPE:
+			return (LWGEOM *)lwmpoly_add((const LWMPOLY *)to,
+				where, what);
+
+                case MULTISURFACETYPE:
+                        return (LWGEOM *)lwmsurface_add((const LWMSURFACE *)to,
+                                where, what);
+
+		case COLLECTIONTYPE:
+			return (LWGEOM *)lwcollection_add(
+				(const LWCOLLECTION *)to, where, what);
+
+		default:
+			lwerror("lwgeom_add: unknown geometry type: %d",
+				TYPE_GETTYPE(to->type));
+			return NULL;
+	}
+}
+
+/*
+ * Return an alloced string
+ */
+char *
+lwgeom_to_ewkt(LWGEOM *lwgeom)
+{
+	uchar *serialized = lwgeom_serialize(lwgeom);
+	char *ret;
+	if ( ! serialized ) {
+		lwerror("Error serializing geom %p", lwgeom);
+	}
+	ret = unparse_WKT(serialized, lwalloc, lwfree);
+	lwfree(serialized);
+	return ret;
+}
+
+/*
+ * Return an alloced string
+ */
+char *
+lwgeom_to_hexwkb(LWGEOM *lwgeom, unsigned int byteorder)
+{
+	uchar *serialized = lwgeom_serialize(lwgeom);
+	char *hexwkb = unparse_WKB(serialized, lwalloc, lwfree, byteorder,NULL,1);
+	lwfree(serialized);
+	return hexwkb;
+}
+
+/*
+ * Return an alloced string
+ */
+uchar *
+lwgeom_to_ewkb(LWGEOM *lwgeom, char byteorder, size_t *outsize)
+{
+	uchar *serialized = lwgeom_serialize(lwgeom);
+
+	/*
+	 * We cast return to "unsigned" char as we are
+	 * requesting a "binary" output, not HEX
+	 * (last argument set to 0)
+	 */
+	uchar *hexwkb = (uchar *)unparse_WKB(serialized, lwalloc, lwfree,
+		byteorder, outsize, 0);
+	lwfree(serialized);
+	return hexwkb;
+}
+
+/*
+ * Make an LWGEOM object from a EWKB binary representation.
+ * Currently highly unoptimized as it:
+ * 	- convert EWKB to HEXEWKB 
+ *	- construct PG_LWGEOM
+ *	- deserialize it
+ */
+LWGEOM *
+lwgeom_from_ewkb(uchar *ewkb, size_t size)
+{
+	size_t hexewkblen = size*2;
+	char *hexewkb;
+	long int i;
+	LWGEOM *ret;
+	SERIALIZED_LWGEOM *serialized_lwgeom;
+
+	/* "HEXify" the EWKB */
+	hexewkb = lwalloc(hexewkblen+1);
+	for (i=0; i<size; ++i) deparse_hex(ewkb[i], &hexewkb[i*2]);
+	hexewkb[hexewkblen] = '\0';
+
+	/* Rely on grammar parser to construct a LWGEOM */
+	serialized_lwgeom = parse_lwgeom_wkt(hexewkb);
+
+	/* Free intermediate HEXified representation */
+	lwfree(hexewkb);
+
+	/* Deserialize */
+	ret = lwgeom_deserialize(serialized_lwgeom->lwgeom);
+
+	return ret;
+}
+
+/*
+ * geom1 same as geom2
+ *  iff
+ *      + have same type 
+ *	+ have same # objects
+ *      + have same bvol
+ *      + each object in geom1 has a corresponding object in geom2 (see above)
+ */
+char
+lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
+{
+	LWDEBUGF(2, "lwgeom_same(%s, %s) called",
+		lwgeom_typename(TYPE_GETTYPE(lwgeom1->type)),
+		lwgeom_typename(TYPE_GETTYPE(lwgeom2->type)));
+
+	if ( TYPE_GETTYPE(lwgeom1->type) != TYPE_GETTYPE(lwgeom2->type) )
+	{
+		LWDEBUG(3, " type differ");
+
+		return 0;
+	}
+
+	if ( TYPE_GETZM(lwgeom1->type) != TYPE_GETZM(lwgeom2->type) )
+	{
+		LWDEBUG(3, " ZM flags differ");
+
+		return 0;
+	}
+
+	/* Check boxes if both already computed  */
+	if ( lwgeom1->bbox && lwgeom2->bbox )
+	{
+		/*lwnotice("bbox1:%p, bbox2:%p", lwgeom1->bbox, lwgeom2->bbox);*/
+		if ( ! box2d_same(lwgeom1->bbox, lwgeom2->bbox) )
+		{
+			LWDEBUG(3, " bounding boxes differ");
+
+			return 0;
+		}
+	}
+
+	/* geoms have same type, invoke type-specific function */
+	switch(TYPE_GETTYPE(lwgeom1->type))
+	{
+		case POINTTYPE:
+			return lwpoint_same((LWPOINT *)lwgeom1,
+				(LWPOINT *)lwgeom2);
+		case LINETYPE:
+			return lwline_same((LWLINE *)lwgeom1,
+				(LWLINE *)lwgeom2);
+		case POLYGONTYPE:
+			return lwpoly_same((LWPOLY *)lwgeom1,
+				(LWPOLY *)lwgeom2);
+		case MULTIPOINTTYPE:
+		case MULTILINETYPE:
+		case MULTIPOLYGONTYPE:
+		case COLLECTIONTYPE:
+			return lwcollection_same((LWCOLLECTION *)lwgeom1,
+				(LWCOLLECTION *)lwgeom2);
+		default:
+			lwerror("lwgeom_same: unknown geometry type: %d",
+				TYPE_GETTYPE(lwgeom1->type));
+			return 0;
+	}
+
+}
+
+void
+lwgeom_changed(LWGEOM *lwgeom)
+{
+	if ( lwgeom->bbox ) lwfree(lwgeom->bbox);
+	lwgeom->bbox = NULL;
+	TYPE_SETHASBBOX(lwgeom->type, 0);
+}
+
+void
+lwgeom_dropBBOX(LWGEOM *lwgeom)
+{
+	if ( lwgeom->bbox ) lwfree(lwgeom->bbox);
+	lwgeom->bbox = NULL;
+	TYPE_SETHASBBOX(lwgeom->type, 0);
+}
+
+/*
+ * Ensure there's a box in the LWGEOM.
+ * If the box is already there just return,
+ * else compute it.
+ */
+void
+lwgeom_addBBOX(LWGEOM *lwgeom)
+{
+	if ( lwgeom->bbox ) return;
+	lwgeom->bbox = lwgeom_compute_box2d(lwgeom);
+	TYPE_SETHASBBOX(lwgeom->type, 1);
+}
+
+void
+lwgeom_dropSRID(LWGEOM *lwgeom)
+{
+	TYPE_SETHASSRID(lwgeom->type, 0);
+	lwgeom->SRID = -1;
+}
+
+LWGEOM *
+lwgeom_segmentize2d(LWGEOM *lwgeom, double dist)
+{
+	switch(TYPE_GETTYPE(lwgeom->type))
+	{
+		case LINETYPE:
+			return (LWGEOM *)lwline_segmentize2d((LWLINE *)lwgeom,
+				dist);
+		case POLYGONTYPE:
+			return (LWGEOM *)lwpoly_segmentize2d((LWPOLY *)lwgeom,
+				dist);
+		case MULTILINETYPE:
+		case MULTIPOLYGONTYPE:
+		case COLLECTIONTYPE:
+			return (LWGEOM *)lwcollection_segmentize2d(
+				(LWCOLLECTION *)lwgeom, dist);
+
+		default:
+			return lwgeom_clone(lwgeom);
+	}
+}
+
+void
+lwgeom_longitude_shift(LWGEOM *lwgeom)
+{
+	int i;
+	switch(TYPE_GETTYPE(lwgeom->type))
+	{
+		LWPOINT *point;
+		LWLINE *line;
+		LWPOLY *poly;
+		LWCOLLECTION *coll;
+
+		case POINTTYPE:
+			point = (LWPOINT *)lwgeom;
+			ptarray_longitude_shift(point->point);
+			return;
+		case LINETYPE:
+			line = (LWLINE *)lwgeom;
+			ptarray_longitude_shift(line->points);
+			return;
+		case POLYGONTYPE:
+			poly = (LWPOLY *)lwgeom;
+			for (i=0; i<poly->nrings; i++)
+				ptarray_longitude_shift(poly->rings[i]);
+			return;
+		case MULTILINETYPE:
+		case MULTIPOLYGONTYPE:
+		case COLLECTIONTYPE:
+			coll = (LWCOLLECTION *)lwgeom;
+			for (i=0; i<coll->ngeoms; i++)
+				lwgeom_longitude_shift(coll->geoms[i]);
+			return;
+		default:
+			lwerror("%s:%d: unknown geom type: %d",
+				__FILE__, __LINE__,
+				TYPE_GETTYPE(lwgeom->type));
+	}
+}

Added: trunk/liblwgeom/lwgeom_api.c
===================================================================
--- trunk/liblwgeom/lwgeom_api.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwgeom_api.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,2185 @@
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "liblwgeom.h"
+#include "wktparse.h"
+
+/*
+ * Lower this to reduce integrity checks
+ */
+#define PARANOIA_LEVEL 1
+
+
+
+/**********************************************************************
+ * BOX routines
+ *
+ * returns the float thats very close to the input, but <=
+ *  handles the funny differences in float4 and float8 reps.
+ **********************************************************************/
+
+
+/*
+ * These are taken from glibc
+ * some machines do *not* have these functions defined, so we give
+ *  an implementation of them here.
+ */
+typedef int int32_tt;
+typedef unsigned int u_int32_tt;
+
+typedef union
+{
+  float value;
+  u_int32_tt word;
+} ieee_float_shape_type;
+
+#define GET_FLOAT_WORD(i,d)			\
+	do {					\
+		ieee_float_shape_type gf_u;	\
+		gf_u.value = (d);		\
+		(i) = gf_u.word;		\
+	} while (0)
+
+
+#define SET_FLOAT_WORD(d,i)			\
+	do {					\
+		ieee_float_shape_type sf_u;	\
+		sf_u.word = (i);		\
+		(d) = sf_u.value;		\
+	} while (0)
+
+
+/*
+ * Returns the next smaller or next larger float
+ * from x (in direction of y).
+ */
+float
+nextafterf_custom(float x, float y)
+{
+        int32_tt hx,hy,ix,iy;
+
+        GET_FLOAT_WORD(hx,x);
+        GET_FLOAT_WORD(hy,y);
+        ix = hx&0x7fffffff;             /* |x| */
+        iy = hy&0x7fffffff;             /* |y| */
+
+        if((ix>0x7f800000) ||   /* x is nan */
+           (iy>0x7f800000))     /* y is nan */
+           return x+y;
+        if(x==y) return y;              /* x=y, return y */
+        if(ix==0) {                             /* x == 0 */
+            SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */
+            y = x*x;
+            if(y==x) return y; else return x;   /* raise underflow flag */
+        }
+        if(hx>=0) {                             /* x > 0 */
+            if(hx>hy) {                         /* x > y, x -= ulp */
+                hx -= 1;
+            } else {                            /* x < y, x += ulp */
+                hx += 1;
+            }
+        } else {                                /* x < 0 */
+            if(hy>=0||hx>hy){                   /* x < y, x -= ulp */
+                hx -= 1;
+            } else {                            /* x > y, x += ulp */
+                hx += 1;
+            }
+        }
+        hy = hx&0x7f800000;
+        if(hy>=0x7f800000) return x+x;  /* overflow  */
+        if(hy<0x00800000) {             /* underflow */
+            y = x*x;
+            if(y!=x) {          /* raise underflow flag */
+                SET_FLOAT_WORD(y,hx);
+                return y;
+            }
+        }
+        SET_FLOAT_WORD(x,hx);
+        return x;
+}
+
+
+float nextDown_f(double d)
+{
+	float result  = d;
+
+	if ( ((double) result) <=d)
+		return result;
+
+	return nextafterf_custom(result, result - 1000000);
+
+}
+
+/*
+ * Returns the float thats very close to the input, but >=.
+ * handles the funny differences in float4 and float8 reps.
+ */
+float
+nextUp_f(double d)
+{
+	float result  = d;
+
+	if ( ((double) result) >=d)
+		return result;
+
+	return nextafterf_custom(result, result + 1000000);
+}
+
+
+/*
+ * Returns the double thats very close to the input, but <.
+ * handles the funny differences in float4 and float8 reps.
+ */
+double
+nextDown_d(float d)
+{
+	double result  = d;
+
+	if ( result < d)
+		return result;
+
+	return nextafterf_custom(result, result - 1000000);
+}
+
+/*
+ * Returns the double thats very close to the input, but >
+ * handles the funny differences in float4 and float8 reps.
+ */
+double
+nextUp_d(float d)
+{
+	double result  = d;
+
+	if ( result > d)
+		return result;
+
+	return nextafterf_custom(result, result + 1000000);
+}
+
+
+
+/*
+ * Convert BOX3D to BOX2D
+ * returned box2d is allocated with 'lwalloc'
+ */
+BOX2DFLOAT4 *
+box3d_to_box2df(BOX3D *box)
+{
+	BOX2DFLOAT4 *result = (BOX2DFLOAT4*) lwalloc(sizeof(BOX2DFLOAT4));
+
+#if PARANOIA_LEVEL > 0
+	if (box == NULL)
+	{
+		lwerror("box3d_to_box2df got NUL box");
+		return NULL;
+	}
+#endif
+
+	result->xmin = nextDown_f(box->xmin);
+	result->ymin = nextDown_f(box->ymin);
+
+	result->xmax = nextUp_f(box->xmax);
+	result->ymax = nextUp_f(box->ymax);
+
+	return result;
+}
+
+/*
+ * Convert BOX3D to BOX2D using pre-allocated BOX2D
+ * returned box2d is allocated with 'lwalloc'
+ * return 0 on error (NULL input box)
+ */
+int
+box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *result)
+{
+#if PARANOIA_LEVEL > 0
+	if (box == NULL)
+	{
+		lwerror("box3d_to_box2df got NUL box");
+		return 0;
+	}
+#endif
+
+	result->xmin = nextDown_f(box->xmin);
+	result->ymin = nextDown_f(box->ymin);
+
+	result->xmax = nextUp_f(box->xmax);
+	result->ymax = nextUp_f(box->ymax);
+
+	return 1;
+}
+
+
+
+/*
+ * Convert BOX2D to BOX3D
+ * zmin and zmax are set to NO_Z_VALUE
+ */
+BOX3D
+box2df_to_box3d(BOX2DFLOAT4 *box)
+{
+	BOX3D result;
+
+#if PARANOIA_LEVEL > 0
+	if (box == NULL)
+		lwerror("box2df_to_box3d got NULL box");
+#endif
+
+	result.xmin = box->xmin;
+	result.ymin = box->ymin;
+
+	result.xmax = box->xmax;
+	result.ymax = box->ymax;
+
+	result.zmin = result.zmax = NO_Z_VALUE;
+
+	return result;
+}
+
+/*
+ * Convert BOX2D to BOX3D, using pre-allocated BOX3D as output
+ * Z values are set to NO_Z_VALUE.
+ */
+void
+box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *out)
+{
+	if (box == NULL) return;
+
+	out->xmin = box->xmin;
+	out->ymin = box->ymin;
+
+	out->xmax = box->xmax;
+	out->ymax = box->ymax;
+
+	out->zmin = out->zmax = NO_Z_VALUE;
+}
+
+
+
+/*
+ * Returns a BOX3D that encloses b1 and b2
+ * box3d_union(NULL,A) --> A
+ * box3d_union(A,NULL) --> A
+ * box3d_union(A,B) --> A union B
+ */
+BOX3D *
+box3d_union(BOX3D *b1, BOX3D *b2)
+{
+	BOX3D *result;
+
+	result = lwalloc(sizeof(BOX3D));
+
+	if ( (b1 == NULL) && (b2 == NULL) )
+	{
+		return NULL;
+	}
+
+	if  (b1 == NULL)
+	{
+		/*return b2 */
+		memcpy(result, b2, sizeof(BOX3D));
+		return result;
+	}
+	if (b2 == NULL)
+	{
+		/*return b1 */
+		memcpy(result, b1, sizeof(BOX3D));
+		return result;
+	}
+
+	if (b1->xmin < b2->xmin)
+		result->xmin = b1->xmin;
+	else
+		result->xmin = b2->xmin;
+
+	if (b1->ymin < b2->ymin)
+			result->ymin = b1->ymin;
+	else
+		result->ymin = b2->ymin;
+
+
+	if (b1->xmax > b2->xmax)
+		result->xmax = b1->xmax;
+	else
+		result->xmax = b2->xmax;
+
+	if (b1->ymax > b2->ymax)
+		result->ymax = b1->ymax;
+	else
+		result->ymax = b2->ymax;
+
+	if (b1->zmax > b2->zmax)
+			result->zmax = b1->zmax;
+	else
+			result->zmax = b2->zmax;
+
+	if (b1->zmin > b2->zmin)
+		result->zmin = b1->zmin;
+	else
+		result->zmin = b2->zmin;
+
+	return result;
+}
+
+/* Make given ubox a union of b1 and b2 */
+int
+box3d_union_p(BOX3D *b1, BOX3D *b2, BOX3D *ubox)
+{
+
+        LWDEBUG(2, "box3d_union_p called: (xmin, xmax), (ymin, ymax), (zmin, zmax)");
+        LWDEBUGF(4, "b1: (%.16f, %.16f),(%.16f, %.16f),(%.16f, %.16f)", b1->xmin, b1->xmax, b1->ymin, b1->ymax, b1->zmin, b1->zmax);
+        LWDEBUGF(4, "b2: (%.16f, %.16f),(%.16f, %.16f),(%.16f, %.16f)", b2->xmin, b2->xmax, b2->ymin, b2->ymax, b2->zmin, b2->zmax);
+
+	if ( (b1 == NULL) && (b2 == NULL) )
+	{
+		return 0;
+	}
+
+	if  (b1 == NULL)
+	{
+		memcpy(ubox, b2, sizeof(BOX3D));
+		return 1;
+	}
+	if (b2 == NULL)
+	{
+		memcpy(ubox, b1, sizeof(BOX3D));
+		return 1;
+	}
+
+	if (b1->xmin < b2->xmin)
+		ubox->xmin = b1->xmin;
+	else
+		ubox->xmin = b2->xmin;
+
+	if (b1->ymin < b2->ymin)
+		ubox->ymin = b1->ymin;
+	else
+		ubox->ymin = b2->ymin;
+
+
+	if (b1->xmax > b2->xmax)
+		ubox->xmax = b1->xmax;
+	else
+		ubox->xmax = b2->xmax;
+
+	if (b1->ymax > b2->ymax)
+		ubox->ymax = b1->ymax;
+	else
+		ubox->ymax = b2->ymax;
+
+	if (b1->zmax > b2->zmax)
+		ubox->zmax = b1->zmax;
+	else
+		ubox->zmax = b2->zmax;
+
+	if (b1->zmin < b2->zmin)
+		ubox->zmin = b1->zmin;
+	else
+		ubox->zmin = b2->zmin;
+
+	return 1;
+}
+
+#if 0 /* UNUSED */
+/*
+ * Returns a pointer to internal storage, or NULL
+ * if the serialized form does not have a BBOX.
+ */
+BOX2DFLOAT4 *
+getbox2d_internal(uchar *srl)
+{
+	if (TYPE_HASBBOX(srl[0])) return (BOX2DFLOAT4 *)(srl+1);
+	else return NULL;
+}
+#endif /* UNUSED */
+
+/*
+ * Same as getbox2d, but modifies box instead of returning result on the stack
+ */
+int
+getbox2d_p(uchar *srl, BOX2DFLOAT4 *box)
+{
+	uchar type = srl[0];
+	uchar *loc;
+	BOX3D box3d;
+
+	LWDEBUG(2, "getbox2d_p call");
+
+	loc = srl+1;
+
+	if (lwgeom_hasBBOX(type))
+	{
+		/*woot - this is easy */
+		LWDEBUG(4, "getbox2d_p: has box");
+		memcpy(box, loc, sizeof(BOX2DFLOAT4));
+		return 1;
+	}
+
+	LWDEBUG(4, "getbox2d_p: has no box - computing");
+
+	/* We have to actually compute it! */
+	if ( ! compute_serialized_box3d_p(srl, &box3d) ) return 0;
+
+	LWDEBUGF(4, "getbox2d_p: compute_serialized_box3d returned %p", box3d);
+
+	if ( ! box3d_to_box2df_p(&box3d, box) ) return 0;
+
+	LWDEBUG(4, "getbox2d_p: box3d converted to box2d");
+
+	return 1;
+}
+
+/************************************************************************
+ * POINTARRAY support functions
+ *
+ * TODO: should be moved to ptarray.c probably
+ *
+ ************************************************************************/
+
+/*
+ * Copies a point from the point array into the parameter point
+ * will set point's z=NO_Z_VALUE if pa is 2d
+ * will set point's m=NO_M_VALUE if pa is 3d or 2d
+ *
+ * NOTE: point is a real POINT3D *not* a pointer
+ */
+POINT4D
+getPoint4d(const POINTARRAY *pa, int n)
+{
+	POINT4D result;
+	getPoint4d_p(pa, n, &result);
+	return result;
+}
+
+/*
+ * Copies a point from the point array into the parameter point
+ * will set point's z=NO_Z_VALUE  if pa is 2d
+ * will set point's m=NO_M_VALUE  if pa is 3d or 2d
+ *
+ * NOTE: this will modify the point4d pointed to by 'point'.
+ */
+int
+getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *op)
+{
+	uchar *ptr;
+	int zmflag;
+
+#if PARANOIA_LEVEL > 0
+	if ( ! pa ) lwerror("getPoint4d_p: NULL pointarray");
+
+	if ( (n<0) || (n>=pa->npoints))
+	{
+		lwerror("getPoint4d_p: point offset out of range");
+	}
+#endif
+
+        LWDEBUG(4, "getPoint4d_p called.");
+
+	/* Get a pointer to nth point offset and zmflag */
+	ptr=getPoint_internal(pa, n);
+	zmflag=TYPE_GETZM(pa->dims);
+
+        LWDEBUGF(4, "ptr %p, zmflag %d", ptr, zmflag);
+
+	switch (zmflag)
+	{
+		case 0: /* 2d  */
+			memcpy(op, ptr, sizeof(POINT2D));
+			op->m=NO_M_VALUE;
+			op->z=NO_Z_VALUE;
+			break;
+
+		case 3: /* ZM */
+			memcpy(op, ptr, sizeof(POINT4D));
+			break;
+
+		case 2: /* Z */
+			memcpy(op, ptr, sizeof(POINT3DZ));
+			op->m=NO_M_VALUE;
+			break;
+
+		case 1: /* M */
+			memcpy(op, ptr, sizeof(POINT3DM));
+			op->m=op->z; /* we use Z as temporary storage */
+			op->z=NO_Z_VALUE;
+			break;
+
+		default:
+			lwerror("Unknown ZM flag ??");
+	}
+	return 1;
+
+}
+
+
+
+/*
+ * Copy a point from the point array into the parameter point
+ * will set point's z=NO_Z_VALUE if pa is 2d
+ * NOTE: point is a real POINT3DZ *not* a pointer
+ */
+POINT3DZ
+getPoint3dz(const POINTARRAY *pa, int n)
+{
+	POINT3DZ result;
+	getPoint3dz_p(pa, n, &result);
+	return result;
+}
+
+/*
+ * Copy a point from the point array into the parameter point
+ * will set point's z=NO_Z_VALUE if pa is 2d
+ *
+ * NOTE: point is a real POINT3DZ *not* a pointer
+ */
+POINT3DM
+getPoint3dm(const POINTARRAY *pa, int n)
+{
+	POINT3DM result;
+	getPoint3dm_p(pa, n, &result);
+	return result;
+}
+
+/*
+ * Copy a point from the point array into the parameter point
+ * will set point's z=NO_Z_VALUE if pa is 2d
+ * 
+ * NOTE: this will modify the point3dz pointed to by 'point'.
+ */
+int
+getPoint3dz_p(const POINTARRAY *pa, int n, POINT3DZ *op)
+{
+	uchar *ptr;
+
+#if PARANOIA_LEVEL > 0
+	if ( ! pa ) return 0;
+
+	if ( (n<0) || (n>=pa->npoints))
+	{
+		LWDEBUGF(4, "%d out of numpoint range (%d)", n, pa->npoints);
+		return 0; /*error */
+	}
+#endif
+
+	LWDEBUGF(2, "getPoint3dz_p called on array of %d-dimensions / %u pts",
+		TYPE_NDIMS(pa->dims), pa->npoints);
+
+	/* Get a pointer to nth point offset */
+	ptr=getPoint_internal(pa, n);
+
+	/*
+	 * if input POINTARRAY has the Z, it is always
+	 * at third position so make a single copy
+	 */
+	if ( TYPE_HASZ(pa->dims) )
+	{
+		memcpy(op, ptr, sizeof(POINT3DZ));
+	}
+
+	/*
+	 * Otherwise copy the 2d part and initialize
+	 * Z to NO_Z_VALUE
+	 */
+	else
+	{
+		memcpy(op, ptr, sizeof(POINT2D));
+		op->z=NO_Z_VALUE;
+	}
+
+	return 1;
+
+}
+
+/*
+ * Copy a point from the point array into the parameter point
+ * will set point's m=NO_Z_VALUE if pa has no M
+ * 
+ * NOTE: this will modify the point3dm pointed to by 'point'.
+ */
+int
+getPoint3dm_p(const POINTARRAY *pa, int n, POINT3DM *op)
+{
+	uchar *ptr;
+	int zmflag;
+
+#if PARANOIA_LEVEL > 0
+	if ( ! pa ) return 0;
+
+	if ( (n<0) || (n>=pa->npoints))
+	{
+		lwerror("%d out of numpoint range (%d)", n, pa->npoints);
+		return 0; /*error */
+	}
+#endif 
+
+	LWDEBUGF(2, "getPoint3dm_p(%d) called on array of %d-dimensions / %u pts",
+		n, TYPE_NDIMS(pa->dims), pa->npoints);
+
+
+	/* Get a pointer to nth point offset and zmflag */
+	ptr=getPoint_internal(pa, n);
+	zmflag=TYPE_GETZM(pa->dims);
+
+	/*
+	 * if input POINTARRAY has the M and NO Z,
+	 * we can issue a single memcpy
+	 */
+	if ( zmflag == 1 )
+	{
+		memcpy(op, ptr, sizeof(POINT3DM));
+		return 1;
+	}
+
+	/*
+	 * Otherwise copy the 2d part and 
+	 * initialize M to NO_M_VALUE
+	 */
+	memcpy(op, ptr, sizeof(POINT2D));
+
+	/*
+	 * Then, if input has Z skip it and
+	 * copy next double, otherwise initialize
+	 * M to NO_M_VALUE
+	 */
+	if ( zmflag == 3 )
+	{
+		ptr+=sizeof(POINT3DZ);
+		memcpy(&(op->m), ptr, sizeof(double));
+	}
+	else
+	{
+		op->m=NO_M_VALUE;
+	}
+
+	return 1;
+}
+
+
+/*
+ * Copy a point from the point array into the parameter point
+ * z value (if present) is not returned.
+ *
+ * NOTE: point is a real POINT2D *not* a pointer
+ */
+POINT2D
+getPoint2d(const POINTARRAY *pa, int n)
+{
+	POINT2D result;
+	getPoint2d_p(pa, n, &result);
+	return result;
+}
+
+/*
+ * Copy a point from the point array into the parameter point
+ * z value (if present) is not returned.
+ *
+ * NOTE: this will modify the point2d pointed to by 'point'.
+ */
+int
+getPoint2d_p(const POINTARRAY *pa, int n, POINT2D *point)
+{
+#if PARANOIA_LEVEL > 0
+	if ( ! pa ) return 0;
+
+	if ( (n<0) || (n>=pa->npoints))
+	{
+		lwerror("getPoint2d_p: point offset out of range");
+		return 0; /*error */
+	}
+#endif
+
+	/* this does x,y */
+	memcpy(point, getPoint_internal(pa, n), sizeof(POINT2D));
+	return 1;
+}
+
+/*
+ * set point N to the given value
+ * NOTE that the pointarray can be of any
+ * dimension, the appropriate ordinate values
+ * will be extracted from it
+ *
+ */
+void
+setPoint4d(POINTARRAY *pa, int n, POINT4D *p4d)
+{
+	uchar *ptr=getPoint_internal(pa, n);
+	switch ( TYPE_GETZM(pa->dims) )
+	{
+		case 3:
+			memcpy(ptr, p4d, sizeof(POINT4D));
+			break;
+		case 2:
+			memcpy(ptr, p4d, sizeof(POINT3DZ));
+			break;
+		case 1:
+			memcpy(ptr, p4d, sizeof(POINT2D));
+			ptr+=sizeof(POINT2D);
+			memcpy(ptr, &(p4d->m), sizeof(double));
+			break;
+		case 0:
+			memcpy(ptr, p4d, sizeof(POINT2D));
+			break;
+	}
+}
+
+
+/*
+ * Get a pointer to nth point of a POINTARRAY.
+ * You cannot safely cast this to a real POINT, due to memory alignment
+ * constraints. Use getPoint*_p for that.
+ */
+uchar *
+getPoint_internal(const POINTARRAY *pa, int n)
+{
+	int size;
+
+#if PARANOIA_LEVEL > 0
+	if ( pa == NULL ) {
+		lwerror("getPoint got NULL pointarray");
+		return NULL;
+	}
+
+	if ( (n<0) || (n>=pa->npoints))
+	{
+		return NULL; /*error */
+	}
+#endif
+
+	size = pointArray_ptsize(pa);
+
+	return &(pa->serialized_pointlist[size*n]);
+}
+
+
+
+/*
+ * Constructs a POINTARRAY.
+ *
+ * NOTE: points is *not* copied, so be careful about modification
+ * (can be aligned/missaligned).
+ *
+ * NOTE: ndims is descriptive - it describes what type of data 'points'
+ *       points to.  No data conversion is done.
+ */
+POINTARRAY *
+pointArray_construct(uchar *points, char hasz, char hasm,
+	uint32 npoints)
+{
+	POINTARRAY  *pa;
+	
+	LWDEBUG(2, "pointArray_construct called.");
+
+	pa = (POINTARRAY*)lwalloc(sizeof(POINTARRAY));
+
+	pa->dims = 0;
+	TYPE_SETZM(pa->dims, hasz?1:0, hasm?1:0);
+	pa->npoints = npoints;
+
+	pa->serialized_pointlist = points;
+
+	LWDEBUGF(4, "pointArray_construct returning %p", pa);
+
+	return pa;
+}
+
+
+/*
+ * Size of point represeneted in the POINTARRAY
+ * 16 for 2d, 24 for 3d, 32 for 4d
+ */
+int
+pointArray_ptsize(const POINTARRAY *pa)
+{
+	LWDEBUGF(2, "pointArray_ptsize: TYPE_NDIMS(pa->dims)=%x\n",
+		TYPE_NDIMS(pa->dims));
+
+	return sizeof(double)*TYPE_NDIMS(pa->dims);
+}
+
+
+/***************************************************************************
+ * Basic type handling
+ ***************************************************************************/
+
+
+/* Returns true if this type says it has an SRID (S bit set) */
+char
+lwgeom_hasSRID(uchar type)
+{
+	return TYPE_HASSRID(type);
+}
+
+/* Returns either 2,3, or 4 -- 2=2D, 3=3D, 4=4D */
+int
+lwgeom_ndims(uchar type)
+{
+	return TYPE_NDIMS(type);
+}
+
+/* has M ? */
+int lwgeom_hasM(uchar type)
+{
+	return  ( (type & 0x10) >>4);
+}
+
+/* has Z ? */
+int lwgeom_hasZ(uchar type)
+{
+	return  ( (type & 0x20) >>5);
+}
+
+
+/* get base type (ie. POLYGONTYPE) */
+int
+lwgeom_getType(uchar type)
+{
+        LWDEBUGF(2, "lwgeom_getType %d", type);
+
+	return (type & 0x0F);
+}
+
+
+/* Construct a type (hasBOX=false) */
+uchar
+lwgeom_makeType(char hasz, char hasm, char hasSRID, int type)
+{
+	return lwgeom_makeType_full(hasz, hasm, hasSRID, type, 0);
+}
+
+/*
+ * Construct a type
+ * TODO: needs to be expanded to accept explicit MZ type
+ */
+uchar
+lwgeom_makeType_full(char hasz, char hasm, char hasSRID, int type, char hasBBOX)
+{
+	uchar result = (char)type;
+
+	TYPE_SETZM(result, hasz, hasm);
+	TYPE_SETHASSRID(result, hasSRID);
+	TYPE_SETHASBBOX(result, hasBBOX);
+
+	return result;
+}
+
+/* Returns true if there's a bbox in this LWGEOM (B bit set) */
+char
+lwgeom_hasBBOX(uchar type)
+{
+	return TYPE_HASBBOX(type);
+}
+
+/*****************************************************************************
+ * Basic sub-geometry types
+ *****************************************************************************/
+
+/* handle missaligned unsigned int32 data */
+uint32
+lw_get_uint32(const uchar *loc)
+{
+	uint32 result;
+
+	memcpy(&result, loc, sizeof(uint32));
+	return result;
+}
+
+/* handle missaligned signed int32 data */
+int32
+lw_get_int32(const uchar *loc)
+{
+	int32 result;
+
+	memcpy(&result,loc, sizeof(int32));
+	return result;
+}
+
+
+/*************************************************************************
+ *
+ * Multi-geometry support
+ *
+ * Note - for a simple type (ie. point), this will have
+ * sub_geom[0] = serialized_form.
+ *
+ * For multi-geomtries sub_geom[0] will be a few bytes
+ * into the serialized form.
+ *
+ * This function just computes the length of each sub-object and
+ * pre-caches this info.
+ *
+ * For a geometry collection of multi* geometries, you can inspect
+ * the sub-components
+ * as well.
+ */
+LWGEOM_INSPECTED *
+lwgeom_inspect(const uchar *serialized_form)
+{
+	LWGEOM_INSPECTED *result = lwalloc(sizeof(LWGEOM_INSPECTED));
+	uchar typefl = (uchar)serialized_form[0];
+	uchar type;
+	uchar **sub_geoms;
+	const uchar *loc;
+	int 	t;
+
+	LWDEBUGF(2, "lwgeom_inspect: serialized@%p", serialized_form);
+
+	if (serialized_form == NULL)
+		return NULL;
+
+	result->serialized_form = serialized_form; 
+	result->type = (uchar) serialized_form[0];
+	result->SRID = -1; /* assume */
+
+	type = lwgeom_getType(typefl);
+
+	loc = serialized_form+1;
+
+	if ( lwgeom_hasBBOX(typefl) )
+	{
+		loc += sizeof(BOX2DFLOAT4);
+	}
+
+	if ( lwgeom_hasSRID(typefl) )
+	{
+		result->SRID = lw_get_int32(loc);
+		loc += 4;
+	}
+
+	if ( (type==POINTTYPE) || (type==LINETYPE) || (type==POLYGONTYPE) || (type == CURVETYPE))
+	{
+		/* simple geometry (point/line/polygon)-- not multi! */
+		result->ngeometries = 1;
+		sub_geoms = (uchar**) lwalloc(sizeof(char*));
+		sub_geoms[0] = (uchar *)serialized_form;
+		result->sub_geoms = (uchar **)sub_geoms;
+		return result;
+	}
+
+	/* its a GeometryCollection or multi* geometry */
+
+	result->ngeometries = lw_get_uint32(loc);
+	loc +=4;
+
+	LWDEBUGF(3, "lwgeom_inspect: geometry is a collection of %d elements",
+		result->ngeometries);
+
+	if ( ! result->ngeometries ) return result;
+
+	sub_geoms = lwalloc(sizeof(uchar*) * result->ngeometries );
+	result->sub_geoms = sub_geoms;
+	sub_geoms[0] = (uchar *)loc;
+
+	LWDEBUGF(3, "subgeom[0] @ %p (+%d)", sub_geoms[0], sub_geoms[0]-serialized_form);
+
+	for (t=1;t<result->ngeometries; t++)
+	{
+		/* -1 = entire object */
+		int sub_length = lwgeom_size_subgeom(sub_geoms[t-1], -1);
+		sub_geoms[t] = sub_geoms[t-1] + sub_length;
+                
+		LWDEBUGF(3, "subgeom[%d] @ %p (+%d)",
+			t, sub_geoms[t], sub_geoms[0]-serialized_form);
+	}
+
+	return result;
+
+}
+
+
+/*
+ * 1st geometry has geom_number = 0
+ * if the actual sub-geometry isnt a POINT, null is returned (see _gettype()).
+ * if there arent enough geometries, return null.
+ * this is fine to call on a point (with geom_num=0),
+ * multipoint or geometrycollection
+ */
+LWPOINT *
+lwgeom_getpoint(uchar *serialized_form, int geom_number)
+{
+	int type = lwgeom_getType((uchar)serialized_form[0]);
+	uchar *sub_geom;
+
+	if ((type == POINTTYPE)  && (geom_number == 0))
+	{
+		/* Be nice and do as they want instead of what they say */
+		return lwpoint_deserialize(serialized_form);
+	}
+
+	if ((type != MULTIPOINTTYPE) && (type != COLLECTIONTYPE) )
+		return NULL;
+
+	sub_geom = lwgeom_getsubgeometry(serialized_form, geom_number);
+	if (sub_geom == NULL)
+		return NULL;
+
+	type = lwgeom_getType(sub_geom[0]);
+	if (type != POINTTYPE)
+		return NULL;
+
+	return lwpoint_deserialize(sub_geom);
+}
+
+/*
+ * 1st geometry has geom_number = 0
+ * if the actual sub-geometry isnt a POINT, null is returned (see _gettype()).
+ * if there arent enough geometries, return null.
+ * this is fine to call on a point (with geom_num=0), multipoint
+ * or geometrycollection
+ */
+LWPOINT *lwgeom_getpoint_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
+{
+	uchar *sub_geom;
+	uchar type;
+
+	sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number);
+
+	if (sub_geom == NULL) return NULL;
+
+	type = lwgeom_getType(sub_geom[0]);
+	if (type != POINTTYPE) return NULL;
+
+	return lwpoint_deserialize(sub_geom);
+}
+
+
+/*
+ * 1st geometry has geom_number = 0
+ * if the actual geometry isnt a LINE, null is returned (see _gettype()).
+ * if there arent enough geometries, return null.
+ * this is fine to call on a line, multiline or geometrycollection
+ */
+LWLINE *
+lwgeom_getline(uchar *serialized_form, int geom_number)
+{
+	uchar type = lwgeom_getType( (uchar) serialized_form[0]);
+	uchar *sub_geom;
+
+	if ((type == LINETYPE)  && (geom_number == 0))
+	{
+		/* be nice and do as they want instead of what they say */
+		return lwline_deserialize(serialized_form);
+	}
+
+	if ((type != MULTILINETYPE) && (type != COLLECTIONTYPE) )
+		return NULL;
+
+	sub_geom = lwgeom_getsubgeometry(serialized_form, geom_number);
+	if (sub_geom == NULL) return NULL;
+
+	type = lwgeom_getType((uchar) sub_geom[0]);
+	if (type != LINETYPE) return NULL;
+
+	return lwline_deserialize(sub_geom);
+}
+
+/*
+ * 1st geometry has geom_number = 0
+ * if the actual geometry isnt a LINE, null is returned (see _gettype()).
+ * if there arent enough geometries, return null.
+ * this is fine to call on a line, multiline or geometrycollection
+ */
+LWLINE *
+lwgeom_getline_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
+{
+	uchar *sub_geom;
+	uchar type;
+
+	sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number);
+
+	if (sub_geom == NULL) return NULL;
+
+	type = lwgeom_getType((uchar) sub_geom[0]);
+	if (type != LINETYPE) return NULL;
+
+	return lwline_deserialize(sub_geom);
+}
+
+/*
+ * 1st geometry has geom_number = 0
+ * if the actual geometry isnt a POLYGON, null is returned (see _gettype()).
+ * if there arent enough geometries, return null.
+ * this is fine to call on a polygon, multipolygon or geometrycollection
+ */
+LWPOLY *
+lwgeom_getpoly(uchar *serialized_form, int geom_number)
+{
+	uchar type = lwgeom_getType((uchar)serialized_form[0]);
+	uchar *sub_geom;
+
+	if ((type == POLYGONTYPE)  && (geom_number == 0))
+	{
+		/* Be nice and do as they want instead of what they say */
+		return lwpoly_deserialize(serialized_form);
+	}
+
+	if ((type != MULTIPOLYGONTYPE) && (type != COLLECTIONTYPE) )
+		return NULL;
+
+	sub_geom = lwgeom_getsubgeometry(serialized_form, geom_number);
+	if (sub_geom == NULL) return NULL;
+
+	type = lwgeom_getType(sub_geom[0]);
+	if (type != POLYGONTYPE) return NULL;
+
+	return lwpoly_deserialize(sub_geom);
+}
+
+/*
+ * 1st geometry has geom_number = 0
+ * if the actual geometry isnt a POLYGON, null is returned (see _gettype()).
+ * if there arent enough geometries, return null.
+ * this is fine to call on a polygon, multipolygon or geometrycollection
+ */
+LWPOLY *
+lwgeom_getpoly_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
+{
+	uchar *sub_geom;
+	uchar type;
+
+	sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number);
+
+	if (sub_geom == NULL) return NULL;
+
+	type = lwgeom_getType(sub_geom[0]);
+	if (type != POLYGONTYPE) return NULL;
+
+	return lwpoly_deserialize(sub_geom);
+}
+
+/*
+ * 1st geometry has geom_number = 0
+ * if there arent enough geometries, return null.
+ */
+LWGEOM *lwgeom_getgeom_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
+{
+	uchar *sub_geom;
+	uchar type;
+
+	sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number);
+
+	if (sub_geom == NULL) return NULL;
+
+	type = lwgeom_getType(sub_geom[0]);
+
+	return lwgeom_deserialize(sub_geom);
+}
+
+
+/*
+ * This gets the serialized form of a sub-geometry
+ *
+ * 1st geometry has geom_number = 0
+ * if this isnt a multi* geometry, and geom_number ==0 then it returns
+ * itself.
+ *
+ * Returns null on problems.
+ *
+ * In the future this is how you would access a muli* portion of a
+ * geometry collection.
+ *    GEOMETRYCOLLECTION(MULTIPOINT(0 0, 1 1), LINESTRING(0 0, 1 1))
+ *   ie. lwgeom_getpoint( lwgeom_getsubgeometry( serialized, 0), 1)
+ *           --> POINT(1 1)
+ *
+ * You can inspect the sub-geometry as well if you wish.
+ *
+ */
+uchar *
+lwgeom_getsubgeometry(const uchar *serialized_form, int geom_number)
+{
+	uchar *result;
+	/*major cheat!! */
+	LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized_form);
+
+	result = lwgeom_getsubgeometry_inspected(inspected, geom_number);
+	pfree_inspected(inspected);
+	return result;
+}
+
+uchar *
+lwgeom_getsubgeometry_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
+{
+	if ((geom_number <0) || (geom_number >= inspected->ngeometries) )
+	{
+		lwerror("lwgeom_getsubgeometry_inspected: geom_number out of range");
+		return NULL;
+	}
+
+	return inspected->sub_geoms[geom_number];
+}
+
+
+/*
+ * 1st geometry has geom_number = 0
+ *  use geom_number = -1 to find the actual type of the serialized form.
+ *    ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, -1)
+ *                 --> multipoint
+ *   ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, 0)
+ *                 --> point
+ * gets the 8bit type of the geometry at location geom_number
+ */
+uchar
+lwgeom_getsubtype(uchar *serialized_form, int geom_number)
+{
+	char  result;
+	/*major cheat!! */
+	LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized_form);
+
+	result = lwgeom_getsubtype_inspected(inspected, geom_number);
+	pfree_inspected(inspected);
+	return result;
+}
+
+uchar
+lwgeom_getsubtype_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
+{
+	if ((geom_number <0) || (geom_number >= inspected->ngeometries) )
+		return 99;
+
+	return inspected->sub_geoms[geom_number][0]; /* 1st byte is type */
+}
+
+
+/*
+ * How many sub-geometries are there?
+ * for point,line,polygon will return 1.
+ */
+int
+lwgeom_getnumgeometries(uchar *serialized_form)
+{
+	uchar type = lwgeom_getType((uchar)serialized_form[0]);
+	uchar *loc;
+
+	if ( (type==POINTTYPE) || (type==LINETYPE) || (type==POLYGONTYPE) ||
+            (type==CURVETYPE) || (type==COMPOUNDTYPE) || (type==CURVEPOLYTYPE) )
+	{
+		return 1;
+	}
+
+	loc = serialized_form+1;
+
+	if (lwgeom_hasBBOX((uchar) serialized_form[0]))
+	{
+		loc += sizeof(BOX2DFLOAT4);
+	}
+
+	if (lwgeom_hasSRID((uchar) serialized_form[0]) )
+	{
+		loc += 4;
+	}
+	/* its a GeometryCollection or multi* geometry */
+	return lw_get_uint32(loc);
+}
+
+/*
+ * How many sub-geometries are there?
+ * for point,line,polygon will return 1.
+ */
+int
+lwgeom_getnumgeometries_inspected(LWGEOM_INSPECTED *inspected)
+{
+	return inspected->ngeometries;
+}
+
+
+/*
+ * Set finalType to COLLECTIONTYPE or 0 (0 means choose a best type)
+ *   (ie. give it 2 points and ask it to be a multipoint)
+ *  use SRID=-1 for unknown SRID  (will have 8bit type's S = 0)
+ * all subgeometries must have the same SRID
+ * if you want to construct an inspected, call this then inspect the result...
+ */
+uchar *
+lwgeom_serialized_construct(int SRID, int finalType, char hasz, char hasm,
+	int nsubgeometries, uchar **serialized_subs)
+{
+	uint32 *lengths;
+	int t;
+	int total_length = 0;
+	char type = (char)-1;
+	char this_type = -1;
+	uchar *result;
+	uchar *loc;
+
+	if (nsubgeometries == 0)
+		return lwgeom_constructempty(SRID, hasz, hasm);
+
+	lengths = lwalloc(sizeof(int32) * nsubgeometries);
+
+	for (t=0;t<nsubgeometries;t++)
+	{
+		lengths[t] = lwgeom_size_subgeom(serialized_subs[t],-1);
+		total_length += lengths[t];
+		this_type = lwgeom_getType((uchar) (serialized_subs[t][0]));
+		if (type == (char)-1)
+		{
+			type = this_type;
+		}
+		else if (type == COLLECTIONTYPE)
+		{
+				/* still a collection type... */
+		}
+		else
+		{
+			if ( (this_type == MULTIPOINTTYPE) || (this_type == MULTILINETYPE)  || (this_type == MULTIPOLYGONTYPE) || (this_type == COLLECTIONTYPE) )
+			{
+				type = COLLECTIONTYPE;
+			}
+			else
+			{
+				if ( (this_type == POINTTYPE)  && (type==POINTTYPE) )
+					type=MULTIPOINTTYPE;
+				else if ( (this_type == LINETYPE)  && (type==LINETYPE) )
+					type=MULTILINETYPE;
+				else if ( (this_type == POLYGONTYPE)  && (type==POLYGONTYPE) )
+					type=MULTIPOLYGONTYPE;
+				else if ( (this_type == POLYGONTYPE)  && (type==MULTIPOLYGONTYPE) )
+					; /* nop */
+				else if ( (this_type == LINETYPE)  && (type==MULTILINETYPE) )
+					; /* nop */
+				else if ( (this_type == POINTTYPE)  && (type==MULTIPOINTTYPE) )
+					; /* nop */
+				else
+					type = COLLECTIONTYPE;
+			}
+		}
+	}
+
+	if (type == POINTTYPE)
+		type = MULTIPOINTTYPE;
+	if (type == LINETYPE)
+		type = MULTILINETYPE;
+	if (type == POINTTYPE)
+		type = MULTIPOINTTYPE;
+
+	if (finalType == COLLECTIONTYPE)
+		type = COLLECTIONTYPE;
+
+	/* now we have a multi* or GEOMETRYCOLLECTION, let's serialize it */
+
+	if (SRID != -1)
+		total_length +=4; /* space for SRID */
+
+	total_length +=1 ;   /* main type; */
+	total_length +=4 ;   /* nsubgeometries */
+
+	result = lwalloc(total_length);
+	result[0] = (uchar) lwgeom_makeType(hasz, hasm, SRID != -1,  type);
+	if (SRID != -1)
+	{
+		memcpy(&result[1],&SRID,4);
+		loc = result+5;
+	}
+	else
+		loc = result+1;
+
+	memcpy(loc,&nsubgeometries,4);
+	loc +=4;
+
+	for (t=0;t<nsubgeometries;t++)
+	{
+		memcpy(loc, serialized_subs[t], lengths[t] );
+		loc += lengths[t] ;
+	}
+
+	lwfree(lengths);
+	return result;
+}
+
+
+/*
+ * Construct the empty geometry (GEOMETRYCOLLECTION(EMPTY)).
+ *
+ * Returns serialized form
+ */
+uchar *
+lwgeom_constructempty(int SRID, char hasz, char hasm)
+{
+	int size = 0;
+	uchar *result;
+	int ngeoms = 0;
+	uchar *loc;
+
+	if (SRID != -1)
+		size +=4;
+
+	size += 5;
+
+	result = lwalloc(size);
+
+	result[0] = lwgeom_makeType(hasz, hasm, SRID != -1,  COLLECTIONTYPE);
+	if (SRID != -1)
+	{
+		memcpy(&result[1],&SRID,4);
+		loc = result+5;
+	}
+	else
+		loc = result+1;
+
+	memcpy(loc,&ngeoms,4);
+	return result;
+}
+
+size_t
+lwgeom_empty_length(int SRID)
+{
+	int size = 5;
+	if ( SRID != 1 ) size += 4;
+	return size;
+}
+
+/*
+ * Construct the empty geometry (GEOMETRYCOLLECTION(EMPTY))
+ * writing it into the provided buffer.
+ */
+void
+lwgeom_constructempty_buf(int SRID, char hasz, char hasm,
+	uchar *buf, size_t *retsize)
+{
+	int ngeoms = 0;
+
+	buf[0] =(uchar) lwgeom_makeType( hasz, hasm, SRID != -1,  COLLECTIONTYPE);
+	if (SRID != -1)
+	{
+		memcpy(&buf[1],&SRID,4);
+		buf += 5;
+	}
+	else
+		buf += 1;
+
+	memcpy(buf, &ngeoms, 4);
+
+	if (retsize) *retsize = lwgeom_empty_length(SRID);
+}
+
+/*
+ * helper function (not for general use)
+ * find the size a geometry (or a sub-geometry)
+ * 1st geometry has geom_number = 0
+ *  use geom_number = -1 to find the actual type of the serialized form.
+ *    ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, -1)
+ *                 --> size of the multipoint
+ *   ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, 0)
+ *         --> size of the point
+ * take a geometry, and find its length
+ */
+size_t
+lwgeom_size(const uchar *serialized_form)
+{
+	uchar type = lwgeom_getType((uchar) serialized_form[0]);
+	int t;
+	const uchar *loc;
+	uint32 ngeoms;
+	int sub_size;
+	int result = 1; /* type */
+
+	LWDEBUG(2, "lwgeom_size called");
+
+	if (type == POINTTYPE)
+	{
+		LWDEBUG(3, "lwgeom_size: is a point");
+
+		return lwgeom_size_point(serialized_form);
+	}
+	else if (type == LINETYPE)
+	{
+		LWDEBUG(3, "lwgeom_size: is a line");
+
+		return lwgeom_size_line(serialized_form);
+	}
+        else if(type == CURVETYPE)
+        {
+                LWDEBUG(3, "lwgeom_size: is a curve");
+
+                return lwgeom_size_curve(serialized_form);
+        }
+	else if (type == POLYGONTYPE)
+	{
+		LWDEBUG(3, "lwgeom_size: is a polygon");
+
+		return lwgeom_size_poly(serialized_form);
+	} 
+        else if (type == COMPOUNDTYPE)
+        {
+                LWDEBUG(3, "lwgeom_size: is a compound curve");
+        }
+
+	if ( type == 0 )
+	{
+		lwerror("lwgeom_size called with unknown-typed serialized geometry");
+		return 0;
+	}
+
+	/*
+	 * Handle all the multi* and geometrycollections the same
+	 *
+	 * NOTE: for a geometry collection of GC of GC of GC we will
+	 *       be recursing...
+	 */
+
+	LWDEBUGF(3, "lwgeom_size called on a geoemtry with type %d", type);
+
+	loc = serialized_form+1;
+
+	if (lwgeom_hasBBOX((uchar) serialized_form[0]))
+	{
+		LWDEBUG(3, "lwgeom_size: has bbox");
+
+		loc += sizeof(BOX2DFLOAT4);
+		result +=sizeof(BOX2DFLOAT4);
+	}
+
+	if (lwgeom_hasSRID( (uchar) serialized_form[0]) )
+	{
+		LWDEBUG(3, "lwgeom_size: has srid");
+
+		result +=4;
+		loc +=4;
+	}
+
+
+	ngeoms = lw_get_uint32(loc);
+	loc +=4;
+	result += 4; /* numgeoms */
+
+	LWDEBUGF(3, "lwgeom_size called on a geoemtry with %d elems (result so far: %d)", ngeoms, result);
+
+	for (t=0;t<ngeoms;t++)
+	{
+		sub_size = lwgeom_size(loc);
+
+		LWDEBUGF(3, " subsize %d", sub_size);
+
+		loc += sub_size;
+		result += sub_size;
+	}
+
+	LWDEBUGF(3, "lwgeom_size returning %d", result);
+
+	return result;
+}
+
+size_t
+lwgeom_size_subgeom(const uchar *serialized_form, int geom_number)
+{
+	if (geom_number == -1)
+	{
+		return lwgeom_size(serialized_form);
+	}
+	return lwgeom_size( lwgeom_getsubgeometry(serialized_form,geom_number));
+}
+
+
+
+int
+lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected, int geom_number)
+{
+	return lwgeom_size(inspected->sub_geoms[geom_number]);
+}
+
+int
+compute_serialized_box3d_p(uchar *srl, BOX3D *out)
+{
+	BOX3D *box = compute_serialized_box3d(srl);
+	if ( ! box ) return 0;
+	out->xmin = box->xmin;
+	out->ymin = box->ymin;
+	out->zmin = box->zmin;
+	out->xmax = box->xmax;
+	out->ymax = box->ymax;
+	out->zmax = box->zmax;
+	lwfree(box);
+
+	return 1;
+}
+
+/*
+ * Compute bounding box of a serialized LWGEOM, even if it is
+ * already cached. The computed BOX2DFLOAT4 is stored at
+ * the given location, the function returns 0 is the geometry
+ * does not have a bounding box (EMPTY GEOM)
+ */
+int
+compute_serialized_box2d_p(uchar *srl, BOX2DFLOAT4 *out)
+{
+	  BOX3D *result = compute_serialized_box3d(srl);
+	  if ( ! result ) return 0;
+	  out->xmin = result->xmin;
+	  out->xmax = result->xmax;
+	  out->ymin = result->ymin;
+	  out->ymax = result->ymax;
+	  lwfree(result);
+
+	  return 1;
+}
+
+/*
+ * Don't forget to lwfree() result !
+ */
+BOX3D *
+compute_serialized_box3d(uchar *srl)
+{
+	int type = lwgeom_getType(srl[0]);
+	int t;
+	uchar *loc;
+	uint32 ngeoms;
+	BOX3D *result;
+	BOX3D b1;
+	int sub_size;
+	char nboxes=0;
+
+	LWDEBUGF(2, "compute_serialized_box3d called on type %d", type);
+
+	if (type == POINTTYPE)
+	{
+		LWPOINT *pt = lwpoint_deserialize(srl);
+
+		LWDEBUG(3, "compute_serialized_box3d: lwpoint deserialized");
+
+		result = lwpoint_compute_box3d(pt);
+
+		LWDEBUG(3, "compute_serialized_box3d: bbox found");
+
+		pfree_point(pt);
+		return result;
+	}
+
+	else if (type == LINETYPE)
+	{
+		LWLINE *line = lwline_deserialize(srl);
+		result = lwline_compute_box3d(line);
+		pfree_line(line);
+		return result;
+
+	}
+        else if (type == CURVETYPE)
+        {
+                LWCURVE *curve = lwcurve_deserialize(srl);
+                result = lwcurve_compute_box3d(curve);
+                pfree_curve(curve);
+                return result;
+        }
+	else if (type == POLYGONTYPE)
+	{
+		LWPOLY *poly = lwpoly_deserialize(srl);
+		result = lwpoly_compute_box3d(poly);
+		pfree_polygon(poly);
+		return result;
+	}
+
+	if ( ! ( type == MULTIPOINTTYPE || type == MULTILINETYPE ||
+		type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE ||
+                type == COMPOUNDTYPE || type == CURVEPOLYTYPE ||
+                type == MULTICURVETYPE || type == MULTISURFACETYPE) )
+	{
+		lwnotice("compute_serialized_box3d called on unknown type %d", type);
+		return NULL;
+	}
+
+	loc = srl+1;
+
+	if (lwgeom_hasBBOX(srl[0]))
+	{
+		loc += sizeof(BOX2DFLOAT4);
+	}
+
+	if (lwgeom_hasSRID(srl[0]) )
+	{
+		loc +=4;
+	}
+
+	ngeoms = lw_get_uint32(loc);
+	loc += 4;
+
+	/* each sub-type */
+	result = NULL;
+	for (t=0; t<ngeoms; t++)
+	{
+		if ( compute_serialized_box3d_p(loc, &b1) ) 
+		{
+			LWDEBUG(3, "Geom %d have box:"); 
+#if POSTGIS_DEBUG_LEVEL >= 3
+			printBOX3D(&b1);
+#endif
+
+			if (result)
+			{
+				nboxes += box3d_union_p(result, &b1, result);
+			}
+			else
+			{ 
+				result = lwalloc(sizeof(BOX3D));
+				memcpy(result, &b1, sizeof(BOX3D));
+			}
+		}
+
+		sub_size = lwgeom_size(loc);
+		loc += sub_size;
+	}
+
+	return result;
+
+}
+
+/****************************************************************
+ * memory management 
+ *
+ *  these only delete the memory associated
+ *  directly with the structure - NOT the stuff pointing into
+ *  the original de-serialized info
+ *
+ ****************************************************************/
+
+void
+pfree_inspected(LWGEOM_INSPECTED *inspected)
+{
+	if ( inspected->ngeometries )
+		lwfree(inspected->sub_geoms);
+	lwfree(inspected);
+}
+
+
+void pfree_POINTARRAY(POINTARRAY *pa)
+{
+	lwfree(pa);
+}
+
+
+
+
+/************************************************
+ * debugging routines
+ ************************************************/
+
+
+void printBOX3D(BOX3D *box)
+{
+	lwnotice("BOX3D: %g %g, %g %g", box->xmin, box->ymin,
+		box->xmax, box->ymax);
+}
+
+void printPA(POINTARRAY *pa)
+{
+	int t;
+	POINT4D pt;
+	char *mflag;
+
+
+	if ( TYPE_HASM(pa->dims) ) mflag = "M";
+	else mflag = "";
+
+	lwnotice("      POINTARRAY%s{", mflag);
+	lwnotice("                 ndims=%i,   ptsize=%i",
+		TYPE_NDIMS(pa->dims), pointArray_ptsize(pa));
+	lwnotice("                 npoints = %i", pa->npoints);
+
+	for (t =0; t<pa->npoints;t++)
+	{
+		getPoint4d_p(pa, t, &pt);
+		if (TYPE_NDIMS(pa->dims) == 2)
+		{
+			lwnotice("                    %i : %lf,%lf",t,pt.x,pt.y);
+		}
+		if (TYPE_NDIMS(pa->dims) == 3)
+		{
+			lwnotice("                    %i : %lf,%lf,%lf",t,pt.x,pt.y,pt.z);
+		}
+		if (TYPE_NDIMS(pa->dims) == 4)
+		{
+			lwnotice("                    %i : %lf,%lf,%lf,%lf",t,pt.x,pt.y,pt.z,pt.m);
+		}
+	}
+
+	lwnotice("      }");
+}
+
+void printBYTES(uchar *a, int n)
+{
+	int t;
+	char buff[3];
+
+	buff[2] = 0; /* null terminate */
+
+	lwnotice(" BYTE ARRAY (n=%i) IN HEX: {", n);
+	for (t=0;t<n;t++)
+	{
+		deparse_hex(a[t], buff);
+		lwnotice("    %i : %s", t,buff );
+	}
+	lwnotice("  }");
+}
+
+
+void
+printMULTI(uchar *serialized)
+{
+	LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized);
+	LWLINE  *line;
+	LWPOINT *point;
+	LWPOLY  *poly;
+	int t;
+
+	lwnotice("MULTI* geometry (type = %i), with %i sub-geoms",lwgeom_getType((uchar)serialized[0]), inspected->ngeometries);
+
+	for (t=0;t<inspected->ngeometries;t++)
+	{
+		lwnotice("      sub-geometry %i:", t);
+		line = NULL; point = NULL; poly = NULL;
+
+		line = lwgeom_getline_inspected(inspected,t);
+		if (line !=NULL)
+		{
+			printLWLINE(line);
+		}
+		poly = lwgeom_getpoly_inspected(inspected,t);
+		if (poly !=NULL)
+		{
+			printLWPOLY(poly);
+		}
+		point = lwgeom_getpoint_inspected(inspected,t);
+		if (point !=NULL)
+		{
+			printPA(point->point);
+		}
+    }
+
+    lwnotice("end multi*");
+
+	pfree_inspected(inspected);
+}
+
+void
+printType(uchar type)
+{
+	lwnotice("type 0x%x ==> hasBBOX=%i, hasSRID=%i, ndims=%i, type=%i",(unsigned int) type, lwgeom_hasBBOX(type), lwgeom_hasSRID(type),lwgeom_ndims(type), lwgeom_getType(type));
+}
+
+/*
+ * Get the SRID from the LWGEOM.
+ * None present => -1
+ */
+int
+lwgeom_getsrid(uchar *serialized)
+{
+	uchar type = serialized[0];
+	uchar *loc = serialized+1;
+
+	if ( ! lwgeom_hasSRID(type)) return -1;
+
+	if (lwgeom_hasBBOX(type))
+	{
+		loc += sizeof(BOX2DFLOAT4);
+	}
+
+	return lw_get_int32(loc);
+}
+
+char
+ptarray_isccw(const POINTARRAY *pa)
+{
+	int i;
+	double area = 0;
+	POINT2D p1, p2;
+
+	for (i=0; i<pa->npoints-1; i++)
+	{
+		getPoint2d_p(pa, i, &p1);
+		getPoint2d_p(pa, i+1, &p2);
+		area += (p1.y * p2.x) - (p1.x * p2.y);
+	}
+	if ( area > 0 ) return 0;
+	else return 1;
+}
+
+/*
+ * Returns a BOX2DFLOAT4 that encloses b1 and b2
+ *
+ * box2d_union(NULL,A) --> A
+ * box2d_union(A,NULL) --> A
+ * box2d_union(A,B) --> A union B
+ */
+BOX2DFLOAT4 *
+box2d_union(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2)
+{
+	BOX2DFLOAT4 *result;
+
+	if ( (b1 == NULL) && (b2 == NULL) )
+	{
+		return NULL;
+	}
+
+	result = lwalloc(sizeof(BOX2DFLOAT4));
+
+	if  (b1 == NULL)
+	{
+		memcpy(result, b2, sizeof(BOX2DFLOAT4));
+		return result;
+	}
+	if (b2 == NULL)
+	{
+		memcpy(result, b1, sizeof(BOX2DFLOAT4));
+		return result;
+	}
+
+	if (b1->xmin < b2->xmin) result->xmin = b1->xmin;
+	else result->xmin = b2->xmin;
+
+	if (b1->ymin < b2->ymin) result->ymin = b1->ymin;
+	else result->ymin = b2->ymin;
+
+	if (b1->xmax > b2->xmax) result->xmax = b1->xmax;
+	else result->xmax = b2->xmax;
+
+	if (b1->ymax > b2->ymax) result->ymax = b1->ymax;
+	else result->ymax = b2->ymax;
+
+	return result;
+}
+
+/*
+ * ubox may be one of the two args...
+ * return 1 if done something to ubox, 0 otherwise.
+ */
+int
+box2d_union_p(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2, BOX2DFLOAT4 *ubox)
+{
+	if ( (b1 == NULL) && (b2 == NULL) )
+	{
+		return 0;
+	}
+
+	if  (b1 == NULL)
+	{
+		memcpy(ubox, b2, sizeof(BOX2DFLOAT4));
+		return 1;
+	}
+	if (b2 == NULL)
+	{
+		memcpy(ubox, b1, sizeof(BOX2DFLOAT4));
+		return 1;
+	}
+
+	if (b1->xmin < b2->xmin) ubox->xmin = b1->xmin;
+	else ubox->xmin = b2->xmin;
+
+	if (b1->ymin < b2->ymin) ubox->ymin = b1->ymin;
+	else ubox->ymin = b2->ymin;
+
+	if (b1->xmax > b2->xmax) ubox->xmax = b1->xmax;
+	else ubox->xmax = b2->xmax;
+
+	if (b1->ymax > b2->ymax) ubox->ymax = b1->ymax;
+	else ubox->ymax = b2->ymax;
+
+	return 1;
+}
+
+const char *
+lwgeom_typeflags(uchar type)
+{
+	static char flags[5];
+	int flagno=0;
+	if ( TYPE_HASZ(type) ) flags[flagno++] = 'Z';
+	if ( TYPE_HASM(type) ) flags[flagno++] = 'M';
+	if ( TYPE_HASBBOX(type) ) flags[flagno++] = 'B';
+	if ( TYPE_HASSRID(type) ) flags[flagno++] = 'S';
+	flags[flagno] = '\0';
+
+	LWDEBUGF(4, "Flags: %s - returning %p", flags, flags);
+
+	return flags;
+}
+
+/*
+ * Given a string with at least 2 chars in it, convert them to
+ * a byte value.  No error checking done!
+ */
+uchar
+parse_hex(char *str)
+{
+	/* do this a little brute force to make it faster */
+
+	uchar		result_high = 0;
+	uchar		result_low = 0;
+
+	switch (str[0])
+	{
+		case '0' :
+			result_high = 0;
+			break;
+		case '1' :
+			result_high = 1;
+			break;
+		case '2' :
+			result_high = 2;
+			break;
+		case '3' :
+			result_high = 3;
+			break;
+		case '4' :
+			result_high = 4;
+			break;
+		case '5' :
+			result_high = 5;
+			break;
+		case '6' :
+			result_high = 6;
+			break;
+		case '7' :
+			result_high = 7;
+			break;
+		case '8' :
+			result_high = 8;
+			break;
+		case '9' :
+			result_high = 9;
+			break;
+		case 'A' :
+			result_high = 10;
+			break;
+		case 'B' :
+			result_high = 11;
+			break;
+		case 'C' :
+			result_high = 12;
+			break;
+		case 'D' :
+			result_high = 13;
+			break;
+		case 'E' :
+			result_high = 14;
+			break;
+		case 'F' :
+			result_high = 15;
+			break;
+	}
+	switch (str[1])
+	{
+		case '0' :
+			result_low = 0;
+			break;
+		case '1' :
+			result_low = 1;
+			break;
+		case '2' :
+			result_low = 2;
+			break;
+		case '3' :
+			result_low = 3;
+			break;
+		case '4' :
+			result_low = 4;
+			break;
+		case '5' :
+			result_low = 5;
+			break;
+		case '6' :
+			result_low = 6;
+			break;
+		case '7' :
+			result_low = 7;
+			break;
+		case '8' :
+			result_low = 8;
+			break;
+		case '9' :
+			result_low = 9;
+			break;
+		case 'A' :
+			result_low = 10;
+			break;
+		case 'B' :
+			result_low = 11;
+			break;
+		case 'C' :
+			result_low = 12;
+			break;
+		case 'D' :
+			result_low = 13;
+			break;
+		case 'E' :
+			result_low = 14;
+			break;
+		case 'F' :
+			result_low = 15;
+			break;
+	}
+	return (uchar) ((result_high<<4) + result_low);
+}
+
+
+/*
+ * Given one byte, populate result with two byte representing
+ * the hex number.
+ *
+ * Ie. deparse_hex( 255, mystr)
+ *		-> mystr[0] = 'F' and mystr[1] = 'F'
+ *
+ * No error checking done
+ */
+void
+deparse_hex(uchar str, char *result)
+{
+	int	input_high;
+	int  input_low;
+	static char outchr[]={"0123456789ABCDEF" };
+
+	input_high = (str>>4);
+	input_low = (str & 0x0F);
+
+	result[0] = outchr[input_high];
+	result[1] = outchr[input_low];
+
+}
+
+SERIALIZED_LWGEOM *
+parse_lwgeom_wkt(char *wkt_input)
+{
+	SERIALIZED_LWGEOM *serialized_form = parse_lwg(wkt_input,
+		lwalloc, lwerror);
+
+
+	LWDEBUGF(2, "parse_lwgeom_wkt with %s",wkt_input);
+
+	if (serialized_form == NULL)
+	{
+		lwerror("parse_WKT:: couldnt parse!");
+		return NULL;
+	}
+
+	return serialized_form;
+
+}
+
+/*
+ * Find interpolation point I
+ * between point A and point B 
+ * so that the len(AI) == len(AB)*F
+ * and I falls on AB segment.
+ *
+ * Example:
+ *
+ *   F=0.5  :    A----I----B 
+ *   F=1    :    A---------B==I 
+ *   F=0    : A==I---------B
+ *   F=.2   :    A-I-------B
+ */
+void
+interpolate_point4d(POINT4D *A, POINT4D *B, POINT4D *I, double F)
+{
+#if PARANOIA_LEVEL > 0
+	double absF=fabs(F);
+	if ( absF < 0 || absF > 1 )
+	{
+		lwerror("interpolate_point4d: invalid F (%g)", F);
+	}
+#endif
+	I->x=A->x+((B->x-A->x)*F);
+	I->y=A->y+((B->y-A->y)*F);
+	I->z=A->z+((B->z-A->z)*F);
+	I->m=A->m+((B->m-A->m)*F);
+}

Added: trunk/liblwgeom/lwgparse.c
===================================================================
--- trunk/liblwgeom/lwgparse.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwgparse.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,1153 @@
+/*
+ * Written by Ralph Mason ralph.mason<at>telogis.com
+ *
+ * Copyright Telogis 2004
+ * www.telogis.com
+ *
+ */
+#include <string.h>
+#include <stdio.h>
+/* Solaris9 does not provide stdint.h */
+/* #include <stdint.h> */
+#include <inttypes.h>
+
+#include "liblwgeom.h"
+#include "wktparse.h"
+
+/*
+ * To get byte order
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+*/
+
+void set_zm(char z, char m);
+void close_parser(void);
+
+typedef uint32_t int4;
+
+typedef struct tag_tuple tuple;
+
+struct tag_outputstate{
+	uchar*	pos;
+};
+
+typedef struct tag_outputstate output_state;
+typedef void (*output_func)(tuple* this, output_state* out);
+typedef void (*read_col_func)(const char **f);
+
+
+
+/* Globals */
+
+int srid=-1;
+
+static int ferror_occured;
+static allocator local_malloc;
+static report_error error_func;
+
+struct tag_tuple{
+	output_func   of;
+	union union_tag {
+		double points[4];
+		int4   pointsi[4];
+
+		struct struct_tag {
+			tuple* 	stack_next;
+			int	type;
+			int	num;
+			int	size_here;
+		} nn;
+	} uu;
+	struct tag_tuple *next;
+};
+
+struct {
+	int	type;
+	int	flags;
+	int	srid;
+	int	ndims;
+	int	hasZ;
+	int	hasM;
+	/* create integer version */
+	int lwgi;
+	/* input is integer (wkb only)*/
+	int from_lwgi;
+
+	int4 alloc_size;
+
+	/*
+		linked list of all tuples
+	*/
+	tuple*	first;
+	tuple*  last;
+
+	/*
+		stack of open geometries
+	*/
+	tuple*  stack;
+
+} the_geom;
+
+tuple* free_list=0;
+int minpoints;
+int checkclosed;
+
+/*
+ * This inicates if the number of points in the geometry is required to
+ * be odd (one) or even (zero, currently not enforced) or whatever (-one)
+ */
+int isodd;
+double *first_point=NULL;
+double *last_point=NULL;
+
+/* External functions */
+extern void init_parser(const char *);
+
+/* Prototypes */
+tuple* alloc_tuple(output_func of,size_t size);
+static void error(const char* err);
+void free_tuple(tuple* to_free);
+void inc_num(void);
+void alloc_stack_tuple(int type,output_func of,size_t size);
+void check_dims(int num);
+void WRITE_DOUBLES(output_state* out,double* points, int cnt);
+#ifdef SHRINK_INTS
+void WRITE_INT4(output_state * out,int4 val);
+#endif
+void empty_stack(tuple* this,output_state* out);
+void alloc_lwgeom(int srid);
+void write_point_2(tuple* this,output_state* out);
+void write_point_3(tuple* this,output_state* out);
+void write_point_4(tuple* this,output_state* out);
+void write_point_2i(tuple* this,output_state* out);
+void write_point_3i(tuple* this,output_state* out);
+void write_point_4i(tuple* this,output_state* out);
+void alloc_point_2d(double x,double y);
+void alloc_point_3d(double x,double y,double z);
+void alloc_point_4d(double x,double y,double z,double m);
+void write_type(tuple* this,output_state* out);
+void write_count(tuple* this,output_state* out);
+void write_type_count(tuple* this,output_state* out);
+void alloc_point(void);
+void alloc_linestring(void);
+void alloc_linestring_closed(void);
+void alloc_circularstring(void);
+void alloc_circularstring_closed(void);
+void alloc_polygon(void);
+void alloc_multipoint(void);
+void alloc_multilinestring(void);
+void alloc_multicurve(void);
+void alloc_multipolygon(void);
+void alloc_multisurface(void);
+void alloc_geomertycollection(void);
+void alloc_counter(void);
+void alloc_empty(void);
+SERIALIZED_LWGEOM* make_serialized_lwgeom(void);
+uchar strhex_readbyte(const char *in);
+uchar read_wkb_byte(const char **in);
+void read_wkb_bytes(const char **in, uchar* out, int cnt);
+int4 read_wkb_int(const char **in);
+double read_wkb_double(const char **in, int convert_from_int);
+void read_wkb_point(const char **b);
+void read_wkb_polygon(const char **b);
+void read_wkb_linestring(const char **b);
+void read_wkb_curve(const char **b);
+void read_wkb_ordinate_array(const char **b);
+void read_collection(const char **b, read_col_func f);
+void parse_wkb(const char **b);
+void alloc_wkb(const char *parser);
+SERIALIZED_LWGEOM* parse_it(const char* geometry, allocator allocfunc, report_error errfunc);
+SERIALIZED_LWGEOM* parse_lwg(const char* geometry, allocator allocfunc, report_error errfunc);
+SERIALIZED_LWGEOM* parse_lwgi(const char* geometry, allocator allocfunc, report_error errfunc);
+
+void
+set_srid(double d_srid)
+{
+	if ( d_srid >= 0 )
+		d_srid+=0.1;
+	else
+		d_srid-=0.1;
+
+
+	srid=(int)(d_srid+0.1);
+}
+
+tuple *
+alloc_tuple(output_func of,size_t size)
+{
+	tuple* ret = free_list;
+
+	if ( ! ret ){
+		int toalloc = (ALLOC_CHUNKS /sizeof(tuple));
+		ret = malloc( toalloc *sizeof(tuple) );
+
+		free_list = ret;
+
+		while(--toalloc){
+			ret->next = ret+1;
+			ret++;
+		}
+
+		ret->next = NULL;
+
+		return alloc_tuple(of,size);
+	}
+
+	free_list = ret->next;
+	ret->of = of;
+	ret->next = NULL;
+
+	if ( the_geom.last ) {
+		the_geom.last->next = ret;
+		the_geom.last = ret;
+	}
+	else {
+		the_geom.first = the_geom.last = ret;
+	}
+
+	the_geom.alloc_size += size;
+	return ret;
+}
+
+static void
+error(const char* err)
+{
+	error_func(err);
+	ferror_occured=1;
+}
+
+void
+free_tuple(tuple* to_free)
+{
+
+	tuple* list_end = to_free;
+
+	if( !to_free)
+		return;
+
+	while(list_end->next){
+		list_end=list_end->next;
+	}
+
+	list_end->next = free_list;
+	free_list = to_free;
+}
+
+void
+inc_num(void)
+{
+	the_geom.stack->uu.nn.num++;
+}
+
+/*
+	Allocate a 'counting' tuple
+*/
+void
+alloc_stack_tuple(int type,output_func of,size_t size)
+{
+	tuple*	p;
+	inc_num();
+
+        LWDEBUGF(2, "alloc_stack_tuple %d, %d", type, size);
+	
+	p = alloc_tuple(of,size);
+	p->uu.nn.stack_next = the_geom.stack;
+	p->uu.nn.type = type;
+	p->uu.nn.size_here = the_geom.alloc_size;
+	p->uu.nn.num = 0;
+	the_geom.stack = p;
+}
+
+void
+pop(void)
+{
+	the_geom.stack = the_geom.stack->uu.nn.stack_next;
+}
+
+void
+popc(void)
+{
+
+	if ( the_geom.stack->uu.nn.num < minpoints){
+		error("geometry requires more points");
+	}
+        if(isodd != -1 && the_geom.stack->uu.nn.num % 2 != isodd) {
+                error("geometry must have an odd number of points");
+        }
+	if ( checkclosed && first_point && last_point) {
+		if ( memcmp(first_point, last_point,
+			sizeof(double)*the_geom.ndims) )
+		{
+			error("geometry contains non-closed rings");
+		}
+	}	
+
+	the_geom.stack = the_geom.stack->uu.nn.stack_next;
+}
+
+
+void
+check_dims(int num)
+{
+        LWDEBUGF(2, "check_dims the_geom.ndims = %d, num = %d", the_geom.ndims, num);
+
+	if( the_geom.ndims != num){
+		if (the_geom.ndims) {
+			error("Can not mix dimensionality in a geometry");
+		} else {
+
+                        LWDEBUGF(3, "check_dims: setting dim %d", num);
+
+			the_geom.ndims = num;
+			if ( num > 2 ) the_geom.hasZ = 1;
+			if ( num > 3 ) the_geom.hasM = 1;
+		}
+	}
+}
+
+#define WRITE_INT4_REAL(x,y) { memcpy(x->pos,&y,4); x->pos+=4;}
+#define WRITE_INT4_REAL_MULTIPLE(x,y,z) { memcpy(x->pos,&y,z*4); x->pos+=(z*4);}
+
+/*
+	we can shrink ints to one byte if they are less than 127
+	by setting the extra bit.  Because if the different byte
+	ordering possibilities we need to set the lsb on little
+	endian to show a packed one and the msb on a big endian
+	machine
+*/
+#ifdef SHRINK_INTS
+void
+WRITE_INT4(output_state * out,int4 val)
+{
+	if ( val <= 0x7f ){
+		if ( getMachineEndian() == NDR ){
+			val = (val<<1) | 1;
+		}
+		else{
+			val |=0x80;
+		}
+
+		*out->pos++ = (uchar)val;
+		the_geom.alloc_size-=3;
+	}
+	else{
+		if ( getMachineEndian() == NDR ){
+			val <<=1;
+		}
+		WRITE_INT4_REAL(out,val);
+	}
+}
+#else
+#define WRITE_INT4 WRITE_INT4_REAL
+#endif
+
+
+void
+WRITE_DOUBLES(output_state* out,double* points, int cnt)
+{
+	if ( the_geom.lwgi){
+		int4 vals[4];
+		int i;
+
+		for(i=0; i<cnt;i++){
+			vals[i] = (int4)(((points[i]+180.0)*0xB60B60)+.5);
+		}
+		memcpy(out->pos,vals,sizeof(int4)*cnt);
+		out->pos+=sizeof(int4)*cnt;
+	}
+	else{
+		memcpy(out->pos,points,sizeof(double)*cnt);
+		out->pos+=sizeof(double)*cnt;
+	}
+
+}
+
+void
+empty_stack(tuple *this,output_state* out)
+{
+    /* Do nothing but provide an empty base for the geometry stack */
+}
+
+void
+alloc_lwgeom(int srid)
+{
+        LWDEBUGF(2, "alloc_lwgeom %d", srid);
+
+	the_geom.srid=srid;
+	the_geom.alloc_size=0;
+	the_geom.stack=NULL;
+	the_geom.ndims=0;
+	the_geom.hasZ=0;
+	the_geom.hasM=0;
+
+	/* Free if used already */
+	if ( the_geom.first ){
+		free_tuple(the_geom.first);
+		the_geom.first=the_geom.last=NULL;
+	}
+
+	if ( srid != -1 ){
+		the_geom.alloc_size+=4;
+	}
+
+    /* Setup up an empty tuple as the stack base */
+    the_geom.stack = alloc_tuple(empty_stack, 0);
+}
+
+void
+write_point_2(tuple* this,output_state* out)
+{
+	WRITE_DOUBLES(out,this->uu.points,2);
+}
+
+void
+write_point_3(tuple* this,output_state* out)
+{
+	WRITE_DOUBLES(out,this->uu.points,3);
+}
+
+void
+write_point_4(tuple* this,output_state* out)
+{
+	WRITE_DOUBLES(out,this->uu.points,4);
+}
+
+void
+write_point_2i(tuple* this,output_state* out)
+{
+	WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,2);
+}
+
+void
+write_point_3i(tuple* this,output_state* out)
+{
+	WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,3);
+}
+
+void
+write_point_4i(tuple* this,output_state* out)
+{
+	WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,4);
+}
+
+void
+alloc_point_2d(double x,double y)
+{
+	tuple* p = alloc_tuple(write_point_2,the_geom.lwgi?8:16);
+	p->uu.points[0] = x;
+	p->uu.points[1] = y;
+
+        LWDEBUGF(2, "alloc_point_2d %f,%f", x, y);
+	
+	/* keep track of point */
+	if ( checkclosed ) {
+		if ( ! the_geom.stack->uu.nn.num )
+			first_point = p->uu.points;
+		last_point = p->uu.points;
+	}
+
+	inc_num();
+	check_dims(2);
+}
+
+void
+alloc_point_3d(double x,double y,double z)
+{
+	tuple* p = alloc_tuple(write_point_3,the_geom.lwgi?12:24);
+	p->uu.points[0] = x;
+	p->uu.points[1] = y;
+	p->uu.points[2] = z;
+
+        LWDEBUGF(2, "alloc_point_3d %f, %f, %f", x, y, z);
+	
+	/* keep track of point */
+	if ( checkclosed ) {
+		if ( ! the_geom.stack->uu.nn.num )
+			first_point = p->uu.points;
+		last_point = p->uu.points;
+	}
+
+	inc_num();
+	check_dims(3);
+}
+
+void
+alloc_point_4d(double x,double y,double z,double m)
+{
+	tuple* p = alloc_tuple(write_point_4,the_geom.lwgi?16:32);
+	p->uu.points[0] = x;
+	p->uu.points[1] = y;
+	p->uu.points[2] = z;
+	p->uu.points[3] = m;
+
+        LWDEBUGF(2, "alloc_point_4d %f, %f, %f, %f", x, y, z, m);
+
+	/* keep track of point */
+	if ( checkclosed ) {
+		if ( ! the_geom.stack->uu.nn.num )
+			first_point = p->uu.points;
+		last_point = p->uu.points;
+	}
+
+	inc_num();
+	check_dims(4);
+}
+
+void
+write_type(tuple* this,output_state* out)
+{
+	uchar type=0;
+
+	/* Empty handler - switch back */
+	if ( this->uu.nn.type == 0xff )
+		this->uu.nn.type = COLLECTIONTYPE;
+
+	type |= this->uu.nn.type;
+
+	if (the_geom.ndims) /* Support empty */
+	{
+		TYPE_SETZM(type, the_geom.hasZ, the_geom.hasM);
+	}
+
+	if ( the_geom.srid != -1 ){
+		type |= 0x40;
+	}
+
+	*(out->pos)=type;
+	out->pos++;
+
+	if ( the_geom.srid != -1 ){
+		/* Only the first geometry will have a srid attached */
+		WRITE_INT4(out,the_geom.srid);
+		the_geom.srid = -1;
+	}
+}
+
+void
+write_count(tuple* this,output_state* out)
+{
+	int num = this->uu.nn.num;
+	WRITE_INT4(out,num);
+}
+
+void
+write_type_count(tuple* this,output_state* out)
+{
+	write_type(this,out);
+	write_count(this,out);
+}
+
+void
+alloc_point(void)
+{
+        LWDEBUG(2, "alloc_point");
+
+	if( the_geom.lwgi)
+		alloc_stack_tuple(POINTTYPEI,write_type,1);
+	else
+		alloc_stack_tuple(POINTTYPE,write_type,1);
+
+	minpoints=1;
+	checkclosed=0;
+        isodd=-1;
+}
+
+void
+alloc_linestring(void)
+{
+        LWDEBUG(2, "alloc_linestring");
+
+	if( the_geom.lwgi)
+		alloc_stack_tuple(LINETYPEI,write_type,1);
+	else
+		alloc_stack_tuple(LINETYPE,write_type,1);
+
+	minpoints=2;
+	checkclosed=0;
+        isodd=-1;
+}
+
+void alloc_linestring_closed(void)
+{
+        LWDEBUG(2, "alloc_linestring_closed called.");
+
+        alloc_linestring();
+        checkclosed=1;
+}
+
+void
+alloc_circularstring(void)
+{
+        LWDEBUG(2, "alloc_circularstring");
+
+        alloc_stack_tuple(CURVETYPE,write_type,1);
+        minpoints=3;
+        checkclosed=0;
+        isodd=1;
+}
+
+void alloc_circularstring_closed(void)
+{
+        LWDEBUG(2, "alloc_circularstring_closed");
+
+        alloc_circularstring();
+        checkclosed=1;
+}
+
+void
+alloc_polygon(void)
+{
+        LWDEBUG(2, "alloc_polygon");
+
+	if( the_geom.lwgi)
+		alloc_stack_tuple(POLYGONTYPEI, write_type,1);
+	else
+		alloc_stack_tuple(POLYGONTYPE, write_type,1);
+
+	minpoints=3;
+	checkclosed=1;
+        isodd=-1;
+
+}
+
+void
+alloc_curvepolygon(void)
+{
+        LWDEBUG(2, "alloc_curvepolygon called.");
+
+        alloc_stack_tuple(CURVEPOLYTYPE, write_type, 1);
+        minpoints=3;
+        checkclosed=1;
+        isodd=-1;
+}
+
+void
+alloc_compoundcurve(void)
+{
+        LWDEBUG(2, "alloc_compoundcurve called.");
+
+        alloc_stack_tuple(COMPOUNDTYPE, write_type, 1);
+}
+
+void
+alloc_multipoint(void)
+{
+        LWDEBUG(2, "alloc_multipoint");
+
+	alloc_stack_tuple(MULTIPOINTTYPE,write_type,1);
+}
+
+void
+alloc_multilinestring(void)
+{
+        LWDEBUG(2, "alloc_multilinestring");
+
+	alloc_stack_tuple(MULTILINETYPE,write_type,1);
+}
+
+void
+alloc_multicurve(void)
+{
+        LWDEBUG(2, "alloc_multicurve");
+
+        alloc_stack_tuple(MULTICURVETYPE,write_type,1);
+}
+
+void
+alloc_multipolygon(void)
+{
+        LWDEBUG(2, "alloc_multipolygon");
+
+	alloc_stack_tuple(MULTIPOLYGONTYPE,write_type,1);
+}
+
+void
+alloc_multisurface(void)
+{
+        LWDEBUG(2, "alloc_multisurface called");
+
+        alloc_stack_tuple(MULTISURFACETYPE,write_type,1);
+}
+
+void
+alloc_geomertycollection(void)
+{
+        LWDEBUG(2, "alloc_geometrycollection");
+
+	alloc_stack_tuple(COLLECTIONTYPE,write_type,1);
+}
+
+void
+alloc_counter(void)
+{
+        LWDEBUG(2, "alloc_counter");
+
+	alloc_stack_tuple(0,write_count,4);
+}
+
+void
+alloc_empty(void)
+{
+	tuple* st = the_geom.stack;
+
+	LWDEBUG(2, "alloc_empty");
+
+	/* Find the last geometry */
+	while(st->uu.nn.type == 0){
+		st =st->uu.nn.stack_next;
+	}
+
+	/* Reclaim memory */
+	free_tuple(st->next);
+
+	/* Put an empty geometry collection on the top of the stack */
+	st->next=NULL;
+	the_geom.stack=st;
+	the_geom.alloc_size=st->uu.nn.size_here;
+
+	/* Mark as a empty stop */
+	if (st->uu.nn.type != 0xFF){
+		st->uu.nn.type=0xFF;
+		st->of = write_type_count;
+		the_geom.alloc_size+=4;
+		st->uu.nn.size_here=the_geom.alloc_size;
+	}
+
+	st->uu.nn.num=0;
+}
+
+SERIALIZED_LWGEOM *
+make_serialized_lwgeom(void)
+{
+	SERIALIZED_LWGEOM *out_serialized_lwgeom;
+	uchar* out_c;
+	output_state out;
+	tuple* cur;
+	
+	LWDEBUG(2, "make_serialized_lwgeom");
+
+	/* Allocate the SERIALIZED_LWGEOM structure */
+	out_serialized_lwgeom = (SERIALIZED_LWGEOM *)local_malloc(sizeof(SERIALIZED_LWGEOM));
+
+	/* Allocate the LWGEOM itself */
+	out_c = (uchar*)local_malloc(the_geom.alloc_size);
+	out.pos = out_c;
+	cur = the_geom.first ;
+
+	while(cur){
+		cur->of(cur,&out);
+		cur=cur->next;
+	}
+
+	/* Setup the SERIALIZED_LWGEOM structure */
+	out_serialized_lwgeom->lwgeom = out_c;
+	out_serialized_lwgeom->size = the_geom.alloc_size;
+
+	return out_serialized_lwgeom;
+}
+
+void
+lwg_parse_yynotice(char* s)
+{
+        lwnotice(s);
+}
+
+int
+lwg_parse_yyerror(char* s)
+{
+	error("parse error - invalid geometry");
+	/* error_func("parse error - invalid geometry"); */
+	return 1;
+}
+
+/*
+ Table below generated using this ruby.
+
+ a=(0..0xff).to_a.collect{|x|0xff};('0'..'9').each{|x|a[x[0]]=x[0]-'0'[0]}
+ ('a'..'f').each{|x|v=x[0]-'a'[0]+10;a[x[0]]=a[x.upcase[0]]=v}
+ puts '{'+a.join(",")+'}'
+
+ */
+static const uchar to_hex[]  = {
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	0,1,2,3,4,5,6,7,8,9,255,255,255,255,255,255,255,10,11,12,13,14,
+	15,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255,255,255,255,10,11,12,13,14,15,255,
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+	255,255,255,255,255,255,255,255};
+
+uchar
+strhex_readbyte(const char* in)
+{
+	if ( *in == 0 ){
+		if ( ! ferror_occured){
+			error("invalid wkb");
+		}
+		return 0;
+	}
+	return to_hex[(int)*in]<<4 | to_hex[(int)*(in+1)];
+}
+
+uchar
+read_wkb_byte(const char** in)
+{
+	uchar ret = strhex_readbyte(*in);
+	(*in)+=2;
+	return ret;
+}
+
+int swap_order;
+
+void
+read_wkb_bytes(const char** in, uchar* out, int cnt)
+{
+	if ( ! swap_order ){
+		while(cnt--) *out++ = read_wkb_byte(in);
+	}
+	else{
+		out += (cnt-1);
+		while(cnt--) *out-- = read_wkb_byte(in);
+	}
+}
+
+int4
+read_wkb_int(const char** in)
+{
+	int4 ret=0;
+	read_wkb_bytes(in,(uchar*)&ret,4);
+	return ret;
+}
+
+double
+read_wkb_double(const char** in, int convert_from_int)
+{
+	double ret=0;
+
+	if ( ! convert_from_int){
+		read_wkb_bytes(in,(uchar*)&ret,8);
+		return ret;
+	}else{
+		ret  = read_wkb_int(in);
+		ret /= 0xb60b60;
+		return ret-180.0;
+ 	}
+}
+
+void
+read_wkb_point(const char **b)
+{
+	int i;
+	tuple* p = NULL;
+
+
+	if(the_geom.lwgi && the_geom.from_lwgi ){
+		/*
+		 * Special case - reading from lwgi to lwgi
+		 * we don't want to go via doubles in the middle.
+		 */
+		switch(the_geom.ndims){
+			case 2: p=alloc_tuple(write_point_2i,8); break;
+			case 3: p=alloc_tuple(write_point_3i,12); break;
+			case 4: p=alloc_tuple(write_point_4i,16); break;
+		}
+
+		for(i=0;i<the_geom.ndims;i++){
+			p->uu.pointsi[i]=read_wkb_int(b);
+		}
+	}
+	else{
+		int mul = the_geom.lwgi ? 1 : 2;
+
+		switch(the_geom.ndims){
+			case 2: p=alloc_tuple(write_point_2,8*mul); break;
+			case 3: p=alloc_tuple(write_point_3,12*mul); break;
+			case 4: p=alloc_tuple(write_point_4,16*mul); break;
+		}
+
+		for(i=0;i<the_geom.ndims;i++){
+			p->uu.points[i]=read_wkb_double(b,the_geom.from_lwgi);
+		}
+	}
+
+
+	/* keep track of point */
+	if ( checkclosed ) {
+		if ( ! the_geom.stack->uu.nn.num )
+			first_point = p->uu.points;
+		last_point = p->uu.points;
+	}
+
+	inc_num();
+	check_dims(the_geom.ndims);
+}
+
+void
+read_wkb_polygon(const char **b)
+{
+	/* Stack the number of ORDINATE_ARRAYs (rings) */
+	int4 cnt=read_wkb_int(b);
+	alloc_counter();
+
+	/* Read through each ORDINATE_ARRAY in turn */
+	while(cnt--){
+		if ( ferror_occured )	return;
+
+		/* Things to check for POLYGON ORDINATE_ARRAYs */
+		minpoints=3;
+		checkclosed=1;
+		isodd=-1;
+
+		read_wkb_ordinate_array(b);
+	}
+
+	pop();
+}
+
+void
+read_wkb_linestring(const char **b)
+{
+
+	/* Things to check for LINESTRING ORDINATE_ARRAYs */
+	minpoints=2;
+	checkclosed=0;
+	isodd=-1;
+
+	read_wkb_ordinate_array(b);
+}
+
+
+void
+read_wkb_curve(const char **b)
+{
+
+	/* Things to check for CURVE ORDINATE_ARRAYs */
+	minpoints=3;
+	checkclosed=0;
+	isodd=-1;
+
+	read_wkb_ordinate_array(b);
+}
+
+void
+read_wkb_ordinate_array(const char **b)
+{
+	/* Read through a WKB ordinate array */
+	int4 cnt=read_wkb_int(b);
+	alloc_counter();
+
+	while(cnt--){
+		if ( ferror_occured )	return;
+		read_wkb_point(b);
+	}
+
+	/* Perform a check of the ordinate array */
+	popc();
+}
+
+void
+read_collection(const char **b, read_col_func f)
+{
+	/* Read through a COLLECTION or an EWKB */
+	int4 cnt=read_wkb_int(b);
+	alloc_counter();
+
+	while(cnt--){
+		if ( ferror_occured )	return;
+		f(b);
+	}
+
+	pop();
+}
+
+void
+parse_wkb(const char **b)
+{
+	int4 type;
+	uchar xdr = read_wkb_byte(b);
+	int4 localsrid;
+
+        LWDEBUG(2, "parse_wkb");
+
+	swap_order=0;
+
+	if ( xdr != getMachineEndian() )
+	{
+		swap_order=1;
+	}
+
+	type = read_wkb_int(b);
+
+	/* quick exit on error */
+	if ( ferror_occured ) return;
+
+	the_geom.ndims=2;
+	if (type & WKBZOFFSET)
+	{
+		the_geom.hasZ = 1;
+		the_geom.ndims++;
+	}
+	else the_geom.hasZ = 0;
+	if (type & WKBMOFFSET)
+	{
+		the_geom.hasM = 1;
+		the_geom.ndims++;
+	}
+	else the_geom.hasM = 0;
+
+	if (type & WKBSRIDFLAG )
+	{
+		/* local (in-EWKB) srid spec overrides SRID=#; */
+		localsrid = read_wkb_int(b);
+		if ( localsrid != -1 )
+		{
+			if ( the_geom.srid == -1 ) the_geom.alloc_size += 4;
+			the_geom.srid = localsrid;
+		}
+	}
+
+	type &=0x0f;
+
+	if ( the_geom.lwgi  ){
+
+		if ( type<= POLYGONTYPE )
+			alloc_stack_tuple(type +9,write_type,1);
+		else
+			alloc_stack_tuple(type,write_type,1);
+	}
+	else{
+		/* If we are writing lwg and are reading wbki */
+		int4 towrite=type;
+		if (towrite >= POINTTYPEI && towrite <= POLYGONTYPEI){
+			towrite-=9;
+		}
+		alloc_stack_tuple(towrite,write_type,1);
+	}
+
+	switch(type ){
+		case	POINTTYPE:
+			read_wkb_point(b);
+			break;
+
+		case	LINETYPE:
+			read_wkb_linestring(b);
+			break;
+
+                case    CURVETYPE:
+                        read_wkb_curve(b);
+                        break;
+
+		case	POLYGONTYPE:
+			read_wkb_polygon(b);
+			break;
+
+                case    COMPOUNDTYPE:
+                        read_collection(b,parse_wkb);
+                        break;
+
+                case    CURVEPOLYTYPE:
+                        read_collection(b,parse_wkb);
+                        break;
+
+		case	MULTIPOINTTYPE:
+		case	MULTILINETYPE:
+                case    MULTICURVETYPE:
+		case	MULTIPOLYGONTYPE:
+                case    MULTISURFACETYPE:
+		case	COLLECTIONTYPE:
+			read_collection(b,parse_wkb);
+			break;
+
+		case	POINTTYPEI:
+			the_geom.from_lwgi=1;
+			read_wkb_point(b);
+			break;
+
+		case	LINETYPEI:
+			the_geom.from_lwgi=1;
+			read_wkb_linestring(b);
+			break;
+
+		case	POLYGONTYPEI:
+			the_geom.from_lwgi=1;
+			read_wkb_polygon(b);
+			break;
+
+		default:
+			error("Invalid type in wbk");
+	}
+
+	the_geom.from_lwgi=0;
+
+	pop();
+}
+
+
+void
+alloc_wkb(const char *parser)
+{
+        LWDEBUG(2, "alloc_wkb");
+
+	parse_wkb(&parser);
+}
+
+/*
+	Parse a string and return a LW_GEOM
+*/
+SERIALIZED_LWGEOM *
+parse_it(const char *geometry, allocator allocfunc, report_error errfunc)
+{
+        LWDEBUGF(2, "parse_it: %s", geometry);
+
+	local_malloc = allocfunc;
+	error_func=errfunc;
+
+	ferror_occured = 0;
+
+	init_parser(geometry);
+
+	lwg_parse_yyparse();
+
+	close_parser();
+
+	if (ferror_occured)
+		return NULL;
+
+	return make_serialized_lwgeom();
+}
+
+SERIALIZED_LWGEOM *
+parse_lwg(const char* geometry,allocator allocfunc,report_error errfunc)
+{
+	the_geom.lwgi=0;
+	return parse_it(geometry,allocfunc,errfunc);
+}
+
+SERIALIZED_LWGEOM *
+parse_lwgi(const char* geometry,allocator allocfunc,report_error errfunc)
+{
+	the_geom.lwgi=1;
+	return parse_it(geometry,allocfunc,errfunc);
+}
+
+void
+set_zm(char z, char m)
+{
+        LWDEBUGF(2, "set_zm %d, %d", z, m);
+
+	the_geom.hasZ = z;
+	the_geom.hasM = m;
+	the_geom.ndims = 2+z+m;
+}
+

Added: trunk/liblwgeom/lwgunparse.c
===================================================================
--- trunk/liblwgeom/lwgunparse.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwgunparse.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,765 @@
+/*
+ * Written by Ralph Mason ralph.mason<at>telogis.com
+ *
+ * Copyright Telogis 2004
+ * www.telogis.com
+ *
+ * $Id: wktunparse.c 2781 2008-05-22 20:43:00Z mcayland $
+ */
+
+
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+/* TO get byte order */
+#include <sys/types.h>
+#include <sys/param.h>
+/* Solaris9 does not provide stdint.h */
+/* #include <stdint.h> */
+#include <inttypes.h>
+
+#include "liblwgeom.h"
+#include "wktparse.h"
+
+
+/*-- Typedefs ---------------------------------------------- */
+
+typedef uint32_t int4;
+typedef uchar* (*outfunc)(uchar*,int);
+typedef uchar* (*outwkbfunc)(uchar*);
+
+/*-- Prototypes -------------------------------------------- */
+
+void ensure(int chars);
+void to_end(void);
+void write_str(const char* str);
+void write_double(double val);
+void write_int(int i);
+int4 read_int(uchar** geom);
+double read_double(uchar** geom);
+uchar* output_point(uchar* geom,int supress);
+uchar* output_single(uchar* geom,int supress);
+uchar* output_collection(uchar* geom,outfunc func,int supress);
+uchar* output_collection_2(uchar* geom,int suppress);
+uchar* output_multipoint(uchar* geom,int suppress);
+uchar* output_compound(uchar* geom, int suppress);
+uchar* output_multisurface(uchar* geom, int suppress);
+
+void write_wkb_hex_bytes(uchar* ptr, unsigned int cnt, size_t size);
+void write_wkb_bin_bytes(uchar* ptr, unsigned int cnt, size_t size);
+void write_wkb_bin_flip_bytes(uchar* ptr, unsigned int cnt, size_t size);
+void write_wkb_hex_flip_bytes(uchar* ptr, unsigned int cnt, size_t size);
+
+void write_wkb_int(int i);
+uchar* output_wkb_collection(uchar* geom,outwkbfunc func);
+uchar* output_wkb_collection_2(uchar* geom);
+uchar* output_wkb_point(uchar* geom);
+uchar* output_wkb(uchar* geom);
+
+/*-- Globals ----------------------------------------------- */
+
+static int dims;
+static allocator local_malloc;
+static freeor local_free;
+static char*  out_start;
+static char*  out_pos;
+static int len;
+static int lwgi;
+static uchar endianbyte;
+void (*write_wkb_bytes)(uchar* ptr,unsigned int cnt,size_t size);
+
+/*---------------------------------------------------------- */
+
+
+
+/*
+ * Ensure there is enough space for chars bytes.
+ * Reallocate memory is this is not the case.
+ */
+void
+ensure(int chars){
+
+	int pos = out_pos - out_start;
+
+	if (  (pos + chars) >= len ){
+		char* newp =(char*)local_malloc(len*2);
+		memcpy(newp,out_start,len);
+		local_free(out_start);
+		out_start = newp;
+		out_pos = newp + pos;
+		len *=2;
+	}
+}
+
+void
+to_end(void)
+{
+	while(*out_pos){
+		out_pos++;
+	}
+}
+
+void
+write_str(const char* str)
+{
+	ensure(32);
+	strcpy(out_pos,str);
+	to_end();
+}
+
+void
+write_double(double val){
+	ensure(32);
+	if (lwgi)
+		sprintf(out_pos,"%.8g",val);
+	else
+		sprintf(out_pos,"%.15g",val);
+	to_end();
+}
+
+void
+write_int(int i){
+	ensure(32);
+	sprintf(out_pos,"%i",i);
+	to_end();
+}
+
+int4
+read_int(uchar** geom)
+{
+	int4 ret;
+#ifdef SHRINK_INTS
+	if ( getMachineEndian() == NDR ){
+		if( (**geom)& 0x01){
+			ret = **geom >>1;
+			(*geom)++;
+			return ret;
+		}
+	}
+	else{
+		if( (**geom)& 0x80){
+			ret = **geom & ~0x80;
+			(*geom)++;
+			return ret;
+		}
+	}
+#endif
+	memcpy(&ret,*geom,4);
+
+#ifdef SHRINK_INTS
+	if ( getMachineEndian() == NDR ){
+		ret >>= 1;
+	}
+#endif
+
+	(*geom)+=4;
+	return ret;
+}
+
+double round(double);
+
+double read_double(uchar** geom){
+	if (lwgi){
+		double ret = *((int4*)*geom);
+		ret /= 0xb60b60;
+		(*geom)+=4;
+		return ret-180.0;
+	}
+	else{
+		double ret;
+ 		memcpy(&ret, *geom, 8);
+		(*geom)+=8;
+		return ret;
+	}
+}
+           
+uchar *
+output_point(uchar* geom,int supress)
+{
+	int i;
+
+	for( i = 0 ; i < dims ; i++ ){
+		write_double(read_double(&geom));
+		if (i +1 < dims )
+			write_str(" ");
+	}
+	return geom;
+}
+
+uchar *
+output_single(uchar* geom,int supress)
+{
+	write_str("(");
+	geom=output_point(geom,supress);
+	write_str(")");
+	return geom;
+}
+
+uchar *
+output_collection(uchar* geom,outfunc func,int supress)
+{
+	int cnt = read_int(&geom);
+	if ( cnt == 0 ){
+		write_str(" EMPTY");
+	}
+	else{
+		write_str("(");
+		while(cnt--){
+			geom=func(geom,supress);
+			if ( cnt ){
+				write_str(",");
+			}
+		}
+		write_str(")");
+	}
+	return geom;
+}
+
+uchar *
+output_collection_2(uchar* geom,int suppress)
+{
+	return output_collection(geom,output_point,suppress);
+}
+
+uchar *output_wkt(uchar* geom, int supress);
+
+/* special case for multipoint to supress extra brackets */
+uchar *output_multipoint(uchar* geom,int suppress){
+	unsigned type = *geom & 0x0f;
+	
+	if ( type  == POINTTYPE )
+		return output_point(++geom,suppress);
+	else if ( type == POINTTYPEI ){
+		lwgi++;
+		geom=output_point(++geom,0);
+		lwgi--;
+		return geom;
+	}
+	
+	return output_wkt(geom,suppress);
+}
+
+/* special case for compound to suppress linestring but not circularstring */
+uchar *output_compound(uchar* geom, int suppress) {
+        unsigned type;
+
+#ifdef PGIS_DEBUG_CALLS
+        lwnotice("output_compound called.");
+#endif
+
+        type=*geom++;
+        switch(TYPE_GETTYPE(type)) 
+        {
+                case LINETYPE:
+                        geom = output_collection(geom,output_point,0);
+                        break;
+                case CURVETYPE:
+                        write_str("CIRCULARSTRING");
+                        geom = output_collection(geom,output_point,1);
+                        break;
+        }
+	return geom;
+}
+
+uchar *output_multisurface(uchar* geom, int suppress) {
+        unsigned type;
+
+#ifdef PGIS_DEBUG_CALLS
+        lwnotice("output_multisurface called.");
+#endif
+
+        type=*geom++;
+        switch(TYPE_GETTYPE(type))
+        {
+                case POLYGONTYPE:
+                        geom = output_collection(geom, output_collection_2,0);
+                        break;
+                case CURVEPOLYTYPE:
+                        write_str("CURVEPOLYGON");
+                        geom = output_collection(geom, output_compound,1);
+                        break;
+        }
+        return geom;
+}
+
+/*
+ * Suppress=0 -- write TYPE, M, coords
+ * Suppress=1 -- write TYPE, coords 
+ * Suppress=2 -- write only coords
+ */
+uchar *
+output_wkt(uchar* geom, int supress)
+{
+
+	unsigned type=*geom++;
+	char writeM=0;
+	dims = TYPE_NDIMS(type); /* ((type & 0x30) >> 4)+2; */
+
+#ifdef PGIS_DEBUG_CALLS
+        lwnotice("output_wkt called.");
+#endif
+
+	if ( ! supress && !TYPE_HASZ(type) && TYPE_HASM(type) ) writeM=1;
+
+
+	/* Skip the bounding box if there is one */
+	if ( TYPE_HASBBOX(type) )
+	{
+		geom+=16;
+	}
+
+	if ( TYPE_HASSRID(type) ) {
+		write_str("SRID=");write_int(read_int(&geom));write_str(";");
+	}
+
+	switch(TYPE_GETTYPE(type)) {
+		case POINTTYPE:
+			if ( supress < 2 )
+			{
+				if (writeM) write_str("POINTM");
+				else write_str("POINT");
+			}
+			geom=output_single(geom,0);
+			break;
+		case LINETYPE:
+			if ( supress < 2 )
+			{
+				if (writeM) write_str("LINESTRINGM");
+				else write_str("LINESTRING");
+			}
+			geom = output_collection(geom,output_point,0);
+			break;
+                case CURVETYPE:
+                        if ( supress < 2 )
+                        {
+                                if(writeM) write_str("CIRCULARSTRINGM");
+                                else write_str("CIRCULARSTRING");
+                        }
+                        geom = output_collection(geom,output_point,0);
+                        break;
+		case POLYGONTYPE:
+			if ( supress < 2 )
+			{
+				if (writeM) write_str("POLYGONM");
+				else write_str("POLYGON");
+			}
+			geom = output_collection(geom,output_collection_2,0);
+			break;
+                case COMPOUNDTYPE:
+                        if ( supress < 2 )
+                        {
+                                if (writeM) write_str("COMPOUNDCURVEM");
+                                else write_str("COMPOUNDCURVE");
+                        }
+                        geom = output_collection(geom, output_compound,1);
+                        break;
+                case CURVEPOLYTYPE:
+                        if (supress < 2)
+                        {
+                                if(writeM) write_str("CURVEPOLYGONM");
+                                else write_str("CURVEPOLYGON");
+                        }
+                        geom = output_collection(geom, output_compound,0);
+                        break;
+		case MULTIPOINTTYPE:
+			if ( supress < 2 )
+			{
+				if (writeM) write_str("MULTIPOINTM");
+				else write_str("MULTIPOINT");
+			}
+			geom = output_collection(geom,output_multipoint,2);
+			break;
+		case MULTILINETYPE:
+			if ( supress < 2 )
+			{
+				if (writeM) write_str("MULTILINESTRINGM");
+				else write_str("MULTILINESTRING");
+			}
+			geom = output_collection(geom,output_wkt,2);
+			break;
+                case MULTICURVETYPE:
+                        if ( supress < 2 )
+                        {
+                                if (writeM) write_str("MULTICURVEM");
+                                else write_str("MULTICURVE");
+                        }
+                        geom = output_collection(geom,output_compound,2);
+                        break;
+		case MULTIPOLYGONTYPE:
+			if ( supress < 2 )
+			{
+				if (writeM) write_str("MULTIPOLYGONM");
+				else write_str("MULTIPOLYGON");
+			}
+			geom = output_collection(geom,output_wkt,2);
+			break;
+                case MULTISURFACETYPE:
+                        if ( supress < 2)
+                        {
+                                if (writeM) write_str("MULTISURFACEM");
+                                else write_str("MULTISURFACE");
+                        } 
+                        geom = output_collection(geom,output_multisurface,2);
+                        break;
+		case COLLECTIONTYPE:
+			if ( supress < 2 )
+			{
+				if (writeM) write_str("GEOMETRYCOLLECTIONM");
+				else write_str("GEOMETRYCOLLECTION");
+			}
+			geom = output_collection(geom,output_wkt,1);
+			break;
+
+		case POINTTYPEI:
+			if ( supress < 2 )
+			{
+				if (writeM) write_str("POINTM");
+				else write_str("POINT");
+			}
+			lwgi++;
+			geom=output_single(geom,0);
+			lwgi--;
+			break;
+		case LINETYPEI:
+			if ( supress < 2 )
+			{
+				if (writeM) write_str("LINESTRINGM");
+				else write_str("LINESTRING");
+			}
+			lwgi++;
+			geom = output_collection(geom,output_point,0);
+			lwgi--;
+			break;
+		case POLYGONTYPEI:
+			if ( supress < 2 )
+			{
+				if (writeM) write_str("POLYGONM");
+				else write_str("POLYGON");
+			}
+			lwgi++;
+			geom =output_collection(geom,output_collection_2,0);
+			lwgi--;
+			break;
+	}
+	return geom;
+}
+
+char *
+unparse_WKT(uchar* serialized, allocator alloc, freeor free)
+{
+
+#ifdef PGIS_DEBUG_CALLS
+        lwnotice("unparse_WKT called.");
+#endif
+
+	if (serialized==NULL)
+		return NULL;
+
+	local_malloc=alloc;
+	local_free=free;
+	len = 128;
+	out_start = out_pos = alloc(len);
+	lwgi=0;
+
+	output_wkt(serialized, 0);
+
+	return out_start;
+}
+
+static char outchr[]={"0123456789ABCDEF" };
+
+/* Write HEX bytes flipping */
+void
+write_wkb_hex_flip_bytes(uchar* ptr, unsigned int cnt, size_t size)
+{
+	unsigned int bc; /* byte count */
+
+	ensure(cnt*2*size);
+
+	while(cnt--){
+		for(bc=size; bc; bc--)
+		{
+			*out_pos++ = outchr[ptr[bc-1]>>4];
+			*out_pos++ = outchr[ptr[bc-1]&0x0F];
+		}
+		ptr+=size;
+	}
+}
+
+/* Write HEX bytes w/out flipping */
+void
+write_wkb_hex_bytes(uchar* ptr, unsigned int cnt, size_t size)
+{
+	unsigned int bc; /* byte count */
+
+	ensure(cnt*2*size);
+
+	while(cnt--){
+		for(bc=0; bc<size; bc++)
+		{
+			*out_pos++ = outchr[ptr[bc]>>4];
+			*out_pos++ = outchr[ptr[bc]&0x0F];
+		}
+		ptr+=size;
+	}
+}
+
+/* Write BIN bytes flipping */
+void
+write_wkb_bin_flip_bytes(uchar* ptr, unsigned int cnt, size_t size)
+{
+	unsigned int bc; /* byte count */
+
+	ensure(cnt*size);
+
+	while(cnt--)
+	{
+		for(bc=size; bc; bc--)
+			*out_pos++ = ptr[bc-1];
+		ptr+=size;
+	}
+}
+
+
+/* Write BIN bytes w/out flipping */
+void
+write_wkb_bin_bytes(uchar* ptr, unsigned int cnt, size_t size)
+{
+	unsigned int bc; /* byte count */
+
+	ensure(cnt*size);
+
+	/* Could just use a memcpy here ... */
+	while(cnt--)
+	{
+		for(bc=0; bc<size; bc++)
+			*out_pos++ = ptr[bc];
+		ptr+=size;
+	}
+}
+
+uchar *
+output_wkb_point(uchar* geom)
+{
+	if ( lwgi ){
+		write_wkb_bytes(geom,dims,4);
+		return geom + (4*dims);
+	}
+	else{
+		write_wkb_bytes(geom,dims,8);
+		return geom + (8*dims);
+	}
+}
+
+void
+write_wkb_int(int i){
+	write_wkb_bytes((uchar*)&i,1,4);
+}
+
+uchar *
+output_wkb_collection(uchar* geom,outwkbfunc func)
+{
+	int cnt = read_int(&geom);
+#ifdef PGIS_DEBUG
+	lwnotice("output_wkb_collection: %d iterations loop", cnt);
+#endif
+	write_wkb_int(cnt);
+	while(cnt--) geom=func(geom);
+	return geom;
+}
+
+uchar *
+output_wkb_collection_2(uchar* geom){
+	return output_wkb_collection(geom,output_wkb_point);
+}
+
+uchar *
+output_wkb(uchar* geom)
+{
+	unsigned char type=*geom++;
+	int4 wkbtype;
+
+	dims = TYPE_NDIMS(type); 
+#ifdef PGIS_DEBUG
+	lwnotice("output_wkb: dims set to %d", dims);
+#endif
+
+	/* Skip the bounding box */
+	if ( TYPE_HASBBOX(type) ) { 
+		geom+=16;
+	}
+
+	wkbtype = TYPE_GETTYPE(type); 
+
+	if ( TYPE_HASZ(type) )
+		 wkbtype |= WKBZOFFSET;
+	if ( TYPE_HASM(type) )
+		 wkbtype |= WKBMOFFSET;
+	if ( TYPE_HASSRID(type) ) {
+		wkbtype |= WKBSRIDFLAG;
+	}
+
+
+	/* Write byteorder (as from WKB specs...) */
+	write_wkb_bytes(&endianbyte,1,1);
+
+	write_wkb_int(wkbtype);
+
+	if ( TYPE_HASSRID(type) ) {
+		write_wkb_int(read_int(&geom));
+	}
+
+	switch(TYPE_GETTYPE(type)){
+		case POINTTYPE:
+			geom=output_wkb_point(geom);
+			break;
+		case LINETYPE:
+			geom=output_wkb_collection(geom,output_wkb_point);
+			break;
+                case CURVETYPE:
+                        geom=output_wkb_collection(geom,output_wkb_point);
+                        break;
+		case POLYGONTYPE:
+			geom=output_wkb_collection(geom,output_wkb_collection_2);
+			break;
+                case COMPOUNDTYPE:
+                        geom=output_wkb_collection(geom,output_wkb);
+                        break;
+                case CURVEPOLYTYPE:
+                        geom=output_wkb_collection(geom,output_wkb);
+                        break;
+                case MULTICURVETYPE:
+                case MULTISURFACETYPE:
+		case MULTIPOINTTYPE:
+		case MULTILINETYPE:
+		case MULTIPOLYGONTYPE:
+		case COLLECTIONTYPE:
+			geom = output_wkb_collection(geom,output_wkb);
+			break;
+
+		/*
+			These don't output standard wkb at the moment
+			the output and integer version.
+
+			however you could run it through the wkt parser
+			for a lwg and then output that.  There should
+			also be a force_to_real_(lwgi)
+		*/
+		case POINTTYPEI:
+			lwgi++;
+			geom=output_wkb_point(geom);
+			lwgi--;
+			break;
+		case LINETYPEI:
+			lwgi++;
+			geom = output_wkb_collection(geom,output_wkb_point);
+			lwgi--;
+			break;
+		case POLYGONTYPEI:
+			lwgi++;
+			geom = output_wkb_collection(geom,output_wkb_collection_2);
+			lwgi--;
+			break;
+	}
+	return geom;
+}
+
+char *
+unparse_WKB(uchar* serialized, allocator alloc, freeor free, char endian, size_t *outsize, uchar hex)
+{
+#ifdef PGIS_DEBUG
+	lwnotice("unparse_WKB(%p,...) called", serialized);
+#endif
+
+	if (serialized==NULL)
+		return NULL;
+
+	local_malloc=alloc;
+	local_free=free;
+	len = 128;
+	out_start = out_pos = alloc(len);
+	lwgi=0;
+
+	if ( endian == (char)-1 )
+	{
+		endianbyte = getMachineEndian();
+		if ( hex ) write_wkb_bytes = write_wkb_hex_bytes;
+		else write_wkb_bytes = write_wkb_bin_bytes;
+	}
+	else
+	{
+		endianbyte = endian;
+		if ( endianbyte != getMachineEndian() )
+		{
+			if ( hex ) write_wkb_bytes = write_wkb_hex_flip_bytes;
+			else write_wkb_bytes = write_wkb_bin_flip_bytes;
+		}
+		else
+		{
+			if ( hex ) write_wkb_bytes = write_wkb_hex_bytes;
+			else write_wkb_bytes = write_wkb_bin_bytes;
+		}
+	}
+
+	output_wkb(serialized);
+
+	if ( hex ) {
+		ensure(1);
+		*out_pos=0;
+	}
+
+	if ( outsize ) *outsize = (out_pos-out_start);
+
+	return out_start;
+}
+
+
+/******************************************************************
+ * $Log$
+ * Revision 1.23  2006/02/06 11:12:22  strk
+ * uint32_t typedef moved back from wktparse.h to lwgparse.c and wktunparse.c
+ *
+ * Revision 1.22  2006/02/03 20:53:37  strk
+ * Swapped stdint.h (unavailable on Solaris9) with inttypes.h
+ *
+ * Revision 1.21  2006/02/03 09:52:14  strk
+ * Changed int4 typedefs to use POSIX uint32_t
+ *
+ * Revision 1.20  2006/01/09 15:12:02  strk
+ * ISO C90 comments
+ *
+ * Revision 1.19  2005/03/10 18:19:16  strk
+ * Made void args explicit to make newer compilers happy
+ *
+ * Revision 1.18  2005/02/21 16:16:14  strk
+ * Changed byte to uchar to avoid clashes with win32 headers.
+ *
+ * Revision 1.17  2005/02/07 13:21:10  strk
+ * Replaced DEBUG* macros with PGIS_DEBUG*, to avoid clashes with postgresql DEBUG
+ *
+ * Revision 1.16  2005/01/18 09:32:03  strk
+ * Changed unparse_WKB interface to take an output size pointer and an HEXFORM
+ * specifier. Reworked code in wktunparse to use function pointers.
+ *
+ * Revision 1.15  2004/12/21 15:19:01  strk
+ * Canonical binary reverted back to EWKB, now supporting SRID inclusion.
+ *
+ * Revision 1.14  2004/12/17 11:08:53  strk
+ * Moved getMachineEndian from parser to liblwgeom.{h,c}.
+ * Added XDR and NDR defines.
+ * Fixed all usage of them.
+ *
+ * Revision 1.13  2004/10/25 12:27:33  strk
+ * Removed useless network type includes,
+ * Added param.h include for BYTE_ORDER defines under win32.
+ *
+ * Revision 1.12  2004/10/21 19:48:34  strk
+ * Stricter syntax fixes. Reported by Sébastien NICAISE <snicaise at iciatechnologies.com>
+ *
+ * Revision 1.11  2004/10/15 07:35:41  strk
+ * Fixed a bug introduced by me (byteorder skipped for inner geoms in WKB)
+ *
+ * Revision 1.10  2004/10/11 14:03:33  strk
+ * Added endiannes specification to unparse_WKB, AsBinary, lwgeom_to_wkb.
+ *
+ ******************************************************************/

Added: trunk/liblwgeom/lwline.c
===================================================================
--- trunk/liblwgeom/lwline.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwline.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,516 @@
+/**********************************************************************
+ * $Id: lwline.c 2797 2008-05-31 09:56:44Z mcayland $
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+/* basic LWLINE functions */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "liblwgeom.h"
+
+
+
+/*
+ * Construct a new LWLINE.  points will *NOT* be copied
+ * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
+ */
+LWLINE *
+lwline_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *points)
+{
+	LWLINE *result;
+	result = (LWLINE*) lwalloc(sizeof(LWLINE));
+
+        LWDEBUG(2, "lwline_construct called.");
+
+	result->type = lwgeom_makeType_full(
+		TYPE_HASZ(points->dims),
+		TYPE_HASM(points->dims),
+		(SRID!=-1), LINETYPE,
+		0);
+
+        LWDEBUGF(3, "lwline_construct type=%d", result->type);
+
+	result->SRID = SRID;
+	result->points = points;
+	result->bbox = bbox;
+
+	return result;
+}
+
+/*
+ * given the LWGEOM serialized form (or a pointer into a muli* one)
+ * construct a proper LWLINE.
+ * serialized_form should point to the 8bit type format (with type = 2)
+ * See serialized form doc
+ */
+LWLINE *
+lwline_deserialize(uchar *serialized_form)
+{
+	uchar type;
+	LWLINE *result;
+	uchar *loc =NULL;
+	uint32 npoints;
+	POINTARRAY *pa;
+
+	type = (uchar) serialized_form[0];
+
+	if ( lwgeom_getType(type) != LINETYPE)
+	{
+		lwerror("lwline_deserialize: attempt to deserialize a line which is really a %s", lwgeom_typename(type));
+		return NULL;
+	}
+
+	result = (LWLINE*) lwalloc(sizeof(LWLINE)) ;
+	result->type = type;
+
+	loc = serialized_form+1;
+
+	if (lwgeom_hasBBOX(type))
+	{
+		LWDEBUG(3, "lwline_deserialize: input has bbox");
+
+		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+		memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
+		loc += sizeof(BOX2DFLOAT4);
+	}
+	else
+	{
+		result->bbox = NULL;
+		/*lwnotice("line has NO bbox"); */
+	}
+
+	if ( lwgeom_hasSRID(type))
+	{
+		/*lwnotice("line has srid"); */
+		result->SRID = lw_get_int32(loc);
+		loc +=4; /* type + SRID */
+	}
+	else
+	{
+		/*lwnotice("line has NO srid"); */
+		result->SRID = -1;
+	}
+
+	/* we've read the type (1 byte) and SRID (4 bytes, if present) */
+
+	npoints = lw_get_uint32(loc);
+	/*lwnotice("line npoints = %d", npoints); */
+	loc +=4;
+	pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), npoints);
+	result->points = pa;
+
+	return result;
+}
+
+/*
+ * convert this line into its serialize form
+ * result's first char will be the 8bit type.  See serialized form doc
+ */
+uchar *
+lwline_serialize(LWLINE *line)
+{
+	size_t size, retsize;
+	uchar * result;
+
+	if (line == NULL) lwerror("lwline_serialize:: given null line");
+
+	size = lwline_serialize_size(line);
+	result = lwalloc(size);
+	lwline_serialize_buf(line, result, &retsize);
+
+	if ( retsize != size )
+	{
+		lwerror("lwline_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
+	}
+
+	return result;
+}
+
+/*
+ * convert this line into its serialize form writing it into
+ * the given buffer, and returning number of bytes written into
+ * the given int pointer.
+ * result's first char will be the 8bit type.  See serialized form doc
+ */
+void
+lwline_serialize_buf(LWLINE *line, uchar *buf, size_t *retsize)
+{
+	char hasSRID;
+	uchar *loc;
+	int ptsize;
+	size_t size;
+
+	LWDEBUGF(2, "lwline_serialize_buf(%p, %p, %p) called",
+		line, buf, retsize);
+
+	if (line == NULL)
+		lwerror("lwline_serialize:: given null line");
+
+	if ( TYPE_GETZM(line->type) != TYPE_GETZM(line->points->dims) )
+		lwerror("Dimensions mismatch in lwline");
+
+	ptsize = pointArray_ptsize(line->points);
+
+	hasSRID = (line->SRID != -1);
+
+	buf[0] = (uchar) lwgeom_makeType_full(
+		TYPE_HASZ(line->type), TYPE_HASM(line->type),
+		hasSRID, LINETYPE, line->bbox ? 1 : 0);
+	loc = buf+1;
+
+	LWDEBUGF(3, "lwline_serialize_buf added type (%d)", line->type);
+
+	if (line->bbox)
+	{
+		memcpy(loc, line->bbox, sizeof(BOX2DFLOAT4));
+		loc += sizeof(BOX2DFLOAT4);
+
+		LWDEBUG(3, "lwline_serialize_buf added BBOX");
+	}
+
+	if (hasSRID)
+	{
+		memcpy(loc, &line->SRID, sizeof(int32));
+		loc += sizeof(int32);
+
+		LWDEBUG(3, "lwline_serialize_buf added SRID");
+	}
+
+	memcpy(loc, &line->points->npoints, sizeof(uint32));
+	loc += sizeof(uint32);
+
+	LWDEBUGF(3, "lwline_serialize_buf added npoints (%d)",
+		line->points->npoints);
+
+	/*copy in points */
+	size = line->points->npoints*ptsize;
+	memcpy(loc, getPoint_internal(line->points, 0), size);
+	loc += size;
+
+	LWDEBUGF(3, "lwline_serialize_buf copied serialized_pointlist (%d bytes)",
+		ptsize * line->points->npoints);
+
+	if (retsize) *retsize = loc-buf;
+
+	/*printBYTES((uchar *)result, loc-buf); */
+
+	LWDEBUGF(3, "lwline_serialize_buf returning (loc: %p, size: %d)",
+		loc, loc-buf);
+}
+
+/*
+ * Find bounding box (standard one) 
+ * zmin=zmax=NO_Z_VALUE if 2d 
+ */
+BOX3D *
+lwline_compute_box3d(LWLINE *line)
+{
+	BOX3D *ret;
+
+	if (line == NULL) return NULL;
+
+	ret = ptarray_compute_box3d(line->points);
+	return ret;
+}
+
+/* find length of this deserialized line */
+size_t
+lwline_serialize_size(LWLINE *line)
+{
+	size_t size = 1;  /* type */
+
+	LWDEBUG(2, "lwline_serialize_size called");
+
+	if ( line->SRID != -1 ) size += 4; /* SRID */
+	if ( line->bbox ) size += sizeof(BOX2DFLOAT4);
+
+	size += 4; /* npoints */
+	size += pointArray_ptsize(line->points)*line->points->npoints;
+
+	LWDEBUGF(3, "lwline_serialize_size returning %d", size);
+
+	return size;
+}
+
+void pfree_line (LWLINE  *line)
+{
+	lwfree(line->points);
+	lwfree(line);
+}
+
+/* find length of this serialized line */
+size_t
+lwgeom_size_line(const uchar *serialized_line)
+{
+	int type = (uchar) serialized_line[0];
+	uint32 result = 1;  /*type */
+	const uchar *loc;
+	uint32 npoints;
+
+	LWDEBUG(2, "lwgeom_size_line called");
+
+	if ( lwgeom_getType(type) != LINETYPE)
+		lwerror("lwgeom_size_line::attempt to find the length of a non-line");
+
+
+	loc = serialized_line+1;
+
+	if (lwgeom_hasBBOX(type))
+	{
+		loc += sizeof(BOX2DFLOAT4);
+		result +=sizeof(BOX2DFLOAT4);
+	}
+
+	if ( lwgeom_hasSRID(type))
+	{
+		loc += 4; /* type + SRID */
+		result +=4;
+	}
+
+	/* we've read the type (1 byte) and SRID (4 bytes, if present) */
+	npoints = lw_get_uint32(loc);
+	result += sizeof(uint32); /* npoints */
+
+	result += TYPE_NDIMS(type) * sizeof(double) * npoints;
+
+	LWDEBUGF(3, "lwgeom_size_line returning %d", result);
+
+	return result;
+}
+
+void printLWLINE(LWLINE *line)
+{
+	lwnotice("LWLINE {");
+	lwnotice("    ndims = %i", (int)TYPE_NDIMS(line->type));
+	lwnotice("    SRID = %i", (int)line->SRID);
+	printPA(line->points);
+	lwnotice("}");
+}
+
+int
+lwline_compute_box2d_p(LWLINE *line, BOX2DFLOAT4 *box)
+{
+	return ptarray_compute_box2d_p(line->points, box);
+}
+
+/* Clone LWLINE object. POINTARRAY is not copied. */
+LWLINE *
+lwline_clone(const LWLINE *g)
+{
+	LWLINE *ret = lwalloc(sizeof(LWLINE));
+       
+	LWDEBUGF(2, "lwline_clone called with %p", g);
+
+	memcpy(ret, g, sizeof(LWLINE));
+	if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
+	return ret;
+}
+
+/*
+ * Add 'what' to this line at position 'where'.
+ * where=0 == prepend
+ * where=-1 == append
+ * Returns a MULTILINE or a GEOMETRYCOLLECTION
+ */
+LWGEOM *
+lwline_add(const LWLINE *to, uint32 where, const LWGEOM *what)
+{
+	LWCOLLECTION *col;
+	LWGEOM **geoms;
+	int newtype;
+
+	if ( where != -1 && where != 0 )
+	{
+		lwerror("lwline_add only supports 0 or -1 as second argument, got %d", where);
+		return NULL;
+	}
+
+	/* dimensions compatibility are checked by caller */
+
+	/* Construct geoms array */
+	geoms = lwalloc(sizeof(LWGEOM *)*2);
+	if ( where == -1 ) /* append */
+	{
+		geoms[0] = lwgeom_clone((LWGEOM *)to);
+		geoms[1] = lwgeom_clone(what);
+	}
+	else /* prepend */
+	{
+		geoms[0] = lwgeom_clone(what);
+		geoms[1] = lwgeom_clone((LWGEOM *)to);
+	}
+
+	/* reset SRID and wantbbox flag from component types */
+	geoms[0]->SRID = geoms[1]->SRID = -1;
+	TYPE_SETHASSRID(geoms[0]->type, 0);
+	TYPE_SETHASSRID(geoms[1]->type, 0);
+	TYPE_SETHASBBOX(geoms[0]->type, 0);
+	TYPE_SETHASBBOX(geoms[1]->type, 0);
+
+	/* Find appropriate geom type */
+	if ( TYPE_GETTYPE(what->type) == LINETYPE ) newtype = MULTILINETYPE;
+	else newtype = COLLECTIONTYPE;
+
+	col = lwcollection_construct(newtype,
+		to->SRID, NULL,
+		2, geoms);
+	
+	return (LWGEOM *)col;
+}
+
+void
+lwline_reverse(LWLINE *line)
+{
+	ptarray_reverse(line->points);
+}
+
+LWLINE *
+lwline_segmentize2d(LWLINE *line, double dist)
+{
+	return lwline_construct(line->SRID, NULL,
+		ptarray_segmentize2d(line->points, dist));
+}
+
+/* check coordinate equality  */
+char
+lwline_same(const LWLINE *l1, const LWLINE *l2)
+{
+	return ptarray_same(l1->points, l2->points);
+}
+
+/*
+ * Construct a LWLINE from an array of LWPOINTs
+ * LWLINE dimensions are large enough to host all input dimensions.
+ */
+LWLINE *
+lwline_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points)
+{
+	int zmflag=0;
+	unsigned int i;
+	POINTARRAY *pa;
+	uchar *newpoints, *ptr;
+	size_t ptsize, size;
+
+	/*
+	 * Find output dimensions, check integrity
+	 */
+	for (i=0; i<npoints; i++)
+	{
+		if ( TYPE_GETTYPE(points[i]->type) != POINTTYPE )
+		{
+			lwerror("lwline_from_lwpointarray: invalid input type: %s",
+				lwgeom_typename(TYPE_GETTYPE(points[i]->type)));
+			return NULL;
+		}
+		if ( TYPE_HASZ(points[i]->type) ) zmflag |= 2;
+		if ( TYPE_HASM(points[i]->type) ) zmflag |= 1;
+		if ( zmflag == 3 ) break;
+	}
+
+	if ( zmflag == 0 ) ptsize=2*sizeof(double);
+	else if ( zmflag == 3 ) ptsize=4*sizeof(double);
+	else ptsize=3*sizeof(double);
+
+	/*
+	 * Allocate output points array
+	 */
+	size = ptsize*npoints;
+	newpoints = lwalloc(size);
+	memset(newpoints, 0, size);
+
+	ptr=newpoints;
+	for (i=0; i<npoints; i++)
+	{
+		size=pointArray_ptsize(points[i]->point);
+		memcpy(ptr, getPoint_internal(points[i]->point, 0), size);
+		ptr+=ptsize;
+	}
+
+	pa = pointArray_construct(newpoints, zmflag&2, zmflag&1, npoints);
+
+	return lwline_construct(SRID, NULL, pa);
+}
+
+/*
+ * Construct a LWLINE from a LWMPOINT
+ */
+LWLINE *
+lwline_from_lwmpoint(int SRID, LWMPOINT *mpoint)
+{
+	unsigned int i;
+	POINTARRAY *pa;
+	char zmflag = TYPE_GETZM(mpoint->type);
+	size_t ptsize, size;
+	uchar *newpoints, *ptr;
+
+	if ( zmflag == 0 ) ptsize=2*sizeof(double);
+	else if ( zmflag == 3 ) ptsize=4*sizeof(double);
+	else ptsize=3*sizeof(double);
+
+	/* Allocate space for output points */
+	size = ptsize*mpoint->ngeoms;
+	newpoints = lwalloc(size);
+	memset(newpoints, 0, size);
+
+	ptr=newpoints;
+	for (i=0; i<mpoint->ngeoms; i++)
+	{
+		memcpy(ptr,
+			getPoint_internal(mpoint->geoms[i]->point, 0),
+			ptsize);
+		ptr+=ptsize;
+	}
+
+	pa = pointArray_construct(newpoints, zmflag&2, zmflag&1,
+		mpoint->ngeoms);
+
+	LWDEBUGF(3, "lwline_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag);
+
+	return lwline_construct(SRID, NULL, pa);
+}
+
+LWLINE *
+lwline_addpoint(LWLINE *line, LWPOINT *point, unsigned int where)
+{
+	POINTARRAY *newpa;
+	LWLINE *ret;
+
+	newpa = ptarray_addPoint(line->points,
+		getPoint_internal(point->point, 0),
+		TYPE_NDIMS(point->type), where);
+
+	ret = lwline_construct(line->SRID, NULL, newpa);
+
+	return ret;
+}
+
+LWLINE *
+lwline_removepoint(LWLINE *line, unsigned int index)
+{
+	POINTARRAY *newpa;
+	LWLINE *ret;
+
+	newpa = ptarray_removePoint(line->points, index);
+
+	ret = lwline_construct(line->SRID, NULL, newpa);
+
+	return ret;
+}
+
+/*
+ * Note: input will be changed, make sure you have permissions for this.
+ */
+void
+lwline_setPoint4d(LWLINE *line, unsigned int index, POINT4D *newpoint)
+{
+	setPoint4d(line->points, index, newpoint);
+}

Added: trunk/liblwgeom/lwmcurve.c
===================================================================
--- trunk/liblwgeom/lwmcurve.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwmcurve.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,125 @@
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "liblwgeom.h"
+
+LWMCURVE *
+lwmcurve_deserialize(uchar *srl)
+{
+        LWMCURVE *result;
+        LWGEOM_INSPECTED *insp;
+        int stype;
+        int type = lwgeom_getType(srl[0]);
+        int i;
+
+        if(type != MULTICURVETYPE)
+        {
+                lwerror("lwmcurve_deserialize called on NON multicurve: %d", type);
+                return NULL;
+        }
+
+        insp = lwgeom_inspect(srl);
+
+        result = lwalloc(sizeof(LWMCURVE));
+        result->type = insp->type;
+        result->SRID = insp->SRID;
+        result->ngeoms = insp->ngeometries;
+        result->geoms = lwalloc(sizeof(LWCURVE *)*insp->ngeometries);
+
+        if(lwgeom_hasBBOX(srl[0]))
+        {
+                result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+                memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4));
+        }
+        else result->bbox = NULL;
+
+        for(i = 0; i < insp->ngeometries; i++)
+        {
+                stype = lwgeom_getType(insp->sub_geoms[i][0]);
+                if(stype == CURVETYPE)
+                {
+                        result->geoms[i] = (LWGEOM *)lwcurve_deserialize(insp->sub_geoms[i]);
+                }
+                else if(stype == LINETYPE)
+                {
+                        result->geoms[i] = (LWGEOM *)lwline_deserialize(insp->sub_geoms[i]);
+                }
+                else
+                {
+                        lwerror("Only Circular and Line strings are currenly permitted in a MultiCurve.");
+                        free(result);
+                        free(insp);
+                        return NULL;
+                }
+                        
+                if(TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type))
+                {
+                        lwerror("Mixed diminsions (multicurve: %d, curve %d:%d)",
+                                TYPE_NDIMS(result->type), i,
+                                TYPE_NDIMS(result->geoms[i]->type));
+                        free(result);
+                        free(insp);
+                        return NULL;
+                }
+        }
+        return result;
+}
+
+/*
+ * Add 'what' to this multicurve at position 'where'.
+ * where=0 == prepend
+ * where=-1 == append
+ * Returns a MULTICURVE or a COLLECTION
+ */
+LWGEOM *
+lwmcurve_add(const LWMCURVE *to, uint32 where, const LWGEOM *what)
+{
+        LWCOLLECTION *col;
+        LWGEOM **geoms;
+        int newtype;
+        uint32 i;
+
+        if(where == -1) where = to->ngeoms;
+        else if(where < -1 || where > to->ngeoms)
+        {
+                lwerror("lwmcurve_add: add position out of range %d..%d",
+                        -1, to->ngeoms);
+                return NULL;
+        }
+
+        /* dimensions compatibility are checked by caller */
+
+        /* Construct geoms array */
+        geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
+        for(i = 0; i < where; i++)
+        {
+                geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+        }
+        geoms[where] = lwgeom_clone(what);
+        for(i = where; i < to->ngeoms; i++) 
+        {
+                geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+        }
+
+        if(TYPE_GETTYPE(what->type) == CURVETYPE) newtype = MULTICURVETYPE;
+        else newtype = COLLECTIONTYPE;
+
+        col = lwcollection_construct(newtype,
+                to->SRID, NULL,
+                to->ngeoms + 1, geoms);
+
+        return (LWGEOM *)col;
+}
+        

Added: trunk/liblwgeom/lwmline.c
===================================================================
--- trunk/liblwgeom/lwmline.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwmline.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,110 @@
+/**********************************************************************
+ * $Id: lwmline.c 2369 2006-05-30 08:38:58Z strk $
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "liblwgeom.h"
+
+LWMLINE *
+lwmline_deserialize(uchar *srl)
+{
+	LWMLINE *result;
+	LWGEOM_INSPECTED *insp;
+	int type = lwgeom_getType(srl[0]);
+	int i;
+
+	if ( type != MULTILINETYPE ) 
+	{
+		lwerror("lwmline_deserialize called on NON multiline: %d",
+			type);
+		return NULL;
+	}
+
+	insp = lwgeom_inspect(srl);
+
+	result = lwalloc(sizeof(LWMLINE));
+	result->type = insp->type;
+	result->SRID = insp->SRID;
+	result->ngeoms = insp->ngeometries;
+	result->geoms = lwalloc(sizeof(LWLINE *)*insp->ngeometries);
+
+	if (lwgeom_hasBBOX(srl[0]))
+	{
+		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+		memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4));
+	}
+	else result->bbox = NULL;
+
+
+	for (i=0; i<insp->ngeometries; i++)
+	{
+		result->geoms[i] = lwline_deserialize(insp->sub_geoms[i]);
+		if ( TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type) )
+		{
+			lwerror("Mixed dimensions (multiline:%d, line%d:%d)",
+				TYPE_NDIMS(result->type), i,
+				TYPE_NDIMS(result->geoms[i]->type)
+			);
+			return NULL;
+		}
+	}
+
+	return result;
+}
+
+/*
+ * Add 'what' to this multiline at position 'where'.
+ * where=0 == prepend
+ * where=-1 == append
+ * Returns a MULTILINE or a COLLECTION
+ */
+LWGEOM *
+lwmline_add(const LWMLINE *to, uint32 where, const LWGEOM *what)
+{
+	LWCOLLECTION *col;
+	LWGEOM **geoms;
+	int newtype;
+	uint32 i;
+
+	if ( where == -1 ) where = to->ngeoms;
+	else if ( where < -1 || where > to->ngeoms )
+	{
+		lwerror("lwmline_add: add position out of range %d..%d",
+			-1, to->ngeoms);
+		return NULL;
+	}
+
+	/* dimensions compatibility are checked by caller */
+
+	/* Construct geoms array */
+	geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
+	for (i=0; i<where; i++)
+	{
+		geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+	}
+	geoms[where] = lwgeom_clone(what);
+	for (i=where; i<to->ngeoms; i++)
+	{
+		geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+	}
+
+	if ( TYPE_GETTYPE(what->type) == LINETYPE ) newtype = MULTILINETYPE;
+	else newtype = COLLECTIONTYPE;
+
+	col = lwcollection_construct(newtype,
+		to->SRID, NULL,
+		to->ngeoms+1, geoms);
+	
+	return (LWGEOM *)col;
+
+}

Added: trunk/liblwgeom/lwmpoint.c
===================================================================
--- trunk/liblwgeom/lwmpoint.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwmpoint.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,109 @@
+/**********************************************************************
+ * $Id: lwmpoint.c 2369 2006-05-30 08:38:58Z strk $
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "liblwgeom.h"
+
+LWMPOINT *
+lwmpoint_deserialize(uchar *srl)
+{
+	LWMPOINT *result;
+	LWGEOM_INSPECTED *insp;
+	int type = lwgeom_getType(srl[0]);
+	int i;
+
+	if ( type != MULTIPOINTTYPE ) 
+	{
+		lwerror("lwmpoint_deserialize called on NON multipoint: %d",
+			type);
+		return NULL;
+	}
+
+	insp = lwgeom_inspect(srl);
+
+	result = lwalloc(sizeof(LWMPOINT));
+	result->type = insp->type;
+	result->SRID = insp->SRID;
+	result->ngeoms = insp->ngeometries;
+	result->geoms = lwalloc(sizeof(LWPOINT *)*result->ngeoms);
+
+	if (lwgeom_hasBBOX(srl[0]))
+	{
+		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+		memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4));
+	}
+	else result->bbox = NULL;
+
+	for (i=0; i<insp->ngeometries; i++)
+	{
+		result->geoms[i] = lwpoint_deserialize(insp->sub_geoms[i]);
+		if ( TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type) )
+		{
+			lwerror("Mixed dimensions (multipoint:%d, point%d:%d)",
+				TYPE_NDIMS(result->type), i,
+				TYPE_NDIMS(result->geoms[i]->type)
+			);
+			return NULL;
+		}
+	}
+
+	return result;
+}
+
+/*
+ * Add 'what' to this multipoint at position 'where'.
+ * where=0 == prepend
+ * where=-1 == append
+ * Returns a MULTIPOINT or a COLLECTION
+ */
+LWGEOM *
+lwmpoint_add(const LWMPOINT *to, uint32 where, const LWGEOM *what)
+{
+	LWCOLLECTION *col;
+	LWGEOM **geoms;
+	int newtype;
+	uint32 i;
+
+	if ( where == -1 ) where = to->ngeoms;
+	else if ( where < -1 || where > to->ngeoms )
+	{
+		lwerror("lwmpoint_add: add position out of range %d..%d",
+			-1, to->ngeoms);
+		return NULL;
+	}
+
+	/* dimensions compatibility are checked by caller */
+
+	/* Construct geoms array */
+	geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
+	for (i=0; i<where; i++)
+	{
+		geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+	}
+	geoms[where] = lwgeom_clone(what);
+	for (i=where; i<to->ngeoms; i++)
+	{
+		geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+	}
+
+	if ( TYPE_GETTYPE(what->type) == POINTTYPE ) newtype = MULTIPOINTTYPE;
+	else newtype = COLLECTIONTYPE;
+
+	col = lwcollection_construct(newtype,
+		to->SRID, NULL,
+		to->ngeoms+1, geoms);
+	
+	return (LWGEOM *)col;
+
+}

Added: trunk/liblwgeom/lwmpoly.c
===================================================================
--- trunk/liblwgeom/lwmpoly.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwmpoly.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,112 @@
+/**********************************************************************
+ * $Id: lwmpoly.c 2797 2008-05-31 09:56:44Z mcayland $
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "liblwgeom.h"
+
+
+LWMPOLY *
+lwmpoly_deserialize(uchar *srl)
+{
+	LWMPOLY *result;
+	LWGEOM_INSPECTED *insp;
+	int type = lwgeom_getType(srl[0]);
+	int i;
+
+	LWDEBUG(2, "lwmpoly_deserialize called");
+
+	if ( type != MULTIPOLYGONTYPE ) 
+	{
+		lwerror("lwmpoly_deserialize called on NON multipoly: %d",
+			type);
+		return NULL;
+	}
+
+	insp = lwgeom_inspect(srl);
+
+	result = lwalloc(sizeof(LWMPOLY));
+	result->type = insp->type;
+	result->SRID = insp->SRID;
+	result->ngeoms = insp->ngeometries;
+	result->geoms = lwalloc(sizeof(LWPOLY *)*insp->ngeometries);
+
+	if (lwgeom_hasBBOX(srl[0]))
+	{
+		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+		memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4));
+	}
+	else result->bbox = NULL;
+
+	for (i=0; i<insp->ngeometries; i++)
+	{
+		result->geoms[i] = lwpoly_deserialize(insp->sub_geoms[i]);
+		if ( TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type) )
+		{
+			lwerror("Mixed dimensions (multipoly:%d, poly%d:%d)",
+				TYPE_NDIMS(result->type), i,
+				TYPE_NDIMS(result->geoms[i]->type)
+			);
+			return NULL;
+		}
+	}
+
+	return result;
+}
+
+/*
+ * Add 'what' to this multiline at position 'where'.
+ * where=0 == prepend
+ * where=-1 == append
+ * Returns a MULTIPOLY or a COLLECTION
+ */
+LWGEOM *
+lwmpoly_add(const LWMPOLY *to, uint32 where, const LWGEOM *what)
+{
+	LWCOLLECTION *col;
+	LWGEOM **geoms;
+	int newtype;
+	uint32 i;
+
+	if ( where == -1 ) where = to->ngeoms;
+	else if ( where < -1 || where > to->ngeoms )
+	{
+		lwerror("lwmline_add: add position out of range %d..%d",
+			-1, to->ngeoms);
+		return NULL;
+	}
+
+	/* dimensions compatibility are checked by caller */
+
+	/* Construct geoms array */
+	geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
+	for (i=0; i<where; i++)
+	{
+		geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+	}
+	geoms[where] = lwgeom_clone(what);
+	for (i=where; i<to->ngeoms; i++)
+	{
+		geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+	}
+
+	if ( TYPE_GETTYPE(what->type) == POLYGONTYPE ) newtype = MULTIPOLYGONTYPE;
+	else newtype = COLLECTIONTYPE;
+
+	col = lwcollection_construct(newtype,
+		to->SRID, NULL,
+		to->ngeoms+1, geoms);
+	
+	return (LWGEOM *)col;
+
+}

Added: trunk/liblwgeom/lwmsurface.c
===================================================================
--- trunk/liblwgeom/lwmsurface.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwmsurface.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,129 @@
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "liblwgeom.h"
+
+
+LWMSURFACE *
+lwmsurface_deserialize(uchar *srl)
+{
+        LWMSURFACE *result;
+        LWGEOM_INSPECTED *insp;
+        int stype;
+        int type = lwgeom_getType(srl[0]);
+        int i;
+
+        LWDEBUG(2, "lwmsurface_deserialize called");
+
+        if(type != MULTISURFACETYPE)
+        {
+                lwerror("lwmsurface_deserialize called on a non-multisurface: %d", type);
+                return NULL;
+        }
+
+        insp = lwgeom_inspect(srl);
+
+        result = lwalloc(sizeof(LWMSURFACE));
+        result->type = insp->type;
+        result->SRID = insp->SRID;
+        result->ngeoms = insp->ngeometries;
+        result->geoms = lwalloc(sizeof(LWPOLY *)*insp->ngeometries);
+
+        if(lwgeom_hasBBOX(srl[0]))
+        {
+                result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+                memcpy(result->bbox, srl + 1, sizeof(BOX2DFLOAT4));
+        }
+        else result->bbox = NULL;
+
+        for(i = 0; i < insp->ngeometries; i++)
+        {
+                stype = lwgeom_getType(insp->sub_geoms[i][0]);
+                if(stype == POLYGONTYPE) 
+                {
+                        result->geoms[i] = (LWGEOM *)lwpoly_deserialize(insp->sub_geoms[i]);
+                }
+                else if(stype == CURVEPOLYTYPE)
+                {
+                        result->geoms[i] = (LWGEOM *)lwcurvepoly_deserialize(insp->sub_geoms[i]);
+                }
+                else
+                {
+                        lwerror("Only Polygons and Curved Polygons are supported in a MultiSurface.");
+                        lwfree(result);
+                        lwfree(insp);
+                        return NULL;
+                }
+
+                if(TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type))
+                {
+                        lwerror("Mixed dimensions (multisurface: %d, surface %d:%d", 
+                                TYPE_NDIMS(result->type), i, 
+                                TYPE_NDIMS(result->geoms[i]->type));
+                        lwfree(result);
+                        lwfree(insp);
+                        return NULL;
+                }
+        }
+        return result;
+}
+
+/*
+ * Add 'what' to this multisurface at position 'where'
+ * where=0 == prepend
+ * where=-1 == append
+ * Returns a MULTISURFACE or a COLLECTION
+ */
+LWGEOM *
+lwmsurface_add(const LWMSURFACE *to, uint32 where, const LWGEOM *what)
+{
+        LWCOLLECTION *col;
+        LWGEOM **geoms;
+        int newtype;
+        uint32 i;
+        
+        if(where == -1) where = to->ngeoms;
+        else if(where < -1 || where > to->ngeoms)
+        {
+                lwerror("lwmsurface_add: add position out of range %d..%d",
+                        -1, to->ngeoms);
+                return NULL;
+        }
+
+        /* dimensions compatibility are checked by caller */
+
+        /* Construct geoms array */
+        geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
+        for(i = 0; i < where; i++)
+        {
+                geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+        }
+        geoms[where] = lwgeom_clone(what);
+        for(i = where; i < to->ngeoms; i++)
+        {
+                geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+        }
+
+        if(TYPE_GETTYPE(what->type) == POLYGONTYPE 
+                || TYPE_GETTYPE(what->type) == CURVEPOLYTYPE) 
+            newtype = MULTISURFACETYPE;
+        else newtype = COLLECTIONTYPE;
+
+        col = lwcollection_construct(newtype,
+            to->SRID, NULL, to->ngeoms + 1, geoms);
+
+        return (LWGEOM *)col;
+}
+

Added: trunk/liblwgeom/lwpoint.c
===================================================================
--- trunk/liblwgeom/lwpoint.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwpoint.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,431 @@
+/**********************************************************************
+ * $Id: lwpoint.c 2797 2008-05-31 09:56:44Z mcayland $
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "liblwgeom.h"
+
+
+/*
+ * Convert this point into its serialize form
+ * result's first char will be the 8bit type.  See serialized form doc
+ */
+uchar *
+lwpoint_serialize(LWPOINT *point)
+{
+	size_t size, retsize;
+	uchar *result;
+
+	size = lwpoint_serialize_size(point);
+	result = lwalloc(size);
+	lwpoint_serialize_buf(point, result, &retsize);
+
+	if ( retsize != size )
+	{
+		lwerror("lwpoint_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
+	}
+
+	return result;
+}
+
+/*
+ * Convert this point into its serialize form writing it into
+ * the given buffer, and returning number of bytes written into
+ * the given int pointer.
+ * result's first char will be the 8bit type.  See serialized form doc
+ */
+void
+lwpoint_serialize_buf(LWPOINT *point, uchar *buf, size_t *retsize)
+{
+	int size=1;
+	char hasSRID;
+	uchar *loc;
+	int ptsize = pointArray_ptsize(point->point);
+
+	if ( TYPE_GETZM(point->type) != TYPE_GETZM(point->point->dims) )
+		lwerror("Dimensions mismatch in lwpoint");
+
+	LWDEBUGF(2, "lwpoint_serialize_buf(%p, %p) called", point, buf);
+	/*printLWPOINT(point); */
+
+	hasSRID = (point->SRID != -1);
+
+	if (hasSRID) size +=4;  /*4 byte SRID */
+	if (point->bbox) size += sizeof(BOX2DFLOAT4); /* bvol */
+
+	size += sizeof(double)*TYPE_NDIMS(point->type);
+
+	buf[0] = (uchar) lwgeom_makeType_full(
+		TYPE_HASZ(point->type), TYPE_HASM(point->type),
+		hasSRID, POINTTYPE, point->bbox?1:0);
+	loc = buf+1;
+
+	if (point->bbox)
+	{
+		memcpy(loc, point->bbox, sizeof(BOX2DFLOAT4));
+		loc += sizeof(BOX2DFLOAT4);
+	}
+
+	if (hasSRID)
+	{
+		memcpy(loc, &point->SRID, sizeof(int32));
+		loc += 4;
+	}
+
+	/* copy in points */
+	memcpy(loc, getPoint_internal(point->point, 0), ptsize);
+
+	if (retsize) *retsize = size;
+}
+
+/*
+ * Find bounding box (standard one) 
+ *   zmin=zmax=NO_Z_VALUE if 2d 
+ */
+BOX3D *
+lwpoint_compute_box3d(LWPOINT *point)
+{
+	LWDEBUGF(2, "lwpoint_compute_box3d called with point %p", point);
+
+	if (point == NULL)
+	{
+		LWDEBUG(3, "lwpoint_compute_box3d returning NULL");
+
+		return NULL;
+	}
+
+	LWDEBUG(3, "lwpoint_compute_box3d returning ptarray_compute_box3d return");
+
+	return ptarray_compute_box3d(point->point);
+}
+
+/*
+ * Convenience functions to hide the POINTARRAY
+ * TODO: obsolete this
+ */
+int
+lwpoint_getPoint2d_p(const LWPOINT *point, POINT2D *out)
+{
+	return getPoint2d_p(point->point, 0, out);
+}
+
+/* convenience functions to hide the POINTARRAY */
+int
+lwpoint_getPoint3dz_p(const LWPOINT *point, POINT3DZ *out)
+{
+	return getPoint3dz_p(point->point,0,out);
+}
+int
+lwpoint_getPoint3dm_p(const LWPOINT *point, POINT3DM *out)
+{
+	return getPoint3dm_p(point->point,0,out);
+}
+int
+lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
+{
+	return getPoint4d_p(point->point,0,out);
+}
+
+/* find length of this deserialized point */
+size_t
+lwpoint_serialize_size(LWPOINT *point)
+{
+	size_t size = 1; /* type */
+
+	LWDEBUG(2, "lwpoint_serialize_size called");
+
+	if ( point->SRID != -1 ) size += 4; /* SRID */
+	if ( point->bbox ) size += sizeof(BOX2DFLOAT4);
+
+	size += TYPE_NDIMS(point->type) * sizeof(double); /* point */
+
+	LWDEBUGF(3, "lwpoint_serialize_size returning %d", size);
+
+	return size; 
+}
+
+/*
+ * Construct a new point.  point will not be copied
+ * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
+ */
+LWPOINT *
+lwpoint_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *point)
+{
+	LWPOINT *result ;
+
+	if (point == NULL)
+		return NULL; /* error */
+
+	result = lwalloc(sizeof(LWPOINT));
+	result->type = lwgeom_makeType_full(TYPE_HASZ(point->dims), TYPE_HASM(point->dims), (SRID!=-1), POINTTYPE, 0);
+	result->SRID = SRID;
+	result->point = point;
+	result->bbox = bbox;
+
+	return result;
+}
+
+LWPOINT *
+make_lwpoint2d(int SRID, double x, double y)
+{
+	POINT2D p;
+	POINTARRAY *pa = ptarray_construct(0, 0, 1);
+
+	p.x = x;
+	p.y = y;
+
+	memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT2D));
+
+	return lwpoint_construct(SRID, NULL, pa);
+}
+
+LWPOINT *
+make_lwpoint3dz(int SRID, double x, double y, double z)
+{
+	POINT3DZ p;
+	POINTARRAY *pa = ptarray_construct(1, 0, 1);
+
+	p.x = x;
+	p.y = y;
+	p.z = z;
+
+	memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT3DZ));
+
+	return lwpoint_construct(SRID, NULL, pa);
+}
+
+LWPOINT *
+make_lwpoint3dm(int SRID, double x, double y, double m)
+{
+	POINTARRAY *pa = ptarray_construct(0, 1, 1);
+	POINT3DM p;
+
+	p.x = x;
+	p.y = y;
+	p.m = m;
+
+	memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT3DM));
+
+	return lwpoint_construct(SRID, NULL, pa);
+}
+
+LWPOINT *
+make_lwpoint4d(int SRID, double x, double y, double z, double m)
+{
+	POINTARRAY *pa = ptarray_construct(1, 1, 1);
+	POINT4D p;
+	
+	p.x = x;
+	p.y = y;
+	p.z = z;
+	p.m = m;
+
+	memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT4D));
+
+	return lwpoint_construct(SRID, NULL, pa);
+}
+
+/*
+ * Given the LWPOINT serialized form (or a pointer into a muli* one)
+ * construct a proper LWPOINT.
+ * serialized_form should point to the 8bit type format (with type = 1)
+ * See serialized form doc
+ */
+LWPOINT *
+lwpoint_deserialize(uchar *serialized_form)
+{
+	uchar type;
+	int geom_type;
+	LWPOINT *result;
+	uchar *loc = NULL;
+	POINTARRAY *pa;
+
+	LWDEBUG(2, "lwpoint_deserialize called");
+
+	result = (LWPOINT*) lwalloc(sizeof(LWPOINT)) ;
+
+	type = serialized_form[0];
+	geom_type = lwgeom_getType(type);
+
+	if ( geom_type != POINTTYPE)
+	{
+		lwerror("lwpoint_deserialize: attempt to deserialize a point which is really a %s", lwgeom_typename(geom_type));
+		return NULL;
+	}
+	result->type = type;
+
+	loc = serialized_form+1;
+
+	if (lwgeom_hasBBOX(type))
+	{
+		LWDEBUG(3, "lwpoint_deserialize: input has bbox");
+
+		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+		memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
+		loc += sizeof(BOX2DFLOAT4);
+	}
+	else
+	{
+		result->bbox = NULL;
+	}
+
+	if ( lwgeom_hasSRID(type))
+	{
+		LWDEBUG(3, "lwpoint_deserialize: input has SRID");
+
+		result->SRID = lw_get_int32(loc);
+		loc += 4; /* type + SRID */
+	}
+	else
+	{
+		result->SRID = -1;
+	}
+
+	/* we've read the type (1 byte) and SRID (4 bytes, if present) */
+
+	pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), 1);
+
+	result->point = pa;
+
+	return result;
+}
+
+void pfree_point    (LWPOINT *pt)
+{
+	pfree_POINTARRAY(pt->point);
+	lwfree(pt);
+}
+
+void printLWPOINT(LWPOINT *point)
+{
+	lwnotice("LWPOINT {");
+	lwnotice("    ndims = %i", (int)TYPE_NDIMS(point->type));
+	lwnotice("    BBOX = %i", TYPE_HASBBOX(point->type) ? 1 : 0 );
+	lwnotice("    SRID = %i", (int)point->SRID);
+	printPA(point->point);
+	lwnotice("}");
+}
+
+int
+lwpoint_compute_box2d_p(LWPOINT *point, BOX2DFLOAT4 *box)
+{
+	return ptarray_compute_box2d_p(point->point, box);
+}
+
+/* Clone LWPOINT object. POINTARRAY is not copied. */
+LWPOINT *
+lwpoint_clone(const LWPOINT *g)
+{
+	LWPOINT *ret = lwalloc(sizeof(LWPOINT));
+
+	LWDEBUG(2, "lwpoint_clone called");
+
+	memcpy(ret, g, sizeof(LWPOINT));
+	if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
+	return ret;
+}
+
+/*
+ * Add 'what' to this point at position 'where'.
+ * where=0 == prepend
+ * where=-1 == append
+ * Returns a MULTIPOINT or a GEOMETRYCOLLECTION
+ */
+LWGEOM *
+lwpoint_add(const LWPOINT *to, uint32 where, const LWGEOM *what)
+{
+	LWCOLLECTION *col;
+	LWGEOM **geoms;
+	int newtype;
+
+	if ( where != -1 && where != 0 )
+	{
+		lwerror("lwpoint_add only supports 0 or -1 as second argument, got %d", where);
+		return NULL;
+	}
+
+	/* dimensions compatibility are checked by caller */
+
+
+	/* Construct geoms array */
+	geoms = lwalloc(sizeof(LWGEOM *)*2);
+	if ( where == -1 ) /* append */
+	{
+		geoms[0] = lwgeom_clone((LWGEOM *)to);
+		geoms[1] = lwgeom_clone(what);
+	}
+	else /* prepend */
+	{
+		geoms[0] = lwgeom_clone(what);
+		geoms[1] = lwgeom_clone((LWGEOM *)to);
+	}
+	/* reset SRID and wantbbox flag from component types */
+	lwgeom_dropSRID(geoms[0]);
+	lwgeom_dropBBOX(geoms[0]);
+	lwgeom_dropSRID(geoms[1]);
+	lwgeom_dropBBOX(geoms[1]);
+
+	/* Find appropriate geom type */
+	if ( TYPE_GETTYPE(what->type) == POINTTYPE ) newtype = MULTIPOINTTYPE;
+	else newtype = COLLECTIONTYPE;
+
+	col = lwcollection_construct(newtype,
+		to->SRID, NULL,
+		2, geoms);
+	
+	return (LWGEOM *)col;
+}
+
+/* Find length of this serialized point */
+size_t
+lwgeom_size_point(const uchar *serialized_point)
+{
+	uint32  result = 1;
+	uchar type;
+	const uchar *loc;
+
+	type = serialized_point[0];
+
+	if ( lwgeom_getType(type) != POINTTYPE) return 0;
+
+	LWDEBUGF(2, "lwgeom_size_point called (%d)", result);
+
+	loc = serialized_point+1;
+
+	if (lwgeom_hasBBOX(type))
+	{
+		loc += sizeof(BOX2DFLOAT4);
+		result +=sizeof(BOX2DFLOAT4);
+
+		LWDEBUGF(3, "lwgeom_size_point: has bbox (%d)", result);
+	}
+
+	if ( lwgeom_hasSRID(type))
+	{
+		LWDEBUGF(3, "lwgeom_size_point: has srid (%d)", result);
+
+		loc +=4; /* type + SRID */
+		result +=4;
+	}
+
+	result += lwgeom_ndims(type)*sizeof(double);
+
+	return result;
+}
+
+/* check coordinate equality  */
+char
+lwpoint_same(const LWPOINT *p1, const LWPOINT *p2)
+{
+	return ptarray_same(p1->point, p2->point);
+}

Added: trunk/liblwgeom/lwpoly.c
===================================================================
--- trunk/liblwgeom/lwpoly.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwpoly.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,567 @@
+/**********************************************************************
+ * $Id: lwpoly.c 2797 2008-05-31 09:56:44Z mcayland $
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+/* basic LWPOLY manipulation */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "liblwgeom.h"
+
+
+#define CHECK_POLY_RINGS_ZM 1
+
+/* construct a new LWPOLY.  arrays (points/points per ring) will NOT be copied
+ * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
+ */
+LWPOLY *
+lwpoly_construct(int SRID, BOX2DFLOAT4 *bbox, unsigned int nrings, POINTARRAY **points)
+{
+	LWPOLY *result;
+	int hasz, hasm;
+#ifdef CHECK_POLY_RINGS_ZM
+	char zm;
+	unsigned int i;
+#endif
+
+	if ( nrings < 1 ) lwerror("lwpoly_construct: need at least 1 ring");
+
+	hasz = TYPE_HASZ(points[0]->dims);
+	hasm = TYPE_HASM(points[0]->dims);
+
+#ifdef CHECK_POLY_RINGS_ZM
+	zm = TYPE_GETZM(points[0]->dims);
+	for (i=1; i<nrings; i++)
+	{
+		if ( zm != TYPE_GETZM(points[i]->dims) )
+			lwerror("lwpoly_construct: mixed dimensioned rings");
+	}
+#endif
+
+	result = (LWPOLY*) lwalloc(sizeof(LWPOLY));
+	result->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1), POLYGONTYPE,
+		0);
+	result->SRID = SRID;
+	result->nrings = nrings;
+	result->rings = points;
+	result->bbox = bbox;
+
+	return result;
+}
+
+
+/*
+ * given the LWPOLY serialized form (or a pointer into a muli* one)
+ * construct a proper LWPOLY.
+ * serialized_form should point to the 8bit type format (with type = 3)
+ * See serialized form doc
+ */
+LWPOLY *
+lwpoly_deserialize(uchar *serialized_form)
+{
+
+	LWPOLY *result;
+	uint32 nrings;
+	int ndims, hasz, hasm;
+	uint32 npoints;
+	uchar type;
+	uchar *loc;
+	int t;
+
+	if (serialized_form == NULL)
+	{
+		lwerror("lwpoly_deserialize called with NULL arg");
+		return NULL;
+	}
+
+	result = (LWPOLY*) lwalloc(sizeof(LWPOLY));
+
+	type = serialized_form[0];
+	result->type = type;
+
+	ndims = TYPE_NDIMS(type);
+	hasz = TYPE_HASZ(type);
+	hasm = TYPE_HASM(type);
+	loc = serialized_form;
+
+	if ( TYPE_GETTYPE(type) != POLYGONTYPE)
+	{
+		lwerror("lwpoly_deserialize: attempt to deserialize a poly which is really a %s", lwgeom_typename(type));
+		return NULL;
+	}
+
+
+	loc = serialized_form+1;
+
+	if (lwgeom_hasBBOX(type)) {
+		LWDEBUG(3, "lwpoly_deserialize: input has bbox");
+
+		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
+		memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
+		loc += sizeof(BOX2DFLOAT4);
+	} else {
+		result->bbox = NULL;
+	}
+
+	if ( lwgeom_hasSRID(type))
+	{
+		result->SRID = lw_get_int32(loc);
+		loc +=4; /* type + SRID */
+	}
+	else
+	{
+		result->SRID = -1;
+	}
+
+	nrings = lw_get_uint32(loc);
+	result->nrings = nrings;
+	loc +=4;
+	result->rings = (POINTARRAY**) lwalloc(nrings* sizeof(POINTARRAY*));
+
+	for (t =0;t<nrings;t++)
+	{
+		/* read in a single ring and make a PA */
+		npoints = lw_get_uint32(loc);
+		loc +=4;
+
+		result->rings[t] = pointArray_construct(loc, hasz, hasm, npoints);
+		loc += sizeof(double)*ndims*npoints;
+	}
+
+	return result;
+}
+
+/*
+ * create the serialized form of the polygon
+ * result's first char will be the 8bit type.  See serialized form doc
+ * points copied
+ */
+uchar *
+lwpoly_serialize(LWPOLY *poly)
+{
+	size_t size, retsize;
+	uchar *result;
+
+	size = lwpoly_serialize_size(poly);
+	result = lwalloc(size);
+	lwpoly_serialize_buf(poly, result, &retsize);
+	
+	if ( retsize != size )
+	{
+		lwerror("lwpoly_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
+	}
+
+	return result;
+}
+
+/*
+ * create the serialized form of the polygon writing it into the
+ * given buffer, and returning number of bytes written into
+ * the given int pointer.
+ * result's first char will be the 8bit type.  See serialized form doc
+ * points copied
+ */
+void
+lwpoly_serialize_buf(LWPOLY *poly, uchar *buf, size_t *retsize)
+{
+	size_t size=1;  /* type byte */
+	char hasSRID;
+	int t;
+	uchar *loc;
+	int ptsize;
+
+	LWDEBUG(2, "lwpoly_serialize_buf called");
+
+	ptsize = sizeof(double)*TYPE_NDIMS(poly->type);
+
+	hasSRID = (poly->SRID != -1);
+
+	size += 4; /* nrings */
+	size += 4*poly->nrings; /* npoints/ring */
+
+	buf[0] = (uchar) lwgeom_makeType_full(
+		TYPE_HASZ(poly->type), TYPE_HASM(poly->type),
+		hasSRID, POLYGONTYPE, poly->bbox ? 1 : 0);
+	loc = buf+1;
+
+	if (poly->bbox)
+	{
+		memcpy(loc, poly->bbox, sizeof(BOX2DFLOAT4));
+		size += sizeof(BOX2DFLOAT4); /* bvol */
+		loc += sizeof(BOX2DFLOAT4);
+	}
+
+	if (hasSRID)
+	{
+		memcpy(loc, &poly->SRID, sizeof(int32));
+		loc += 4;
+		size +=4;  /* 4 byte SRID */
+	}
+
+	memcpy(loc, &poly->nrings, sizeof(int32));  /* nrings */
+	loc+=4;
+
+	for (t=0;t<poly->nrings;t++)
+	{
+		POINTARRAY *pa = poly->rings[t];
+		size_t pasize;
+		uint32 npoints;
+
+		if ( TYPE_GETZM(poly->type) != TYPE_GETZM(pa->dims) )
+			lwerror("Dimensions mismatch in lwpoly");
+
+		npoints = pa->npoints;
+
+		memcpy(loc, &npoints, sizeof(uint32)); /* npoints this ring */
+		loc+=4;
+
+		pasize = npoints*ptsize;
+		size += pasize;
+
+		/* copy points */
+		memcpy(loc, getPoint_internal(pa, 0), pasize);
+		loc += pasize;
+
+	}
+
+	if (retsize) *retsize = size;
+}
+
+
+/* find bounding box (standard one)  zmin=zmax=0 if 2d (might change to NaN) */
+BOX3D *
+lwpoly_compute_box3d(LWPOLY *poly)
+{
+	BOX3D *result;
+
+	/* just need to check outer ring -- interior rings are inside */
+	POINTARRAY *pa = poly->rings[0];  
+	result  = ptarray_compute_box3d(pa);
+
+	return result;
+}
+
+/* find length of this serialized polygon */
+size_t
+lwgeom_size_poly(const uchar *serialized_poly)
+{
+	uint32 result = 1; /* char type */
+	uint32 nrings;
+	int ndims;
+	int t;
+	uchar type;
+	uint32 npoints;
+	const uchar *loc;
+
+	if (serialized_poly == NULL)
+		return -9999;
+
+
+	type = (uchar) serialized_poly[0];
+	ndims = lwgeom_ndims(type);
+
+	if ( lwgeom_getType(type) != POLYGONTYPE)
+		return -9999;
+
+
+	loc = serialized_poly+1;
+
+	if (lwgeom_hasBBOX(type))
+	{
+		LWDEBUG(3, "lwgeom_size_poly: has bbox");
+
+		loc += sizeof(BOX2DFLOAT4);
+		result +=sizeof(BOX2DFLOAT4);
+	}
+
+
+	if ( lwgeom_hasSRID(type))
+	{
+		LWDEBUG(3, "lwgeom_size_poly: has srid");
+
+		loc +=4; /* type + SRID */
+		result += 4;
+	}
+
+
+	nrings = lw_get_uint32(loc);
+	loc +=4;
+	result +=4;
+
+        LWDEBUGF(3, "lwgeom_size_poly contains %d rings", nrings);
+
+	for (t =0;t<nrings;t++)
+	{
+		/* read in a single ring and make a PA */
+		npoints = lw_get_uint32(loc);
+		loc += 4;
+		result += 4;
+
+		if (ndims == 3)
+		{
+			loc += 24*npoints;
+			result += 24*npoints;
+		}
+		else if (ndims == 2)
+		{
+			loc += 16*npoints;
+			result += 16*npoints;
+		}
+		else if (ndims == 4)
+		{
+			loc += 32*npoints;
+			result += 32*npoints;
+		}
+	}
+
+        LWDEBUGF(3, "lwgeom_size_poly returning %d", result);
+
+	return result;
+}
+
+/* find length of this deserialized polygon */
+size_t
+lwpoly_serialize_size(LWPOLY *poly)
+{
+	size_t size = 1; /* type */
+	uint32 i;
+
+	if ( poly->SRID != -1 ) size += 4; /* SRID */
+	if ( poly->bbox ) size += sizeof(BOX2DFLOAT4);
+
+	LWDEBUGF(2, "lwpoly_serialize_size called with poly[%p] (%d rings)",
+			poly, poly->nrings);
+
+	size += 4; /* nrings */
+
+	for (i=0; i<poly->nrings; i++)
+	{
+		size += 4; /* npoints */
+		size += poly->rings[i]->npoints*TYPE_NDIMS(poly->type)*sizeof(double);
+	}
+
+	LWDEBUGF(3, "lwpoly_serialize_size returning %d", size);
+
+	return size;
+}
+
+void pfree_polygon  (LWPOLY  *poly)
+{
+	int t;
+
+	for (t=0;t<poly->nrings;t++)
+	{
+		pfree_POINTARRAY(poly->rings[t]);
+	}
+
+	lwfree(poly);
+}
+
+void printLWPOLY(LWPOLY *poly)
+{
+	int t;
+	lwnotice("LWPOLY {");
+	lwnotice("    ndims = %i", (int)TYPE_NDIMS(poly->type));
+	lwnotice("    SRID = %i", (int)poly->SRID);
+	lwnotice("    nrings = %i", (int)poly->nrings);
+	for (t=0;t<poly->nrings;t++)
+	{
+		lwnotice("    RING # %i :",t);
+		printPA(poly->rings[t]);
+	}
+	lwnotice("}");
+}
+
+int
+lwpoly_compute_box2d_p(LWPOLY *poly, BOX2DFLOAT4 *box)
+{
+	BOX2DFLOAT4 boxbuf;
+	uint32 i;
+
+	if ( ! poly->nrings ) return 0;
+	if ( ! ptarray_compute_box2d_p(poly->rings[0], box) ) return 0;
+	for (i=1; i<poly->nrings; i++)
+	{
+		if ( ! ptarray_compute_box2d_p(poly->rings[0], &boxbuf) )
+			return 0;
+		if ( ! box2d_union_p(box, &boxbuf, box) )
+			return 0;
+	}
+	return 1;
+}
+
+/* Clone LWLINE object. POINTARRAY are not copied, it's ring array is. */
+LWPOLY *
+lwpoly_clone(const LWPOLY *g)
+{
+	LWPOLY *ret = lwalloc(sizeof(LWPOLY));
+	memcpy(ret, g, sizeof(LWPOLY));
+	ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
+	memcpy(ret->rings, g->rings, sizeof(POINTARRAY *)*g->nrings);
+	if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
+	return ret;
+}
+
+/*
+ * Add 'what' to this poly at position 'where'.
+ * where=0 == prepend
+ * where=-1 == append
+ * Returns a MULTIPOLYGON or a GEOMETRYCOLLECTION
+ */
+LWGEOM *
+lwpoly_add(const LWPOLY *to, uint32 where, const LWGEOM *what)
+{
+	LWCOLLECTION *col;
+	LWGEOM **geoms;
+	int newtype;
+
+	if ( where != -1 && where != 0 )
+	{
+		lwerror("lwpoly_add only supports 0 or -1 as second argument, got %d", where);
+		return NULL;
+	}
+
+	/* dimensions compatibility are checked by caller */
+
+	/* Construct geoms array */
+	geoms = lwalloc(sizeof(LWGEOM *)*2);
+	if ( where == -1 ) /* append */
+	{
+		geoms[0] = lwgeom_clone((LWGEOM *)to);
+		geoms[1] = lwgeom_clone(what);
+	}
+	else /* prepend */
+	{
+		geoms[0] = lwgeom_clone(what);
+		geoms[1] = lwgeom_clone((LWGEOM *)to);
+	}
+
+	/* reset SRID and wantbbox flag from component types */
+	geoms[0]->SRID = geoms[1]->SRID = -1;
+	TYPE_SETHASSRID(geoms[0]->type, 0);
+	TYPE_SETHASSRID(geoms[1]->type, 0);
+	TYPE_SETHASBBOX(geoms[0]->type, 0);
+	TYPE_SETHASBBOX(geoms[1]->type, 0);
+
+	/* Find appropriate geom type */
+	if ( TYPE_GETTYPE(what->type) == POLYGONTYPE ) newtype = MULTIPOLYGONTYPE;
+	else newtype = COLLECTIONTYPE;
+
+	col = lwcollection_construct(newtype,
+		to->SRID, NULL,
+		2, geoms);
+	
+	return (LWGEOM *)col;
+}
+
+void
+lwpoly_forceRHR(LWPOLY *poly)
+{
+	int i;
+
+	if ( ptarray_isccw(poly->rings[0]) )
+	{
+		ptarray_reverse(poly->rings[0]);
+	}
+
+	for (i=1; i<poly->nrings; i++)
+	{
+		if ( ! ptarray_isccw(poly->rings[i]) )
+		{
+			ptarray_reverse(poly->rings[i]);
+		}
+	}
+}
+
+
+void
+lwpoly_reverse(LWPOLY *poly)
+{
+	int i;
+
+	for (i=0; i<poly->nrings; i++)
+		ptarray_reverse(poly->rings[i]);
+}
+
+LWPOLY *
+lwpoly_segmentize2d(LWPOLY *poly, double dist)
+{
+	POINTARRAY **newrings;
+	unsigned int i;
+	
+	newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
+	for (i=0; i<poly->nrings; i++)
+	{
+		newrings[i] = ptarray_segmentize2d(poly->rings[i], dist);
+	}
+	return lwpoly_construct(poly->SRID, NULL,
+		poly->nrings, newrings);
+}
+
+/*
+ * check coordinate equality 
+ * ring and coordinate order is considered
+ */
+char
+lwpoly_same(const LWPOLY *p1, const LWPOLY *p2)
+{
+	unsigned int i;
+
+	if ( p1->nrings != p2->nrings ) return 0;
+	for (i=0; i<p1->nrings; i++)
+	{
+		if ( ! ptarray_same(p1->rings[i], p2->rings[i]) )
+			return 0;
+	}
+	return 1;
+}
+
+/*
+ * Construct a polygon from a LWLINE being
+ * the shell and an array of LWLINE (possibly NULL) being holes.
+ * Pointarrays from intput geoms are cloned.
+ * SRID must be the same for each input line.
+ * Input lines must have at least 4 points, and be closed.
+ */
+LWPOLY *
+lwpoly_from_lwlines(const LWLINE *shell,
+	unsigned int nholes, const LWLINE **holes)
+{
+	unsigned int nrings;
+	POINTARRAY **rings = lwalloc((nholes+1)*sizeof(POINTARRAY *));
+	int SRID = shell->SRID;
+	LWPOLY *ret;
+
+	if ( shell->points->npoints < 4 )
+		lwerror("lwpoly_from_lwlines: shell must have at least 4 points");
+	if ( ! ptarray_isclosed2d(shell->points) )
+		lwerror("lwpoly_from_lwlines: shell must be closed");
+	rings[0] = ptarray_clone(shell->points);
+
+	for (nrings=1; nrings<=nholes; nrings++)
+	{
+		const LWLINE *hole = holes[nrings-1];
+
+		if ( hole->SRID != SRID )
+			lwerror("lwpoly_from_lwlines: mixed SRIDs in input lines");
+
+		if ( hole->points->npoints < 4 )
+			lwerror("lwpoly_from_lwlines: holes must have at least 4 points");
+		if ( ! ptarray_isclosed2d(hole->points) )
+			lwerror("lwpoly_from_lwlines: holes must be closed");
+
+		rings[nrings] = ptarray_clone(hole->points);
+	}
+
+	ret = lwpoly_construct(SRID, NULL, nrings, rings);
+	return ret;
+}

Added: trunk/liblwgeom/lwutil.c
===================================================================
--- trunk/liblwgeom/lwutil.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/lwutil.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,274 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+/* Global variables */
+#include "../postgis_config.h"
+#include "liblwgeom.h"
+
+void *init_allocator(size_t size);
+void init_freeor(void *mem);
+void *init_reallocator(void *mem, size_t size);
+void init_noticereporter(const char *fmt, ...);
+void init_errorreporter(const char *fmt, ...);
+
+lwallocator lwalloc_var = init_allocator;
+lwreallocator lwrealloc_var = init_reallocator;
+lwfreeor lwfree_var = init_freeor;
+lwreporter lwerror = init_errorreporter;
+lwreporter lwnotice = init_noticereporter;
+
+static char *lwgeomTypeName[] = {
+	"Unknown",
+	"Point",
+	"Line",
+	"Polygon",
+	"MultiPoint",
+	"MultiLine",
+	"MultiPolygon",
+	"GeometryCollection",
+        "Curve",
+        "CompoundString",
+        "Invalid Type",  /* POINTTYPEI */
+        "Invalid Type",  /* LINETYPEI */
+        "Invalid Type",  /* POLYTYPEI */
+        "CurvePolygon",
+        "MultiCurve",
+        "MultiSurface"
+};
+
+
+/*
+ * Initialisation allocators
+ *
+ * These are used the first time any of the allocators are called
+ * to enable executables/libraries that link into liblwgeom to
+ * be able to set up their own allocators. This is mainly useful
+ * for older PostgreSQL versions that don't have functions that
+ * are called upon startup.
+ */
+
+void *
+init_allocator(size_t size)
+{
+	lwgeom_init_allocators();
+
+	return lwalloc_var(size);
+}
+
+void 
+init_freeor(void *mem)
+{
+	lwgeom_init_allocators();
+
+	lwfree_var(mem);
+}
+
+void *
+init_reallocator(void *mem, size_t size)
+{
+	lwgeom_init_allocators();
+
+	return lwrealloc_var(mem, size);
+}
+
+void
+init_noticereporter(const char *fmt, ...)
+{
+	va_list ap;
+
+	lwgeom_init_allocators();
+
+	va_start(ap, fmt);
+	lwnotice(fmt, ap);
+	va_end(ap);
+}
+	
+void
+init_errorreporter(const char *fmt, ...)
+{
+	va_list ap;
+
+	lwgeom_init_allocators();
+
+	va_start(ap, fmt);
+	lwerror(fmt, ap);
+	va_end(ap);
+}
+
+
+/*
+ * Default allocators
+ *
+ * We include some default allocators that use malloc/free/realloc
+ * along with stdout/stderr since this is the most common use case
+ *
+ */
+
+void *
+default_allocator(size_t size)
+{
+	void *mem = malloc(size);
+	return mem;
+}
+
+void
+default_freeor(void *mem)
+{
+	free(mem);
+}
+
+void *
+default_reallocator(void *mem, size_t size)
+{
+	void *ret = realloc(mem, size);
+	return ret;
+}
+
+void
+default_noticereporter(const char *fmt, ...)
+{
+	char *msg;
+	va_list ap;
+
+	va_start (ap, fmt);
+
+	/*
+	 * This is a GNU extension.
+	 * Dunno how to handle errors here.
+	 */
+	if (!vasprintf (&msg, fmt, ap))
+	{
+		va_end (ap);
+		return;
+	}
+	printf("%s\n", msg);
+	va_end(ap);
+	free(msg);
+}
+
+void
+default_errorreporter(const char *fmt, ...)
+{
+	char *msg;
+	va_list ap;
+
+	va_start (ap, fmt);
+
+	/*
+	 * This is a GNU extension.
+	 * Dunno how to handle errors here.
+	 */
+	if (!vasprintf (&msg, fmt, ap))
+	{
+		va_end (ap);
+		return;
+	}
+	fprintf(stderr, "%s\n", msg);
+	va_end(ap);
+	free(msg);
+	exit(1);
+}
+
+
+/*
+ * This function should be called from lwgeom_init_allocators() by programs
+ * which wish to use the default allocators above
+ */
+
+void lwgeom_install_default_allocators()
+{
+	lwalloc_var = default_allocator;
+	lwrealloc_var = default_reallocator;
+	lwfree_var = default_freeor;
+	lwerror = default_errorreporter;	
+	lwnotice = default_noticereporter;
+}
+ 
+
+const char *
+lwgeom_typename(int type)
+{
+	// something went wrong somewhere
+	if ( type < 0 || type > 12 ) {
+		// assert(0);
+		return "Invalid type";
+	}
+	return lwgeomTypeName[type];
+}
+
+void *
+lwalloc(size_t size)
+{
+	void *mem = lwalloc_var(size);
+	LWDEBUGF(5, "lwalloc: %d@%p", size, mem);
+	return mem;
+}
+
+void *
+lwrealloc(void *mem, size_t size)
+{
+	LWDEBUGF(5, "lwrealloc: %d@%p", size, mem);
+	return lwrealloc_var(mem, size);
+}
+
+void
+lwfree(void *mem)
+{
+	lwfree_var(mem);
+}
+
+/*
+ * Removes trailing zeros and dot for a %f formatted number.
+ * Modifies input.
+ */
+void
+trim_trailing_zeros(char *str)
+{
+	char *ptr, *totrim=NULL;
+	int len;
+	int i;
+
+	LWDEBUGF(3, "input: %s", str);
+	
+	ptr = strchr(str, '.');
+	if ( ! ptr ) return; /* no dot, no decimal digits */
+
+	LWDEBUGF(3, "ptr: %s", ptr);
+
+	len = strlen(ptr);
+	for (i=len-1; i; i--)
+	{
+		if ( ptr[i] != '0' ) break;
+		totrim=&ptr[i];
+	}
+	if ( totrim )
+	{
+		if ( ptr == totrim-1 ) *ptr = '\0';
+		else *totrim = '\0';
+	}
+	
+	LWDEBUGF(3, "output: %s", str);
+}
+
+char
+getMachineEndian(void)
+{
+	static int endian_check_int = 1; /* dont modify this!!! */
+
+	return *((char *) &endian_check_int); /* 0 = big endian | xdr,
+					       * 1 = little endian | ndr
+	                                       */
+}
+
+
+void
+errorIfSRIDMismatch(int srid1, int srid2)
+{
+	if ( srid1 != srid2 )
+	{
+		lwerror("Operation on mixed SRID geometries");
+	}
+}

Added: trunk/liblwgeom/measures.c
===================================================================
--- trunk/liblwgeom/measures.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/measures.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,845 @@
+/**********************************************************************
+ * $Id: measures.c 2797 2008-05-31 09:56:44Z mcayland $
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+#include <math.h>
+#include <string.h>
+
+#include "liblwgeom.h"
+
+
+/*
+ * pt_in_ring_2d(): crossing number test for a point in a polygon
+ *      input:   p = a point,
+ *               pa = vertex points of a ring V[n+1] with V[n]=V[0]
+ *      returns: 0 = outside, 1 = inside
+ *
+ *	Our polygons have first and last point the same,
+ *
+ */
+int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring)
+{
+	int cn = 0;    /* the crossing number counter */
+	int i;
+	POINT2D v1, v2;
+
+#if INTEGRITY_CHECKS
+	POINT2D first, last;
+
+	getPoint2d_p(ring, 0, &first);
+	getPoint2d_p(ring, ring->npoints-1, &last);
+	if ( memcmp(&first, &last, sizeof(POINT2D)) )
+	{
+		lwerror("pt_in_ring_2d: V[n] != V[0] (%g %g != %g %g)",
+			first.x, first.y, last.x, last.y);
+			
+	}
+#endif
+
+	LWDEBUGF(2, "pt_in_ring_2d called with point: %g %g", p->x, p->y);
+	/* printPA(ring); */
+
+	/* loop through all edges of the polygon */
+	getPoint2d_p(ring, 0, &v1);
+    	for (i=0; i<ring->npoints-1; i++)
+	{   
+		double vt;
+		getPoint2d_p(ring, i+1, &v2);
+
+		/* edge from vertex i to vertex i+1 */
+       		if
+		(
+			/* an upward crossing */
+			((v1.y <= p->y) && (v2.y > p->y))
+			/* a downward crossing */
+       		 	|| ((v1.y > p->y) && (v2.y <= p->y))
+		)
+	 	{
+
+			vt = (double)(p->y - v1.y) / (v2.y - v1.y);
+
+			/* P.x <intersect */
+			if (p->x < v1.x + vt * (v2.x - v1.x))
+			{
+				/* a valid crossing of y=p.y right of p.x */
+           	     		++cn;
+			}
+		}
+		v1 = v2;
+	}
+
+	LWDEBUGF(3, "pt_in_ring_2d returning %d", cn&1);
+
+	return (cn&1);    /* 0 if even (out), and 1 if odd (in) */
+}
+
+double distance2d_pt_pt(POINT2D *p1, POINT2D *p2)
+{
+	double hside = p2->x - p1->x;
+	double vside = p2->y - p1->y;
+
+	return sqrt ( hside*hside + vside*vside );
+
+	/* the above is more readable
+	   return sqrt(
+	  	(p2->x-p1->x) * (p2->x-p1->x) + (p2->y-p1->y) * (p2->y-p1->y)
+		);  */
+}
+
+/*distance2d from p to line A->B */
+double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B)
+{
+	double	r,s;
+
+	/*if start==end, then use pt distance */
+	if (  ( A->x == B->x) && (A->y == B->y) )
+		return distance2d_pt_pt(p,A);
+
+	/*
+	 * otherwise, we use comp.graphics.algorithms
+	 * Frequently Asked Questions method
+	 *
+	 *  (1)     	      AC dot AB
+         *         r = ---------
+         *               ||AB||^2
+	 *	r has the following meaning:
+	 *	r=0 P = A
+	 *	r=1 P = B
+	 *	r<0 P is on the backward extension of AB
+	 *	r>1 P is on the forward extension of AB
+	 *	0<r<1 P is interior to AB
+	 */
+
+	r = ( (p->x-A->x) * (B->x-A->x) + (p->y-A->y) * (B->y-A->y) )/( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
+
+	if (r<0) return distance2d_pt_pt(p,A);
+	if (r>1) return distance2d_pt_pt(p,B);
+
+
+	/*
+	 * (2)
+	 *	     (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
+	 *	s = -----------------------------
+	 *	             	L^2
+	 *
+	 *	Then the distance from C to P = |s|*L.
+	 *
+	 */
+
+	s = ( (A->y-p->y)*(B->x-A->x)- (A->x-p->x)*(B->y-A->y) ) /
+		( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
+
+	return LW_ABS(s) * sqrt(
+		(B->x-A->x)*(B->x-A->x) + (B->y-A->y)*(B->y-A->y)
+		);
+}
+
+/* find the minimum 2d distance from AB to CD */
+double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D)
+{
+
+	double	s_top, s_bot,s;
+	double	r_top, r_bot,r;
+
+	LWDEBUGF(2, "distance2d_seg_seg [%g,%g]->[%g,%g] by [%g,%g]->[%g,%g]",
+		A->x,A->y,B->x,B->y, C->x,C->y, D->x, D->y);
+
+
+	/*A and B are the same point */
+	if (  ( A->x == B->x) && (A->y == B->y) )
+		return distance2d_pt_seg(A,C,D);
+
+		/*U and V are the same point */
+
+	if (  ( C->x == D->x) && (C->y == D->y) )
+		return distance2d_pt_seg(D,A,B);
+
+	/* AB and CD are line segments */
+	/* from comp.graphics.algo
+
+	Solving the above for r and s yields
+				(Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy)
+	           r = ----------------------------- (eqn 1)
+				(Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
+
+		 	(Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
+		s = ----------------------------- (eqn 2)
+			(Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
+	Let P be the position vector of the intersection point, then
+		P=A+r(B-A) or
+		Px=Ax+r(Bx-Ax)
+		Py=Ay+r(By-Ay)
+	By examining the values of r & s, you can also determine some other limiting conditions:
+		If 0<=r<=1 & 0<=s<=1, intersection exists
+		r<0 or r>1 or s<0 or s>1 line segments do not intersect
+		If the denominator in eqn 1 is zero, AB & CD are parallel
+		If the numerator in eqn 1 is also zero, AB & CD are collinear.
+
+	*/
+	r_top = (A->y-C->y)*(D->x-C->x) - (A->x-C->x)*(D->y-C->y) ;
+	r_bot = (B->x-A->x)*(D->y-C->y) - (B->y-A->y)*(D->x-C->x) ;
+
+	s_top = (A->y-C->y)*(B->x-A->x) - (A->x-C->x)*(B->y-A->y);
+	s_bot = (B->x-A->x)*(D->y-C->y) - (B->y-A->y)*(D->x-C->x);
+
+	if  ( (r_bot==0) || (s_bot == 0) )
+	{
+		return (
+			LW_MIN(distance2d_pt_seg(A,C,D),
+				LW_MIN(distance2d_pt_seg(B,C,D),
+					LW_MIN(distance2d_pt_seg(C,A,B),
+						distance2d_pt_seg(D,A,B))
+				)
+			)
+		);
+	}
+	s = s_top/s_bot;
+	r=  r_top/r_bot;
+
+	if ((r<0) || (r>1) || (s<0) || (s>1) )
+	{
+		/*no intersection */
+		return (
+			LW_MIN(distance2d_pt_seg(A,C,D),
+				LW_MIN(distance2d_pt_seg(B,C,D),
+					LW_MIN(distance2d_pt_seg(C,A,B),
+						distance2d_pt_seg(D,A,B))
+				)
+			)
+		);
+
+	}
+	else
+		return -0; /*intersection exists */
+
+}
+
+/*
+ * search all the segments of pointarray to see which one is closest to p1
+ * Returns minimum distance between point and pointarray
+ */
+double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa)
+{
+	double result = 0;
+	int t;
+	POINT2D	start, end;
+
+	getPoint2d_p(pa, 0, &start);
+
+	for (t=1; t<pa->npoints; t++)
+	{
+		double dist;
+		getPoint2d_p(pa, t, &end);
+		dist = distance2d_pt_seg(p, &start, &end);
+		if (t==1) result = dist;
+		else result = LW_MIN(result, dist);
+
+		if ( result == 0 ) return 0;
+
+		start = end;
+	}
+
+	return result;
+}
+
+/* test each segment of l1 against each segment of l2.  Return min */
+double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2)
+{
+	double 	result = 99999999999.9;
+	char result_okay = 0; /*result is a valid min */
+	int t,u;
+	POINT2D	start, end;
+	POINT2D	start2, end2;
+
+	LWDEBUGF(2, "distance2d_ptarray_ptarray called (points: %d-%d)",
+			l1->npoints, l2->npoints);
+
+	getPoint2d_p(l1, 0, &start);
+	for (t=1; t<l1->npoints; t++) /*for each segment in L1 */
+	{
+		getPoint2d_p(l1, t, &end);
+
+		getPoint2d_p(l2, 0, &start2);
+		for (u=1; u<l2->npoints; u++) /*for each segment in L2 */
+		{
+			double dist;
+
+			getPoint2d_p(l2, u, &end2);
+
+			dist = distance2d_seg_seg(&start, &end, &start2, &end2);
+
+			LWDEBUGF(4, "line_line; seg %i * seg %i, dist = %g\n",t,u,dist);
+
+			if (result_okay)
+				result = LW_MIN(result,dist);
+			else
+			{
+				result_okay = 1;
+				result = dist;
+			}
+
+			LWDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f",
+				t, u, dist, result);
+
+			if (result <= 0) return 0; /*intersection */
+
+			start2 = end2;
+		}
+		start = end;
+	}
+
+	return result;
+}
+
+/* true if point is in poly (and not in its holes) */
+int pt_in_poly_2d(POINT2D *p, LWPOLY *poly)
+{
+	int i;
+
+	/* Not in outer ring */
+	if ( ! pt_in_ring_2d(p, poly->rings[0]) ) return 0;
+
+	/* Check holes */
+	for (i=1; i<poly->nrings; i++)
+	{
+		/* Inside a hole */
+		if ( pt_in_ring_2d(p, poly->rings[i]) ) return 0;
+	}
+
+	return 1; /* In outer ring, not in holes */
+}
+
+/*
+ * Brute force.
+ * Test line-ring distance against each ring.
+ * If there's an intersection (distance==0) then return 0 (crosses boundary).
+ * Otherwise, test to see if any point is inside outer rings of polygon,
+ * but not in inner rings.
+ * If so, return 0  (line inside polygon),
+ * otherwise return min distance to a ring (could be outside
+ * polygon or inside a hole)
+ */
+double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly)
+{
+	POINT2D pt;
+	int i;
+	double mindist = 0;
+
+	LWDEBUGF(2, "distance2d_ptarray_poly called (%d rings)", poly->nrings);
+
+	for (i=0; i<poly->nrings; i++)
+	{
+		double dist = distance2d_ptarray_ptarray(pa, poly->rings[i]);
+		if (i) mindist = LW_MIN(mindist, dist);
+		else mindist = dist;
+
+		LWDEBUGF(3, " distance from ring %d: %f, mindist: %f",
+			i, dist, mindist);
+
+		if ( mindist <= 0 ) return 0.0; /* intersection */
+	}
+
+	/*
+	 * No intersection, have to check if a point is
+	 * inside polygon
+	 */
+	getPoint2d_p(pa, 0, &pt);
+
+	/*
+	 * Outside outer ring, so min distance to a ring
+	 * is the actual min distance
+	 */
+	if ( ! pt_in_ring_2d(&pt, poly->rings[0]) ) return mindist;
+
+
+	/*
+	 * Its in the outer ring.
+	 * Have to check if its inside a hole
+	 */
+	for (i=1; i<poly->nrings; i++)
+	{
+		if ( pt_in_ring_2d(&pt, poly->rings[i]) )
+		{
+			/*
+			 * Its inside a hole, then the actual
+			 * distance is the min ring distance
+			 */
+			return mindist;
+		}
+	}
+
+	return 0.0; /* Not in hole, so inside polygon */
+}
+
+double distance2d_point_point(LWPOINT *point1, LWPOINT *point2)
+{
+	POINT2D p1;
+	POINT2D p2;
+
+	getPoint2d_p(point1->point, 0, &p1);
+	getPoint2d_p(point2->point, 0, &p2);
+
+	return distance2d_pt_pt(&p1, &p2);
+}
+
+double distance2d_point_line(LWPOINT *point, LWLINE *line)
+{
+	POINT2D p;
+	POINTARRAY *pa = line->points;
+	getPoint2d_p(point->point, 0, &p);
+	return distance2d_pt_ptarray(&p, pa);
+}
+
+double distance2d_line_line(LWLINE *line1, LWLINE *line2)
+{
+	POINTARRAY *pa1 = line1->points;
+	POINTARRAY *pa2 = line2->points;
+	return distance2d_ptarray_ptarray(pa1, pa2);
+}
+
+/*
+ * 1. see if pt in outer boundary. if no, then treat the outer ring like a line
+ * 2. if in the boundary, test to see if its in a hole.
+ *    if so, then return dist to hole, else return 0 (point in polygon)
+ */
+double distance2d_point_poly(LWPOINT *point, LWPOLY *poly)
+{
+	POINT2D p;
+	int i;
+
+	getPoint2d_p(point->point, 0, &p);
+
+	LWDEBUG(2, "distance2d_point_poly called");
+
+	/* Return distance to outer ring if not inside it */
+	if ( ! pt_in_ring_2d(&p, poly->rings[0]) )
+	{
+		LWDEBUG(3, " not inside outer-ring");
+
+		return distance2d_pt_ptarray(&p, poly->rings[0]);
+	}
+
+	/*
+	 * Inside the outer ring.
+	 * Scan though each of the inner rings looking to
+	 * see if its inside.  If not, distance==0.
+	 * Otherwise, distance = pt to ring distance
+	 */
+	for (i=1; i<poly->nrings; i++) 
+	{
+		/* Inside a hole. Distance = pt -> ring */
+		if ( pt_in_ring_2d(&p, poly->rings[i]) )
+		{
+			LWDEBUG(3, " inside an hole");
+
+			return distance2d_pt_ptarray(&p, poly->rings[i]);
+		}
+	}
+
+	LWDEBUG(3, " inside the polygon");
+
+	return 0.0; /* Is inside the polygon */
+}
+
+/*
+ * Brute force.
+ * Test to see if any rings intersect.
+ * If yes, dist=0.
+ * Test to see if one inside the other and if they are inside holes.
+ * Find min distance ring-to-ring.
+ */
+double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2)
+{
+	POINT2D pt;
+	double mindist = -1;
+	int i;
+
+	LWDEBUG(2, "distance2d_poly_poly called");
+
+	/* if poly1 inside poly2 return 0 */
+	getPoint2d_p(poly1->rings[0], 0, &pt);
+	if ( pt_in_poly_2d(&pt, poly2) ) return 0.0;  
+
+	/* if poly2 inside poly1 return 0 */
+	getPoint2d_p(poly2->rings[0], 0, &pt);
+	if ( pt_in_poly_2d(&pt, poly1) ) return 0.0;  
+
+	LWDEBUG(3, "  polys not inside each other");
+
+	/*
+	 * foreach ring in Poly1
+	 * foreach ring in Poly2
+	 *   if intersect, return 0
+	 */
+	for (i=0; i<poly1->nrings; i++)
+	{
+		int j;
+		for (j=0; j<poly2->nrings; j++)
+		{
+			double d = distance2d_ptarray_ptarray(poly1->rings[i],
+				poly2->rings[j]);
+			if ( d <= 0 ) return 0.0;
+
+			/* mindist is -1 when not yet set */
+			if (mindist > -1) mindist = LW_MIN(mindist, d);
+			else mindist = d;
+
+			LWDEBUGF(3, "  ring%i-%i dist: %f, mindist: %f", i, j, d, mindist);
+		}
+
+	}
+
+	/* otherwise return closest approach of rings (no intersection) */
+	return mindist;
+
+}
+
+double distance2d_line_poly(LWLINE *line, LWPOLY *poly)
+{
+	return distance2d_ptarray_poly(line->points, poly);
+}
+
+
+/*find the 2d length of the given POINTARRAY (even if it's 3d) */
+double lwgeom_pointarray_length2d(POINTARRAY *pts)
+{
+	double dist = 0.0;
+	int i;
+	POINT2D frm;
+	POINT2D to;
+
+	if ( pts->npoints < 2 ) return 0.0;
+	for (i=0; i<pts->npoints-1;i++)
+	{
+		getPoint2d_p(pts, i, &frm);
+		getPoint2d_p(pts, i+1, &to);
+		dist += sqrt( ( (frm.x - to.x)*(frm.x - to.x) )  +
+				((frm.y - to.y)*(frm.y - to.y) ) );
+	}
+	return dist;
+}
+
+/*
+ * Find the 3d/2d length of the given POINTARRAY
+ * (depending on its dimensions)
+ */
+double
+lwgeom_pointarray_length(POINTARRAY *pts)
+{
+	double dist = 0.0;
+	int i;
+	POINT3DZ frm;
+	POINT3DZ to;
+
+	if ( pts->npoints < 2 ) return 0.0;
+
+	/* compute 2d length if 3d is not available */
+	if ( ! TYPE_HASZ(pts->dims) ) return lwgeom_pointarray_length2d(pts);
+
+	for (i=0; i<pts->npoints-1;i++)
+	{
+		getPoint3dz_p(pts, i, &frm);
+		getPoint3dz_p(pts, i+1, &to);
+		dist += sqrt( ( (frm.x - to.x)*(frm.x - to.x) )  +
+				((frm.y - to.y)*(frm.y - to.y) ) +
+				((frm.z - to.z)*(frm.z - to.z) ) );
+	}
+
+	return dist;
+}
+
+/*
+ * This should be rewritten to make use of the curve itself.
+ */
+double
+lwgeom_curvepolygon_area(LWCURVEPOLY *curvepoly)
+{
+        LWPOLY *poly = (LWPOLY *)lwgeom_segmentize((LWGEOM *)curvepoly, 32);
+        return lwgeom_polygon_area(poly);
+}
+
+/*
+ * Find the area of the outer ring - sum (area of inner rings).
+ * Could use a more numerically stable calculator...
+ */
+double
+lwgeom_polygon_area(LWPOLY *poly)
+{
+	double poly_area=0.0;
+	int i;
+	POINT2D p1;
+	POINT2D p2;
+
+	LWDEBUGF(2, "in lwgeom_polygon_area (%d rings)", poly->nrings);
+
+	for (i=0; i<poly->nrings; i++)
+	{
+		int j;
+		POINTARRAY *ring = poly->rings[i];
+		double ringarea = 0.0;
+
+		LWDEBUGF(4, " rings %d has %d points", i, ring->npoints);
+
+		for (j=0; j<ring->npoints-1; j++)
+    		{
+			getPoint2d_p(ring, j, &p1);
+			getPoint2d_p(ring, j+1, &p2);
+			ringarea += ( p1.x * p2.y ) - ( p1.y * p2.x );
+		}
+
+		ringarea  /= 2.0;
+
+		LWDEBUGF(4, " ring 1 has area %lf",ringarea);
+
+		ringarea  = fabs(ringarea);
+		if (i != 0)	/*outer */
+			ringarea  = -1.0*ringarea ; /* its a hole */
+
+		poly_area += ringarea;
+	}
+
+	return poly_area;
+}
+
+/*
+ * Compute the sum of polygon rings length.
+ * Could use a more numerically stable calculator...
+ */
+double lwgeom_polygon_perimeter(LWPOLY *poly)
+{
+	double result=0.0;
+	int i;
+
+	LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
+
+	for (i=0; i<poly->nrings; i++)
+		result += lwgeom_pointarray_length(poly->rings[i]);
+
+	return result;
+}
+
+/*
+ * Compute the sum of polygon rings length (forcing 2d computation).
+ * Could use a more numerically stable calculator...
+ */
+double lwgeom_polygon_perimeter2d(LWPOLY *poly)
+{
+	double result=0.0;
+	int i;
+
+	LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
+
+	for (i=0; i<poly->nrings; i++)
+		result += lwgeom_pointarray_length2d(poly->rings[i]);
+
+	return result;
+}
+
+double
+lwgeom_mindistance2d_recursive(uchar *lw1, uchar *lw2)
+{
+  return lwgeom_mindistance2d_recursive_tolerance( lw1, lw2, 0.0 );
+}
+
+double
+lwgeom_mindistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance)
+{
+	LWGEOM_INSPECTED *in1, *in2;
+	int i, j;
+	double mindist = -1;
+
+	in1 = lwgeom_inspect(lw1);
+	in2 = lwgeom_inspect(lw2);
+
+	for (i=0; i<in1->ngeometries; i++)
+	{
+		uchar *g1 = lwgeom_getsubgeometry_inspected(in1, i);
+		int t1 = lwgeom_getType(g1[0]);
+		double dist=tolerance;
+
+		/* it's a multitype... recurse */
+		if ( t1 >= 4 )
+		{
+			dist = lwgeom_mindistance2d_recursive_tolerance(g1, lw2, tolerance);
+			if ( dist <= tolerance ) return tolerance; /* can't be closer */
+			if ( mindist == -1 ) mindist = dist;
+			else mindist = LW_MIN(dist, mindist);
+			continue;
+		}
+
+		for (j=0; j<in2->ngeometries; j++)
+		{
+			uchar *g2 = lwgeom_getsubgeometry_inspected(in2, j);
+			int t2 = lwgeom_getType(g2[0]);
+
+			if  ( t1 == POINTTYPE )
+			{
+				if  ( t2 == POINTTYPE )
+				{
+					dist = distance2d_point_point(
+						lwpoint_deserialize(g1),
+						lwpoint_deserialize(g2)
+					);
+				}
+				else if  ( t2 == LINETYPE )
+				{
+					dist = distance2d_point_line(
+						lwpoint_deserialize(g1),
+						lwline_deserialize(g2)
+					);
+				}
+				else if  ( t2 == POLYGONTYPE )
+				{
+					dist = distance2d_point_poly(
+						lwpoint_deserialize(g1),
+						lwpoly_deserialize(g2)
+					);
+				}
+			}
+			else if ( t1 == LINETYPE )
+			{
+				if ( t2 == POINTTYPE )
+				{
+					dist = distance2d_point_line(
+						lwpoint_deserialize(g2),
+						lwline_deserialize(g1)
+					);
+				}
+				else if ( t2 == LINETYPE )
+				{
+					dist = distance2d_line_line(
+						lwline_deserialize(g1),
+						lwline_deserialize(g2)
+					);
+				}
+				else if ( t2 == POLYGONTYPE )
+				{
+					dist = distance2d_line_poly(
+						lwline_deserialize(g1),
+						lwpoly_deserialize(g2)
+					);
+				}
+			}
+			else if ( t1 == POLYGONTYPE )
+			{
+				if ( t2 == POLYGONTYPE )
+				{
+					dist = distance2d_poly_poly(
+						lwpoly_deserialize(g2),
+						lwpoly_deserialize(g1)
+					);
+				}
+				else if ( t2 == POINTTYPE )
+				{
+					dist = distance2d_point_poly(
+						lwpoint_deserialize(g2),
+						lwpoly_deserialize(g1)
+					);
+				}
+				else if ( t2 == LINETYPE )
+				{
+					dist = distance2d_line_poly(
+						lwline_deserialize(g2),
+						lwpoly_deserialize(g1)
+					);
+				}
+			}
+			else /* it's a multitype... recurse */
+			{
+				dist = lwgeom_mindistance2d_recursive_tolerance(g1, g2, tolerance);
+			}
+
+			if (mindist == -1 ) mindist = dist;
+			else mindist = LW_MIN(dist, mindist);
+
+			LWDEBUGF(3, "dist %d-%d: %f - mindist: %f",
+				i, j, dist, mindist);
+
+
+			if (mindist <= tolerance) return tolerance; /* can't be closer */
+
+		}
+
+	}
+
+	if (mindist<0) mindist = 0; 
+
+	return mindist;
+}
+
+
+
+int
+lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad)
+{
+	POINT2D center;
+
+	center.x = cx;
+	center.y = cy;
+
+	if ( distance2d_pt_pt(p, &center) < rad ) return 1;
+	else return 0;
+
+}
+
+/*
+ * Compute the azimuth of segment AB in radians.
+ * Return 0 on exception (same point), 1 otherwise.
+ */
+int
+azimuth_pt_pt(POINT2D *A, POINT2D *B, double *d)
+{
+	if ( A->x == B->x )
+	{
+		if ( A->y < B->y ) *d=0.0;
+		else if ( A->y > B->y ) *d=M_PI; 
+		else return 0;
+		return 1;
+	}
+
+	if ( A->y == B->y )
+	{
+		if ( A->x < B->x ) *d=M_PI/2; 
+		else if ( A->x > B->x ) *d=M_PI+(M_PI/2);
+		else return 0;
+		return 1;
+	}
+
+	if ( A->x < B->x )
+	{
+		if ( A->y < B->y )
+		{
+			*d=atan(fabs(A->x - B->x) / fabs(A->y - B->y) );
+		}
+		else /* ( A->y > B->y )  - equality case handled above */
+		{
+			*d=atan(fabs(A->y - B->y) / fabs(A->x - B->x) )
+				+ (M_PI/2);
+		}
+	}
+
+	else /* ( A->x > B->x ) - equality case handled above */
+	{
+		if ( A->y > B->y )
+		{
+			*d=atan(fabs(A->x - B->x) / fabs(A->y - B->y) )
+				+ M_PI;
+		}
+		else /* ( A->y < B->y )  - equality case handled above */
+		{
+			*d=atan(fabs(A->y - B->y) / fabs(A->x - B->x) )
+				+ (M_PI+(M_PI/2));
+		}
+	}
+
+	return 1;
+}
+

Added: trunk/liblwgeom/ptarray.c
===================================================================
--- trunk/liblwgeom/ptarray.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/ptarray.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,836 @@
+/**********************************************************************
+ * $Id: ptarray.c 2797 2008-05-31 09:56:44Z mcayland $
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ * 
+ **********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "liblwgeom.h"
+
+
+POINTARRAY *
+ptarray_construct(char hasz, char hasm, unsigned int npoints)
+{
+	uchar dims = 0;
+	size_t size; 
+	uchar *ptlist;
+	POINTARRAY *pa;
+	
+	TYPE_SETZM(dims, hasz?1:0, hasm?1:0);
+	size = TYPE_NDIMS(dims)*npoints*sizeof(double);
+
+	ptlist = (uchar *)lwalloc(size);
+	pa = lwalloc(sizeof(POINTARRAY));
+	pa->dims = dims;
+	pa->serialized_pointlist = ptlist;
+	pa->npoints = npoints;
+
+	return pa;
+
+}
+
+void
+ptarray_reverse(POINTARRAY *pa)
+{
+	POINT4D pbuf;
+	uint32 i;
+	int ptsize = pointArray_ptsize(pa);
+	int last = pa->npoints-1;
+	int mid = last/2;
+
+	for (i=0; i<=mid; i++)
+	{
+		uchar *from, *to;
+		from = getPoint_internal(pa, i);
+		to = getPoint_internal(pa, (last-i));
+		memcpy((uchar *)&pbuf, to, ptsize);
+		memcpy(to, from, ptsize);
+		memcpy(from, (uchar *)&pbuf, ptsize);
+	}
+
+}
+
+/*
+ * calculate the 2d bounding box of a set of points
+ * write result to the provided BOX2DFLOAT4
+ * Return 0 if bounding box is NULL (empty geom)
+ */
+int
+ptarray_compute_box2d_p(const POINTARRAY *pa, BOX2DFLOAT4 *result)
+{
+	int t;
+	POINT2D pt;
+	BOX3D box;
+
+	if (pa->npoints == 0) return 0;
+
+	getPoint2d_p(pa, 0, &pt);
+
+	box.xmin = pt.x;
+	box.xmax = pt.x;
+	box.ymin = pt.y;
+	box.ymax = pt.y;
+
+	for (t=1; t<pa->npoints; t++)
+	{
+		getPoint2d_p(pa, t, &pt);
+		if (pt.x < box.xmin) box.xmin = pt.x;
+		if (pt.y < box.ymin) box.ymin = pt.y;
+		if (pt.x > box.xmax) box.xmax = pt.x;
+		if (pt.y > box.ymax) box.ymax = pt.y;
+	}
+
+	box3d_to_box2df_p(&box, result);
+
+	return 1;
+}
+
+/*
+ * Calculate the 2d bounding box of a set of points.
+ * Return allocated BOX2DFLOAT4 or NULL (for empty array).
+ */
+BOX2DFLOAT4 *
+ptarray_compute_box2d(const POINTARRAY *pa)
+{
+	int t;
+	POINT2D pt;
+	BOX2DFLOAT4 *result;
+
+	if (pa->npoints == 0) return NULL;
+
+	result = lwalloc(sizeof(BOX2DFLOAT4));
+
+	getPoint2d_p(pa, 0, &pt);
+
+	result->xmin = pt.x;
+	result->xmax = pt.x;
+	result->ymin = pt.y;
+	result->ymax = pt.y;
+
+	for (t=1;t<pa->npoints;t++)
+	{
+		getPoint2d_p(pa, t, &pt);
+		if (pt.x < result->xmin) result->xmin = pt.x;
+		if (pt.y < result->ymin) result->ymin = pt.y;
+		if (pt.x > result->xmax) result->xmax = pt.x;
+		if (pt.y > result->ymax) result->ymax = pt.y;
+	}
+
+	return result;
+}
+
+/*
+ * Returns a modified POINTARRAY so that no segment is 
+ * longer then the given distance (computed using 2d).
+ * Every input point is kept.
+ * Z and M values for added points (if needed) are set to 0.
+ */
+POINTARRAY *
+ptarray_segmentize2d(POINTARRAY *ipa, double dist)
+{
+	double	segdist;
+	POINT4D	p1, p2;
+	void *ip, *op;
+	POINT4D pbuf;
+	POINTARRAY *opa;
+	int maxpoints = ipa->npoints;
+	int ptsize = pointArray_ptsize(ipa);
+	int ipoff=0; /* input point offset */
+
+	pbuf.x = pbuf.y = pbuf.z = pbuf.m = 0;
+
+	/* Initial storage */
+	opa = (POINTARRAY *)lwalloc(ptsize * maxpoints);
+	opa->dims = ipa->dims;
+	opa->npoints = 0;
+	opa->serialized_pointlist = (uchar *)lwalloc(maxpoints*ptsize);
+
+	/* Add first point */
+	opa->npoints++;
+	getPoint4d_p(ipa, ipoff, &p1);
+	op = getPoint_internal(opa, opa->npoints-1);
+	memcpy(op, &p1, ptsize); 
+	ipoff++;
+
+	while (ipoff<ipa->npoints)
+	{
+		/*
+		 * We use these pointers to avoid
+		 * "strict-aliasing rules break" warning raised
+		 * by gcc (3.3 and up).
+		 *
+		 * It looks that casting a variable address (also
+		 * referred to as "type-punned pointer")
+		 * breaks those "strict" rules.
+		 *
+		 */
+		POINT4D *p1ptr=&p1, *p2ptr=&p2;
+
+		getPoint4d_p(ipa, ipoff, &p2);
+
+		segdist = distance2d_pt_pt((POINT2D *)p1ptr, (POINT2D *)p2ptr);
+
+		if (segdist > dist) /* add an intermediate point */
+		{
+			pbuf.x = p1.x + (p2.x-p1.x)/segdist * dist;
+			pbuf.y = p1.y + (p2.y-p1.y)/segdist * dist;
+			/* might also compute z and m if available... */
+			ip = &pbuf;
+			memcpy(&p1, ip, ptsize);
+		}
+		else /* copy second point */
+		{
+			ip = &p2;
+			p1 = p2;
+			ipoff++;
+		}
+
+		/* Add point */
+		if ( ++(opa->npoints) > maxpoints ) {
+			maxpoints *= 1.5;
+			opa->serialized_pointlist = (uchar *)lwrealloc(
+				opa->serialized_pointlist,
+				maxpoints*ptsize
+			);
+		}
+		op = getPoint_internal(opa, opa->npoints-1);
+		memcpy(op, ip, ptsize); 
+	}
+
+	return opa;
+}
+
+char
+ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2)
+{
+	unsigned int i;
+	size_t ptsize;
+
+	if ( TYPE_GETZM(pa1->dims) != TYPE_GETZM(pa2->dims) ) return 0;
+
+	if ( pa1->npoints != pa2->npoints ) return 0;
+
+	ptsize = pointArray_ptsize(pa1);
+
+	for (i=0; i<pa1->npoints; i++)
+	{
+		if ( memcmp(getPoint_internal(pa1, i), getPoint_internal(pa2, i), ptsize) )
+			return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Add a point in a pointarray.
+ * 'where' is the offset (starting at 0)
+ * if 'where' == -1 append is required.
+ */
+POINTARRAY *
+ptarray_addPoint(POINTARRAY *pa, uchar *p, size_t pdims, unsigned int where)
+{
+	POINTARRAY *ret;
+	POINT4D pbuf;
+	size_t ptsize = pointArray_ptsize(pa);
+
+	LWDEBUGF(3, "pa %x p %x size %d where %d",
+		pa, p, pdims, where);
+
+	if ( pdims < 2 || pdims > 4 )
+	{
+		lwerror("ptarray_addPoint: point dimension out of range (%d)",
+			pdims);
+		return NULL;
+	}
+
+	if ( where > pa->npoints )
+	{
+		lwerror("ptarray_addPoint: offset out of range (%d)",
+			where);
+		return NULL;
+	}
+
+	LWDEBUG(3, "called with a %dD point");
+	
+	pbuf.x = pbuf.y = pbuf.z = pbuf.m = 0.0;
+	memcpy((uchar *)&pbuf, p, pdims*sizeof(double));
+
+	LWDEBUG(3, "initialized point buffer");
+
+	ret = ptarray_construct(TYPE_HASZ(pa->dims),
+		TYPE_HASM(pa->dims), pa->npoints+1);
+	
+	if ( where == -1 ) where = pa->npoints;
+
+	if ( where )
+	{
+		memcpy(getPoint_internal(ret, 0), getPoint_internal(pa, 0), ptsize*where);
+	}
+
+	memcpy(getPoint_internal(ret, where), (uchar *)&pbuf, ptsize);
+
+	if ( where+1 != ret->npoints )
+	{
+		memcpy(getPoint_internal(ret, where+1),
+			getPoint_internal(pa, where),
+			ptsize*(pa->npoints-where));
+	}
+
+	return ret;
+}
+
+/*
+ * Remove a point from a pointarray.
+ * 'which' is the offset (starting at 0)
+ * Returned pointarray is newly allocated
+ */
+POINTARRAY *
+ptarray_removePoint(POINTARRAY *pa, unsigned int which)
+{
+	POINTARRAY *ret;
+	size_t ptsize = pointArray_ptsize(pa);
+
+	LWDEBUGF(3, "pa %x which %d", pa, which);
+
+#if PARANOIA_LEVEL > 0
+	if ( which > pa->npoints-1 )
+	{
+		lwerror("ptarray_removePoint: offset (%d) out of range (%d..%d)",
+			which, 0, pa->npoints-1);
+		return NULL;
+	}
+
+	if ( pa->npoints < 3 )
+	{
+		lwerror("ptarray_removePointe: can't remove a point from a 2-vertex POINTARRAY");
+	}
+#endif
+
+	ret = ptarray_construct(TYPE_HASZ(pa->dims),
+		TYPE_HASM(pa->dims), pa->npoints-1);
+	
+	/* copy initial part */
+	if ( which )
+	{
+		memcpy(getPoint_internal(ret, 0), getPoint_internal(pa, 0), ptsize*which);
+	}
+
+	/* copy final part */
+	if ( which < pa->npoints-1 )
+	{
+		memcpy(getPoint_internal(ret, which), getPoint_internal(pa, which+1),
+			ptsize*(pa->npoints-which-1));
+	}
+
+	return ret;
+}
+
+/* 
+ * Clone a pointarray 
+ */
+POINTARRAY *
+ptarray_clone(const POINTARRAY *in)
+{
+	POINTARRAY *out = lwalloc(sizeof(POINTARRAY));
+	size_t size;
+
+        LWDEBUG(3, "ptarray_clone called.");
+
+	out->dims = in->dims;
+	out->npoints = in->npoints;
+
+	size = in->npoints*sizeof(double)*TYPE_NDIMS(in->dims);
+	out->serialized_pointlist = lwalloc(size);
+	memcpy(out->serialized_pointlist, in->serialized_pointlist, size);
+
+	return out;
+}
+
+int
+ptarray_isclosed2d(const POINTARRAY *in)
+{
+	if ( memcmp(getPoint_internal(in, 0), getPoint_internal(in, in->npoints-1), sizeof(POINT2D)) ) return 0;
+	return 1;
+}
+
+/*
+ * calculate the BOX3D bounding box of a set of points
+ * returns a lwalloced BOX3D, or NULL on empty array.
+ * zmin/zmax values are set to NO_Z_VALUE if not available.
+ */
+BOX3D *
+ptarray_compute_box3d(const POINTARRAY *pa)
+{
+	BOX3D *result = lwalloc(sizeof(BOX3D));
+
+	if ( ! ptarray_compute_box3d_p(pa, result) )
+	{
+		lwfree(result);
+		return NULL;
+	}
+
+	return result;
+}
+
+/*
+ * calculate the BOX3D bounding box of a set of points
+ * zmin/zmax values are set to NO_Z_VALUE if not available.
+ * write result to the provided BOX3D
+ * Return 0 if bounding box is NULL (empty geom)
+ */
+int
+ptarray_compute_box3d_p(const POINTARRAY *pa, BOX3D *result)
+{
+	int t;
+	POINT3DZ pt;
+
+	LWDEBUGF(3, "ptarray_compute_box3d call (array has %d points)", pa->npoints);
+	
+	if (pa->npoints == 0) return 0;
+
+	getPoint3dz_p(pa, 0, &pt);
+
+	LWDEBUG(3, "got point 0");
+
+	result->xmin = pt.x;
+	result->xmax = pt.x;
+	result->ymin = pt.y;
+	result->ymax = pt.y;
+
+	if ( TYPE_HASZ(pa->dims) ) {
+		result->zmin = pt.z;
+		result->zmax = pt.z;
+	} else {
+		result->zmin = NO_Z_VALUE;
+		result->zmax = NO_Z_VALUE;
+	}
+
+	LWDEBUGF(3, "scanning other %d points", pa->npoints);
+
+	for (t=1; t<pa->npoints; t++)
+	{
+		getPoint3dz_p(pa,t,&pt);
+		if (pt.x < result->xmin) result->xmin = pt.x;
+		if (pt.y < result->ymin) result->ymin = pt.y;
+		if (pt.x > result->xmax) result->xmax = pt.x;
+		if (pt.y > result->ymax) result->ymax = pt.y;
+
+		if ( TYPE_HASZ(pa->dims) ) {
+			if (pt.z > result->zmax) result->zmax = pt.z;
+			if (pt.z < result->zmin) result->zmin = pt.z;
+		}
+	}
+
+	LWDEBUG(3, "returning box");
+
+	return 1;
+}
+
+/*
+ * TODO: implement point interpolation
+ */
+POINTARRAY *
+ptarray_substring(POINTARRAY *ipa, double from, double to)
+{
+	DYNPTARRAY *dpa;
+	POINTARRAY *opa;
+	POINT4D pt;
+	POINT4D p1, p2;
+	POINT4D *p1ptr=&p1; /* don't break strict-aliasing rule */
+	POINT4D *p2ptr=&p2;
+	int nsegs, i;
+	double length, slength, tlength;
+	int state = 0; /* 0=before, 1=inside */
+
+	/*
+	 * Create a dynamic pointarray with an initial capacity
+	 * equal to full copy of input points
+	 */
+	dpa = dynptarray_create(ipa->npoints, ipa->dims);
+
+	/* Compute total line length */
+	length = lwgeom_pointarray_length2d(ipa);
+
+
+	LWDEBUGF(3, "Total length: %g", length);
+
+
+	/* Get 'from' and 'to' lengths */
+	from = length*from;
+	to = length*to;
+
+
+	LWDEBUGF(3, "From/To: %g/%g", from, to);
+
+
+	tlength = 0;
+	getPoint4d_p(ipa, 0, &p1);
+	nsegs = ipa->npoints - 1;
+	for( i = 0; i < nsegs; i++ )
+	{
+		double dseg;
+
+		getPoint4d_p(ipa, i+1, &p2);
+
+
+		LWDEBUGF(3 ,"Segment %d: (%g,%g,%g,%g)-(%g,%g,%g,%g)",
+			i, p1.x, p1.y, p1.z, p1.m, p2.x, p2.y, p2.z, p2.m);
+
+
+		/* Find the length of this segment */
+		slength = distance2d_pt_pt((POINT2D *)p1ptr, (POINT2D *)p2ptr);
+
+		/*
+		 * We are before requested start.
+		 */
+		if ( state == 0 ) /* before */
+		{
+
+			LWDEBUG(3, " Before start");
+
+			/*
+			 * Didn't reach the 'from' point,
+			 * nothing to do
+			 */
+			if ( from > tlength + slength ) goto END;
+
+			else if ( from == tlength + slength )
+			{
+
+				LWDEBUG(3, "  Second point is our start");
+
+				/*
+				 * Second point is our start
+				 */
+				dynptarray_addPoint4d(dpa, &p2, 1);
+				state=1; /* we're inside now */
+				goto END;
+			}
+
+			else if ( from == tlength )
+			{
+
+				LWDEBUG(3, "  First point is our start");
+
+				/*
+				 * First point is our start
+				 */
+				dynptarray_addPoint4d(dpa, &p1, 1);
+
+				/*
+				 * We're inside now, but will check
+				 * 'to' point as well
+				 */
+				state=1;
+			}
+
+			else  /* tlength < from < tlength+slength */
+			{
+
+				LWDEBUG(3, "  Seg contains first point");
+
+				/*
+				 * Our start is between first and
+				 * second point
+				 */
+				dseg = (from - tlength) / slength;
+				interpolate_point4d(&p1, &p2, &pt, dseg);
+
+				dynptarray_addPoint4d(dpa, &pt, 1);
+
+				/*
+				 * We're inside now, but will check
+				 * 'to' point as well
+				 */
+				state=1;
+			}
+		}
+
+		if ( state == 1 ) /* inside */
+		{
+
+			LWDEBUG(3, " Inside");
+
+			/*
+			 * Didn't reach the 'end' point,
+			 * just copy second point
+			 */
+			if ( to > tlength + slength ) 
+			{
+				dynptarray_addPoint4d(dpa, &p2, 0);
+				goto END;
+			}
+
+			/*
+			 * 'to' point is our second point.
+			 */
+			else if ( to == tlength + slength )
+			{
+
+				LWDEBUG(3, " Second point is our end");
+
+				dynptarray_addPoint4d(dpa, &p2, 0);
+				break; /* substring complete */
+			}
+
+			/*
+			 * 'to' point is our first point.
+			 * (should only happen if 'to' is 0)
+			 */
+			else if ( to == tlength )
+			{
+
+				LWDEBUG(3, " First point is our end");
+
+				dynptarray_addPoint4d(dpa, &p1, 0);
+
+				break; /* substring complete */
+			}
+
+			/*
+			 * 'to' point falls on this segment
+			 * Interpolate and break.
+			 */
+			else if ( to < tlength + slength )
+			{
+
+				LWDEBUG(3, " Seg contains our end");
+
+				dseg = (to - tlength) / slength;
+				interpolate_point4d(&p1, &p2, &pt, dseg);
+
+				dynptarray_addPoint4d(dpa, &pt, 0);
+
+				break;
+			}
+
+			else
+			{
+				LWDEBUG(3, "Unhandled case");
+			}
+		}
+
+
+		END:
+
+		tlength += slength;
+		memcpy(&p1, &p2, sizeof(POINT4D));
+	}
+
+	/* Get constructed pointarray and release memory associated
+	 * with the dynamic pointarray
+	 */
+	opa = dpa->pa;
+	lwfree(dpa);
+
+	LWDEBUGF(3, "Out of loop, ptarray has %d points", opa->npoints);
+
+	return opa;
+}
+
+/*
+ * Write into the *ret argument coordinates of the closes point on
+ * the given segment to the reference input point.
+ */
+void
+closest_point_on_segment(POINT2D *p, POINT2D *A, POINT2D *B, POINT2D *ret)
+{
+	double r;
+
+	if (  ( A->x == B->x) && (A->y == B->y) )
+	{
+		*ret = *A;
+		return;
+	}
+
+	/*
+	 * We use comp.graphics.algorithms Frequently Asked Questions method
+	 *
+	 * (1)           AC dot AB
+	 *           r = ----------
+	 *                ||AB||^2
+	 *	r has the following meaning:
+	 *	r=0 P = A
+	 *	r=1 P = B
+	 *	r<0 P is on the backward extension of AB
+	 *	r>1 P is on the forward extension of AB
+	 *	0<r<1 P is interior to AB
+	 *	
+	 */
+	r = ( (p->x-A->x) * (B->x-A->x) + (p->y-A->y) * (B->y-A->y) )/( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
+
+	if (r<0) {
+		*ret = *A; return;
+	}
+	if (r>1) {
+		*ret = *B;
+		return;
+	}
+
+	ret->x = A->x + ( (B->x - A->x) * r );
+	ret->y = A->y + ( (B->y - A->y) * r );
+}
+
+/*
+ * Given a point, returns the location of closest point on pointarray
+ */
+double
+ptarray_locate_point(POINTARRAY *pa, POINT2D *p)
+{
+	double mindist=-1;
+	double tlen, plen;
+	int t, seg=-1;
+	POINT2D	start, end;
+	POINT2D proj;
+
+	getPoint2d_p(pa, 0, &start);
+	for (t=1; t<pa->npoints; t++)
+	{
+		double dist;
+		getPoint2d_p(pa, t, &end);
+		dist = distance2d_pt_seg(p, &start, &end);
+
+		if (t==1 || dist < mindist ) {
+			mindist = dist;
+			seg=t-1;
+		}
+
+		if ( mindist == 0 ) break;
+
+		start = end;
+	}
+
+	LWDEBUGF(3, "Closest segment: %d", seg);
+
+	/*
+	 * If mindist is not 0 we need to project the 
+	 * point on the closest segment.
+	 */
+	if ( mindist > 0 )
+	{
+		getPoint2d_p(pa, seg, &start);
+		getPoint2d_p(pa, seg+1, &end);
+		closest_point_on_segment(p, &start, &end, &proj);
+	} else {
+		proj = *p;
+	}
+
+	LWDEBUGF(3, "Closest point on segment: %g,%g", proj.x, proj.y);
+
+	tlen = lwgeom_pointarray_length2d(pa);
+
+	LWDEBUGF(3, "tlen %g", tlen);
+
+	plen=0;
+	getPoint2d_p(pa, 0, &start);
+	for (t=0; t<seg; t++, start=end)
+	{
+		getPoint2d_p(pa, t+1, &end);
+		plen += distance2d_pt_pt(&start, &end);
+
+		LWDEBUGF(4, "Segment %d made plen %g", t, plen);
+	}
+
+	plen+=distance2d_pt_pt(&proj, &start);
+
+	LWDEBUGF(3, "plen %g, tlen %g", plen, tlen);
+	LWDEBUGF(3, "mindist: %g", mindist);
+
+	return plen/tlen;
+}
+
+/*
+ * Longitude shift for a pointarray.
+ *  Y remains the same
+ *  X is converted:
+ *	 from -180..180 to 0..360
+ *	 from 0..360 to -180..180
+ *  X < 0 becomes X + 360
+ *  X > 180 becomes X - 360
+ */
+void
+ptarray_longitude_shift(POINTARRAY *pa)
+{
+	int i;
+	double x;
+
+	for (i=0; i<pa->npoints; i++) {
+		memcpy(&x, getPoint_internal(pa, i), sizeof(double));
+		if ( x < 0 ) x+= 360;
+		else if ( x > 180 ) x -= 360;
+		memcpy(getPoint_internal(pa, i), &x, sizeof(double));
+	}
+}
+
+DYNPTARRAY *
+dynptarray_create(size_t initial_capacity, int dims)
+{
+	DYNPTARRAY *ret=lwalloc(sizeof(DYNPTARRAY));
+
+        LWDEBUGF(3, "dynptarray_create called, dims=%d.", dims);
+
+	if ( initial_capacity < 1 ) initial_capacity=1;
+
+	ret->pa=lwalloc(sizeof(POINTARRAY));
+	ret->pa->dims=dims;
+	ret->ptsize=pointArray_ptsize(ret->pa);
+	ret->capacity=initial_capacity;
+	ret->pa->serialized_pointlist=lwalloc(ret->ptsize*ret->capacity);
+	ret->pa->npoints=0;
+
+	return ret;
+}
+
+/*
+ * Add a POINT4D to the dynamic pointarray.
+ *
+ * The dynamic pointarray may be of any dimension, only
+ * accepted dimensions will be copied.
+ *
+ * If allow_duplicates is set to 0 (false) a check
+ * is performed to see if last point in array is equal to the
+ * provided one. NOTE that the check is 4d based, with missing
+ * ordinates in the pointarray set to NO_Z_VALUE and NO_M_VALUE
+ * respectively.
+ */
+int
+dynptarray_addPoint4d(DYNPTARRAY *dpa, POINT4D *p4d, int allow_duplicates)
+{
+	POINTARRAY *pa=dpa->pa;
+	POINT4D tmp;
+
+        LWDEBUG(3, "dynptarray_addPoint4d called.");
+
+	if ( ! allow_duplicates && pa->npoints > 0 )
+	{
+		getPoint4d_p(pa, pa->npoints-1, &tmp);
+
+		/*
+		 * return 0 and do nothing else if previous point in list is
+		 * equal to this one  (4D equality)
+		 */
+		if ( ! memcmp(p4d, &tmp, sizeof(POINT4D)) ) return 0;
+	}
+
+	++pa->npoints;
+	if ( pa->npoints > dpa->capacity )
+	{
+		dpa->capacity*=2;
+		pa->serialized_pointlist = lwrealloc(
+			pa->serialized_pointlist,
+			dpa->capacity*dpa->ptsize);
+	}
+
+	setPoint4d(pa, pa->npoints-1, p4d);
+
+	return 1;
+}
+

Added: trunk/liblwgeom/vsprintf.c
===================================================================
--- trunk/liblwgeom/vsprintf.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/vsprintf.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,162 @@
+/* Like vsprintf but provides a pointer to malloc'd storage, which must
+   be freed by the caller.
+   Copyright (C) 1994, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+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, 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.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if __STDC__
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
+
+#include <math.h>
+
+#ifdef TEST
+int global_total_width;
+#endif
+
+static int
+int_vasprintf (result, format, args)
+     char **result;
+     const char *format;
+     va_list *args;
+{
+  const char *p = format;
+  /* Add one to make sure that it is never zero, which might cause malloc
+     to return NULL.  */
+  int total_width = strlen (format) + 1;
+  va_list ap;
+
+  memcpy (&ap, args, sizeof (va_list));
+
+  while (*p != '\0')
+    {
+      if (*p++ == '%')
+	{
+	  while (strchr ("-+ #0", *p))
+	    ++p;
+	  if (*p == '*')
+	    {
+	      ++p;
+	      total_width += abs (va_arg (ap, int));
+	    }
+	  else
+	    total_width += strtoul (p, (char **) &p, 10);
+	  if (*p == '.')
+	    {
+	      ++p;
+	      if (*p == '*')
+		{
+		  ++p;
+		  total_width += abs (va_arg (ap, int));
+		}
+	      else
+		total_width += strtoul (p, (char **) &p, 10);
+	    }
+	  while (strchr ("hlLjtz", *p))
+	    ++p;
+	  /* Should be big enough for any format specifier except %s
+	     and floats.  */
+	  total_width += 30;
+	  switch (*p)
+	    {
+	    case 'd':
+	    case 'i':
+	    case 'o':
+	    case 'u':
+	    case 'x':
+	    case 'X':
+	    case 'c':
+	      (void) va_arg (ap, int);
+	      break;
+	    case 'f':
+	      {
+		double arg = va_arg (ap, double);
+		if (arg >= 1.0 || arg <= -1.0)
+		  /* Since an ieee double can have an exponent of 307, we'll
+		     make the buffer wide enough to cover the gross case. */
+		  total_width += 307;
+	      }
+	      break;
+	    case 'e':
+	    case 'E':
+	    case 'g':
+	    case 'G':
+	      (void) va_arg (ap, double);
+	      break;
+	    case 's':
+	      total_width += strlen (va_arg (ap, char *));
+	      break;
+	    case 'p':
+	    case 'n':
+	      (void) va_arg (ap, char *);
+	      break;
+	    }
+	  p++;
+	}
+    }
+#ifdef TEST
+  global_total_width = total_width;
+#endif
+  *result = malloc (total_width);
+  if (*result != NULL)
+    return vsprintf (*result, format, *args);
+  else
+    return 0;
+}
+
+int
+vasprintf (result, format, args)
+     char **result;
+     const char *format;
+     va_list args;
+{
+  return int_vasprintf (result, format, &args);
+}
+
+int
+asprintf
+#if __STDC__
+     (char **result, const char *format, ...)
+#else
+     (result, va_alist)
+     char **result;
+     va_dcl
+#endif
+{
+  va_list args;
+  int done;
+
+#if __STDC__
+  va_start (args, format);
+#else
+  char *format;
+  va_start (args);
+  format = va_arg (args, char *);
+#endif
+  done = vasprintf (result, format, args);
+  va_end (args);
+
+  return done;
+} 

Added: trunk/liblwgeom/wktparse.h
===================================================================
--- trunk/liblwgeom/wktparse.h	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/wktparse.h	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,106 @@
+/*
+ * Written by Ralph Mason ralph.mason<at>telogis.com
+ *
+ * Copyright Telogis 2004
+ * www.telogis.com
+ *
+ */
+
+#ifndef _WKTPARSE_H
+#define _WKTPARSE_H
+
+#include <stdlib.h>
+
+
+#ifndef _LIBLWGEOM_H
+typedef unsigned char uchar;
+
+typedef struct serialized_lwgeom {
+    uchar *lwgeom;
+    int size;
+} SERIALIZED_LWGEOM;
+#endif
+typedef void* (*allocator)(size_t size);
+typedef void  (*freeor)(void* mem);
+typedef void  (*report_error)(const char* string, ...);
+
+/*typedef unsigned long int4;*/
+
+/* How much memory is allocated at a time(bytes) for tuples */
+#define ALLOC_CHUNKS 8192
+
+/* to shrink ints less than 0x7f to 1 byte */
+/* #define SHRINK_INTS */
+
+#define	POINTTYPE	1
+#define	LINETYPE	2
+#define	POLYGONTYPE	3
+#define	MULTIPOINTTYPE	4
+#define	MULTILINETYPE	5
+#define	MULTIPOLYGONTYPE	6
+#define	COLLECTIONTYPE	7
+
+/* Extended lwgeom integer types */
+#define POINTTYPEI    10
+#define LINETYPEI     11
+#define POLYGONTYPEI  12
+
+#define CURVETYPE       8
+#define COMPOUNDTYPE    9
+#define CURVEPOLYTYPE   13
+#define MULTICURVETYPE          14
+#define MULTISURFACETYPE        15
+
+extern int srid;
+
+/*
+
+   These functions are used by  the
+   generated parser and are not meant
+   for public use
+
+*/
+
+void set_srid(double srid);
+void alloc_lwgeom(int srid);
+
+void alloc_point_2d(double x,double y);
+void alloc_point_3d(double x,double y,double z);
+void alloc_point_4d(double x,double y,double z,double m);
+
+void alloc_point(void);
+void alloc_linestring(void);
+void alloc_linestring_closed(void);
+void alloc_circularstring(void);
+void alloc_circularstring_closed(void);
+void alloc_polygon(void);
+void alloc_compoundcurve(void);
+void alloc_curvepolygon(void);
+void alloc_multipoint(void);
+void alloc_multilinestring(void);
+void alloc_multicurve(void);
+void alloc_multipolygon(void);
+void alloc_multisurface(void);
+void alloc_geomertycollection(void);
+void alloc_empty();
+void alloc_counter(void);
+
+
+void pop(void);
+void popc(void);
+
+void alloc_wkb(const char* parser);
+
+/*
+	Use these functions to parse and unparse lwgeoms
+	You are responsible for freeing the returned memory.
+*/
+
+SERIALIZED_LWGEOM* parse_lwg(const char* wkt,allocator allocfunc,report_error errfunc);
+SERIALIZED_LWGEOM* parse_lwgi(const char* wkt,allocator allocfunc,report_error errfunc);
+char* unparse_WKT(uchar* serialized, allocator alloc,freeor free);
+char* unparse_WKB(uchar* serialized, allocator alloc,freeor free, char endian, size_t *outsize, uchar hexform);
+int lwg_parse_yyparse(void);
+int lwg_parse_yyerror(char* s);
+
+#endif /* _WKTPARSE_H */

Added: trunk/liblwgeom/wktparse.lex
===================================================================
--- trunk/liblwgeom/wktparse.lex	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/wktparse.lex	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,71 @@
+/*
+ * Written by Ralph Mason ralph.mason<at>telogis.com
+ *
+ * Copyright Telogis 2004
+ * www.telogis.com
+ *
+ */
+
+%x vals_ok
+%{
+#include "wktparse.tab.h"
+#include <unistd.h>
+#include <stdlib.h> // need stdlib for atof() definition 
+
+void init_parser(const char *src);
+void close_parser(void);
+int lwg_parse_yywrap(void);
+int lwg_parse_yylex(void);
+
+static YY_BUFFER_STATE buf_state;
+   void init_parser(const char *src) { BEGIN(0);buf_state = lwg_parse_yy_scan_string(src); }
+   void close_parser() { lwg_parse_yy_delete_buffer(buf_state); }
+   int lwg_parse_yywrap(void){ return 1; }
+
+%}
+
+%%
+
+<vals_ok>[-|\+]?[0-9]+(\.[0-9]+)?([Ee](\+|-)?[0-9]+)? { lwg_parse_yylval.value=atof(lwg_parse_yytext); return VALUE; }
+<vals_ok>[-|\+]?(\.[0-9]+)([Ee](\+|-)?[0-9]+)? { lwg_parse_yylval.value=atof(lwg_parse_yytext); return VALUE; }
+
+<INITIAL>00[0-9A-F]* {  lwg_parse_yylval.wkb=lwg_parse_yytext; return WKB;}
+<INITIAL>01[0-9A-F]* {  lwg_parse_yylval.wkb=lwg_parse_yytext; return WKB;}
+
+<*>POINT 	{ return POINT; }
+<*>POINTM 	{ return POINTM; }
+<*>LINESTRING { return LINESTRING; }
+<*>LINESTRINGM { return LINESTRINGM; }
+<*>CIRCULARSTRING { return CIRCULARSTRING; }
+<*>CIRCULARSTRINGM { return CIRCULARSTRINGM; }
+<*>POLYGON { return POLYGON; }
+<*>POLYGONM { return POLYGONM; }
+<*>COMPOUNDCURVE { return COMPOUNDCURVE; }
+<*>COMPOUNDCURVEM { return COMPOUNDCURVEM; }
+<*>CURVEPOLYGON { return CURVEPOLYGON; }
+<*>CURVEPOLYGONM { return CURVEPOLYGONM; }
+<*>MULTIPOINT { return MULTIPOINT; }
+<*>MULTIPOINTM { return MULTIPOINTM; }
+<*>MULTILINESTRING { return MULTILINESTRING; }
+<*>MULTILINESTRINGM { return MULTILINESTRINGM; }
+<*>MULTICURVE { return MULTICURVE; }
+<*>MULTICURVEM { return MULTICURVEM; }
+<*>MULTIPOLYGON { return MULTIPOLYGON; }
+<*>MULTIPOLYGONM { return MULTIPOLYGONM; }
+<*>MULTISURFACE { return MULTISURFACE; }
+<*>MULTISURFACEM { return MULTISURFACEM; }
+<*>GEOMETRYCOLLECTION { return GEOMETRYCOLLECTION; }
+<*>GEOMETRYCOLLECTIONM { return GEOMETRYCOLLECTIONM; }
+<*>SRID { BEGIN(vals_ok); return SRID; }
+<*>EMPTY { return EMPTY; }
+
+<*>\(	{ BEGIN(vals_ok); return LPAREN; }
+<*>\)	{ return RPAREN; }
+<*>,	{ return COMMA ; }
+<*>=	{ return EQUALS ; }
+<*>;	{ BEGIN(0); return SEMICOLON; }
+<*>[ \t\n\r]+ /*eat whitespace*/
+<*>.	{ return lwg_parse_yytext[0]; }
+
+%%
+

Added: trunk/liblwgeom/wktparse.tab.c
===================================================================
--- trunk/liblwgeom/wktparse.tab.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/wktparse.tab.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,1991 @@
+/* A Bison parser, made by GNU Bison 1.875c.  */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+   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, 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* Written by Richard Stallman by simplifying the original so called
+   ``semantic'' parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+/* If NAME_PREFIX is specified substitute the variables and functions
+   names.  */
+#define yyparse lwg_parse_yyparse
+#define yylex   lwg_parse_yylex
+#define yyerror lwg_parse_yyerror
+#define yylval  lwg_parse_yylval
+#define yychar  lwg_parse_yychar
+#define yydebug lwg_parse_yydebug
+#define yynerrs lwg_parse_yynerrs
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     POINT = 258,
+     LINESTRING = 259,
+     POLYGON = 260,
+     MULTIPOINT = 261,
+     MULTILINESTRING = 262,
+     MULTIPOLYGON = 263,
+     GEOMETRYCOLLECTION = 264,
+     CIRCULARSTRING = 265,
+     COMPOUNDCURVE = 266,
+     CURVEPOLYGON = 267,
+     MULTICURVE = 268,
+     MULTISURFACE = 269,
+     POINTM = 270,
+     LINESTRINGM = 271,
+     POLYGONM = 272,
+     MULTIPOINTM = 273,
+     MULTILINESTRINGM = 274,
+     MULTIPOLYGONM = 275,
+     GEOMETRYCOLLECTIONM = 276,
+     CIRCULARSTRINGM = 277,
+     COMPOUNDCURVEM = 278,
+     CURVEPOLYGONM = 279,
+     MULTICURVEM = 280,
+     MULTISURFACEM = 281,
+     SRID = 282,
+     EMPTY = 283,
+     VALUE = 284,
+     LPAREN = 285,
+     RPAREN = 286,
+     COMMA = 287,
+     EQUALS = 288,
+     SEMICOLON = 289,
+     WKB = 290
+   };
+#endif
+#define POINT 258
+#define LINESTRING 259
+#define POLYGON 260
+#define MULTIPOINT 261
+#define MULTILINESTRING 262
+#define MULTIPOLYGON 263
+#define GEOMETRYCOLLECTION 264
+#define CIRCULARSTRING 265
+#define COMPOUNDCURVE 266
+#define CURVEPOLYGON 267
+#define MULTICURVE 268
+#define MULTISURFACE 269
+#define POINTM 270
+#define LINESTRINGM 271
+#define POLYGONM 272
+#define MULTIPOINTM 273
+#define MULTILINESTRINGM 274
+#define MULTIPOLYGONM 275
+#define GEOMETRYCOLLECTIONM 276
+#define CIRCULARSTRINGM 277
+#define COMPOUNDCURVEM 278
+#define CURVEPOLYGONM 279
+#define MULTICURVEM 280
+#define MULTISURFACEM 281
+#define SRID 282
+#define EMPTY 283
+#define VALUE 284
+#define LPAREN 285
+#define RPAREN 286
+#define COMMA 287
+#define EQUALS 288
+#define SEMICOLON 289
+#define WKB 290
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 9 "wktparse.y"
+
+#include "wktparse.h"
+#include <unistd.h>
+#include <stdio.h>
+
+void set_zm(char z, char m);
+int lwg_parse_yylex(void);
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#line 20 "wktparse.y"
+typedef union YYSTYPE {
+	double value;
+	const char* wkb;
+} YYSTYPE;
+/* Line 191 of yacc.c.  */
+#line 169 "y.tab.c"
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 214 of yacc.c.  */
+#line 181 "y.tab.c"
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+# ifndef YYFREE
+#  define YYFREE free
+# endif
+# ifndef YYMALLOC
+#  define YYMALLOC malloc
+# endif
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   define YYSTACK_ALLOC alloca
+#  endif
+# else
+#  if defined (alloca) || defined (_ALLOCA_H)
+#   define YYSTACK_ALLOC alloca
+#  else
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+     && (! defined (__cplusplus) \
+	 || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))				\
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined (__GNUC__) && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  register YYSIZE_T yyi;		\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (0)
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+   typedef signed char yysigned_char;
+#else
+   typedef short yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL  6
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   180
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS  36
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS  107
+/* YYNRULES -- Number of rules. */
+#define YYNRULES  169
+/* YYNRULES -- Number of states. */
+#define YYNSTATES  237
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   290
+
+#define YYTRANSLATE(YYX) 						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const unsigned char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const unsigned short yyprhs[] =
+{
+       0,     0,     3,     4,     9,    10,    13,    15,    17,    19,
+      21,    23,    25,    27,    29,    31,    33,    35,    37,    39,
+      43,    45,    48,    49,    53,    55,    57,    58,    61,    62,
+      65,    69,    70,    74,    75,    79,    81,    82,    87,    89,
+      93,    95,    96,    99,   102,   103,   107,   109,   111,   112,
+     115,   116,   119,   120,   123,   124,   129,   131,   135,   138,
+     139,   143,   146,   147,   151,   153,   155,   157,   159,   160,
+     163,   164,   167,   168,   171,   172,   177,   179,   183,   184,
+     188,   189,   193,   195,   196,   201,   203,   205,   209,   213,
+     214,   218,   219,   223,   225,   226,   231,   233,   237,   238,
+     242,   243,   247,   249,   250,   255,   257,   259,   263,   267,
+     270,   271,   275,   277,   279,   280,   283,   284,   287,   288,
+     293,   295,   299,   300,   304,   305,   309,   311,   312,   317,
+     319,   321,   325,   329,   330,   334,   335,   339,   341,   342,
+     347,   349,   353,   354,   358,   359,   363,   365,   366,   371,
+     373,   375,   379,   383,   384,   388,   389,   393,   395,   396,
+     401,   403,   405,   409,   411,   413,   415,   418,   422,   427
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const short yyrhs[] =
+{
+      37,     0,    -1,    -1,    41,    34,    38,    40,    -1,    -1,
+      39,    40,    -1,    42,    -1,    43,    -1,    59,    -1,    71,
+      -1,   104,    -1,    86,    -1,   114,    -1,    51,    -1,    92,
+      -1,    98,    -1,   120,    -1,   126,    -1,   132,    -1,    27,
+      33,    29,    -1,    35,    -1,     3,    45,    -1,    -1,    15,
+      44,    45,    -1,    46,    -1,    48,    -1,    -1,    47,   142,
+      -1,    -1,    49,    50,    -1,    30,   138,    31,    -1,    -1,
+       6,    52,    54,    -1,    -1,    18,    53,    54,    -1,   142,
+      -1,    -1,    55,    30,    56,    31,    -1,    57,    -1,    56,
+      32,    57,    -1,    48,    -1,    -1,    58,   138,    -1,     4,
+      61,    -1,    -1,    16,    60,    61,    -1,    62,    -1,    64,
+      -1,    -1,    63,   142,    -1,    -1,    65,    68,    -1,    -1,
+      67,    68,    -1,    -1,    69,    30,    70,    31,    -1,   138,
+      -1,    70,    32,   138,    -1,    10,    75,    -1,    -1,    22,
+      72,    75,    -1,    10,    76,    -1,    -1,    22,    74,    76,
+      -1,    77,    -1,    79,    -1,    77,    -1,    81,    -1,    -1,
+      78,   142,    -1,    -1,    80,    83,    -1,    -1,    82,    83,
+      -1,    -1,    84,    30,    85,    31,    -1,   138,    -1,    85,
+      32,   138,    -1,    -1,    11,    87,    89,    -1,    -1,    23,
+      88,    89,    -1,   142,    -1,    -1,    90,    30,    91,    31,
+      -1,    64,    -1,    71,    -1,    91,    32,    64,    -1,    91,
+      32,    71,    -1,    -1,     7,    93,    95,    -1,    -1,    19,
+      94,    95,    -1,   142,    -1,    -1,    96,    30,    97,    31,
+      -1,    64,    -1,    97,    32,    64,    -1,    -1,    13,    99,
+     101,    -1,    -1,    25,   100,   101,    -1,   142,    -1,    -1,
+     102,    30,   103,    31,    -1,    64,    -1,    71,    -1,   103,
+      32,    64,    -1,   103,    32,    71,    -1,     5,   106,    -1,
+      -1,    17,   105,   106,    -1,   107,    -1,   109,    -1,    -1,
+     108,   142,    -1,    -1,   110,   111,    -1,    -1,   112,    30,
+     113,    31,    -1,    68,    -1,   113,    32,    68,    -1,    -1,
+      12,   115,   117,    -1,    -1,    24,   116,   117,    -1,   142,
+      -1,    -1,   118,    30,   119,    31,    -1,    66,    -1,    73,
+      -1,   119,    32,    66,    -1,   119,    32,    73,    -1,    -1,
+       8,   121,   123,    -1,    -1,    20,   122,   123,    -1,   142,
+      -1,    -1,   124,    30,   125,    31,    -1,   109,    -1,   125,
+      32,   109,    -1,    -1,    14,   127,   129,    -1,    -1,    26,
+     128,   129,    -1,   142,    -1,    -1,   130,    30,   131,    31,
+      -1,   109,    -1,   114,    -1,   131,    32,   109,    -1,   131,
+      32,   114,    -1,    -1,     9,   133,   135,    -1,    -1,    21,
+     134,   135,    -1,   142,    -1,    -1,   136,    30,   137,    31,
+      -1,   142,    -1,    40,    -1,   137,    32,    40,    -1,   139,
+      -1,   140,    -1,   141,    -1,    29,    29,    -1,    29,    29,
+      29,    -1,    29,    29,    29,    29,    -1,    28,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const unsigned short yyrline[] =
+{
+       0,    36,    36,    36,    38,    38,    41,    43,    45,    47,
+      49,    51,    53,    55,    57,    59,    61,    63,    65,    68,
+      71,    77,    79,    79,    82,    84,    87,    87,    90,    90,
+      93,    98,    98,   100,   100,   103,   105,   105,   108,   110,
+     113,   116,   116,   122,   124,   124,   127,   129,   132,   132,
+     135,   135,   138,   138,   141,   141,   144,   146,   151,   153,
+     153,   156,   158,   158,   161,   163,   166,   168,   171,   171,
+     174,   174,   177,   177,   180,   180,   183,   185,   190,   190,
+     192,   192,   195,   197,   197,   200,   202,   204,   206,   211,
+     211,   214,   214,   218,   220,   220,   223,   225,   230,   230,
+     233,   233,   237,   239,   239,   242,   244,   246,   248,   253,
+     255,   255,   258,   260,   263,   263,   266,   266,   269,   269,
+     272,   274,   279,   279,   281,   281,   285,   287,   287,   290,
+     292,   294,   296,   301,   301,   303,   303,   307,   309,   309,
+     312,   314,   319,   319,   321,   321,   325,   327,   327,   330,
+     332,   334,   336,   341,   341,   344,   344,   348,   350,   350,
+     354,   356,   358,   362,   364,   366,   369,   372,   375,   378
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "POINT", "LINESTRING", "POLYGON",
+  "MULTIPOINT", "MULTILINESTRING", "MULTIPOLYGON", "GEOMETRYCOLLECTION",
+  "CIRCULARSTRING", "COMPOUNDCURVE", "CURVEPOLYGON", "MULTICURVE",
+  "MULTISURFACE", "POINTM", "LINESTRINGM", "POLYGONM", "MULTIPOINTM",
+  "MULTILINESTRINGM", "MULTIPOLYGONM", "GEOMETRYCOLLECTIONM",
+  "CIRCULARSTRINGM", "COMPOUNDCURVEM", "CURVEPOLYGONM", "MULTICURVEM",
+  "MULTISURFACEM", "SRID", "EMPTY", "VALUE", "LPAREN", "RPAREN", "COMMA",
+  "EQUALS", "SEMICOLON", "WKB", "$accept", "geometry", "@1", "@2",
+  "geometry_int", "srid", "geom_wkb", "geom_point", "@3", "point",
+  "empty_point", "@4", "nonempty_point", "@5", "point_int",
+  "geom_multipoint", "@6", "@7", "multipoint", "@8", "multipoint_int",
+  "mpoint_element", "@9", "geom_linestring", "@10", "linestring",
+  "empty_linestring", "@11", "nonempty_linestring", "@12",
+  "nonempty_linestring_closed", "@13", "linestring_1", "@14",
+  "linestring_int", "geom_circularstring", "@15",
+  "geom_circularstring_closed", "@16", "circularstring",
+  "circularstring_closed", "empty_circularstring", "@17",
+  "nonempty_circularstring", "@18", "nonempty_circularstring_closed",
+  "@19", "circularstring_1", "@20", "circularstring_int",
+  "geom_compoundcurve", "@21", "@22", "compoundcurve", "@23",
+  "compoundcurve_int", "geom_multilinestring", "@24", "@25",
+  "multilinestring", "@26", "multilinestring_int", "geom_multicurve",
+  "@27", "@28", "multicurve", "@29", "multicurve_int", "geom_polygon",
+  "@30", "polygon", "empty_polygon", "@31", "nonempty_polygon", "@32",
+  "polygon_1", "@33", "polygon_int", "geom_curvepolygon", "@34", "@35",
+  "curvepolygon", "@36", "curvepolygon_int", "geom_multipolygon", "@37",
+  "@38", "multipolygon", "@39", "multipolygon_int", "geom_multisurface",
+  "@40", "@41", "multisurface", "@42", "multisurface_int",
+  "geom_geometrycollection", "@43", "@44", "geometrycollection", "@45",
+  "geometrycollection_int", "a_point", "point_2d", "point_3d", "point_4d",
+  "empty", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const unsigned short yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const unsigned char yyr1[] =
+{
+       0,    36,    38,    37,    39,    37,    40,    40,    40,    40,
+      40,    40,    40,    40,    40,    40,    40,    40,    40,    41,
+      42,    43,    44,    43,    45,    45,    47,    46,    49,    48,
+      50,    52,    51,    53,    51,    54,    55,    54,    56,    56,
+      57,    58,    57,    59,    60,    59,    61,    61,    63,    62,
+      65,    64,    67,    66,    69,    68,    70,    70,    71,    72,
+      71,    73,    74,    73,    75,    75,    76,    76,    78,    77,
+      80,    79,    82,    81,    84,    83,    85,    85,    87,    86,
+      88,    86,    89,    90,    89,    91,    91,    91,    91,    93,
+      92,    94,    92,    95,    96,    95,    97,    97,    99,    98,
+     100,    98,   101,   102,   101,   103,   103,   103,   103,   104,
+     105,   104,   106,   106,   108,   107,   110,   109,   112,   111,
+     113,   113,   115,   114,   116,   114,   117,   118,   117,   119,
+     119,   119,   119,   121,   120,   122,   120,   123,   124,   123,
+     125,   125,   127,   126,   128,   126,   129,   130,   129,   131,
+     131,   131,   131,   133,   132,   134,   132,   135,   136,   135,
+     137,   137,   137,   138,   138,   138,   139,   140,   141,   142
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const unsigned char yyr2[] =
+{
+       0,     2,     0,     4,     0,     2,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     3,
+       1,     2,     0,     3,     1,     1,     0,     2,     0,     2,
+       3,     0,     3,     0,     3,     1,     0,     4,     1,     3,
+       1,     0,     2,     2,     0,     3,     1,     1,     0,     2,
+       0,     2,     0,     2,     0,     4,     1,     3,     2,     0,
+       3,     2,     0,     3,     1,     1,     1,     1,     0,     2,
+       0,     2,     0,     2,     0,     4,     1,     3,     0,     3,
+       0,     3,     1,     0,     4,     1,     1,     3,     3,     0,
+       3,     0,     3,     1,     0,     4,     1,     3,     0,     3,
+       0,     3,     1,     0,     4,     1,     1,     3,     3,     2,
+       0,     3,     1,     1,     0,     2,     0,     2,     0,     4,
+       1,     3,     0,     3,     0,     3,     1,     0,     4,     1,
+       1,     3,     3,     0,     3,     0,     3,     1,     0,     4,
+       1,     3,     0,     3,     0,     3,     1,     0,     4,     1,
+       1,     3,     3,     0,     3,     0,     3,     1,     0,     4,
+       1,     1,     3,     1,     1,     1,     2,     3,     4,     1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const unsigned char yydefact[] =
+{
+       4,     0,     0,     0,     0,     0,     1,    26,    48,   114,
+      31,    89,   133,   153,    68,    78,   122,    98,   142,    22,
+      44,   110,    33,    91,   135,   155,    59,    80,   124,   100,
+     144,    20,     5,     6,     7,    13,     8,     9,    11,    14,
+      15,    10,    12,    16,    17,    18,     2,    19,    21,    24,
+       0,    25,     0,    43,    46,     0,    47,    54,   109,   112,
+       0,   113,   118,    36,    94,   138,   158,    58,    64,     0,
+      65,    74,    83,   127,   103,   147,    26,    48,   114,    36,
+      94,   138,   158,    68,    83,   127,   103,   147,     0,   169,
+      27,     0,    29,    49,    51,     0,   115,   117,     0,    32,
+       0,    35,    90,     0,    93,   134,     0,   137,   154,     0,
+     157,    69,    71,     0,    79,     0,    82,   123,     0,   126,
+      99,     0,   102,   143,     0,   146,    23,    45,   111,    34,
+      92,   136,   156,    60,    81,   125,   101,   145,     3,     0,
+       0,   163,   164,   165,     0,    54,    28,    50,   116,     0,
+       0,    50,    52,    50,   116,   166,    30,     0,    56,   120,
+       0,    40,     0,    38,     0,    96,     0,   140,     0,   161,
+       0,   160,     0,    76,    85,    86,     0,    68,    62,   129,
+      54,   130,     0,   105,   106,     0,   149,   150,     0,   167,
+      55,     0,   119,    54,    37,    28,    42,    95,    50,   139,
+     116,   159,     0,    75,     0,    84,    50,    61,    66,    67,
+      74,    68,    53,   128,    52,   104,    50,   148,   116,   168,
+      57,   121,    39,    97,   141,   162,    77,    87,    88,    73,
+      63,   131,   132,   107,   108,   151,   152
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const short yydefgoto[] =
+{
+      -1,     2,    88,     3,    32,     4,    33,    34,    76,    48,
+      49,    50,    51,    52,    92,    35,    63,    79,    99,   100,
+     162,   163,   164,    36,    77,    53,    54,    55,    56,    57,
+     179,   180,    94,    95,   157,    37,    83,   181,   211,    67,
+     207,    68,    69,    70,    71,   209,   210,   112,   113,   172,
+      38,    72,    84,   114,   115,   176,    39,    64,    80,   102,
+     103,   166,    40,    74,    86,   120,   121,   185,    41,    78,
+      58,    59,    60,    61,    62,    97,    98,   160,    42,    73,
+      85,   117,   118,   182,    43,    65,    81,   105,   106,   168,
+      44,    75,    87,   123,   124,   188,    45,    66,    82,   108,
+     109,   170,   140,   141,   142,   143,   101
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -166
+static const short yypact[] =
+{
+     -17,   -14,    21,   145,    -7,     5,  -166,    29,    30,    40,
+    -166,  -166,  -166,  -166,    51,  -166,  -166,  -166,  -166,  -166,
+    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
+    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
+    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
+      23,  -166,    53,  -166,  -166,    23,  -166,  -166,  -166,  -166,
+      23,  -166,  -166,    23,    23,    23,    23,  -166,  -166,    23,
+    -166,  -166,    23,    23,    23,    23,    29,    30,    40,    23,
+      23,    23,    23,    51,    23,    23,    23,    23,   145,  -166,
+    -166,    55,  -166,  -166,  -166,    56,  -166,  -166,    57,  -166,
+      58,  -166,  -166,    59,  -166,  -166,    61,  -166,  -166,    62,
+    -166,  -166,  -166,    63,  -166,    64,  -166,  -166,    65,  -166,
+    -166,    66,  -166,  -166,    67,  -166,  -166,  -166,  -166,  -166,
+    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,    70,
+      54,  -166,  -166,  -166,    55,  -166,    72,  -166,  -166,   112,
+      55,     8,    19,     8,    28,    73,  -166,   -18,  -166,  -166,
+      16,  -166,    18,  -166,    55,  -166,    24,  -166,    31,  -166,
+      33,  -166,    35,  -166,  -166,  -166,    42,    74,  -166,  -166,
+    -166,  -166,    44,  -166,  -166,    46,  -166,  -166,    48,    76,
+    -166,    55,  -166,  -166,  -166,    72,  -166,  -166,  -166,  -166,
+    -166,  -166,   145,  -166,    55,  -166,     8,  -166,  -166,  -166,
+    -166,    74,  -166,  -166,    19,  -166,     8,  -166,    28,  -166,
+    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
+    -166,  -166,  -166,  -166,  -166,  -166,  -166
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const short yypgoto[] =
+{
+    -166,  -166,  -166,  -166,   -88,  -166,  -166,  -166,  -166,    27,
+    -166,  -166,  -142,  -166,  -166,  -166,  -166,  -166,    32,  -166,
+    -166,   -89,  -166,  -166,  -166,    36,  -166,  -166,  -108,  -166,
+    -107,  -166,  -136,  -166,  -166,  -148,  -166,  -105,  -166,    60,
+    -101,  -165,  -166,  -166,  -166,  -166,  -166,   -98,  -166,  -166,
+    -166,  -166,  -166,    88,  -166,  -166,  -166,  -166,  -166,    93,
+    -166,  -166,  -166,  -166,  -166,    89,  -166,  -166,  -166,  -166,
+      68,  -166,  -166,  -146,  -166,  -166,  -166,  -166,  -147,  -166,
+    -166,    91,  -166,  -166,  -166,  -166,  -166,    96,  -166,  -166,
+    -166,  -166,  -166,    52,  -166,  -166,  -166,  -166,  -166,    92,
+    -166,  -166,  -122,  -166,  -166,  -166,   -49
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -117
+static const short yytable[] =
+{
+     138,    90,   167,   175,   161,   184,    93,   187,   186,   159,
+       1,    96,   208,   190,   191,   104,   107,   110,    14,     5,
+     111,     6,   158,   116,   119,   122,   125,    46,   173,   177,
+      26,   104,   107,   110,    47,   116,   119,   122,   125,   165,
+      16,   178,   196,   174,   212,   183,   208,   192,   193,   194,
+     195,    89,    28,   161,   224,   197,   198,   221,   228,   -28,
+     -50,   169,   199,   200,   201,   202,   203,   204,   234,   220,
+    -116,   236,   235,   205,   206,   213,   214,   215,   216,   217,
+     218,   -70,   226,    91,   139,   156,   144,   145,   146,   147,
+     223,   148,   149,   150,   151,   152,   153,   154,   227,   155,
+     171,   -41,   189,   126,   -72,   219,   222,   231,   233,   232,
+     230,   129,   229,   127,   225,     7,     8,     9,    10,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,   137,
+      89,     0,     0,   133,     0,     0,   128,    31,     7,     8,
+       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,   134,   130,   132,   136,   135,   131,     0,     0,
+      31
+};
+
+static const short yycheck[] =
+{
+      88,    50,   148,   151,   146,   153,    55,   154,   154,   145,
+      27,    60,   177,    31,    32,    64,    65,    66,    10,    33,
+      69,     0,   144,    72,    73,    74,    75,    34,   150,    10,
+      22,    80,    81,    82,    29,    84,    85,    86,    87,   147,
+      12,    22,   164,   151,   180,   153,   211,    31,    32,    31,
+      32,    28,    24,   195,   200,    31,    32,   193,   206,    30,
+      30,   149,    31,    32,    31,    32,    31,    32,   216,   191,
+      30,   218,   218,    31,    32,    31,    32,    31,    32,    31,
+      32,    30,   204,    30,    29,    31,    30,    30,    30,    30,
+     198,    30,    30,    30,    30,    30,    30,    30,   206,    29,
+     149,    29,    29,    76,    30,    29,   195,   214,   216,   214,
+     211,    79,   210,    77,   202,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    87,
+      28,    -1,    -1,    83,    -1,    -1,    78,    35,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    84,    80,    82,    86,    85,    81,    -1,    -1,
+      35
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const unsigned char yystos[] =
+{
+       0,    27,    37,    39,    41,    33,     0,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    35,    40,    42,    43,    51,    59,    71,    86,    92,
+      98,   104,   114,   120,   126,   132,    34,    29,    45,    46,
+      47,    48,    49,    61,    62,    63,    64,    65,   106,   107,
+     108,   109,   110,    52,    93,   121,   133,    75,    77,    78,
+      79,    80,    87,   115,    99,   127,    44,    60,   105,    53,
+      94,   122,   134,    72,    88,   116,   100,   128,    38,    28,
+     142,    30,    50,   142,    68,    69,   142,   111,   112,    54,
+      55,   142,    95,    96,   142,   123,   124,   142,   135,   136,
+     142,   142,    83,    84,    89,    90,   142,   117,   118,   142,
+     101,   102,   142,   129,   130,   142,    45,    61,   106,    54,
+      95,   123,   135,    75,    89,   117,   101,   129,    40,    29,
+     138,   139,   140,   141,    30,    30,    30,    30,    30,    30,
+      30,    30,    30,    30,    30,    29,    31,    70,   138,    68,
+     113,    48,    56,    57,    58,    64,    97,   109,   125,    40,
+     137,   142,    85,   138,    64,    71,    91,    10,    22,    66,
+      67,    73,   119,    64,    71,   103,   109,   114,   131,    29,
+      31,    32,    31,    32,    31,    32,   138,    31,    32,    31,
+      32,    31,    32,    31,    32,    31,    32,    76,    77,    81,
+      82,    74,    68,    31,    32,    31,    32,    31,    32,    29,
+     138,    68,    57,    64,   109,    40,   138,    64,    71,    83,
+      76,    66,    73,    64,    71,   109,   114
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL		goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK;						\
+      goto yybackup;						\
+    }								\
+  else								\
+    { 								\
+      yyerror ("syntax error: cannot back up");\
+      YYERROR;							\
+    }								\
+while (0)
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)		\
+   ((Current).first_line   = (Rhs)[1].first_line,	\
+    (Current).first_column = (Rhs)[1].first_column,	\
+    (Current).last_line    = (Rhs)[N].last_line,	\
+    (Current).last_column  = (Rhs)[N].last_column)
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (0)
+
+# define YYDSYMPRINT(Args)			\
+do {						\
+  if (yydebug)					\
+    yysymprint Args;				\
+} while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location)		\
+do {								\
+  if (yydebug)							\
+    {								\
+      YYFPRINTF (stderr, "%s ", Title);				\
+      yysymprint (stderr, 					\
+                  Token, Value);	\
+      YYFPRINTF (stderr, "\n");					\
+    }								\
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short *bottom, short *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    short *bottom;
+    short *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (/* Nothing. */; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+    int yyrule;
+#endif
+{
+  int yyi;
+  unsigned int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+             yyrule - 1, yylno);
+  /* Print the symbols being reduced, and their result.  */
+  for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (Rule);		\
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvaluep;
+
+  if (yytype < YYNTOKENS)
+    {
+      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+    }
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  switch (yytype)
+    {
+      default:
+        break;
+    }
+  YYFPRINTF (yyoutput, ")");
+}
+
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yytype, yyvaluep)
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvaluep;
+
+  switch (yytype)
+    {
+
+      default:
+        break;
+    }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+  void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+  
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  short	yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
+  register short *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule.  */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack. Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	short *yyss1 = yyss;
+
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow ("parser stack overflow",
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyoverflowlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyoverflowlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	short *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyoverflowlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+#line 36 "wktparse.y"
+    { alloc_lwgeom(srid); }
+    break;
+
+  case 4:
+#line 38 "wktparse.y"
+    { alloc_lwgeom(-1); }
+    break;
+
+  case 19:
+#line 68 "wktparse.y"
+    { set_srid(yyvsp[0].value); }
+    break;
+
+  case 20:
+#line 71 "wktparse.y"
+    { alloc_wkb(yyvsp[0].wkb); }
+    break;
+
+  case 22:
+#line 79 "wktparse.y"
+    { set_zm(0, 1); }
+    break;
+
+  case 26:
+#line 87 "wktparse.y"
+    { alloc_point(); }
+    break;
+
+  case 27:
+#line 87 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 28:
+#line 90 "wktparse.y"
+    { alloc_point(); }
+    break;
+
+  case 29:
+#line 90 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 31:
+#line 98 "wktparse.y"
+    { alloc_multipoint(); }
+    break;
+
+  case 32:
+#line 98 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 33:
+#line 100 "wktparse.y"
+    { set_zm(0, 1); alloc_multipoint(); }
+    break;
+
+  case 34:
+#line 100 "wktparse.y"
+    {pop(); }
+    break;
+
+  case 36:
+#line 105 "wktparse.y"
+    { alloc_counter(); }
+    break;
+
+  case 37:
+#line 105 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 41:
+#line 116 "wktparse.y"
+    { alloc_point(); }
+    break;
+
+  case 42:
+#line 116 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 44:
+#line 124 "wktparse.y"
+    { set_zm(0, 1); }
+    break;
+
+  case 48:
+#line 132 "wktparse.y"
+    { alloc_linestring(); }
+    break;
+
+  case 49:
+#line 132 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 50:
+#line 135 "wktparse.y"
+    { alloc_linestring(); }
+    break;
+
+  case 51:
+#line 135 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 52:
+#line 138 "wktparse.y"
+    { alloc_linestring_closed(); }
+    break;
+
+  case 53:
+#line 138 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 54:
+#line 141 "wktparse.y"
+    { alloc_counter(); }
+    break;
+
+  case 55:
+#line 141 "wktparse.y"
+    { popc(); }
+    break;
+
+  case 59:
+#line 153 "wktparse.y"
+    {set_zm(0, 1); }
+    break;
+
+  case 62:
+#line 158 "wktparse.y"
+    {set_zm(0, 1); }
+    break;
+
+  case 68:
+#line 171 "wktparse.y"
+    { alloc_circularstring(); }
+    break;
+
+  case 69:
+#line 171 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 70:
+#line 174 "wktparse.y"
+    { alloc_circularstring(); }
+    break;
+
+  case 71:
+#line 174 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 72:
+#line 177 "wktparse.y"
+    { alloc_circularstring_closed(); }
+    break;
+
+  case 73:
+#line 177 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 74:
+#line 180 "wktparse.y"
+    { alloc_counter(); }
+    break;
+
+  case 75:
+#line 180 "wktparse.y"
+    { popc(); }
+    break;
+
+  case 78:
+#line 190 "wktparse.y"
+    { alloc_compoundcurve(); }
+    break;
+
+  case 79:
+#line 190 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 80:
+#line 192 "wktparse.y"
+    {set_zm(0, 1); alloc_compoundcurve(); }
+    break;
+
+  case 81:
+#line 192 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 83:
+#line 197 "wktparse.y"
+    { alloc_counter(); }
+    break;
+
+  case 84:
+#line 197 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 89:
+#line 211 "wktparse.y"
+    { alloc_multilinestring(); }
+    break;
+
+  case 90:
+#line 212 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 91:
+#line 214 "wktparse.y"
+    { set_zm(0, 1); alloc_multilinestring(); }
+    break;
+
+  case 92:
+#line 215 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 94:
+#line 220 "wktparse.y"
+    { alloc_counter(); }
+    break;
+
+  case 95:
+#line 220 "wktparse.y"
+    { pop();}
+    break;
+
+  case 98:
+#line 230 "wktparse.y"
+    { alloc_multicurve(); }
+    break;
+
+  case 99:
+#line 231 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 100:
+#line 233 "wktparse.y"
+    { set_zm(0, 1); alloc_multicurve(); }
+    break;
+
+  case 101:
+#line 234 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 103:
+#line 239 "wktparse.y"
+    { alloc_counter(); }
+    break;
+
+  case 104:
+#line 239 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 110:
+#line 255 "wktparse.y"
+    { set_zm(0, 1); }
+    break;
+
+  case 114:
+#line 263 "wktparse.y"
+    { alloc_polygon(); }
+    break;
+
+  case 115:
+#line 263 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 116:
+#line 266 "wktparse.y"
+    { alloc_polygon(); }
+    break;
+
+  case 117:
+#line 266 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 118:
+#line 269 "wktparse.y"
+    { alloc_counter(); }
+    break;
+
+  case 119:
+#line 269 "wktparse.y"
+    { pop();}
+    break;
+
+  case 122:
+#line 279 "wktparse.y"
+    { alloc_curvepolygon(); }
+    break;
+
+  case 123:
+#line 279 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 124:
+#line 281 "wktparse.y"
+    { set_zm(0, 1); alloc_curvepolygon(); }
+    break;
+
+  case 125:
+#line 282 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 127:
+#line 287 "wktparse.y"
+    { alloc_counter(); }
+    break;
+
+  case 128:
+#line 287 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 133:
+#line 301 "wktparse.y"
+    { alloc_multipolygon(); }
+    break;
+
+  case 134:
+#line 301 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 135:
+#line 303 "wktparse.y"
+    { set_zm(0, 1); alloc_multipolygon(); }
+    break;
+
+  case 136:
+#line 304 "wktparse.y"
+    { pop();}
+    break;
+
+  case 138:
+#line 309 "wktparse.y"
+    { alloc_counter(); }
+    break;
+
+  case 139:
+#line 309 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 142:
+#line 319 "wktparse.y"
+    {alloc_multisurface(); }
+    break;
+
+  case 143:
+#line 319 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 144:
+#line 321 "wktparse.y"
+    { set_zm(0, 1); alloc_multisurface(); }
+    break;
+
+  case 145:
+#line 322 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 147:
+#line 327 "wktparse.y"
+    { alloc_counter(); }
+    break;
+
+  case 148:
+#line 327 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 153:
+#line 341 "wktparse.y"
+    { alloc_geomertycollection(); }
+    break;
+
+  case 154:
+#line 342 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 155:
+#line 344 "wktparse.y"
+    { set_zm(0, 1); alloc_geomertycollection(); }
+    break;
+
+  case 156:
+#line 345 "wktparse.y"
+    { pop();}
+    break;
+
+  case 158:
+#line 350 "wktparse.y"
+    { alloc_counter(); }
+    break;
+
+  case 159:
+#line 350 "wktparse.y"
+    { pop(); }
+    break;
+
+  case 166:
+#line 369 "wktparse.y"
+    {alloc_point_2d(yyvsp[-1].value,yyvsp[0].value); }
+    break;
+
+  case 167:
+#line 372 "wktparse.y"
+    {alloc_point_3d(yyvsp[-2].value,yyvsp[-1].value,yyvsp[0].value); }
+    break;
+
+  case 168:
+#line 375 "wktparse.y"
+    {alloc_point_4d(yyvsp[-3].value,yyvsp[-2].value,yyvsp[-1].value,yyvsp[0].value); }
+    break;
+
+  case 169:
+#line 378 "wktparse.y"
+    { alloc_empty(); }
+    break;
+
+
+    }
+
+/* Line 1000 of yacc.c.  */
+#line 1761 "y.tab.c"
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+
+
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (YYPACT_NINF < yyn && yyn < YYLAST)
+	{
+	  YYSIZE_T yysize = 0;
+	  int yytype = YYTRANSLATE (yychar);
+	  const char* yyprefix;
+	  char *yymsg;
+	  int yyx;
+
+	  /* Start YYX at -YYN if negative to avoid negative indexes in
+	     YYCHECK.  */
+	  int yyxbegin = yyn < 0 ? -yyn : 0;
+
+	  /* Stay within bounds of both yycheck and yytname.  */
+	  int yychecklim = YYLAST - yyn;
+	  int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+	  int yycount = 0;
+
+	  yyprefix = ", expecting ";
+	  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	      {
+		yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
+		yycount += 1;
+		if (yycount == 5)
+		  {
+		    yysize = 0;
+		    break;
+		  }
+	      }
+	  yysize += (sizeof ("syntax error, unexpected ")
+		     + yystrlen (yytname[yytype]));
+	  yymsg = (char *) YYSTACK_ALLOC (yysize);
+	  if (yymsg != 0)
+	    {
+	      char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+	      yyp = yystpcpy (yyp, yytname[yytype]);
+
+	      if (yycount < 5)
+		{
+		  yyprefix = ", expecting ";
+		  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+		    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+		      {
+			yyp = yystpcpy (yyp, yyprefix);
+			yyp = yystpcpy (yyp, yytname[yyx]);
+			yyprefix = " or ";
+		      }
+		}
+	      yyerror (yymsg);
+	      YYSTACK_FREE (yymsg);
+	    }
+	  else
+	    yyerror ("syntax error; also virtual memory exhausted");
+	}
+      else
+#endif /* YYERROR_VERBOSE */
+	yyerror ("syntax error");
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* If at end of input, pop the error token,
+	     then the rest of the stack, then return failure.  */
+	  if (yychar == YYEOF)
+	     for (;;)
+	       {
+		 YYPOPSTACK;
+		 if (yyssp == yyss)
+		   YYABORT;
+		 YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+		 yydestruct (yystos[*yyssp], yyvsp);
+	       }
+        }
+      else
+	{
+	  YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+	  yydestruct (yytoken, &yylval);
+	  yychar = YYEMPTY;
+
+	}
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+#ifdef __GNUC__
+  /* Pacify GCC when the user code never invokes YYERROR and the label
+     yyerrorlab therefore never appears in user code.  */
+  if (0)
+     goto yyerrorlab;
+#endif
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+      yydestruct (yystos[yystate], yyvsp);
+      YYPOPSTACK;
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here.  |
+`----------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+
+
+#line 379 "wktparse.y"
+
+
+
+
+
+

Added: trunk/liblwgeom/wktparse.tab.h
===================================================================
--- trunk/liblwgeom/wktparse.tab.h	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/wktparse.tab.h	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,120 @@
+/* A Bison parser, made by GNU Bison 1.875c.  */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+   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, 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     POINT = 258,
+     LINESTRING = 259,
+     POLYGON = 260,
+     MULTIPOINT = 261,
+     MULTILINESTRING = 262,
+     MULTIPOLYGON = 263,
+     GEOMETRYCOLLECTION = 264,
+     CIRCULARSTRING = 265,
+     COMPOUNDCURVE = 266,
+     CURVEPOLYGON = 267,
+     MULTICURVE = 268,
+     MULTISURFACE = 269,
+     POINTM = 270,
+     LINESTRINGM = 271,
+     POLYGONM = 272,
+     MULTIPOINTM = 273,
+     MULTILINESTRINGM = 274,
+     MULTIPOLYGONM = 275,
+     GEOMETRYCOLLECTIONM = 276,
+     CIRCULARSTRINGM = 277,
+     COMPOUNDCURVEM = 278,
+     CURVEPOLYGONM = 279,
+     MULTICURVEM = 280,
+     MULTISURFACEM = 281,
+     SRID = 282,
+     EMPTY = 283,
+     VALUE = 284,
+     LPAREN = 285,
+     RPAREN = 286,
+     COMMA = 287,
+     EQUALS = 288,
+     SEMICOLON = 289,
+     WKB = 290
+   };
+#endif
+#define POINT 258
+#define LINESTRING 259
+#define POLYGON 260
+#define MULTIPOINT 261
+#define MULTILINESTRING 262
+#define MULTIPOLYGON 263
+#define GEOMETRYCOLLECTION 264
+#define CIRCULARSTRING 265
+#define COMPOUNDCURVE 266
+#define CURVEPOLYGON 267
+#define MULTICURVE 268
+#define MULTISURFACE 269
+#define POINTM 270
+#define LINESTRINGM 271
+#define POLYGONM 272
+#define MULTIPOINTM 273
+#define MULTILINESTRINGM 274
+#define MULTIPOLYGONM 275
+#define GEOMETRYCOLLECTIONM 276
+#define CIRCULARSTRINGM 277
+#define COMPOUNDCURVEM 278
+#define CURVEPOLYGONM 279
+#define MULTICURVEM 280
+#define MULTISURFACEM 281
+#define SRID 282
+#define EMPTY 283
+#define VALUE 284
+#define LPAREN 285
+#define RPAREN 286
+#define COMMA 287
+#define EQUALS 288
+#define SEMICOLON 289
+#define WKB 290
+
+
+
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#line 20 "wktparse.y"
+typedef union YYSTYPE {
+	double value;
+	const char* wkb;
+} YYSTYPE;
+/* Line 1275 of yacc.c.  */
+#line 112 "y.tab.h"
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE lwg_parse_yylval;
+
+
+

Added: trunk/liblwgeom/wktparse.y
===================================================================
--- trunk/liblwgeom/wktparse.y	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/liblwgeom/wktparse.y	2008-06-29 19:11:48 UTC (rev 2815)
@@ -0,0 +1,383 @@
+/*
+ * Written by Ralph Mason ralph.mason<at>telogis.com
+ *
+ * Copyright Telogis 2004
+ * www.telogis.com
+ *
+ */
+
+%{
+#include "wktparse.h"
+#include <unistd.h>
+#include <stdio.h>
+
+void set_zm(char z, char m);
+int lwg_parse_yylex(void);
+%}
+
+%start geometry
+
+%union {
+	double value;
+	const char* wkb;
+}
+
+%token POINT LINESTRING POLYGON MULTIPOINT MULTILINESTRING MULTIPOLYGON GEOMETRYCOLLECTION CIRCULARSTRING COMPOUNDCURVE CURVEPOLYGON MULTICURVE MULTISURFACE
+%token POINTM LINESTRINGM POLYGONM MULTIPOINTM MULTILINESTRINGM MULTIPOLYGONM GEOMETRYCOLLECTIONM CIRCULARSTRINGM COMPOUNDCURVEM CURVEPOLYGONM  MULTICURVEM MULTISURFACEM
+%token SRID      
+%token EMPTY
+%token <value> VALUE
+%token LPAREN RPAREN COMMA EQUALS SEMICOLON
+%token  <wkb> WKB
+
+%%
+
+geometry :
+	srid  SEMICOLON  { alloc_lwgeom(srid); } geometry_int 
+	|
+	{ alloc_lwgeom(-1); } geometry_int
+
+geometry_int :
+	geom_wkb
+	|
+	geom_point
+	|
+	geom_linestring
+	|
+        geom_circularstring
+        |
+	geom_polygon
+	|
+        geom_compoundcurve
+        |
+        geom_curvepolygon
+        |
+	geom_multipoint 
+	|
+	geom_multilinestring
+        |
+        geom_multicurve
+	|
+	geom_multipolygon
+	|
+        geom_multisurface
+        |
+	geom_geometrycollection
+
+srid :
+	SRID EQUALS VALUE { set_srid($3); } 
+
+geom_wkb :
+	WKB { alloc_wkb($1); }
+
+
+/* POINT */
+
+geom_point :
+	POINT point
+	|
+	POINTM { set_zm(0, 1); } point 
+
+point :
+	empty_point
+	|
+	nonempty_point
+
+empty_point :
+	{ alloc_point(); } empty { pop(); } 
+
+nonempty_point :
+	{ alloc_point(); } point_int { pop(); } 
+
+point_int :
+	LPAREN a_point RPAREN
+
+/* MULTIPOINT */
+
+geom_multipoint :
+	MULTIPOINT { alloc_multipoint(); } multipoint  { pop(); }
+	| 
+	MULTIPOINTM { set_zm(0, 1); alloc_multipoint(); } multipoint {pop(); }
+
+multipoint :
+	empty
+	|
+	{ alloc_counter(); } LPAREN multipoint_int RPAREN { pop(); } 
+
+multipoint_int :
+	mpoint_element
+	|
+	multipoint_int COMMA mpoint_element
+
+mpoint_element :
+	nonempty_point
+	|
+	/* this is to allow MULTIPOINT(0 0, 1 1) */
+	{ alloc_point(); } a_point { pop(); }
+
+
+/* LINESTRING */
+
+geom_linestring :
+	LINESTRING linestring
+	|
+	LINESTRINGM { set_zm(0, 1); } linestring
+
+linestring :
+	empty_linestring
+	|
+	nonempty_linestring
+
+empty_linestring :
+	{ alloc_linestring(); } empty { pop(); } 
+
+nonempty_linestring :
+	{ alloc_linestring(); } linestring_1 { pop(); } 
+
+nonempty_linestring_closed :
+        { alloc_linestring_closed(); } linestring_1 { pop(); }
+
+linestring_1 :
+	{ alloc_counter(); } LPAREN linestring_int RPAREN { popc(); }
+
+linestring_int :
+	a_point
+	|
+	linestring_int COMMA a_point;
+
+/* CIRCULARSTRING */
+
+geom_circularstring :
+        CIRCULARSTRING circularstring
+        |
+        CIRCULARSTRINGM {set_zm(0, 1); } circularstring
+
+geom_circularstring_closed :
+        CIRCULARSTRING circularstring_closed
+        |
+        CIRCULARSTRINGM {set_zm(0, 1); } circularstring_closed
+
+circularstring :
+        empty_circularstring
+        |
+        nonempty_circularstring
+
+circularstring_closed :
+        empty_circularstring
+        |
+        nonempty_circularstring_closed
+
+empty_circularstring :
+        { alloc_circularstring(); } empty { pop(); }
+
+nonempty_circularstring :
+        { alloc_circularstring(); } circularstring_1 { pop(); }
+
+nonempty_circularstring_closed :
+        { alloc_circularstring_closed(); } circularstring_1 { pop(); }
+
+circularstring_1 :
+        { alloc_counter(); } LPAREN circularstring_int RPAREN { popc(); }
+
+circularstring_int :
+        a_point
+        |
+        circularstring_int COMMA a_point;
+
+/* COMPOUNDCURVE */
+
+geom_compoundcurve:
+        COMPOUNDCURVE { alloc_compoundcurve(); } compoundcurve { pop(); }
+        |
+        COMPOUNDCURVEM {set_zm(0, 1); alloc_compoundcurve(); } compoundcurve { pop(); }
+
+compoundcurve:
+        empty
+        |
+        { alloc_counter(); } LPAREN compoundcurve_int RPAREN { pop(); }
+
+compoundcurve_int:
+        nonempty_linestring
+        |
+        geom_circularstring
+        |
+        compoundcurve_int COMMA nonempty_linestring
+        |
+        compoundcurve_int COMMA geom_circularstring
+
+/* MULTILINESTRING */
+
+geom_multilinestring :
+	MULTILINESTRING { alloc_multilinestring(); }
+		multilinestring  { pop(); }
+	|
+	MULTILINESTRINGM { set_zm(0, 1); alloc_multilinestring(); }
+		multilinestring { pop(); } 
+
+multilinestring :
+	empty
+	|
+	{ alloc_counter(); } LPAREN multilinestring_int RPAREN{ pop();}
+
+multilinestring_int :
+	nonempty_linestring
+	|
+	multilinestring_int COMMA nonempty_linestring
+
+/* MULTICURVESTRING */
+
+geom_multicurve :
+        MULTICURVE { alloc_multicurve(); }
+                multicurve { pop(); }
+        |
+        MULTICURVEM { set_zm(0, 1); alloc_multicurve(); }
+                multicurve { pop(); }
+
+multicurve :
+        empty
+        |
+        { alloc_counter(); } LPAREN multicurve_int RPAREN { pop(); }
+
+multicurve_int :
+        nonempty_linestring
+        |
+        geom_circularstring
+        |
+        multicurve_int COMMA nonempty_linestring
+        |
+        multicurve_int COMMA geom_circularstring
+
+/* POLYGON */
+
+geom_polygon :
+	POLYGON polygon
+	|
+	POLYGONM { set_zm(0, 1); } polygon 
+
+polygon :
+	empty_polygon
+	|
+	nonempty_polygon
+
+empty_polygon :
+	{ alloc_polygon(); } empty  { pop(); } 
+
+nonempty_polygon :
+	{ alloc_polygon(); } polygon_1  { pop(); } 
+
+polygon_1 :
+	{ alloc_counter(); } LPAREN polygon_int RPAREN { pop();} 
+
+polygon_int :
+	linestring_1
+	|
+	polygon_int COMMA linestring_1
+
+/* CURVEPOLYGON */
+
+geom_curvepolygon :
+        CURVEPOLYGON { alloc_curvepolygon(); } curvepolygon { pop(); }
+        |
+        CURVEPOLYGONM { set_zm(0, 1); alloc_curvepolygon(); } 
+                        curvepolygon { pop(); }
+
+curvepolygon :
+        empty
+        |
+        { alloc_counter(); } LPAREN curvepolygon_int RPAREN { pop(); }
+
+curvepolygon_int :
+        nonempty_linestring_closed
+        |
+        geom_circularstring_closed
+        |
+        curvepolygon_int COMMA nonempty_linestring_closed
+        |
+        curvepolygon_int COMMA geom_circularstring_closed
+
+/* MULTIPOLYGON */
+
+geom_multipolygon :
+	MULTIPOLYGON { alloc_multipolygon(); } multipolygon { pop(); }
+	|
+	MULTIPOLYGONM { set_zm(0, 1); alloc_multipolygon(); }
+		multipolygon { pop();} 
+
+multipolygon :
+	empty
+	|
+	{ alloc_counter(); } LPAREN multipolygon_int RPAREN { pop(); }
+
+multipolygon_int :
+	nonempty_polygon
+	|
+	multipolygon_int COMMA nonempty_polygon
+
+/* MULTISURFACE */
+
+geom_multisurface :
+        MULTISURFACE {alloc_multisurface(); } multisurface { pop(); }
+        |
+        MULTISURFACEM { set_zm(0, 1); alloc_multisurface(); }
+                multisurface { pop(); }
+
+multisurface :
+        empty
+        |
+        { alloc_counter(); } LPAREN multisurface_int RPAREN { pop(); }
+
+multisurface_int :
+        nonempty_polygon
+        |
+        geom_curvepolygon
+        |
+        multisurface_int COMMA nonempty_polygon
+        |
+        multisurface_int COMMA geom_curvepolygon
+
+/* GEOMETRYCOLLECTION */
+
+geom_geometrycollection :
+	GEOMETRYCOLLECTION { alloc_geomertycollection(); }
+		geometrycollection { pop(); }
+	|
+	GEOMETRYCOLLECTIONM { set_zm(0, 1); alloc_geomertycollection(); }
+		geometrycollection { pop();}
+
+geometrycollection :
+	empty
+	|
+	{ alloc_counter(); } LPAREN geometrycollection_int RPAREN { pop(); }
+
+geometrycollection_int :
+	/* to support GEOMETRYCOLLECTION(EMPTY) for backward compatibility */
+	empty
+	|
+	geometry_int
+	|
+	geometrycollection_int COMMA geometry_int
+
+
+a_point :
+	point_2d
+	|
+	point_3d
+	|
+	point_4d 
+
+point_2d :
+	VALUE VALUE {alloc_point_2d($1,$2); }
+
+point_3d :
+	VALUE VALUE VALUE {alloc_point_3d($1,$2,$3); }
+
+point_4d :
+	VALUE VALUE VALUE VALUE {alloc_point_4d($1,$2,$3,$4); }
+
+empty :
+	EMPTY { alloc_empty(); }
+%%
+
+
+
+

Modified: trunk/lwgeom/Makefile.in
===================================================================
--- trunk/lwgeom/Makefile.in	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/Makefile.in	2008-06-29 19:11:48 UTC (rev 2815)
@@ -20,33 +20,8 @@
 # SQL objects (files requiring C pre-processing)
 SQL_OBJS=lwpostgis.sql.in
 
-# Standalone LWGEOM objects
-SA_OBJS=measures.o \
-	box2d.o \
-	ptarray.o \
-	lwgeom_api.o \
-	lwgeom.o \
-	lwpoint.o \
-	lwline.o \
-	lwpoly.o \
-	lwmpoint.o \
-	lwmline.o \
-	lwmpoly.o \
-	lwcollection.o \
-	lwcurve.o \
-	lwcompound.o \
-	lwcurvepoly.o \
-	lwmcurve.o \
-	lwmsurface.o \
-	wktunparse.o \
-	lwgparse.o \
-	wktparse.tab.o \
-	lex.yy.o \
-	vsprintf.o	
-
 # PostgreSQL objects
-PG_OBJS=liblwgeom.o \
-	lwgeom_pg.o \
+PG_OBJS=lwgeom_pg.o \
 	lwgeom_debug.o \
 	lwgeom_spheroid.o \
 	lwgeom_ogc.o \
@@ -75,10 +50,11 @@
 	lwgeom_rtree.o
 
 # Objects to build using PGXS
-OBJS=$(SA_OBJS) $(PG_OBJS)
+OBJS=$(PG_OBJS)
 
 # Libraries to link into the module (proj, geos)
-SHLIB_LINK=@SHLIB_LINK@
+PG_CPPFLAGS=@CPPFLAGS@ -I../liblwgeom
+SHLIB_LINK=@SHLIB_LINK@ -L../liblwgeom -llwgeom
 
 # Extra files to remove during 'make clean'
 EXTRA_CLEAN=$(SQL_OBJS)

Deleted: trunk/lwgeom/box2d.c
===================================================================
--- trunk/lwgeom/box2d.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/box2d.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,54 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "liblwgeom.h"
-
-#ifndef EPSILON
-#define EPSILON        1.0E-06
-#endif
-#ifndef FPeq
-#define FPeq(A,B)     (fabs((A) - (B)) <= EPSILON)
-#endif
-
-
-/* Expand given box of 'd' units in all directions */
-void
-expand_box2d(BOX2DFLOAT4 *box, double d)
-{
-	box->xmin -= d;
-	box->ymin -= d;
-
-	box->xmax += d;
-	box->ymax += d;
-}
-
-
-/*
- * This has been changed in PostGIS 1.1.2 to
- * check exact equality of values (rather then using
- * the FPeq macro taking into account coordinate drifts).
- */
-char
-box2d_same(BOX2DFLOAT4 *box1, BOX2DFLOAT4 *box2)
-{
-	return(	(box1->xmax==box2->xmax) &&
-		(box1->xmin==box2->xmin) &&
-		(box1->ymax==box2->ymax) &&
-		(box1->ymin==box2->ymin));
-#if 0 
-	return(FPeq(box1->xmax, box2->xmax) &&
-				   FPeq(box1->xmin, box2->xmin) &&
-				   FPeq(box1->ymax, box2->ymax) &&
-				   FPeq(box1->ymin, box2->ymin));
-#endif
-}
-
-BOX2DFLOAT4 *
-box2d_clone(const BOX2DFLOAT4 *in)
-{
-	BOX2DFLOAT4 *ret = lwalloc(sizeof(BOX2DFLOAT4));
-	memcpy(ret, in, sizeof(BOX2DFLOAT4));
-	return ret;
-}

Deleted: trunk/lwgeom/lex.yy.c
===================================================================
--- trunk/lwgeom/lex.yy.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lex.yy.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,4562 +0,0 @@
-#define yy_create_buffer lwg_parse_yy_create_buffer
-#define yy_delete_buffer lwg_parse_yy_delete_buffer
-#define yy_scan_buffer lwg_parse_yy_scan_buffer
-#define yy_scan_string lwg_parse_yy_scan_string
-#define yy_scan_bytes lwg_parse_yy_scan_bytes
-#define yy_flex_debug lwg_parse_yy_flex_debug
-#define yy_init_buffer lwg_parse_yy_init_buffer
-#define yy_flush_buffer lwg_parse_yy_flush_buffer
-#define yy_load_buffer_state lwg_parse_yy_load_buffer_state
-#define yy_switch_to_buffer lwg_parse_yy_switch_to_buffer
-#define yyin lwg_parse_yyin
-#define yyleng lwg_parse_yyleng
-#define yylex lwg_parse_yylex
-#define yyout lwg_parse_yyout
-#define yyrestart lwg_parse_yyrestart
-#define yytext lwg_parse_yytext
-#define yywrap lwg_parse_yywrap
-
-#line 20 "lex.yy.c"
-/* A lexical scanner generated by flex */
-
-/* Scanner skeleton version:
- * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
- */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-
-#include <stdio.h>
-#include <unistd.h>
-
-
-/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
-#ifdef c_plusplus
-#ifndef __cplusplus
-#define __cplusplus
-#endif
-#endif
-
-
-#ifdef __cplusplus
-
-#include <stdlib.h>
-
-/* Use prototypes in function declarations. */
-#define YY_USE_PROTOS
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-#if __STDC__
-
-#define YY_USE_PROTOS
-#define YY_USE_CONST
-
-#endif	/* __STDC__ */
-#endif	/* ! __cplusplus */
-
-#ifdef __TURBOC__
- #pragma warn -rch
- #pragma warn -use
-#include <io.h>
-#include <stdlib.h>
-#define YY_USE_CONST
-#define YY_USE_PROTOS
-#endif
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-
-#ifdef YY_USE_PROTOS
-#define YY_PROTO(proto) proto
-#else
-#define YY_PROTO(proto) ()
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart( yyin )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#define YY_BUF_SIZE 16384
-
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-
-extern int yyleng;
-extern FILE *yyin, *yyout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-/* The funky do-while in the following #define is used to turn the definition
- * int a single C statement (which needs a semi-colon terminator).  This
- * avoids problems with code like:
- *
- * 	if ( condition_holds )
- *		yyless( 5 );
- *	else
- *		do_something_else();
- *
- * Prior to using the do-while the compiler would get upset at the
- * "else" because it interpreted the "if" statement as being all
- * done when it reached the ';' after the yyless() call.
- */
-
-/* Return all but the first 'n' matched characters back to the input stream. */
-
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-		*yy_cp = yy_hold_char; \
-		YY_RESTORE_YY_MORE_OFFSET \
-		yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, yytext_ptr )
-
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-typedef unsigned int yy_size_t;
-
-
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via yyrestart()), so that the user can continue scanning by
-	 * just pointing yyin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-	};
-
-static YY_BUFFER_STATE yy_current_buffer = 0;
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- */
-#define YY_CURRENT_BUFFER yy_current_buffer
-
-
-/* yy_hold_char holds the character lost when yytext is formed. */
-static char yy_hold_char;
-
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-
-
-int yyleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 1;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow yywrap()'s to do buffer switches
- * instead of setting up a fresh yyin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void yyrestart YY_PROTO(( FILE *input_file ));
-
-void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
-void yy_load_buffer_state YY_PROTO(( void ));
-YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
-void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
-void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
-
-YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
-YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
-YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
-
-static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
-static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
-static void yy_flex_free YY_PROTO(( void * ));
-
-#define yy_new_buffer yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! yy_current_buffer ) \
-		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
-	yy_current_buffer->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! yy_current_buffer ) \
-		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
-	yy_current_buffer->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
-
-typedef char YY_CHAR;
-FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
-typedef int yy_state_type;
-extern char *yytext;
-#define yytext_ptr yytext
-static yyconst short yy_nxt[][128] =
-    {
-    {
-        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,    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,
-        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,    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,
-
-        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,    0,    0,    0
-    },
-
-    {
-        5,    6,    6,    6,    6,    6,    6,    6,    6,    7,
-        8,    6,    6,    7,    6,    6,    6,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,    6,
-        6,    6,    7,    6,    6,    6,    6,    6,    6,    6,
-        9,   10,    6,    6,   11,    6,    6,    6,   12,    6,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,   13,
-        6,   14,    6,    6,    6,    6,    6,   15,    6,   16,
-
-        6,   17,    6,    6,    6,    6,   18,   19,    6,    6,
-       20,    6,    6,   21,    6,    6,    6,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,   15,
-        6,   16,    6,   17,    6,    6,    6,    6,   18,   19,
-        6,    6,   20,    6,    6,   21,    6,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    6
-    },
-
-    {
-        5,    6,    6,    6,    6,    6,    6,    6,    6,    7,
-        8,    6,    6,    7,    6,    6,    6,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,    6,
-        6,    6,    7,    6,    6,    6,    6,    6,    6,    6,
-
-        9,   10,    6,    6,   11,    6,    6,    6,   12,    6,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,   13,
-        6,   14,    6,    6,    6,    6,    6,   15,    6,   16,
-        6,   17,    6,    6,    6,    6,   18,   19,    6,    6,
-       20,    6,    6,   21,    6,    6,    6,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,   15,
-        6,   16,    6,   17,    6,    6,    6,    6,   18,   19,
-        6,    6,   20,    6,    6,   21,    6,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    6
-    },
-
-    {
-        5,    6,    6,    6,    6,    6,    6,    6,    6,    7,
-
-        8,    6,    6,    7,    6,    6,    6,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,    6,
-        6,    6,    7,    6,    6,    6,    6,    6,    6,    6,
-        9,   10,    6,   22,   11,   22,   23,    6,   24,   24,
-       24,   24,   24,   24,   24,   24,   24,   24,    6,   13,
-        6,   14,    6,    6,    6,    6,    6,   15,    6,   16,
-        6,   17,    6,    6,    6,    6,   18,   19,    6,    6,
-       20,    6,    6,   21,    6,    6,    6,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,   15,
-        6,   16,    6,   17,    6,    6,    6,    6,   18,   19,
-
-        6,    6,   20,    6,    6,   21,    6,    6,    6,    6,
-        6,    6,    6,    6,   22,    6,    6,    6
-    },
-
-    {
-        5,    6,    6,    6,    6,    6,    6,    6,    6,    7,
-        8,    6,    6,    7,    6,    6,    6,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,    6,
-        6,    6,    7,    6,    6,    6,    6,    6,    6,    6,
-        9,   10,    6,   22,   11,   22,   23,    6,   24,   24,
-       24,   24,   24,   24,   24,   24,   24,   24,    6,   13,
-        6,   14,    6,    6,    6,    6,    6,   15,    6,   16,
-        6,   17,    6,    6,    6,    6,   18,   19,    6,    6,
-
-       20,    6,    6,   21,    6,    6,    6,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,   15,
-        6,   16,    6,   17,    6,    6,    6,    6,   18,   19,
-        6,    6,   20,    6,    6,   21,    6,    6,    6,    6,
-        6,    6,    6,    6,   22,    6,    6,    6
-    },
-
-    {
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5,
-       -5,   -5,   -5,   -5,   -5,   -5,   -5,   -5
-    },
-
-    {
-        5,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6,
-
-       -6,   -6,   -6,   -6,   -6,   -6,   -6,   -6
-    },
-
-    {
-        5,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   25,
-       25,   -7,   -7,   25,   -7,   -7,   -7,   -7,   -7,   -7,
-       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
-       -7,   -7,   25,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
-       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
-       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
-       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
-       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
-       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
-
-       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
-       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
-       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7,
-       -7,   -7,   -7,   -7,   -7,   -7,   -7,   -7
-    },
-
-    {
-        5,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   25,
-       25,   -8,   -8,   25,   -8,   -8,   -8,   -8,   -8,   -8,
-       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
-       -8,   -8,   25,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
-       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
-       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
-
-       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
-       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
-       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
-       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
-       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
-       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8,
-       -8,   -8,   -8,   -8,   -8,   -8,   -8,   -8
-    },
-
-    {
-        5,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9
-
-    },
-
-    {
-        5,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10
-    },
-
-    {
-        5,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11
-    },
-
-    {
-        5,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,   26,   27,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12
-    },
-
-    {
-        5,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13
-    },
-
-    {
-        5,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14
-    },
-
-    {
-        5,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
-      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
-      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
-      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
-      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
-
-      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
-      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
-      -15,  -15,  -15,   28,  -15,  -15,  -15,  -15,  -15,   29,
-      -15,  -15,  -15,  -15,  -15,   30,  -15,  -15,  -15,  -15,
-      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15,
-      -15,  -15,  -15,  -15,  -15,   28,  -15,  -15,  -15,  -15,
-      -15,   29,  -15,  -15,  -15,  -15,  -15,   30,  -15,  -15,
-      -15,  -15,  -15,  -15,  -15,  -15,  -15,  -15
-    },
-
-    {
-        5,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,   31,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,   31,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16
-    },
-
-    {
-        5,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,   32,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,   32,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17
-    },
-
-    {
-        5,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,   33,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,   33,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18
-    },
-
-    {
-        5,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,   34,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,   34,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19
-
-    },
-
-    {
-        5,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,   35,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,   35,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20
-    },
-
-    {
-        5,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,   36,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,   36,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21
-    },
-
-    {
-        5,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-
-      -22,  -22,  -22,  -22,  -22,  -22,   37,  -22,   38,   38,
-       38,   38,   38,   38,   38,   38,   38,   38,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22
-    },
-
-    {
-        5,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23
-    },
-
-    {
-        5,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,   40,  -24,   38,   38,
-       38,   38,   38,   38,   38,   38,   38,   38,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,   41,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,   41,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24
-    },
-
-    {
-        5,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,   25,
-       25,  -25,  -25,   25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,   25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-
-      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25
-    },
-
-    {
-        5,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-
-      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,   42,   42,
-       42,   42,   42,   42,   42,   42,   42,   42,  -26,  -26,
-      -26,  -26,  -26,  -26,  -26,   42,   42,   42,   42,   42,
-       42,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-      -26,  -26,  -26,  -26,  -26,  -26,  -26,   42,   42,   42,
-       42,   42,   42,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-
-      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26
-    },
-
-    {
-        5,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,   43,   43,   43,   43,   43,
-       43,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-
-      -27,  -27,  -27,  -27,  -27,  -27,  -27,   43,   43,   43,
-       43,   43,   43,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27
-    },
-
-    {
-        5,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-
-      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,   44,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,  -28,   44,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28
-    },
-
-    {
-        5,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,   45,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,   45,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29
-
-    },
-
-    {
-        5,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,   46,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,   46,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30
-    },
-
-    {
-        5,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-       47,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,   47,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31
-    },
-
-    {
-        5,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,   48,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,   48,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32
-    },
-
-    {
-        5,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,   49,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-
-       49,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33
-    },
-
-    {
-        5,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,   50,  -34,  -34,  -34,
-
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,   50,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34
-    },
-
-    {
-        5,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,   51,  -35,  -35,   52,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,   51,  -35,  -35,   52,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
-    },
-
-    {
-        5,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,   53,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,   53,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
-    },
-
-    {
-        5,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37
-    },
-
-    {
-        5,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,   40,  -38,   38,   38,
-       38,   38,   38,   38,   38,   38,   38,   38,  -38,  -38,
-
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,   41,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,   41,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38
-    },
-
-    {
-        5,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,   54,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,   54,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39
-
-    },
-
-    {
-        5,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40
-    },
-
-    {
-        5,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,   56,  -41,   56,  -41,  -41,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41
-    },
-
-    {
-        5,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,   42,   42,
-       42,   42,   42,   42,   42,   42,   42,   42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,   42,   42,   42,   42,   42,
-       42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,   42,   42,   42,
-       42,   42,   42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42
-    },
-
-    {
-        5,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,   43,   43,   43,   43,   43,
-       43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,   43,   43,   43,
-       43,   43,   43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43
-    },
-
-    {
-        5,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,   58,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,   58,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44
-    },
-
-    {
-        5,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-       59,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,   59,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45
-    },
-
-    {
-        5,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,   60,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,   60,  -46,
-
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46
-    },
-
-    {
-        5,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,   61,  -47,  -47,  -47,  -47,  -47,
-
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,   61,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47
-    },
-
-    {
-        5,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,   62,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,   62,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48
-    },
-
-    {
-        5,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,   63,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,   63,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49
-
-    },
-
-    {
-        5,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,   64,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,   64,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50
-    },
-
-    {
-        5,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,   65,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-       65,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51
-    },
-
-    {
-        5,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,   66,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,   66,  -52,  -52,  -52,  -52,  -52,  -52
-    },
-
-    {
-        5,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,   67,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-       67,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53
-    },
-
-    {
-        5,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,   68,  -54,   68,  -54,  -54,   69,   69,
-       69,   69,   69,   69,   69,   69,   69,   69,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54
-    },
-
-    {
-        5,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,   55,   55,
-
-       55,   55,   55,   55,   55,   55,   55,   55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,   41,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,   41,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55
-    },
-
-    {
-        5,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56
-    },
-
-    {
-        5,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57
-    },
-
-    {
-        5,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,   70,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,   70,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58
-    },
-
-    {
-        5,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,   71,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,   71,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59
-
-    },
-
-    {
-        5,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,   72,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-
-      -60,   72,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60
-    },
-
-    {
-        5,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,   73,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,   73,  -61,  -61,  -61,  -61,  -61,  -61
-    },
-
-    {
-        5,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,   74,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,   74,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62
-    },
-
-    {
-        5,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,   75,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-
-      -63,  -63,  -63,  -63,  -63,   75,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63
-    },
-
-    {
-        5,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,   76,  -64,  -64,  -64,  -64,  -64,  -64,
-
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,   76,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64
-    },
-
-    {
-        5,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,   77,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,   77,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65
-    },
-
-    {
-        5,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,   78,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,   78,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66
-    },
-
-    {
-        5,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67
-    },
-
-    {
-        5,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,   69,   69,
-       69,   69,   69,   69,   69,   69,   69,   69,  -68,  -68,
-
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68
-    },
-
-    {
-        5,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,   69,   69,
-       69,   69,   69,   69,   69,   69,   69,   69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69
-
-    },
-
-    {
-        5,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,   79,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,   79,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70
-    },
-
-    {
-        5,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,   80,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,   80,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71
-    },
-
-    {
-        5,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-       81,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,   81,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72
-    },
-
-    {
-        5,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73
-    },
-
-    {
-        5,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-
-      -74,  -74,  -74,  -74,   82,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,   82,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74
-    },
-
-    {
-        5,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,   83,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,   83,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75
-    },
-
-    {
-        5,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,   84,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,   85,  -76,  -76,  -76,
-       86,  -76,  -76,   87,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,   84,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,   85,  -76,
-      -76,  -76,   86,  -76,  -76,   87,  -76,  -76,  -76,  -76,
-
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76
-    },
-
-    {
-        5,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,   88,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,   88,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77
-    },
-
-    {
-        5,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,   89,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,   89,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78
-    },
-
-    {
-        5,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,   90,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,   90,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79
-
-    },
-
-    {
-        5,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,   91,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-       91,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
-    },
-
-    {
-        5,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,   92,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,   92,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81
-    },
-
-    {
-        5,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,   93,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,   93,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82
-    },
-
-    {
-        5,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,   94,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-
-      -83,  -83,  -83,  -83,   94,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
-    },
-
-    {
-        5,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-
-      -84,  -84,  -84,  -84,  -84,   95,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,   95,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84
-    },
-
-    {
-        5,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,   96,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,   96,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85
-    },
-
-    {
-        5,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,   97,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,   97,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86
-    },
-
-    {
-        5,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,   98,  -87,  -87,  -87,  -87,
-
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,   98,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87
-    },
-
-    {
-        5,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88
-    },
-
-    {
-        5,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,   99,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-       99,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89
-
-    },
-
-    {
-        5,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  100,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  100,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
-    },
-
-    {
-        5,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  101,  -91,
-
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      101,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91
-    },
-
-    {
-        5,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  102,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  102,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92
-    },
-
-    {
-        5,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  103,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  103,  -93,  -93,  -93,  -93,  -93,  -93
-    },
-
-    {
-        5,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  104,  -94,  -94,  -94,  -94,  -94,  -94,
-
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  104,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94
-    },
-
-    {
-        5,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  105,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  105,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95
-    },
-
-    {
-        5,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  106,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      106,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96
-    },
-
-    {
-        5,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  107,  -97,  -97,  108,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  107,  -97,  -97,  108,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97
-    },
-
-    {
-        5,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  109,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  109,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98
-    },
-
-    {
-        5,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  110,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  110,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99
-
-    },
-
-    {
-        5, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100,  111, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100,  111, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100
-    },
-
-    {
-        5, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101,  112, -101, -101,
-
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101,  112,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101
-    },
-
-    {
-        5, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102,  113,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102,  113, -102, -102, -102, -102, -102, -102
-    },
-
-    {
-        5, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103,  114, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103,  114,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103
-    },
-
-    {
-        5, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104,  115, -104,
-
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-      115, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104
-    },
-
-    {
-        5, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105,  116, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105,  116, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105
-    },
-
-    {
-        5, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106,  117,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106,  117, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-
-     -106, -106, -106, -106, -106, -106, -106, -106
-    },
-
-    {
-        5, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107,  118, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-      118, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107
-    },
-
-    {
-        5, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108,  119,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108,  119, -108, -108, -108, -108, -108, -108
-    },
-
-    {
-        5, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-      120, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109,  120, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109
-
-    },
-
-    {
-        5, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110
-    },
-
-    {
-        5, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111,  121, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111,  121, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111
-    },
-
-    {
-        5, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112,  122, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112,  122, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112
-    },
-
-    {
-        5, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113,  123, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113,  123, -113, -113, -113, -113, -113, -113,
-
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113
-    },
-
-    {
-        5, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114,  124,
-
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114,  124, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114
-    },
-
-    {
-        5, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115,  125, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115,  125, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115
-    },
-
-    {
-        5, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116,  126,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116,  126, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-
-     -116, -116, -116, -116, -116, -116, -116, -116
-    },
-
-    {
-        5, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117,  127, -117, -117, -117, -117, -117, -117,
-
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117,  127, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117
-    },
-
-    {
-        5, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118,  128, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118,  128, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118
-    },
-
-    {
-        5, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119,  129, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119,  129, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119
-
-    },
-
-    {
-        5, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120,  130, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120,  130, -120, -120,
-
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120
-    },
-
-    {
-        5, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121,  131, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121,  131, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121
-    },
-
-    {
-        5, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122,  132, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122,  132, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122
-    },
-
-    {
-        5, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123,  133,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-
-     -123,  133, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123
-    },
-
-    {
-        5, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124,  134, -124, -124, -124,
-
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124,  134, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124
-    },
-
-    {
-        5, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125,  135, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125,  135,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125
-    },
-
-    {
-        5, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126,  136, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126,  136,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-
-     -126, -126, -126, -126, -126, -126, -126, -126
-    },
-
-    {
-        5, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127,  137, -127, -127, -127, -127, -127,
-
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127,  137, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127
-    },
-
-    {
-        5, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128,  138, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128,  138,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128
-    },
-
-    {
-        5, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129,  139,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129,  139, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129
-
-    },
-
-    {
-        5, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130,  140, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130,  140,
-
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130
-    },
-
-    {
-        5, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-
-     -131, -131, -131,  141, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131,  141, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131
-    },
-
-    {
-        5, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132,  142, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132,  142, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132
-    },
-
-    {
-        5, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133,  143, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-
-      143, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133
-    },
-
-    {
-        5, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134,  144, -134, -134, -134,
-
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134,  144, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134
-    },
-
-    {
-        5, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135
-    },
-
-    {
-        5, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-
-     -136, -136, -136, -136, -136, -136, -136, -136
-    },
-
-    {
-        5, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137,  145, -137, -137, -137, -137, -137, -137, -137,
-
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137,  145, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137
-    },
-
-    {
-        5, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138
-    },
-
-    {
-        5, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139,  146, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-      146, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139
-
-    },
-
-    {
-        5, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140,  147,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-
-     -140,  147, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140
-    },
-
-    {
-        5, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-
-     -141, -141, -141, -141, -141, -141, -141, -141,  148, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-      148, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141
-    },
-
-    {
-        5, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142,  149,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142,  149, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142
-    },
-
-    {
-        5, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143,  150, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143,  150,
-
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143
-    },
-
-    {
-        5, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144,  151,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144,  151, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144
-    },
-
-    {
-        5, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145,  152, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145,  152, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145
-    },
-
-    {
-        5, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146,  153, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146,  153,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-
-     -146, -146, -146, -146, -146, -146, -146, -146
-    },
-
-    {
-        5, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147,  154, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147,  154,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147
-    },
-
-    {
-        5, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148,  155, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148,  155, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148
-    },
-
-    {
-        5, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149,  156, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149,  156,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149
-
-    },
-
-    {
-        5, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150
-    },
-
-    {
-        5, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151,  157, -151, -151,
-
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151,  157,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151
-    },
-
-    {
-        5, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152,  158, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-      158, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152
-    },
-
-    {
-        5, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153
-    },
-
-    {
-        5, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154
-    },
-
-    {
-        5, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155,  159, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155,  159,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155
-    },
-
-    {
-        5, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-
-     -156, -156, -156, -156, -156, -156, -156, -156
-    },
-
-    {
-        5, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157,  160, -157, -157, -157, -157, -157,
-
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157,  160, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157
-    },
-
-    {
-        5, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158,  161, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158,  161, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158
-    },
-
-    {
-        5, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-
-     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159
-
-    },
-
-    {
-        5, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160,  162, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-
-     -160, -160, -160, -160, -160,  162, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160
-    },
-
-    {
-        5, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-
-     -161, -161, -161, -161, -161, -161, -161,  163, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161,  163,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161
-    },
-
-    {
-        5, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162,  164,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162,  164, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162
-    },
-
-    {
-        5, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163
-    },
-
-    {
-        5, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164,  165, -164,
-
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-      165, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164
-    },
-
-    {
-        5, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165,  166, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165,  166,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165
-    },
-
-    {
-        5, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-
-     -166, -166, -166, -166, -166, -166, -166, -166
-    },
-
-    } ;
-
-
-static yy_state_type yy_get_previous_state YY_PROTO(( void ));
-static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
-static int yy_get_next_buffer YY_PROTO(( void ));
-static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	yytext_ptr = yy_bp; \
-	yyleng = (int) (yy_cp - yy_bp); \
-	yy_hold_char = *yy_cp; \
-	*yy_cp = '\0'; \
-	yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 38
-#define YY_END_OF_BUFFER 39
-static yyconst short int yy_accept[167] =
-    {   0,
-        0,    0,    0,    0,   39,   37,   36,   36,   31,   32,
-       33,   37,   35,   34,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,    1,   36,    3,    4,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    1,    2,    0,
-        0,    3,    4,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    1,    0,    1,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,   29,    0,    2,    0,
-        0,    0,   30,    0,    0,    0,    5,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    6,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,   11,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,   12,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    7,   21,    0,   17,    0,    0,
-        0,    0,    0,    0,    8,   22,    0,   18,    0,    0,
-        0,    0,   15,    0,    0,   23,   25,    0,   13,   16,
-        0,    0,   24,   26,    9,   14,    0,    0,   10,    0,
-       19,    0,   20,    0,   27,   28
-    } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-static yyconst yy_state_type yy_NUL_trans[167] =
-    {   0,
-        6,    6,    6,    6,    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,    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,    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,    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,    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,    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,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0
-    } ;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *yytext;
-#line 1 "wktparse.lex"
-#define INITIAL 0
-/*
- * Written by Ralph Mason ralph.mason<at>telogis.com
- *
- * Copyright Telogis 2004
- * www.telogis.com
- *
- */
-#define vals_ok 1
-
-#line 11 "wktparse.lex"
-#include "wktparse.tab.h"
-#include <unistd.h>
-#include <stdlib.h> // need stdlib for atof() definition 
-
-void init_parser(const char *src);
-void close_parser(void);
-int lwg_parse_yywrap(void);
-int lwg_parse_yylex(void);
-
-static YY_BUFFER_STATE buf_state;
-   void init_parser(const char *src) { BEGIN(0);buf_state = lwg_parse_yy_scan_string(src); }
-   void close_parser() { lwg_parse_yy_delete_buffer(buf_state); }
-   int lwg_parse_yywrap(void){ return 1; }
-
-#line 3281 "lex.yy.c"
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap YY_PROTO(( void ));
-#else
-extern int yywrap YY_PROTO(( void ));
-#endif
-#endif
-
-#ifndef YY_NO_UNPUT
-static void yyunput YY_PROTO(( int c, char *buf_ptr ));
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen YY_PROTO(( yyconst char * ));
-#endif
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-static int yyinput YY_PROTO(( void ));
-#else
-static int input YY_PROTO(( void ));
-#endif
-#endif
-
-#if YY_STACK_USED
-static int yy_start_stack_ptr = 0;
-static int yy_start_stack_depth = 0;
-static int *yy_start_stack = 0;
-#ifndef YY_NO_PUSH_STATE
-static void yy_push_state YY_PROTO(( int new_state ));
-#endif
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state YY_PROTO(( void ));
-#endif
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state YY_PROTO(( void ));
-#endif
-
-#else
-#define YY_NO_PUSH_STATE 1
-#define YY_NO_POP_STATE 1
-#define YY_NO_TOP_STATE 1
-#endif
-
-#ifdef YY_MALLOC_DECL
-YY_MALLOC_DECL
-#else
-#if __STDC__
-#ifndef __cplusplus
-#include <stdlib.h>
-#endif
-#else
-/* Just try to get by without declaring the routines.  This will fail
- * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
- * or sizeof(void*) != sizeof(int).
- */
-#endif
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
-		YY_FATAL_ERROR( "input in flex scanner failed" );
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
-#endif
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL int yylex YY_PROTO(( void ))
-#endif
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-YY_DECL
-	{
-	register yy_state_type yy_current_state;
-	register char *yy_cp = NULL, *yy_bp = NULL;
-	register int yy_act;
-
-#line 27 "wktparse.lex"
-
-
-#line 3422 "lex.yy.c"
-
-	if ( yy_init )
-		{
-		yy_init = 0;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! yy_start )
-			yy_start = 1;	/* first start state */
-
-		if ( ! yyin )
-			yyin = stdin;
-
-		if ( ! yyout )
-			yyout = stdout;
-
-		if ( ! yy_current_buffer )
-			yy_current_buffer =
-				yy_create_buffer( yyin, YY_BUF_SIZE );
-
-		yy_load_buffer_state();
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = yy_c_buf_p;
-
-		/* Support of yytext. */
-		*yy_cp = yy_hold_char;
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = yy_start;
-yy_match:
-		while ( (yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)]) > 0 )
-			{
-			if ( yy_accept[yy_current_state] )
-				{
-				yy_last_accepting_state = yy_current_state;
-				yy_last_accepting_cpos = yy_cp;
-				}
-
-			++yy_cp;
-			}
-
-		yy_current_state = -yy_current_state;
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-
-do_action:	/* This label is used only to access EOF actions. */
-
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = yy_hold_char;
-			yy_cp = yy_last_accepting_cpos + 1;
-			yy_current_state = yy_last_accepting_state;
-			goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 29 "wktparse.lex"
-{ lwg_parse_yylval.value=atof(lwg_parse_yytext); return VALUE; }
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 30 "wktparse.lex"
-{ lwg_parse_yylval.value=atof(lwg_parse_yytext); return VALUE; }
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 32 "wktparse.lex"
-{  lwg_parse_yylval.wkb=lwg_parse_yytext; return WKB;}
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 33 "wktparse.lex"
-{  lwg_parse_yylval.wkb=lwg_parse_yytext; return WKB;}
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 35 "wktparse.lex"
-{ return POINT; }
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 36 "wktparse.lex"
-{ return POINTM; }
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 37 "wktparse.lex"
-{ return LINESTRING; }
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 38 "wktparse.lex"
-{ return LINESTRINGM; }
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 39 "wktparse.lex"
-{ return CIRCULARSTRING; }
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 40 "wktparse.lex"
-{ return CIRCULARSTRINGM; }
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 41 "wktparse.lex"
-{ return POLYGON; }
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 42 "wktparse.lex"
-{ return POLYGONM; }
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 43 "wktparse.lex"
-{ return COMPOUNDCURVE; }
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 44 "wktparse.lex"
-{ return COMPOUNDCURVEM; }
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 45 "wktparse.lex"
-{ return CURVEPOLYGON; }
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 46 "wktparse.lex"
-{ return CURVEPOLYGONM; }
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 47 "wktparse.lex"
-{ return MULTIPOINT; }
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 48 "wktparse.lex"
-{ return MULTIPOINTM; }
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 49 "wktparse.lex"
-{ return MULTILINESTRING; }
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 50 "wktparse.lex"
-{ return MULTILINESTRINGM; }
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 51 "wktparse.lex"
-{ return MULTICURVE; }
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 52 "wktparse.lex"
-{ return MULTICURVEM; }
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 53 "wktparse.lex"
-{ return MULTIPOLYGON; }
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 54 "wktparse.lex"
-{ return MULTIPOLYGONM; }
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 55 "wktparse.lex"
-{ return MULTISURFACE; }
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 56 "wktparse.lex"
-{ return MULTISURFACEM; }
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 57 "wktparse.lex"
-{ return GEOMETRYCOLLECTION; }
-	YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 58 "wktparse.lex"
-{ return GEOMETRYCOLLECTIONM; }
-	YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 59 "wktparse.lex"
-{ BEGIN(vals_ok); return SRID; }
-	YY_BREAK
-case 30:
-YY_RULE_SETUP
-#line 60 "wktparse.lex"
-{ return EMPTY; }
-	YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 62 "wktparse.lex"
-{ BEGIN(vals_ok); return LPAREN; }
-	YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 63 "wktparse.lex"
-{ return RPAREN; }
-	YY_BREAK
-case 33:
-YY_RULE_SETUP
-#line 64 "wktparse.lex"
-{ return COMMA ; }
-	YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 65 "wktparse.lex"
-{ return EQUALS ; }
-	YY_BREAK
-case 35:
-YY_RULE_SETUP
-#line 66 "wktparse.lex"
-{ BEGIN(0); return SEMICOLON; }
-	YY_BREAK
-case 36:
-YY_RULE_SETUP
-#line 67 "wktparse.lex"
-/*eat whitespace*/
-	YY_BREAK
-case 37:
-YY_RULE_SETUP
-#line 68 "wktparse.lex"
-{ return lwg_parse_yytext[0]; }
-	YY_BREAK
-case 38:
-YY_RULE_SETUP
-#line 70 "wktparse.lex"
-ECHO;
-	YY_BREAK
-#line 3683 "lex.yy.c"
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(vals_ok):
-	yyterminate();
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = yy_hold_char;
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed yyin at a new source and called
-			 * yylex().  If so, then we have to assure
-			 * consistency between yy_current_buffer and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			yy_n_chars = yy_current_buffer->yy_n_chars;
-			yy_current_buffer->yy_input_file = yyin;
-			yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state();
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = yytext_ptr + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++yy_c_buf_p;
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = yy_c_buf_p;
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer() )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				yy_did_buffer_switch_on_eof = 0;
-
-				if ( yywrap() )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * yytext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				yy_c_buf_p =
-					yytext_ptr + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state();
-
-				yy_cp = yy_c_buf_p;
-				yy_bp = yytext_ptr + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				yy_c_buf_p =
-				&yy_current_buffer->yy_ch_buf[yy_n_chars];
-
-				yy_current_state = yy_get_previous_state();
-
-				yy_cp = yy_c_buf_p;
-				yy_bp = yytext_ptr + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-	} /* end of yylex */
-
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-
-static int yy_get_next_buffer()
-	{
-	register char *dest = yy_current_buffer->yy_ch_buf;
-	register char *source = yytext_ptr;
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( yy_current_buffer->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		yy_current_buffer->yy_n_chars = yy_n_chars = 0;
-
-	else
-		{
-		int num_to_read =
-			yy_current_buffer->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-#ifdef YY_USES_REJECT
-			YY_FATAL_ERROR(
-"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
-#else
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = yy_current_buffer;
-
-			int yy_c_buf_p_offset =
-				(int) (yy_c_buf_p - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					yy_flex_realloc( (void *) b->yy_ch_buf,
-							 b->yy_buf_size + 2 );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = yy_current_buffer->yy_buf_size -
-						number_to_move - 1;
-#endif
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
-			yy_n_chars, num_to_read );
-
-		yy_current_buffer->yy_n_chars = yy_n_chars;
-		}
-
-	if ( yy_n_chars == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			yyrestart( yyin );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			yy_current_buffer->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	yy_n_chars += number_to_move;
-	yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
-	yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
-	yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
-
-	return ret_val;
-	}
-
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-static yy_state_type yy_get_previous_state()
-	{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-
-	yy_current_state = yy_start;
-
-	for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
-		{
-		if ( *yy_cp )
-			{
-			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
-			}
-		else
-			yy_current_state = yy_NUL_trans[yy_current_state];
-		if ( yy_accept[yy_current_state] )
-			{
-			yy_last_accepting_state = yy_current_state;
-			yy_last_accepting_cpos = yy_cp;
-			}
-		}
-
-	return yy_current_state;
-	}
-
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-
-#ifdef YY_USE_PROTOS
-static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
-#else
-static yy_state_type yy_try_NUL_trans( yy_current_state )
-yy_state_type yy_current_state;
-#endif
-	{
-	register int yy_is_jam;
-	register char *yy_cp = yy_c_buf_p;
-
-	yy_current_state = yy_NUL_trans[yy_current_state];
-	yy_is_jam = (yy_current_state == 0);
-
-	if ( ! yy_is_jam )
-		{
-		if ( yy_accept[yy_current_state] )
-			{
-			yy_last_accepting_state = yy_current_state;
-			yy_last_accepting_cpos = yy_cp;
-			}
-		}
-
-	return yy_is_jam ? 0 : yy_current_state;
-	}
-
-
-#ifndef YY_NO_UNPUT
-#ifdef YY_USE_PROTOS
-static void yyunput( int c, register char *yy_bp )
-#else
-static void yyunput( c, yy_bp )
-int c;
-register char *yy_bp;
-#endif
-	{
-	register char *yy_cp = yy_c_buf_p;
-
-	/* undo effects of setting up yytext */
-	*yy_cp = yy_hold_char;
-
-	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		register int number_to_move = yy_n_chars + 2;
-		register char *dest = &yy_current_buffer->yy_ch_buf[
-					yy_current_buffer->yy_buf_size + 2];
-		register char *source =
-				&yy_current_buffer->yy_ch_buf[number_to_move];
-
-		while ( source > yy_current_buffer->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		yy_current_buffer->yy_n_chars =
-			yy_n_chars = yy_current_buffer->yy_buf_size;
-
-		if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-
-	yytext_ptr = yy_bp;
-	yy_hold_char = *yy_cp;
-	yy_c_buf_p = yy_cp;
-	}
-#endif	/* ifndef YY_NO_UNPUT */
-
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-static int yyinput()
-#else
-static int input()
-#endif
-	{
-	int c;
-
-	*yy_c_buf_p = yy_hold_char;
-
-	if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
-			/* This was really a NUL. */
-			*yy_c_buf_p = '\0';
-
-		else
-			{ /* need more input */
-			int offset = yy_c_buf_p - yytext_ptr;
-			++yy_c_buf_p;
-
-			switch ( yy_get_next_buffer() )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					yyrestart( yyin );
-
-					/* fall through */
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( yywrap() )
-						return EOF;
-
-					if ( ! yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					yy_c_buf_p = yytext_ptr + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) yy_c_buf_p;	/* cast for 8-bit char's */
-	*yy_c_buf_p = '\0';	/* preserve yytext */
-	yy_hold_char = *++yy_c_buf_p;
-
-
-	return c;
-	}
-#endif /* YY_NO_INPUT */
-
-#ifdef YY_USE_PROTOS
-void yyrestart( FILE *input_file )
-#else
-void yyrestart( input_file )
-FILE *input_file;
-#endif
-	{
-	if ( ! yy_current_buffer )
-		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
-
-	yy_init_buffer( yy_current_buffer, input_file );
-	yy_load_buffer_state();
-	}
-
-
-#ifdef YY_USE_PROTOS
-void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
-#else
-void yy_switch_to_buffer( new_buffer )
-YY_BUFFER_STATE new_buffer;
-#endif
-	{
-	if ( yy_current_buffer == new_buffer )
-		return;
-
-	if ( yy_current_buffer )
-		{
-		/* Flush out information for old buffer. */
-		*yy_c_buf_p = yy_hold_char;
-		yy_current_buffer->yy_buf_pos = yy_c_buf_p;
-		yy_current_buffer->yy_n_chars = yy_n_chars;
-		}
-
-	yy_current_buffer = new_buffer;
-	yy_load_buffer_state();
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (yywrap()) processing, but the only time this flag
-	 * is looked at is after yywrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	yy_did_buffer_switch_on_eof = 1;
-	}
-
-
-#ifdef YY_USE_PROTOS
-void yy_load_buffer_state( void )
-#else
-void yy_load_buffer_state()
-#endif
-	{
-	yy_n_chars = yy_current_buffer->yy_n_chars;
-	yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
-	yyin = yy_current_buffer->yy_input_file;
-	yy_hold_char = *yy_c_buf_p;
-	}
-
-
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
-#else
-YY_BUFFER_STATE yy_create_buffer( file, size )
-FILE *file;
-int size;
-#endif
-	{
-	YY_BUFFER_STATE b;
-
-	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	yy_init_buffer( b, file );
-
-	return b;
-	}
-
-
-#ifdef YY_USE_PROTOS
-void yy_delete_buffer( YY_BUFFER_STATE b )
-#else
-void yy_delete_buffer( b )
-YY_BUFFER_STATE b;
-#endif
-	{
-	if ( ! b )
-		return;
-
-	if ( b == yy_current_buffer )
-		yy_current_buffer = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		yy_flex_free( (void *) b->yy_ch_buf );
-
-	yy_flex_free( (void *) b );
-	}
-
-
-
-#ifdef YY_USE_PROTOS
-void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
-#else
-void yy_init_buffer( b, file )
-YY_BUFFER_STATE b;
-FILE *file;
-#endif
-
-
-	{
-	yy_flush_buffer( b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-#if YY_ALWAYS_INTERACTIVE
-	b->yy_is_interactive = 1;
-#else
-#if YY_NEVER_INTERACTIVE
-	b->yy_is_interactive = 0;
-#else
-	b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-#endif
-#endif
-	}
-
-
-#ifdef YY_USE_PROTOS
-void yy_flush_buffer( YY_BUFFER_STATE b )
-#else
-void yy_flush_buffer( b )
-YY_BUFFER_STATE b;
-#endif
-
-	{
-	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == yy_current_buffer )
-		yy_load_buffer_state();
-	}
-
-
-#ifndef YY_NO_SCAN_BUFFER
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
-#else
-YY_BUFFER_STATE yy_scan_buffer( base, size )
-char *base;
-yy_size_t size;
-#endif
-	{
-	YY_BUFFER_STATE b;
-
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	yy_switch_to_buffer( b );
-
-	return b;
-	}
-#endif
-
-
-#ifndef YY_NO_SCAN_STRING
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
-#else
-YY_BUFFER_STATE yy_scan_string( yy_str )
-yyconst char *yy_str;
-#endif
-	{
-	int len;
-	for ( len = 0; yy_str[len]; ++len )
-		;
-
-	return yy_scan_bytes( yy_str, len );
-	}
-#endif
-
-
-#ifndef YY_NO_SCAN_BYTES
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
-#else
-YY_BUFFER_STATE yy_scan_bytes( bytes, len )
-yyconst char *bytes;
-int len;
-#endif
-	{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = len + 2;
-	buf = (char *) yy_flex_alloc( n );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
-
-	for ( i = 0; i < len; ++i )
-		buf[i] = bytes[i];
-
-	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = yy_scan_buffer( buf, n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-	}
-#endif
-
-
-#ifndef YY_NO_PUSH_STATE
-#ifdef YY_USE_PROTOS
-static void yy_push_state( int new_state )
-#else
-static void yy_push_state( new_state )
-int new_state;
-#endif
-	{
-	if ( yy_start_stack_ptr >= yy_start_stack_depth )
-		{
-		yy_size_t new_size;
-
-		yy_start_stack_depth += YY_START_STACK_INCR;
-		new_size = yy_start_stack_depth * sizeof( int );
-
-		if ( ! yy_start_stack )
-			yy_start_stack = (int *) yy_flex_alloc( new_size );
-
-		else
-			yy_start_stack = (int *) yy_flex_realloc(
-					(void *) yy_start_stack, new_size );
-
-		if ( ! yy_start_stack )
-			YY_FATAL_ERROR(
-			"out of memory expanding start-condition stack" );
-		}
-
-	yy_start_stack[yy_start_stack_ptr++] = YY_START;
-
-	BEGIN(new_state);
-	}
-#endif
-
-
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state()
-	{
-	if ( --yy_start_stack_ptr < 0 )
-		YY_FATAL_ERROR( "start-condition stack underflow" );
-
-	BEGIN(yy_start_stack[yy_start_stack_ptr]);
-	}
-#endif
-
-
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state()
-	{
-	return yy_start_stack[yy_start_stack_ptr - 1];
-	}
-#endif
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-#ifdef YY_USE_PROTOS
-static void yy_fatal_error( yyconst char msg[] )
-#else
-static void yy_fatal_error( msg )
-char msg[];
-#endif
-	{
-	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-	}
-
-
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-		yytext[yyleng] = yy_hold_char; \
-		yy_c_buf_p = yytext + n; \
-		yy_hold_char = *yy_c_buf_p; \
-		*yy_c_buf_p = '\0'; \
-		yyleng = n; \
-		} \
-	while ( 0 )
-
-
-/* Internal utility routines. */
-
-#ifndef yytext_ptr
-#ifdef YY_USE_PROTOS
-static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
-#else
-static void yy_flex_strncpy( s1, s2, n )
-char *s1;
-yyconst char *s2;
-int n;
-#endif
-	{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-	}
-#endif
-
-#ifdef YY_NEED_STRLEN
-#ifdef YY_USE_PROTOS
-static int yy_flex_strlen( yyconst char *s )
-#else
-static int yy_flex_strlen( s )
-yyconst char *s;
-#endif
-	{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-	}
-#endif
-
-
-#ifdef YY_USE_PROTOS
-static void *yy_flex_alloc( yy_size_t size )
-#else
-static void *yy_flex_alloc( size )
-yy_size_t size;
-#endif
-	{
-	return (void *) malloc( size );
-	}
-
-#ifdef YY_USE_PROTOS
-static void *yy_flex_realloc( void *ptr, yy_size_t size )
-#else
-static void *yy_flex_realloc( ptr, size )
-void *ptr;
-yy_size_t size;
-#endif
-	{
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return (void *) realloc( (char *) ptr, size );
-	}
-
-#ifdef YY_USE_PROTOS
-static void yy_flex_free( void *ptr )
-#else
-static void yy_flex_free( ptr )
-void *ptr;
-#endif
-	{
-	free( ptr );
-	}
-
-#if YY_MAIN
-int main()
-	{
-	yylex();
-	return 0;
-	}
-#endif
-#line 70 "wktparse.lex"
-
-

Deleted: trunk/lwgeom/liblwgeom.c
===================================================================
--- trunk/lwgeom/liblwgeom.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/liblwgeom.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,205 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#define CONTEXT_PG 0
-#define CONTEXT_SA 1
-
-
-
-#ifdef STANDALONE
-#define DEFAULT_CONTEXT CONTEXT_SA
-#else
-#define DEFAULT_CONTEXT CONTEXT_PG
-#endif
-
-/* Global variables */
-#include "../postgis_config.h"
-
-#if DEFAULT_CONTEXT == CONTEXT_SA
-#include "liblwgeom.h"
-lwallocator lwalloc_var = default_allocator;
-lwreallocator lwrealloc_var = default_reallocator;
-lwfreeor lwfree_var = default_freeor;
-lwreporter lwerror = default_errorreporter;
-lwreporter lwnotice = default_noticereporter;
-#else
-#include "lwgeom_pg.h"
-#include "liblwgeom.h"
-
-lwallocator lwalloc_var = pg_alloc;
-lwreallocator lwrealloc_var = pg_realloc;
-lwfreeor lwfree_var = pg_free;
-lwreporter lwerror = pg_error;
-lwreporter lwnotice = pg_notice;
-#endif
-
-
-static char *lwgeomTypeName[] = {
-	"Unknown",
-	"Point",
-	"Line",
-	"Polygon",
-	"MultiPoint",
-	"MultiLine",
-	"MultiPolygon",
-	"GeometryCollection",
-        "Curve",
-        "CompoundString",
-        "Invalid Type",  /* POINTTYPEI */
-        "Invalid Type",  /* LINETYPEI */
-        "Invalid Type",  /* POLYTYPEI */
-        "CurvePolygon",
-        "MultiCurve",
-        "MultiSurface"
-};
-
-void *
-default_allocator(size_t size)
-{
-	void *mem = malloc(size);
-	return mem;
-}
-
-void
-default_freeor(void *mem)
-{
-	free(mem);
-}
-
-void *
-default_reallocator(void *mem, size_t size)
-{
-	void *ret = realloc(mem, size);
-	return ret;
-}
-
-void
-default_noticereporter(const char *fmt, ...)
-{
-	char *msg;
-	va_list ap;
-
-	va_start (ap, fmt);
-
-	/*
-	 * This is a GNU extension.
-	 * Dunno how to handle errors here.
-	 */
-	if (!vasprintf (&msg, fmt, ap))
-	{
-		va_end (ap);
-		return;
-	}
-	printf("%s\n", msg);
-	va_end(ap);
-	free(msg);
-}
-
-void
-default_errorreporter(const char *fmt, ...)
-{
-	char *msg;
-	va_list ap;
-
-	va_start (ap, fmt);
-
-	/*
-	 * This is a GNU extension.
-	 * Dunno how to handle errors here.
-	 */
-	if (!vasprintf (&msg, fmt, ap))
-	{
-		va_end (ap);
-		return;
-	}
-	fprintf(stderr, "%s\n", msg);
-	va_end(ap);
-	free(msg);
-	exit(1);
-}
-
-const char *
-lwgeom_typename(int type)
-{
-	// something went wrong somewhere
-	if ( type < 0 || type > 12 ) {
-		// assert(0);
-		return "Invalid type";
-	}
-	return lwgeomTypeName[type];
-}
-
-void *
-lwalloc(size_t size)
-{
-	void *mem = lwalloc_var(size);
-	LWDEBUGF(5, "lwalloc: %d@%p", size, mem);
-	return mem;
-}
-
-void *
-lwrealloc(void *mem, size_t size)
-{
-	LWDEBUGF(5, "lwrealloc: %d@%p", size, mem);
-	return lwrealloc_var(mem, size);
-}
-
-void
-lwfree(void *mem)
-{
-	lwfree_var(mem);
-}
-
-/*
- * Removes trailing zeros and dot for a %f formatted number.
- * Modifies input.
- */
-void
-trim_trailing_zeros(char *str)
-{
-	char *ptr, *totrim=NULL;
-	int len;
-	int i;
-
-	LWDEBUGF(3, "input: %s", str);
-	
-	ptr = strchr(str, '.');
-	if ( ! ptr ) return; /* no dot, no decimal digits */
-
-	LWDEBUGF(3, "ptr: %s", ptr);
-
-	len = strlen(ptr);
-	for (i=len-1; i; i--)
-	{
-		if ( ptr[i] != '0' ) break;
-		totrim=&ptr[i];
-	}
-	if ( totrim )
-	{
-		if ( ptr == totrim-1 ) *ptr = '\0';
-		else *totrim = '\0';
-	}
-	
-	LWDEBUGF(3, "output: %s", str);
-}
-
-char
-getMachineEndian(void)
-{
-	static int endian_check_int = 1; /* dont modify this!!! */
-
-	return *((char *) &endian_check_int); /* 0 = big endian | xdr,
-					       * 1 = little endian | ndr
-	                                       */
-}
-
-
-void
-errorIfSRIDMismatch(int srid1, int srid2)
-{
-	if ( srid1 != srid2 )
-	{
-		lwerror("Operation on mixed SRID geometries");
-	}
-}

Deleted: trunk/lwgeom/liblwgeom.h
===================================================================
--- trunk/lwgeom/liblwgeom.h	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/liblwgeom.h	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,1263 +0,0 @@
-#ifndef _LIBLWGEOM_H
-#define _LIBLWGEOM_H 1
-
-#include "../postgis_config.h"
-#include <stdio.h>
-#include "compat.h"
-
-#define INTEGRITY_CHECKS 1
-
-/*
- * Floating point comparitors.
- */
-#define PGIS_EPSILON 1e-12
-#define FP_MAX(A, B) ((A > B) ? A : B)
-#define FP_MIN(A, B) ((A < B) ? A : B)
-#define FP_LT(A, B) ((A + PGIS_EPSILON) < B)
-#define FP_LTEQ(A, B) ((A - PGIS_EPSILON) <= B)
-#define FP_CONTAINS_TOP(A, X, B) (FP_LT(A, X) && FP_LTEQ(X, B))
-#define FP_CONTAINS_BOTTOM(A, X, B) (FP_LTEQ(A, X) && FP_LT(X, B))
-#define FP_CONTAINS_INCL(A, X, B) (FP_LTEQ(A, X) && FP_LTEQ(X, B))
-#define FP_CONTAINS_EXCL(A, X, B) (FP_LT(A, X) && FP_LT(X, B))
-#define FP_CONTAINS(A, X, B) FP_CONTAINS_EXCL(A, X, B)
-
-/*
- * Memory management function types
- */
-typedef void* (*lwallocator)(size_t size);
-typedef void* (*lwreallocator)(void *mem, size_t size);
-typedef void (*lwfreeor)(void* mem);
-typedef void (*lwreporter)(const char* fmt, ...);
-
-#ifndef C_H
-
-typedef unsigned int uint32;
-typedef int int32;
-
-#endif
-
-/*
- * this will change to NaN when I figure out how to
- * get NaN in a platform-independent way
- */
-#define NO_VALUE 0.0
-#define NO_Z_VALUE NO_VALUE
-#define NO_M_VALUE NO_VALUE
-
-
-/* prototypes */
-void *default_allocator(size_t size);
-void *default_reallocator(void *mem, size_t size);
-void default_freeor(void *ptr);
-void default_errorreporter(const char *fmt, ...);
-void default_noticereporter(const char *fmt, ...);
-
-/* globals */
-extern lwreallocator lwrealloc_var;
-extern lwallocator lwalloc_var;
-extern lwfreeor lwfree_var;
-extern lwreporter lwerror;
-extern lwreporter lwnotice;
-
-/* Debug macros */
-#if POSTGIS_DEBUG_LEVEL > 0
-
-/* Display a notice at the given debug level */
-#define LWDEBUG(level, msg) \
-        do { \
-                if (POSTGIS_DEBUG_LEVEL >= level) \
-                        lwnotice("[%s:%s:%d] " msg, __FILE__, __func__, __LINE__); \
-        } while (0);
-
-/* Display a formatted notice at the given debug level (like printf, with variadic arguments) */
-#define LWDEBUGF(level, msg, ...) \
-        do { \
-                if (POSTGIS_DEBUG_LEVEL >= level) \
-                        lwnotice("[%s:%s:%d] " msg, __FILE__, __func__, __LINE__, __VA_ARGS__); \
-        } while (0);
-
-#else
-
-/* Empty prototype that can be optimised away by the compiler for non-debug builds */
-#define LWDEBUG(level, msg) \
-        ((void) 0)
-
-/* Empty prototype that can be optimised away by the compiler for non-debug builds */
-#define LWDEBUGF(level, msg, ...) \
-        ((void) 0)
-
-#endif
-
-/******************************************************************/
-
-typedef unsigned char uchar;
-
-typedef struct
-{
-	float xmin;
-	float ymin;
-	float xmax;
-	float ymax;
-} BOX2DFLOAT4;
-
-typedef struct
-{
-        double xmin, ymin, zmin;
-        double xmax, ymax, zmax;
-} BOX3D;
-
-typedef struct chiptag
-{
-	int size; /* unused (for use by postgresql) */
-
-	int endian_hint; /* the number 1 in the endian of this datastruct */
-
-	BOX3D bvol;
-	int SRID;
-	char future[4];
-	float factor;	/* Usually 1.0.
-			 * Integer values are multiplied by this number
-			 * to get the actual height value
-			 * (for sub-meter accuracy height data).
-			 */
-
-	int datatype;	/* 1 = float32,
-			 * 5 = 24bit integer,
-			 * 6 = 16bit integer (short)
-			 * 7 = 16bit ???
-			 * 8 = 8bit ???
-			 * 101 = float32 (NDR),
-			 * 105 = 24bit integer (NDR),
-			 * 106 = 16bit int (NDR)
-			 * 107 = 16bit ??? (NDR)
-			 * 108 = 8bit ??? (NDR) (this doesn't make sense)
-			 */
-	int height;
-	int width;
-	int compression;	/* 0 = no compression, 1 = differencer
-				 * 0x80 = new value
-				 * 0x7F = nodata
-				 */
-
-	/*
-	 * this is provided for convenience, it should be set to
-	 *  sizeof(chip) bytes into the struct because the serialized form is:
-	 *    <header><data>
-	 * NULL when serialized
-	 */
-	void  *data;	/* data[0] = bottm left,
-			 * data[width] = 1st pixel, 2nd row (uncompressed)
-			 */
-
-} CHIP;
-
-/*
- * standard definition of an ellipsoid (what wkt calls a spheroid)
- *    f = (a-b)/a
- *    e_sq = (a*a - b*b)/(a*a)
- *    b = a - fa
- */
-typedef struct
-{
-	double	a;	/* semimajor axis */
-	double	b; 	/* semiminor axis */
-	double	f;	/* flattening     */
-	double	e;	/* eccentricity (first) */
-	double	e_sq;	/* eccentricity (first), squared */
-	char	name[20]; /* name of ellipse */
-} SPHEROID;
-
-
-/*
- * ALL LWGEOM structures will use POINT3D as an abstract point.
- * This means a 2d geometry will be stored as (x,y) in its serialized
- * form, but all functions will work on (x,y,0).  This keeps all the
- * analysis functions simple.
- * NOTE: for GEOS integration, we'll probably set z=NaN
- *        so look out - z might be NaN for 2d geometries!
- */
-typedef struct { double	x,y,z; } POINT3DZ;
-typedef struct { double	x,y,z; } POINT3D; /* alias for POINT3DZ */
-typedef struct { double	x,y,m; } POINT3DM;
-
-
-/*
- * type for 2d points.  When you convert this to 3d, the
- *   z component will be either 0 or NaN.
- */
-typedef struct
-{
-	 double x;
-	 double y;
-} POINT2D;
-
-typedef struct
-{
-	 double x;
-	 double y;
-	 double z;
-	 double m;
-} POINT4D;
-
-/******************************************************************/
-
-/*
- * Point array abstracts a lot of the complexity of points and point lists.
- * It handles miss-alignment in the serialized form, 2d/3d translation
- *    (2d points converted to 3d will have z=0 or NaN)
- * DONT MIX 2D and 3D POINTS!  *EVERYTHING* is either one or the other
- */
-typedef struct
-{
-    /* array of POINT 2D, 3D or 4D. probably missaligned. */
-    uchar *serialized_pointlist;
-
-    /* use TYPE_* macros to handle */
-    uchar  dims;
-
-    uint32 npoints;
-}  POINTARRAY;
-
-
-/*
- * Use the following to build pointarrays
- * when number of points in output is not 
- * known in advance
- */
-typedef struct {
-	POINTARRAY *pa;
-	size_t ptsize;
-	size_t capacity; /* given in points */
-} DYNPTARRAY;
-
-/* Create a new dynamic pointarray */
-extern DYNPTARRAY *dynptarray_create(size_t initial_capacity, int dims);
-
-/*
- * Add a POINT4D to the dynamic pointarray.
- *
- * The dynamic pointarray may be of any dimension, only
- * accepted dimensions will be copied.
- *
- * If allow_duplicates is set to 0 (false) a check
- * is performed to see if last point in array is equal to the
- * provided one. NOTE that the check is 4d based, with missing
- * ordinates in the pointarray set to NO_Z_VALUE and NO_M_VALUE
- * respectively.
- */
-extern int dynptarray_addPoint4d(DYNPTARRAY *dpa, POINT4D *p4d,
-	int allow_duplicates);
-
-/******************************************************************
- *
- * LWGEOM (any type)
- *
- ******************************************************************/
-
-typedef struct
-{
-	uchar type; 
-	BOX2DFLOAT4 *bbox;
-	uint32 SRID; /* -1 == unneeded */
-	void *data;
-} LWGEOM;
-
-/* POINTYPE */
-typedef struct
-{
-	uchar type; /* POINTTYPE */
-	BOX2DFLOAT4 *bbox;
-   	uint32 SRID;	
-   	POINTARRAY *point;  /* hide 2d/3d (this will be an array of 1 point) */
-}  LWPOINT; /* "light-weight point" */
-
-/* LINETYPE */
-typedef struct
-{
-	uchar type; /* LINETYPE */
-	BOX2DFLOAT4 *bbox;
-   	uint32 SRID;	
-	POINTARRAY    *points; /* array of POINT3D */
-} LWLINE; /* "light-weight line" */
-
-/* POLYGONTYPE */
-typedef struct
-{
-	uchar type; /* POLYGONTYPE */
-	BOX2DFLOAT4 *bbox;
-   	uint32 SRID;	
-	int  nrings;
-	POINTARRAY **rings; /* list of rings (list of points) */
-} LWPOLY; /* "light-weight polygon" */
-
-/* MULTIPOINTTYPE */
-typedef struct
-{
-	uchar type;  
-	BOX2DFLOAT4 *bbox;
-   	uint32 SRID;	
-	int  ngeoms;
-	LWPOINT **geoms;
-} LWMPOINT; 
-
-/* MULTILINETYPE */
-typedef struct
-{  
-	uchar type; 
-	BOX2DFLOAT4 *bbox;
-   	uint32 SRID;	
-	int  ngeoms;
-	LWLINE **geoms;
-} LWMLINE; 
-
-/* MULTIPOLYGONTYPE */
-typedef struct
-{  
-	uchar type; 
-	BOX2DFLOAT4 *bbox;
-   	uint32 SRID;	
-	int  ngeoms;
-	LWPOLY **geoms;
-} LWMPOLY; 
-
-/* COLLECTIONTYPE */
-typedef struct
-{   
-	uchar type; 
-	BOX2DFLOAT4 *bbox;
-   	uint32 SRID;	
-	int  ngeoms;
-	LWGEOM **geoms;
-} LWCOLLECTION; 
-
-/* Casts LWGEOM->LW* (return NULL if cast is illegal) */
-extern LWMPOLY *lwgeom_as_lwmpoly(LWGEOM *lwgeom);
-extern LWMLINE *lwgeom_as_lwmline(LWGEOM *lwgeom);
-extern LWMPOINT *lwgeom_as_lwmpoint(LWGEOM *lwgeom);
-extern LWCOLLECTION *lwgeom_as_lwcollection(LWGEOM *lwgeom);
-extern LWPOLY *lwgeom_as_lwpoly(LWGEOM *lwgeom);
-extern LWLINE *lwgeom_as_lwline(LWGEOM *lwgeom);
-extern LWPOINT *lwgeom_as_lwpoint(LWGEOM *lwgeom);
-
-/* Casts LW*->LWGEOM (always cast) */
-extern LWGEOM *lwmpoly_as_lwgeom(LWMPOLY *obj);
-extern LWGEOM *lwmline_as_lwgeom(LWMLINE *obj);
-extern LWGEOM *lwmpoint_as_lwgeom(LWMPOINT *obj);
-extern LWGEOM *lwcollection_as_lwgeom(LWCOLLECTION *obj);
-extern LWGEOM *lwpoly_as_lwgeom(LWPOLY *obj);
-extern LWGEOM *lwline_as_lwgeom(LWLINE *obj);
-extern LWGEOM *lwpoint_as_lwgeom(LWPOINT *obj);
-
-/*
- * Call this function everytime LWGEOM coordinates 
- * change so to invalidate bounding box
- */
-extern void lwgeom_changed(LWGEOM *lwgeom);
-
-/*
- * Call this function to drop BBOX and SRID
- * from LWGEOM. If LWGEOM type is *not* flagged
- * with the HASBBOX flag and has a bbox, it
- * will be released.
- */
-extern void lwgeom_dropBBOX(LWGEOM *lwgeom);
-
-/* Compute a bbox if not already computed */
-extern void lwgeom_addBBOX(LWGEOM *lwgeom);
-
-extern void lwgeom_dropSRID(LWGEOM *lwgeom);
-
-/******************************************************************/
-
-/*
- * copies a point from the point array into the parameter point
- * will set point's z=0 (or NaN) if pa is 2d
- * will set point's m=0 (or NaN) if pa is 3d or 2d
- * NOTE: point is a real POINT3D *not* a pointer
- */
-extern POINT4D getPoint4d(const POINTARRAY *pa, int n);
-
-/*
- * copies a point from the point array into the parameter point
- * will set point's z=0 (or NaN) if pa is 2d
- * will set point's m=0 (or NaN) if pa is 3d or 2d
- * NOTE: this will modify the point4d pointed to by 'point'.
- */
-extern int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point);
-
-/*
- * copies a point from the point array into the parameter point
- * will set point's z=0 (or NaN) if pa is 2d
- * NOTE: point is a real POINT3D *not* a pointer
- */
-extern POINT3DZ getPoint3dz(const POINTARRAY *pa, int n);
-extern POINT3DM getPoint3dm(const POINTARRAY *pa, int n);
-
-/*
- * copies a point from the point array into the parameter point
- * will set point's z=0 (or NaN) if pa is 2d
- * NOTE: this will modify the point3d pointed to by 'point'.
- */
-extern int getPoint3dz_p(const POINTARRAY *pa, int n, POINT3DZ *point);
-extern int getPoint3dm_p(const POINTARRAY *pa, int n, POINT3DM *point);
-
-
-/*
- * copies a point from the point array into the parameter point
- * z value (if present is not returned)
- * NOTE: point is a real POINT3D *not* a pointer
- */
-extern POINT2D getPoint2d(const POINTARRAY *pa, int n);
-
-/*
- * copies a point from the point array into the parameter point
- * z value (if present is not returned)
- * NOTE: this will modify the point2d pointed to by 'point'.
- */
-extern int getPoint2d_p(const POINTARRAY *pa, int n, POINT2D *point);
-
-/*
- * set point N to the given value
- * NOTE that the pointarray can be of any
- * dimension, the appropriate ordinate values
- * will be extracted from it
- *
- */
-extern void setPoint4d(POINTARRAY *pa, int n, POINT4D *p4d);
-
-/*
- * get a pointer to nth point of a POINTARRAY
- * You'll need to cast it to appropriate dimensioned point.
- * Note that if you cast to a higher dimensional point you'll
- * possibly corrupt the POINTARRAY.
- *
- * WARNING: Don't cast this to a POINT !
- * it would not be reliable due to memory alignment constraints 
- */
-extern uchar *getPoint_internal(const POINTARRAY *pa, int n);
-
-/* --- here is a macro equivalent, for speed... */
-/* #define getPoint(x,n) &( (x)->serialized_pointlist[((x)->ndims*8)*(n)] ) */
-
-
-/*
- * constructs a POINTARRAY.
- * NOTE: points is *not* copied, so be careful about modification
- * (can be aligned/missaligned)
- * NOTE: hasz and hasm are descriptive - it describes what type of data
- *	 'points' points to.  No data conversion is done.
- */
-extern POINTARRAY *pointArray_construct(uchar *points, char hasz, char hasm,
-	uint32 npoints);
-
-/* 
- * Calculate the (BOX3D) bounding box of a set of points.
- * Returns an alloced BOX3D or NULL (for empty geom) in the first form.
- * Write result in user-provided BOX3D in second form (return 0 if untouched).
- * If pa is 2d, then box3d's zmin/zmax will be set to NO_Z_VALUE
- */
-extern BOX3D *ptarray_compute_box3d(const POINTARRAY *pa);
-extern int ptarray_compute_box3d_p(const POINTARRAY *pa, BOX3D *out);
-
-/*
- * size of point represeneted in the POINTARRAY
- * 16 for 2d, 24 for 3d, 32 for 4d
- */
-extern int pointArray_ptsize(const POINTARRAY *pa);
-
-
-#define	POINTTYPE	1
-#define	LINETYPE	2
-#define	POLYGONTYPE	3
-#define	MULTIPOINTTYPE	4
-#define	MULTILINETYPE	5
-#define	MULTIPOLYGONTYPE	6
-#define	COLLECTIONTYPE	7
-
-#define WKBZOFFSET 0x80000000
-#define WKBMOFFSET 0x40000000
-#define WKBSRIDFLAG 0x20000000
-#define WKBBBOXFLAG 0x10000000
-
-/* These macros work on PG_LWGEOM.type, LWGEOM.type and all its subclasses */
-
-#define TYPE_SETTYPE(c,t) ((c)=(((c)&0xF0)|(t)))
-#define TYPE_SETZM(t,z,m) ((t)=(((t)&0xCF)|((z)<<5)|((m)<<4)))
-#define TYPE_SETHASBBOX(t,b) ((t)=(((t)&0x7F)|((b)<<7)))
-#define TYPE_SETHASSRID(t,s) ((t)=(((t)&0xBF)|((s)<<6)))
-
-#define TYPE_HASZ(t) ( ((t)&0x20)>>5 )
-#define TYPE_HASM(t) ( ((t)&0x10)>>4 )
-#define TYPE_HASBBOX(t) ( ((t)&0x80)>>7 )
-#define TYPE_HASSRID(t) ( (((t)&0x40))>>6 )
-#define TYPE_NDIMS(t) ((((t)&0x20)>>5)+(((t)&0x10)>>4)+2)
-#define TYPE_GETTYPE(t) ((t)&0x0F)
-
-/* 0x02==Z 0x01==M */
-#define TYPE_GETZM(t) (((t)&0x30)>>4)
-
-extern char lwgeom_hasBBOX(uchar type); /* true iff B bit set     */
-extern int  lwgeom_ndims(uchar type);   /* returns 2,3 or 4       */
-extern int  lwgeom_hasZ(uchar type);    /* has Z ?                */
-extern int  lwgeom_hasM(uchar type);    /* has M ?                */
-extern int  lwgeom_getType(uchar type); /* returns the tttt value */
-
-extern uchar lwgeom_makeType(char hasZ, char hasM, char hasSRID, int type);
-extern uchar lwgeom_makeType_full(char hasZ, char hasM, char hasSRID, int type, char hasBBOX);
-extern char lwgeom_hasSRID(uchar type); /* true iff S bit is set */
-extern char lwgeom_hasBBOX(uchar type); /* true iff B bit set    */
-
-
-
-/*
- * This is the binary representation of lwgeom compatible
- * with postgresql varlena struct
- */
-typedef struct {
-	uint32 size;        /* varlena header (do not touch directly!) */
-	uchar type;         /* encodes ndims, type, bbox presence,
-		                srid presence */
-	uchar data[1];
-} PG_LWGEOM;
-
-/*
- * Construct a full PG_LWGEOM type (including size header)
- * from a serialized form.
- * The constructed PG_LWGEOM object will be allocated using palloc
- * and the serialized form will be copied.
- * If you specify a SRID other then -1 it will be set.
- * If you request bbox (wantbbox=1) it will be extracted or computed
- * from the serialized form.
- */
-extern PG_LWGEOM *PG_LWGEOM_construct(uchar *serialized, int SRID,
-	int wantbbox);
-
-/*
- * Compute bbox of serialized geom
- */
-extern int compute_serialized_box2d_p(uchar *serialized_form, BOX2DFLOAT4 *box);
-extern BOX3D *compute_serialized_box3d(uchar *serialized_form);
-extern int compute_serialized_box3d_p(uchar *serialized_form, BOX3D *box);
-
-
-/*
- * Evaluate with an heuristic if the provided PG_LWGEOM is worth
- * caching a bbox
- */
-char is_worth_caching_pglwgeom_bbox(const PG_LWGEOM *);
-char is_worth_caching_serialized_bbox(const uchar *);
-char is_worth_caching_lwgeom_bbox(const LWGEOM *);
-
-/*
- * Use this macro to extract the char * required
- * by most functions from an PG_LWGEOM struct.
- * (which is an PG_LWGEOM w/out int32 size casted to char *)
- */
-#define SERIALIZED_FORM(x) ((uchar *)VARDATA((x)))
-
-/*
-    This structure is a "glue" structure for returning a serialized
-    LWGEOM from the parser, along with its size. By using a separate
-    type, we remove the constraint that the output from the
-    parser must be PG_LWGEOM format (and hence protect ourselves
-    from future varlena changes)
-*/
-typedef struct serialized_lwgeom {
-    uchar *lwgeom;
-    int size;
-} SERIALIZED_LWGEOM;
-
-/*
- * This function computes the size in bytes
- * of the serialized geometries.
- */
-extern size_t lwgeom_size(const uchar *serialized_form);
-extern size_t lwgeom_size_subgeom(const uchar *serialized_form, int geom_number);
-extern size_t lwgeom_size_line(const uchar *serialized_line);
-extern size_t lwgeom_size_curve(const uchar *serialized_curve);
-extern size_t lwgeom_size_point(const uchar *serialized_point);
-extern size_t lwgeom_size_poly(const uchar *serialized_line);
-
-
-/*--------------------------------------------------------
- * all the base types (point/line/polygon) will have a
- * basic constructor, basic de-serializer, basic serializer,
- * bounding box finder and (TODO) serialized form size finder.
- *--------------------------------------------------------*/
-
-/*
- * given the LWPOINT serialized form (or a pointer into a muli* one)
- * construct a proper LWPOINT.
- * serialized_form should point to the 8bit type format (with type = 1)
- * Returns NULL if serialized form is not a point.
- * See serialized form doc
- */
-extern LWPOINT *lwpoint_deserialize(uchar *serialized_form);
-
-/*
- * Find size this point would get when serialized (no BBOX)
- */
-extern size_t lwpoint_serialize_size(LWPOINT *point);
-
-/*
- * convert this point into its serialize form
- * result's first char will be the 8bit type. 
- * See serialized form doc
- */
-extern uchar *lwpoint_serialize(LWPOINT *point);
-
-/* same as above, writes to buf */
-extern void lwpoint_serialize_buf(LWPOINT *point, uchar *buf, size_t *size);
-
-/*
- * find bounding box (standard one) 
- * zmin=zmax=0 if 2d (might change to NaN)
- */
-extern BOX3D *lwpoint_compute_box3d(LWPOINT *point);
-
-/*
- * convenience functions to hide the POINTARRAY
- */
-extern int lwpoint_getPoint2d_p(const LWPOINT *point, POINT2D *out);
-extern int lwpoint_getPoint3dz_p(const LWPOINT *point, POINT3DZ *out);
-extern int lwpoint_getPoint3dm_p(const LWPOINT *point, POINT3DM *out);
-extern int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out);
-
-/******************************************************************
- * LWLINE functions
- ******************************************************************/
-
-/*
- * given the LWGEOM serialized form (or a pointer into a muli* one)
- * construct a proper LWLINE.
- * serialized_form should point to the 8bit type format (with type = 2)
- * See SERIALIZED_FORM doc
- */
-extern LWLINE *lwline_deserialize(uchar *serialized_form);
-
-/* find the size this line would get when serialized */
-extern size_t lwline_serialize_size(LWLINE *line);
-
-/*
- * convert this line into its serialize form
- * result's first char will be the 8bit type.  See serialized form doc
- * copies data.
- */
-extern uchar *lwline_serialize(LWLINE *line);
-
-/* same as above, writes to buf */
-extern void lwline_serialize_buf(LWLINE *line, uchar *buf, size_t *size);
-
-/*
- * find bounding box (standard one)  zmin=zmax=0 if 2d (might change to NaN)
- */
-extern BOX3D *lwline_compute_box3d(LWLINE *line);
-
-/******************************************************************
- * LWPOLY functions
- ******************************************************************/
-
-/*
- * given the LWPOLY serialized form (or a pointer into a muli* one)
- * construct a proper LWPOLY.
- * serialized_form should point to the 8bit type format (with type = 3)
- * See SERIALIZED_FORM doc
- */
-extern LWPOLY *lwpoly_deserialize(uchar *serialized_form);
-
-/* find the size this polygon would get when serialized */
-extern size_t lwpoly_serialize_size(LWPOLY *poly);
-
-/*
- * create the serialized form of the polygon
- * result's first char will be the 8bit type.  See serialized form doc
- * points copied
- */
-extern uchar *lwpoly_serialize(LWPOLY *poly);
-
-/* same as above, writes to buf */
-extern void lwpoly_serialize_buf(LWPOLY *poly, uchar *buf, size_t *size);
-
-/*
- * find bounding box (standard one)  zmin=zmax=0 if 2d (might change to NaN)
- */
-extern BOX3D *lwpoly_compute_box3d(LWPOLY *poly);
-
-/******************************************************************
- * LWGEOM functions
- ******************************************************************/
-
-extern size_t lwgeom_serialize_size(LWGEOM *geom);
-extern size_t lwcollection_serialize_size(LWCOLLECTION *coll);
-extern void lwgeom_serialize_buf(LWGEOM *geom, uchar *buf, size_t *size);
-extern uchar *lwgeom_serialize(LWGEOM *geom);
-extern void lwcollection_serialize_buf(LWCOLLECTION *mcoll, uchar *buf, size_t *size);
-
-/*
- * Deserialize an lwgeom serialized form.
- * The deserialized (recursive) structure will store
- * pointers to the serialized form (POINTARRAYs).
- */
-LWGEOM *lwgeom_deserialize(uchar *serializedform);
-
-/*
- * Release memory associated with LWGEOM.
- * POINTARRAYs are not released as they are usually
- * pointers to user-managed memory.
- * BBOX is released.
- */
-void lwgeom_release(LWGEOM *lwgeom);
-
-/******************************************************************
- * LWMULTIx and LWCOLLECTION functions
- ******************************************************************/
-
-LWMPOINT *lwmpoint_deserialize(uchar *serializedform);
-LWMLINE *lwmline_deserialize(uchar *serializedform);
-LWMPOLY *lwmpoly_deserialize(uchar *serializedform);
-LWCOLLECTION *lwcollection_deserialize(uchar *serializedform);
-LWGEOM *lwcollection_getsubgeom(LWCOLLECTION *, int);
-
-/******************************************************************
- * SERIALIZED FORM functions
- ******************************************************************/
-
-
-/******************************************************************
- * Multi-geometries
- *
- * These are all handled equivelently so its easy to write iterator code.
- *  NOTE NOTE: you can hand in a non-multigeometry to most of these functions
- *             and get usual behavior (ie. get geometry 0 on a POINT
- *	       will return the point).
- *             This makes coding even easier since you dont have to necessarily
- *             differenciate between the multi* and non-multi geometries.
- *
- * NOTE: these usually work directly off the serialized form, so
- *	they're a little more difficult to handle (and slower)
- * NOTE NOTE: the get functions maybe slow, so we may want to have an
- *            "analysed" lwgeom that would just have pointer to the start
- *            of each sub-geometry.
- *
- ******************************************************************/
-
-/* use this version for speed.  READ-ONLY! */
-typedef struct
-{
-	int   SRID;
-	const uchar *serialized_form; /* orginal structure */
-	uchar  type;        /* 8-bit type for the LWGEOM */
-	int ngeometries;    /* number of sub-geometries */
-	uchar **sub_geoms;  /* list of pointers (into serialized_form)
-			       of the sub-geoms */
-} LWGEOM_INSPECTED;
-
-extern int lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected,
-	int geom_number);
-
-/*
- * note - for a simple type (ie. point), this will have
- * sub_geom[0] = serialized_form.
- * for multi-geomtries sub_geom[0] will be a few bytes into the
- * serialized form.
- * This function just computes the length of each sub-object and
- * pre-caches this info.
- * For a geometry collection of multi* geometries, you can inspect
- * the sub-components as well.
- */
-extern LWGEOM_INSPECTED *lwgeom_inspect(const uchar *serialized_form);
-
-
-/*
- * 1st geometry has geom_number = 0
- * if the actual sub-geometry isnt a POINT, null is returned (see _gettype()).
- * if there arent enough geometries, return null.
- * this is fine to call on a point (with geom_num=0), multipoint
- * or geometrycollection
- */
-extern LWPOINT *lwgeom_getpoint(uchar *serialized_form, int geom_number);
-extern LWPOINT *lwgeom_getpoint_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
-
-/*
- * 1st geometry has geom_number = 0
- * if the actual geometry isnt a LINE, null is returned (see _gettype()).
- * if there arent enough geometries, return null.
- * this is fine to call on a line, multiline or geometrycollection
- */
-extern LWLINE *lwgeom_getline(uchar *serialized_form, int geom_number);
-extern LWLINE *lwgeom_getline_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
-
-/*
- * 1st geometry has geom_number = 0
- * if the actual geometry isnt a POLYGON, null is returned (see _gettype()).
- * if there arent enough geometries, return null.
- * this is fine to call on a polygon, multipolygon or geometrycollection
- */
-extern LWPOLY *lwgeom_getpoly(uchar *serialized_form, int geom_number);
-extern LWPOLY *lwgeom_getpoly_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
-
-extern LWGEOM *lwgeom_getgeom_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
-
-/*
- * this gets the serialized form of a sub-geometry
- * 1st geometry has geom_number = 0
- * if this isnt a multi* geometry, and geom_number ==0 then it returns
- * itself
- * returns null on problems.
- * in the future this is how you would access a muli* portion of a
- * geometry collection.
- *    GEOMETRYCOLLECTION(MULTIPOINT(0 0, 1 1), LINESTRING(0 0, 1 1))
- *   ie. lwgeom_getpoint( lwgeom_getsubgeometry( serialized, 0), 1)
- *           --> POINT(1 1)
- * you can inspect the sub-geometry as well if you wish.
- */
-extern uchar *lwgeom_getsubgeometry(const uchar *serialized_form, int geom_number);
-extern uchar *lwgeom_getsubgeometry_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
-
-
-/*
- * 1st geometry has geom_number = 0
- *  use geom_number = -1 to find the actual type of the serialized form.
- *    ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, -1)
- *                 --> multipoint
- *   ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, 0)
- *                 --> point
- * gets the 8bit type of the geometry at location geom_number
- */
-extern uchar lwgeom_getsubtype(uchar *serialized_form, int geom_number);
-extern uchar lwgeom_getsubtype_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
-
-
-/*
- * how many sub-geometries are there?
- *  for point,line,polygon will return 1.
- */
-extern int lwgeom_getnumgeometries(uchar *serialized_form);
-extern int lwgeom_getnumgeometries_inspected(LWGEOM_INSPECTED *inspected);
-
-
-
-/*
- * set finalType to COLLECTIONTYPE or 0 (0 means choose a best type)
- *   (ie. give it 2 points and ask it to be a multipoint)
- *  use SRID=-1 for unknown SRID  (will have 8bit type's S = 0)
- * all subgeometries must have the same SRID
- * if you want to construct an inspected, call this then inspect the result...
- */
-extern uchar *lwgeom_serialized_construct(int SRID, int finalType, char hasz, char hasm, int nsubgeometries, uchar **serialized_subs);
-
-
-/* construct the empty geometry (GEOMETRYCOLLECTION(EMPTY)) */
-extern uchar *lwgeom_constructempty(int SRID, char hasz, char hasm);
-extern void lwgeom_constructempty_buf(int SRID, char hasz, char hasm, uchar *buf, size_t *size);
-size_t lwgeom_empty_length(int SRID);
-
-/*
- * get the SRID from the LWGEOM
- * none present => -1
- */
-extern int lwgeom_getsrid(uchar *serialized);
-
-
-/*------------------------------------------------------
- * other stuff
- *
- * handle the double-to-float conversion.  The results of this
- * will usually be a slightly bigger box because of the difference
- * between float8 and float4 representations.
- */
-
-extern BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box);
-extern int box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *res);
-
-extern BOX3D box2df_to_box3d(BOX2DFLOAT4 *box);
-extern void box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *box3d);
-
-extern BOX3D *box3d_union(BOX3D *b1, BOX3D *b2);
-extern int box3d_union_p(BOX3D *b1, BOX3D *b2, BOX3D *ubox);
-
-/*
- * Returns a pointer to the BBOX internal to the serialized form.
- * READ-ONLY!
- * Or NULL if serialized form does not have a BBOX
- * OBSOLETED to avoid memory alignment problems.
- */
-/*extern BOX2DFLOAT4 *getbox2d_internal(uchar *serialized_form);*/
-
-/*
- * this function writes to 'box' and returns 0 if serialized_form
- * does not have a bounding box (empty geom)
- */
-extern int getbox2d_p(uchar *serialized_form, BOX2DFLOAT4 *box);
-
-/* Expand given box of 'd' units in all directions */
-void expand_box2d(BOX2DFLOAT4 *box, double d);
-void expand_box3d(BOX3D *box, double d);
-
-/* Check if to boxes are equal (considering FLOAT approximations) */
-char box2d_same(BOX2DFLOAT4 *box1, BOX2DFLOAT4 *box2);
-
-/****************************************************************
- * memory management -- these only delete the memory associated
- *  directly with the structure - NOT the stuff pointing into
- *  the original de-serialized info
- ****************************************************************/
-
-
-extern void pfree_inspected(LWGEOM_INSPECTED *inspected);
-extern void pfree_point    (LWPOINT *pt);
-extern void pfree_line     (LWLINE  *line);
-extern void pfree_polygon  (LWPOLY  *poly);
-extern void pfree_POINTARRAY(POINTARRAY *pa);
-
-
-/****************************************************************
- * utility
- ****************************************************************/
-
-extern uint32 lw_get_uint32(const uchar *loc);
-extern int32 lw_get_int32(const uchar *loc);
-extern void printBOX3D(BOX3D *b);
-extern void printPA(POINTARRAY *pa);
-extern void printLWPOINT(LWPOINT *point);
-extern void printLWLINE(LWLINE *line);
-extern void printLWPOLY(LWPOLY *poly);
-extern void printBYTES(uchar *a, int n);
-extern void printMULTI(uchar *serialized);
-extern void printType(uchar str);
-
-
-extern float LWGEOM_Minf(float a, float b);
-extern float LWGEOM_Maxf(float a, float b);
-extern double LWGEOM_Mind(double a, double b);
-extern double LWGEOM_Maxd(double a, double b);
-
-extern float  nextDown_f(double d);
-extern float  nextUp_f(double d);
-extern double nextDown_d(float d);
-extern double nextUp_d(float d);
-
-extern float nextafterf_custom(float x, float y);
-
-
-#define LW_MAX(a,b)	((a) >	(b) ? (a) : (b))
-#define LW_MIN(a,b)	((a) <= (b) ? (a) : (b))
-#define LW_ABS(a)	((a) <	(0) ? (-a) : (a))
-
-
-/* general utilities */
-extern double lwgeom_polygon_area(LWPOLY *poly);
-extern double lwgeom_polygon_perimeter(LWPOLY *poly);
-extern double lwgeom_polygon_perimeter2d(LWPOLY *poly);
-extern double lwgeom_pointarray_length2d(POINTARRAY *pts);
-extern double lwgeom_pointarray_length(POINTARRAY *pts);
-extern void lwgeom_force2d_recursive(uchar *serialized, uchar *optr, size_t *retsize);
-extern void lwgeom_force3dz_recursive(uchar *serialized, uchar *optr, size_t *retsize);
-extern void lwgeom_force3dm_recursive(uchar *serialized, uchar *optr, size_t *retsize);
-extern void lwgeom_force4d_recursive(uchar *serialized, uchar *optr, size_t *retsize);
-extern double distance2d_pt_pt(POINT2D *p1, POINT2D *p2);
-extern double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B);
-extern double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D);
-extern double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa);
-extern double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2);
-extern int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring);
-extern int pt_in_poly_2d(POINT2D *p, LWPOLY *poly);
-extern double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly);
-extern double distance2d_point_point(LWPOINT *point1, LWPOINT *point2);
-extern double distance2d_point_line(LWPOINT *point, LWLINE *line);
-extern double distance2d_line_line(LWLINE *line1, LWLINE *line2);
-extern double distance2d_point_poly(LWPOINT *point, LWPOLY *poly);
-extern double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2);
-extern double distance2d_line_poly(LWLINE *line, LWPOLY *poly);
-extern int azimuth_pt_pt(POINT2D *p1, POINT2D *p2, double *ret);
-extern double lwgeom_mindistance2d_recursive(uchar *lw1, uchar *lw2);
-extern double lwgeom_mindistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance);
-extern int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad);
-extern int32 lwgeom_npoints(uchar *serialized);
-extern char ptarray_isccw(const POINTARRAY *pa);
-extern void lwgeom_reverse(LWGEOM *lwgeom);
-extern void lwline_reverse(LWLINE *line);
-extern void lwpoly_reverse(LWPOLY *poly);
-extern void lwpoly_forceRHR(LWPOLY *poly);
-extern void lwgeom_forceRHR(LWGEOM *lwgeom);
-extern char *lwgeom_summary(LWGEOM *lwgeom, int offset);
-extern const char *lwgeom_typename(int type);
-extern int ptarray_compute_box2d_p(const POINTARRAY *pa, BOX2DFLOAT4 *result);
-extern BOX2DFLOAT4 *ptarray_compute_box2d(const POINTARRAY *pa);
-extern int lwpoint_compute_box2d_p(LWPOINT *point, BOX2DFLOAT4 *box);
-extern int lwline_compute_box2d_p(LWLINE *line, BOX2DFLOAT4 *box);
-extern int lwpoly_compute_box2d_p(LWPOLY *poly, BOX2DFLOAT4 *box);
-extern int lwcollection_compute_box2d_p(LWCOLLECTION *col, BOX2DFLOAT4 *box);
-extern BOX2DFLOAT4 *lwgeom_compute_box2d(LWGEOM *lwgeom);
-
-extern void interpolate_point4d(POINT4D *A, POINT4D *B, POINT4D *I, double F);
-
-/* return alloced memory */
-extern BOX2DFLOAT4 *box2d_union(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2);
-
-/* args may overlap ! */
-extern int box2d_union_p(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2, BOX2DFLOAT4 *ubox);
-extern int lwgeom_compute_box2d_p(LWGEOM *lwgeom, BOX2DFLOAT4 *box);
-void lwgeom_longitude_shift(LWGEOM *lwgeom);
-
-/* Is lwgeom1 geometrically equal to lwgeom2 ? */
-char lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2);
-char ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2);
-char lwpoint_same(const LWPOINT *p1, const LWPOINT *p2);
-char lwline_same(const LWLINE *p1, const LWLINE *p2);
-char lwpoly_same(const LWPOLY *p1, const LWPOLY *p2);
-char lwcollection_same(const LWCOLLECTION *p1, const LWCOLLECTION *p2);
-
-/*
- * Add 'what' to 'to' at position 'where'.
- * where=0 == prepend
- * where=-1 == append
- * Mix of dimensions is not allowed (TODO: allow it?).
- * Returns a newly allocated LWGEOM (with NO BBOX)
- */
-extern LWGEOM *lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what);
-
-LWGEOM *lwpoint_add(const LWPOINT *to, uint32 where, const LWGEOM *what);
-LWGEOM *lwline_add(const LWLINE *to, uint32 where, const LWGEOM *what);
-LWGEOM *lwpoly_add(const LWPOLY *to, uint32 where, const LWGEOM *what);
-LWGEOM *lwmpoly_add(const LWMPOLY *to, uint32 where, const LWGEOM *what);
-LWGEOM *lwmline_add(const LWMLINE *to, uint32 where, const LWGEOM *what);
-LWGEOM *lwmpoint_add(const LWMPOINT *to, uint32 where, const LWGEOM *what);
-LWGEOM *lwcollection_add(const LWCOLLECTION *to, uint32 where, const LWGEOM *what);
-
-/*
- * Clone an LWGEOM
- * pointarray are not copied.
- * BBOXes are copied 
- */
-extern LWGEOM *lwgeom_clone(const LWGEOM *lwgeom);
-extern LWPOINT *lwpoint_clone(const LWPOINT *lwgeom);
-extern LWLINE *lwline_clone(const LWLINE *lwgeom);
-extern LWPOLY *lwpoly_clone(const LWPOLY *lwgeom);
-extern LWCOLLECTION *lwcollection_clone(const LWCOLLECTION *lwgeom);
-extern BOX2DFLOAT4 *box2d_clone(const BOX2DFLOAT4 *lwgeom);
-extern POINTARRAY *ptarray_clone(const POINTARRAY *ptarray);
-
-/*
- * Geometry constructors
- * Take ownership of arguments
- */
-extern LWPOINT  *lwpoint_construct(int SRID, BOX2DFLOAT4 *bbox,
-	POINTARRAY *point);
-extern LWLINE *lwline_construct(int SRID, BOX2DFLOAT4 *bbox,
-	POINTARRAY *points);
-
-/*
- * Construct a new LWPOLY.  arrays (points/points per ring) will NOT be copied
- * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
- */
-extern LWPOLY *lwpoly_construct(int SRID, BOX2DFLOAT4 *bbox,
-	unsigned int nrings, POINTARRAY **points);
-
-extern LWCOLLECTION *lwcollection_construct(unsigned int type, int SRID,
-	BOX2DFLOAT4 *bbox, unsigned int ngeoms, LWGEOM **geoms);
-extern LWCOLLECTION *lwcollection_construct_empty(int SRID,
-	char hasZ, char hasM);
-
-/* Other constructors */
-extern LWPOINT *make_lwpoint2d(int SRID, double x, double y);
-extern LWPOINT *make_lwpoint3dz(int SRID, double x, double y, double z);
-extern LWPOINT *make_lwpoint3dm(int SRID, double x, double y, double m);
-extern LWPOINT *make_lwpoint4d(int SRID, double x, double y, double z, double m);
-extern LWLINE *lwline_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points);
-extern LWLINE *lwline_from_lwmpoint(int SRID, LWMPOINT *mpoint);
-extern LWLINE *lwline_addpoint(LWLINE *line, LWPOINT *point, unsigned int where);
-extern LWLINE *lwline_removepoint(LWLINE *line, unsigned int which);
-extern void lwline_setPoint4d(LWLINE *line, unsigned int which, POINT4D *newpoint);
-extern LWPOLY *lwpoly_from_lwlines(const LWLINE *shell, unsigned int nholes, const LWLINE **holes);
-
-/* Return a char string with ASCII versionf of type flags */
-extern const char *lwgeom_typeflags(uchar type);
-
-/* Construct an empty pointarray */
-extern POINTARRAY *ptarray_construct(char hasz, char hasm,
-	unsigned int npoints);
-
-/*
- * extern POINTARRAY *ptarray_construct2d(uint32 npoints, const POINT2D *pts);
- * extern POINTARRAY *ptarray_construct3dz(uint32 npoints, const POINT3DZ *pts);
- * extern POINTARRAY *ptarray_construct3dm(uint32 npoints, const POINT3DM *pts);
- * extern POINTARRAY *ptarray_construct4d(uint32 npoints, const POINT4D *pts);
- */
-
-extern POINTARRAY *ptarray_addPoint(POINTARRAY *pa, uchar *p, size_t pdims,
-	unsigned int where);
-extern POINTARRAY *ptarray_removePoint(POINTARRAY *pa, unsigned int where);
-
-extern int ptarray_isclosed2d(const POINTARRAY *pa);
-
-extern void ptarray_longitude_shift(POINTARRAY *pa);
-
-extern int32 lwgeom_nrings_recursive(uchar *serialized);
-extern void ptarray_reverse(POINTARRAY *pa);
-extern POINTARRAY *ptarray_substring(POINTARRAY *, double, double);
-extern double ptarray_locate_point(POINTARRAY *, POINT2D *);
-extern void closest_point_on_segment(POINT2D *p, POINT2D *A, POINT2D *B, POINT2D *ret);
-
-/*
- * Ensure every segment is at most 'dist' long.
- * Returned LWGEOM might is unchanged if a POINT.
- */
-extern LWGEOM *lwgeom_segmentize2d(LWGEOM *line, double dist);
-extern POINTARRAY *ptarray_segmentize2d(POINTARRAY *ipa, double dist);
-extern LWLINE *lwline_segmentize2d(LWLINE *line, double dist);
-extern LWPOLY *lwpoly_segmentize2d(LWPOLY *line, double dist);
-extern LWCOLLECTION *lwcollection_segmentize2d(LWCOLLECTION *coll, double dist);
-
-extern uchar parse_hex(char *str);
-extern void deparse_hex(uchar str, char *result);
-extern SERIALIZED_LWGEOM *parse_lwgeom_wkt(char *wkt_input);
-
-extern char *lwgeom_to_ewkt(LWGEOM *lwgeom);
-extern char *lwgeom_to_hexwkb(LWGEOM *lwgeom, unsigned int byteorder);
-extern LWGEOM *lwgeom_from_ewkb(uchar *ewkb, size_t ewkblen);
-extern uchar *lwgeom_to_ewkb(LWGEOM *lwgeom, char byteorder, size_t *ewkblen);
-
-extern void *lwalloc(size_t size);
-extern void *lwrealloc(void *mem, size_t size);
-extern void lwfree(void *mem);
-
-/* Utilities */
-extern void trim_trailing_zeros(char *num);
-
-/* Machine endianness */
-#define XDR 0
-#define NDR 1
-extern char getMachineEndian(void);
-
-void errorIfSRIDMismatch(int srid1, int srid2);
-
-/* CURVETYPE */
-typedef struct
-{
-        uchar type; /* CURVETYPE */
-        BOX2DFLOAT4 *bbox;
-        uint32 SRID;
-        POINTARRAY *points; /* array of POINT(3D/3DM) */
-} LWCURVE; /* "light-weight arcline" */
-
-/* COMPOUNDTYPE */
-typedef struct
-{
-        uchar type; /* COMPOUNDTYPE */
-        BOX2DFLOAT4 *bbox;
-        uint32 SRID;
-        int ngeoms;
-        LWGEOM **geoms;
-} LWCOMPOUND; /* "light-weight compound line" */
-
-/* CURVEPOLYTYPE */
-typedef struct
-{
-        uchar type; /* CURVEPOLYTYPE */
-        BOX2DFLOAT4 *bbox;
-        uint32 SRID;
-        int nrings;
-        LWGEOM **rings; /* list of rings (list of points) */
-} LWCURVEPOLY; /* "light-weight polygon" */
-
-/* MULTICURVE */
-typedef struct
-{
-        uchar type;
-        BOX2DFLOAT4 *bbox;
-        uint32 SRID;
-        int ngeoms;
-        LWGEOM **geoms;
-} LWMCURVE;
-
-/* MULTISURFACETYPE */
-typedef struct
-{
-        uchar type;
-        BOX2DFLOAT4 *bbox;
-        uint32 SRID;
-        int ngeoms;
-        LWGEOM **geoms;
-} LWMSURFACE;
-
-#define CURVETYPE       8
-#define COMPOUNDTYPE    9
-#define CURVEPOLYTYPE   13
-#define MULTICURVETYPE          14
-#define MULTISURFACETYPE        15
-
-/******************************************************************
- * LWCURVE functions
- ******************************************************************/
-
-/* Casts LWGEOM->LW* (return NULL if cast is illegal) */
-extern LWCURVE *lwgeom_as_lwcurve(LWGEOM *lwgeom);
-
-
-LWCURVE *lwcurve_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *points);
-
-/*
- * given the LWGEOM serialized form (or a pointer into a muli* one)
- * construct a proper LWCURVE.
- * serialized_form should point to the 8bit type format (with type = 2)
- * See SERIALIZED_FORM doc
- */
-extern LWCURVE *lwcurve_deserialize(uchar *serialized_form);
-
-/* find the size this curve would get when serialized */
-extern size_t lwcurve_serialize_size(LWCURVE *curve);
-
-/*
- * convert this curve into its serialize form
- * result's first char will be the 8bit type.  See serialized form doc
- * copies data.
- */
-extern uchar *lwcurve_serialize(LWCURVE *curve);
-
-/* same as above, writes to buf */
-extern void lwcurve_serialize_buf(LWCURVE *curve, uchar *buf, size_t *size);
-
-/*
- * find bounding box (standard one)  zmin=zmax=0 if 2d (might change to NaN)
- */
-extern BOX3D *lwcurve_compute_box3d(LWCURVE *curve);
-
-LWGEOM *lwcurve_add(const LWCURVE *to, uint32 where, const LWGEOM *what);
-extern int lwcurve_compute_box2d_p(LWCURVE *curve, BOX2DFLOAT4 *box);
-extern BOX3D *lwcurve_compute_box3d(LWCURVE *curve);
-extern void pfree_curve(LWCURVE  *curve);
-LWCURVE *lwcurve_clone(const LWCURVE *curve);
-
-/******************************************************************
- * LWMULTIx and LWCOLLECTION functions
- ******************************************************************/
-
-LWCOMPOUND *lwcompound_deserialize(uchar *serialized_form);
-
-LWGEOM *lwcompound_add(const LWCOMPOUND *to, uint32 where, const LWGEOM *what);
-
-LWCURVEPOLY *lwcurvepoly_deserialize(uchar *serialized_form);
-
-LWGEOM *lwcurvepoly_add(const LWCURVEPOLY *to, uint32 where, const LWGEOM *what);
-
-LWMCURVE *lwmcurve_deserialize(uchar *serialized_form);
-
-LWGEOM *lwmcurve_add(const LWMCURVE *to, uint32 where, const LWGEOM *what);
-
-LWMSURFACE *lwmsurface_deserialize(uchar *serialized_form);
-
-LWGEOM *lwmsurface_add(const LWMSURFACE *to, uint32 where, const LWGEOM *what);
-
-/*******************************************************************************
- * SQLMM internal functions
- ******************************************************************************/
-
-uint32 has_arc(LWGEOM *geom);
-double lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D **result);
-LWGEOM *lwgeom_segmentize(LWGEOM *geom, uint32 perQuad);
-extern double lwgeom_curvepolygon_area(LWCURVEPOLY *curvepoly);
-double lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D **result);
-
-#endif /* !defined _LIBLWGEOM_H  */
-

Deleted: trunk/lwgeom/lwcollection.c
===================================================================
--- trunk/lwgeom/lwcollection.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwcollection.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,356 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "liblwgeom.h"
-
-
-#define CHECK_LWGEOM_ZM 1
-
-LWCOLLECTION *
-lwcollection_construct(unsigned int type, int SRID, BOX2DFLOAT4 *bbox,
-	unsigned int ngeoms, LWGEOM **geoms)
-{
-	LWCOLLECTION *ret;
-	int hasz, hasm;
-#ifdef CHECK_LWGEOM_ZM
-	char zm;
-	unsigned int i;
-#endif
-
-        LWDEBUGF(2, "lwcollection_construct called with %d, %d, %p, %d, %p.", type, SRID, bbox, ngeoms, geoms);
-
-	hasz = 0;
-	hasm = 0;
-	if ( ngeoms > 0 )
-	{
-		hasz = TYPE_HASZ(geoms[0]->type);
-		hasm = TYPE_HASM(geoms[0]->type);
-#ifdef CHECK_LWGEOM_ZM
-		zm = TYPE_GETZM(geoms[0]->type);
-
-                LWDEBUGF(3, "lwcollection_construct type[0]=%d", geoms[0]->type);
-
-		for (i=1; i<ngeoms; i++)
-		{
-                        LWDEBUGF(3, "lwcollection_construct type=[%d]=%d", i, geoms[i]->type);
-
-			if ( zm != TYPE_GETZM(geoms[i]->type) )
-				lwerror("lwcollection_construct: mixed dimension geometries: %d/%d", zm, TYPE_GETZM(geoms[i]->type));
-		}
-#endif
-	}
-
-
-	ret = lwalloc(sizeof(LWCOLLECTION));
-	ret->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1),
-		type, 0);
-	ret->SRID = SRID;
-	ret->ngeoms = ngeoms;
-	ret->geoms = geoms;
-	ret->bbox = bbox;
-
-	return ret;
-}
-
-LWCOLLECTION *
-lwcollection_construct_empty(int SRID, char hasz, char hasm)
-{
-	LWCOLLECTION *ret;
-
-	ret = lwalloc(sizeof(LWCOLLECTION));
-	ret->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1),
-		COLLECTIONTYPE, 0);
-	ret->SRID = SRID;
-	ret->ngeoms = 0;
-	ret->geoms = NULL;
-	ret->bbox = NULL;
-
-	return ret;
-}
-
-
-LWCOLLECTION *
-lwcollection_deserialize(uchar *srl)
-{
-	LWCOLLECTION *result;
-	LWGEOM_INSPECTED *insp;
-	char typefl = srl[0];
-	int type = lwgeom_getType(typefl);
-	int i;
-
-	if ( type != COLLECTIONTYPE ) 
-	{
-		lwerror("lwcollection_deserialize called on NON geometrycollection: %d", type);
-		return NULL;
-	}
-
-	insp = lwgeom_inspect(srl);
-
-	result = lwalloc(sizeof(LWCOLLECTION));
-	result->type = typefl;
-	result->SRID = insp->SRID;
-	result->ngeoms = insp->ngeometries;
-
-	if (lwgeom_hasBBOX(srl[0]))
-	{
-		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-		memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4));
-	}
-	else result->bbox = NULL;
-
-
-	if ( insp->ngeometries )
-	{
-		result->geoms = lwalloc(sizeof(LWGEOM *)*insp->ngeometries);
-		for (i=0; i<insp->ngeometries; i++)
-		{
-			result->geoms[i] =
-				lwgeom_deserialize(insp->sub_geoms[i]);
-		}
-	}
-
-	return result;
-}
-
-LWGEOM *
-lwcollection_getsubgeom(LWCOLLECTION *col, int gnum)
-{
-	return (LWGEOM *)col->geoms[gnum];
-}
-
-/* find serialized size of this collection */
-size_t
-lwcollection_serialize_size(LWCOLLECTION *col)
-{
-	size_t size = 5; /* type + nsubgeoms */
-	int i;
-
-	if ( col->SRID != -1 ) size += 4; /* SRID */
-	if ( col->bbox ) size += sizeof(BOX2DFLOAT4);
-
-	LWDEBUGF(2, "lwcollection_serialize_size[%p]: start size: %d", col, size);
-
-
-	for (i=0; i<col->ngeoms; i++)
-	{
-		size += lwgeom_serialize_size(col->geoms[i]);
-
-		LWDEBUGF(3, "lwcollection_serialize_size[%p]: with geom%d: %d", col, i, size);
-	}
-
-	LWDEBUGF(3, "lwcollection_serialize_size[%p]:  returning %d", col, size);
-
-	return size; 
-}
-
-/*
- * convert this collectoin into its serialize form writing it into
- * the given buffer, and returning number of bytes written into
- * the given int pointer.
- */
-void
-lwcollection_serialize_buf(LWCOLLECTION *coll, uchar *buf, size_t *retsize)
-{
-	size_t size=1; /* type  */
-	size_t subsize=0;
-	char hasSRID;
-	uchar *loc;
-	int i;
-
-	LWDEBUGF(2, "lwcollection_serialize_buf called (%s with %d elems)",
-		lwgeom_typename(TYPE_GETTYPE(coll->type)), coll->ngeoms);
-
-	hasSRID = (coll->SRID != -1);
-
-	buf[0] = lwgeom_makeType_full(
-		TYPE_HASZ(coll->type), TYPE_HASM(coll->type),
-		hasSRID, TYPE_GETTYPE(coll->type), coll->bbox ? 1 : 0);
-	loc = buf+1;
-
-	/* Add BBOX if requested */
-	if ( coll->bbox )
-	{
-		memcpy(loc, coll->bbox, sizeof(BOX2DFLOAT4));
-		size += sizeof(BOX2DFLOAT4);
-		loc += sizeof(BOX2DFLOAT4);
-	}
-
-	/* Add SRID if requested */
-	if (hasSRID)
-	{
-		memcpy(loc, &coll->SRID, 4);
-		size += 4; 
-		loc += 4;
-	}
-
-	/* Write number of subgeoms */
-	memcpy(loc, &coll->ngeoms, 4);
-	size += 4;
-	loc += 4;
-
-	/* Serialize subgeoms */
-	for (i=0; i<coll->ngeoms; i++)
-	{
-		lwgeom_serialize_buf(coll->geoms[i], loc, &subsize);
-		size += subsize;
-		loc += subsize;
-	}
-
-	if (retsize) *retsize = size;
-
-	LWDEBUG(3, "lwcollection_serialize_buf returning");
-}
-
-int
-lwcollection_compute_box2d_p(LWCOLLECTION *col, BOX2DFLOAT4 *box)
-{
-	BOX2DFLOAT4 boxbuf;
-	uint32 i;
-
-	if ( ! col->ngeoms ) return 0;
-	if ( ! lwgeom_compute_box2d_p(col->geoms[0], box) ) return 0;
-	for (i=1; i<col->ngeoms; i++)
-	{
-		if ( ! lwgeom_compute_box2d_p(col->geoms[i], &boxbuf) )
-			return 0;
-		if ( ! box2d_union_p(box, &boxbuf, box) ) return 0;
-	}
-	return 1;
-}
-
-/*
- * Clone LWCOLLECTION object. POINTARRAY are not copied.
- * Bbox is cloned if present in input.
- */
-LWCOLLECTION *
-lwcollection_clone(const LWCOLLECTION *g)
-{
-	uint32 i;
-	LWCOLLECTION *ret = lwalloc(sizeof(LWCOLLECTION));
-	memcpy(ret, g, sizeof(LWCOLLECTION));
-	if ( g->ngeoms > 0 )
-	{
-		ret->geoms = lwalloc(sizeof(LWGEOM *)*g->ngeoms);
-		for (i=0; i<g->ngeoms; i++)
-		{
-			ret->geoms[i] = lwgeom_clone(g->geoms[i]);
-		}
-		if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
-	}
-	else
-	{
-		ret->bbox = NULL; /* empty collection */
-		ret->geoms = NULL;
-	}
-	return ret;
-}
-
-/*
- * Add 'what' to this collection at position 'where'.
- * where=0 == prepend
- * where=-1 == append
- * Returns a GEOMETRYCOLLECTION
- */
-LWGEOM *
-lwcollection_add(const LWCOLLECTION *to, uint32 where, const LWGEOM *what)
-{
-	LWCOLLECTION *col;
-	LWGEOM **geoms;
-	uint32 i;
-
-	if ( where == -1 ) where = to->ngeoms;
-	else if ( where < -1 || where > to->ngeoms )
-	{
-		lwerror("lwcollection_add: add position out of range %d..%d",
-			-1, to->ngeoms);
-		return NULL;
-	}
-
-	/* dimensions compatibility are checked by caller */
-
-	/* Construct geoms array */
-	geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
-	for (i=0; i<where; i++)
-	{
-		geoms[i] = lwgeom_clone(to->geoms[i]);
-		lwgeom_dropSRID(geoms[i]);
-		lwgeom_dropBBOX(geoms[i]);
-	}
-	geoms[where] = lwgeom_clone(what);
-	lwgeom_dropSRID(geoms[where]);
-	lwgeom_dropBBOX(geoms[where]);
-	for (i=where; i<to->ngeoms; i++)
-	{
-		geoms[i+1] = lwgeom_clone(to->geoms[i]);
-		lwgeom_dropSRID(geoms[i+1]);
-		lwgeom_dropBBOX(geoms[i+1]);
-	}
-
-	col = lwcollection_construct(COLLECTIONTYPE,
-		to->SRID, NULL,
-		to->ngeoms+1, geoms);
-	
-	return (LWGEOM *)col;
-
-}
-
-LWCOLLECTION *
-lwcollection_segmentize2d(LWCOLLECTION *col, double dist)
-{
-	unsigned int i;
-	LWGEOM **newgeoms;
-
-	if ( ! col->ngeoms ) return col;
-
-	newgeoms = lwalloc(sizeof(LWGEOM *)*col->ngeoms);
-	for (i=0; i<col->ngeoms; i++)
-		newgeoms[i] = lwgeom_segmentize2d(col->geoms[i], dist);
-
-	return lwcollection_construct(col->type, col->SRID, NULL,
-		col->ngeoms, newgeoms);
-}
-
-/* check for same geometry composition */
-char
-lwcollection_same(const LWCOLLECTION *c1, const LWCOLLECTION *c2)
-{
-	unsigned int i, j;
-	unsigned int *hit;
-
-	LWDEBUG(2, "lwcollection_same called");
-
-	if ( TYPE_GETTYPE(c1->type) != TYPE_GETTYPE(c2->type) ) return 0;
-	if ( c1->ngeoms != c2->ngeoms ) return 0;
-
-	hit = lwalloc(sizeof(unsigned int)*c1->ngeoms);
-	memset(hit, 0, sizeof(unsigned int)*c1->ngeoms);
-
-	for (i=0; i<c1->ngeoms; i++)
-	{
-		char found=0;
-		for (j=0; j<c2->ngeoms; j++)
-		{
-			if ( hit[j] ) continue;
-			if ( lwgeom_same(c1->geoms[i], c2->geoms[j]) )
-			{
-				hit[j] = 1;
-				found=1;
-				break;
-			}
-		}
-		if ( ! found ) return 0;
-	}
-	return 1;
-}

Deleted: trunk/lwgeom/lwcompound.c
===================================================================
--- trunk/lwgeom/lwcompound.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwcompound.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,118 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "liblwgeom.h"
-
-LWCOMPOUND *
-lwcompound_deserialize(uchar *serialized)
-{
-        LWCOMPOUND *result;
-        LWGEOM_INSPECTED *insp;
-        int type = lwgeom_getType(serialized[0]);
-        int i;
-
-        if(type != COMPOUNDTYPE)
-        {
-                lwerror("lwcompound_deserialize called on non compound: %d", type);
-                return NULL;
-        }
-
-        insp = lwgeom_inspect(serialized);
-
-        result = lwalloc(sizeof(LWCOMPOUND));
-        result->type = insp->type;
-        result->SRID = insp->SRID;
-        result->ngeoms = insp->ngeometries;
-        result->geoms = lwalloc(sizeof(LWGEOM *)*insp->ngeometries);
-
-        if(lwgeom_hasBBOX(serialized[0]))
-        {
-                result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-                memcpy(result->bbox, serialized + 1, sizeof(BOX2DFLOAT4));
-        }
-        else result->bbox = NULL;
-
-        for(i = 0; i < insp->ngeometries; i++)
-        {
-                if(lwgeom_getType(insp->sub_geoms[i][0]) == LINETYPE)
-                        result->geoms[i] = (LWGEOM *)lwline_deserialize(insp->sub_geoms[i]);
-                else
-                        result->geoms[i] = (LWGEOM *)lwcurve_deserialize(insp->sub_geoms[i]);
-                if(TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type))
-                {
-                        lwerror("Mixed dimensions (compound:%d, line/curve%d:%d)",
-                            TYPE_NDIMS(result->type), i,
-                            TYPE_NDIMS(result->geoms[i]->type)
-                        );
-                        lwfree(result);
-                        return NULL;
-                }
-        }
-        return result;
-}
-
-/*
- * Add 'what' to this string at position 'where'
- * where=0 == prepend
- * where=-1 == append
- * Returns a COMPOUND or a GEOMETRYCOLLECTION
- */
-LWGEOM *
-lwcompound_add(const LWCOMPOUND *to, uint32 where, const LWGEOM *what)
-{
-        LWCOLLECTION *col;
-        LWGEOM **geoms;
-        int newtype;
-
-        LWDEBUG(2, "lwcompound_add called.");
-
-        if(where != -1 && where != 0)
-        {
-                lwerror("lwcompound_add only supports 0 or -1 as a second argument, not %d", where);
-                return NULL;
-        }
-
-        /* dimensions compatibility are checked by caller */
-
-        /* Construct geoms array */
-        geoms = lwalloc(sizeof(LWGEOM *)*2);
-        if(where == -1) /* append */
-        {
-                geoms[0] = lwgeom_clone((LWGEOM *)to);
-                geoms[1] = lwgeom_clone(what);
-        }
-        else /* prepend */
-        {
-                geoms[0] = lwgeom_clone(what);
-                geoms[1] = lwgeom_clone((LWGEOM *)to);
-        }
-
-        /* reset SRID and wantbbox flag from component types */
-        geoms[0]->SRID = geoms[1]->SRID = -1;
-        TYPE_SETHASSRID(geoms[0]->type, 0);
-        TYPE_SETHASSRID(geoms[1]->type, 0);
-        TYPE_SETHASBBOX(geoms[0]->type, 0);
-        TYPE_SETHASBBOX(geoms[1]->type, 0);
-
-        /* Find appropriate geom type */
-        if(TYPE_GETTYPE(what->type) == LINETYPE || TYPE_GETTYPE(what->type) == CURVETYPE) newtype = COMPOUNDTYPE;
-        else newtype = COLLECTIONTYPE;
-
-        col = lwcollection_construct(newtype,
-                to->SRID, NULL, 2, geoms);
-
-        return (LWGEOM *)col;
-}
-

Deleted: trunk/lwgeom/lwcurve.c
===================================================================
--- trunk/lwgeom/lwcurve.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwcurve.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,707 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-/* basic LWCURVE functions */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include "liblwgeom.h"
-
-BOX3D *lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3);
-void printLWCURVE(LWCURVE *curve);
-void lwcurve_reverse(LWCURVE *curve);
-LWCURVE *lwcurve_segmentize2d(LWCURVE *curve, double dist);
-char lwcurve_same(const LWCURVE *me, const LWCURVE *you);
-LWCURVE *lwcurve_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points);
-LWCURVE *lwcurve_from_lwmpoint(int SRID, LWMPOINT *mpoint);
-LWCURVE *lwcurve_addpoint(LWCURVE *curve, LWPOINT *point, unsigned int where);
-LWCURVE *lwcurve_removepoint(LWCURVE *curve, unsigned int index);
-void lwcurve_setPoint4d(LWCURVE *curve, unsigned int index, POINT4D *newpoint);
-
-
-
-#ifndef MAXFLOAT
-  #define MAXFLOAT      3.402823466e+38F
-#endif
-
-/*
- * Construct a new LWCURVE.  points will *NOT* be copied
- * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
- */
-LWCURVE *
-lwcurve_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *points)
-{
-        LWCURVE *result;
-        
-	/*
-         * The first arc requires three points.  Each additional
-         * arc requires two more points.  Thus the minimum point count
-         * is three, and the count must be odd.
-         */
-        if(points->npoints % 2 != 1 || points->npoints < 3) 
-        {
-                lwerror("lwcurve_construct: invalid point count %d", points->npoints);
-                return NULL;
-        }
-        
-        result = (LWCURVE*) lwalloc(sizeof(LWCURVE));
-
-        result->type = lwgeom_makeType_full(
-                TYPE_HASZ(points->dims),
-                TYPE_HASM(points->dims),
-                (SRID!=-1), CURVETYPE, 0);
-        result->SRID = SRID;
-        result->points = points;
-        result->bbox = bbox;
-         
-        return result;
-}
-
-/*
- * given the LWGEOM serialized form (or a point into a multi* one)
- * construct a propert LWCURVE.
- * serialized_form should point to the 8bit type format (with type = 8)
- * See serialized form doc
- */
-LWCURVE *
-lwcurve_deserialize(uchar *serialized_form)
-{
-        uchar type;
-        LWCURVE *result;
-        uchar *loc=NULL;
-        uint32 npoints;
-        POINTARRAY *pa;
-
-        type = (uchar)serialized_form[0];
-        if(lwgeom_getType(type) != CURVETYPE)
-        {
-                lwerror("lwcurve_deserialize: attempt to deserialize a curve which is really a %s", lwgeom_typename(type));
-                return NULL;
-        }
-
-        result = (LWCURVE*) lwalloc(sizeof(LWCURVE));
-        result->type = type;
-
-        loc = serialized_form + 1;
-
-        if(lwgeom_hasBBOX(type))
-        {
-                LWDEBUG(3, "lwcurve_deserialize: input has bbox");
-
-                result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-                memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
-                loc += sizeof(BOX2DFLOAT4);               
-         }
-         else
-         {
-                LWDEBUG(3, "lwcurve_deserialize: input lacks bbox");           
-               
-                result->bbox = NULL;
-         }
-
-         if(lwgeom_hasSRID(type))
-         {
-                LWDEBUG(3, "lwcurve_deserialize: input has srid");
-
-                result->SRID = lw_get_int32(loc);               
-                loc += 4; /* type + SRID */
-         }
-         else
-         {
-                LWDEBUG(3, "lwcurve_deserialize: input lacks srid");
-
-                result->SRID = -1;                
-         }
-
-         /* we've read the type (1 byte) and SRID (4 bytes, if present) */
-
-         npoints = lw_get_uint32(loc);
-
-         LWDEBUGF(3, "curve npoints = %d", npoints);
-         
-         loc += 4;
-         pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), npoints);
-         result->points = pa;
-         return result;
-}
-
-/*
- * convert this curve into its serialized form
- * result's first char will be the 8bit type. See serialized form doc
- */
-uchar *
-lwcurve_serialize(LWCURVE *curve)
-{
-        size_t size, retsize;
-        uchar * result;
-
-        if(curve == NULL) {
-                lwerror("lwcurve_serialize:: given null curve");
-                return NULL;
-        }
-
-        size = lwcurve_serialize_size(curve);
-        result = lwalloc(size);
-        lwcurve_serialize_buf(curve, result, &retsize);
-        if(retsize != size)
-                lwerror("lwcurve_serialize_size returned %d, ..selialize_buf returned %d", size, retsize);
-        return result;
-}
-
-/*
- * convert this curve into its serialized form writing it into 
- * the given buffer, and returning number of bytes written into 
- * the given int pointer.
- * result's first char will be the 8bit type.  See serialized form doc
- */
-void lwcurve_serialize_buf(LWCURVE *curve, uchar *buf, size_t *retsize)
-{
-        char hasSRID;
-        uchar *loc;
-        int ptsize;
-        size_t size;
-
-        LWDEBUGF(2, "lwcurve_serialize_buf(%p, %p, %p) called",
-                curve, buf, retsize);
-
-        if(curve == NULL) 
-        {
-                lwerror("lwcurve_serialize:: given null curve");
-                return;
-        }
-
-        if(TYPE_GETZM(curve->type) != TYPE_GETZM(curve->points->dims))
-        {
-                lwerror("Dimensions mismatch in lwcurve");
-                return;
-        }
-
-        ptsize = pointArray_ptsize(curve->points);
-
-        hasSRID = (curve->SRID != -1);
-
-        buf[0] = (uchar)lwgeom_makeType_full(
-                TYPE_HASZ(curve->type), TYPE_HASM(curve->type),
-                hasSRID, CURVETYPE, curve->bbox ? 1 : 0);
-        loc = buf+1;
-
-        LWDEBUGF(3, "lwcurve_serialize_buf added type (%d)", curve->type);
-
-        if(curve->bbox)
-        {
-                memcpy(loc, curve->bbox, sizeof(BOX2DFLOAT4));
-                loc += sizeof(BOX2DFLOAT4);
-
-                LWDEBUG(3, "lwcurve_serialize_buf added BBOX");
-        }                
-
-        if(hasSRID)
-        {
-                memcpy(loc, &curve->SRID, sizeof(int32));
-                loc += sizeof(int32);
-
-                LWDEBUG(3, "lwcurve_serialize_buf added SRID");
-        }
-
-        memcpy(loc, &curve->points->npoints, sizeof(uint32));
-        loc += sizeof(uint32);
-
-        LWDEBUGF(3, "lwcurve_serialize_buf added npoints (%d)",
-            curve->points->npoints);
-
-        /* copy in points */
-        size = curve->points->npoints * ptsize;
-        memcpy(loc, getPoint_internal(curve->points, 0), size);
-        loc += size;
-
-        LWDEBUGF(3, "lwcurve_serialize_buf copied serialized_pointlist (%d bytes)",
-                ptsize * curve->points->npoints);        
-
-        if(retsize) *retsize = loc-buf;
-
-        LWDEBUGF(3, "lwcurve_serialize_buf returning (loc: %p, size: %d)",
-                loc, loc-buf);
-}
-
-/* find length of this deserialized curve */
-size_t
-lwcurve_serialize_size(LWCURVE *curve)
-{
-        size_t size = 1; /* type */
-
-        LWDEBUG(2, "lwcurve_serialize_size called");        
-
-        if(curve->SRID != -1) size += 4; /* SRID */
-        if(curve->bbox) size += sizeof(BOX2DFLOAT4);
-
-        size += 4; /* npoints */
-        size += pointArray_ptsize(curve->points) * curve->points->npoints;
-
-        LWDEBUGF(3, "lwcurve_serialize_size returning %d", size);
-
-        return size;
-}
-
-BOX3D *
-lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
-{
-        double x1, x2, y1, y2, z1, z2;
-        double angle, radius, sweep;
-        /*
-        double top, left;
-        */
-        double a1, a2, a3;
-        double xe = 0.0, ye = 0.0;
-        POINT4D *center;
-        int i;
-        BOX3D *box;
-
-        LWDEBUG(2, "lwcircle_compute_box3d called.");
-
-        center = lwalloc(sizeof(POINT4D));
-        radius = lwcircle_center(p1, p2, p3, &center);
-        if(radius < 0.0) return NULL;
-
-        /*
-        top = center->y + radius;
-        left = center->x - radius;
-
-        LWDEBUGF(3, "lwcircle_compute_box3d: top=%.16f, left=%.16f", top, left);
-        */
-
-        x1 = MAXFLOAT;
-        x2 = -1 * MAXFLOAT;
-        y1 = MAXFLOAT;
-        y2 = -1 * MAXFLOAT;
-
-        a1 = atan2(p1->y - center->y, p1->x - center->x);
-        a2 = atan2(p2->y - center->y, p2->x - center->x);
-        a3 = atan2(p3->y - center->y, p3->x - center->x);
-
-        /* Determine sweep angle */
-        if(a1 > a2 && a2 > a3) 
-        {
-                sweep = a3 - a1;
-        }
-        /* Counter-clockwise */
-        else if(a1 < a2 && a2 < a3)
-        {
-                sweep = a3 - a1;
-        }
-        /* Clockwise, wrap */
-        else if((a1 < a2 && a1 > a3) || (a2 < a3 && a1 > a3))
-        {
-                sweep = a3 - a1 + 2*M_PI;
-        }
-        /* Counter-clockwise, wrap */
-        else if((a1 > a2 && a1 < a3) || (a2 > a3 && a1 < a3))
-        {
-                sweep = a3 - a1 - 2*M_PI;
-        } 
-        else 
-        {
-                sweep = 0.0;
-        }
-
-        LWDEBUGF(3, "a1 %.16f, a2 %.16f, a3 %.16f, sweep %.16f", a1, a2, a3, sweep);
-
-        angle = 0.0;
-        for(i=0; i < 6; i++)
-        {
-                switch(i) {
-                case 0:
-                        angle = 0.0;
-                        xe = center->x + radius;
-                        ye = center->y;
-                        break;
-                case 1:
-                        angle = M_PI_2;
-                        xe = center->x;
-                        ye = center->y + radius;
-                        break;
-                case 2:
-                        angle = M_PI;
-                        xe = center->x - radius;
-                        ye = center->y;
-                        break;
-                case 3:
-                        angle = -1 * M_PI_2;
-                        xe = center->x;
-                        ye = center->y - radius;
-                        break;
-                case 4:
-                        angle = a1;
-                        xe = p1->x;
-                        ye = p1->y;
-                        break;
-                case 5:
-                        angle = a3;
-                        xe = p3->x;
-                        ye = p3->y;
-                        break;
-                }
-                if(i < 4) 
-                {
-                        if(sweep > 0.0 && (angle > a3 || angle < a1)) continue;
-                        if(sweep < 0.0 && (angle < a3 || angle > a1)) continue;
-                }
-
-                LWDEBUGF(3, "lwcircle_compute_box3d: potential extreame %d (%.16f, %.16f)", i, xe, ye);
-
-                x1 = (x1 < xe) ? x1 : xe;
-                y1 = (y1 < ye) ? y1 : ye;
-                x2 = (x2 > xe) ? x2 : xe;
-                y2 = (y2 > ye) ? y2 : ye;
-        }
-
-        LWDEBUGF(3, "lwcircle_compute_box3d: extreames found (%.16f %.16f, %.16f %.16f)", x1, y1, x2, y2);
-
-        /*
-        x1 = center->x + x1 * radius;
-        x2 = center->x + x2 * radius;
-        y1 = center->y + y1 * radius;
-        y2 = center->y + y2 * radius;
-        */
-        z1 = (p1->z < p2->z) ? p1->z : p2->z;
-        z1 = (z1 < p3->z) ? z1 : p3->z;
-        z2 = (p1->z > p2->z) ? p1->z : p2->z;
-        z2 = (z2 > p3->z) ? z2 : p3->z;
-
-        box = lwalloc(sizeof(BOX3D));
-        box->xmin = x1; box->xmax = x2;
-        box->ymin = y1; box->ymax = y2;
-        box->zmin = z1; box->zmax = z2;
-
-        lwfree(center);
-
-        return box;
-}
-
-/*
- * Find bounding box (standard one)
- * zmin=zmax=NO_Z_VALUE if 2d
- * TODO: This ignores curvature, which should be taken into account.
- */
-BOX3D *
-lwcurve_compute_box3d(LWCURVE *curve)
-{
-        BOX3D *box, *tmp; 
-        int i;
-        POINT4D *p1 = lwalloc(sizeof(POINT4D));
-        POINT4D *p2 = lwalloc(sizeof(POINT4D));
-        POINT4D *p3 = lwalloc(sizeof(POINT4D));
-
-        LWDEBUG(2, "lwcurve_compute_box3d called.");
-
-        /* initialize box values */
-        box = lwalloc(sizeof(BOX3D));
-        box->xmin = MAXFLOAT; box->xmax = -1 * MAXFLOAT;
-        box->ymin = MAXFLOAT; box->ymax = -1 * MAXFLOAT;
-        box->zmin = MAXFLOAT; box->zmax = -1 * MAXFLOAT;
-        
-        for(i = 2; i < curve->points->npoints; i+=2)
-        {
-                getPoint4d_p(curve->points, i-2, p1);
-                getPoint4d_p(curve->points, i-1, p2);
-                getPoint4d_p(curve->points, i, p3);
-                tmp = lwcircle_compute_box3d(p1, p2, p3);
-                if(tmp == NULL) continue;
-                box->xmin = (box->xmin < tmp->xmin) ? box->xmin : tmp->xmin;
-                box->xmax = (box->xmax > tmp->xmax) ? box->xmax : tmp->xmax;
-                box->ymin = (box->ymin < tmp->ymin) ? box->ymin : tmp->ymin;
-                box->ymax = (box->ymax > tmp->ymax) ? box->ymax : tmp->ymax;
-                box->zmin = (box->zmin < tmp->zmin) ? box->zmin : tmp->zmin;
-                box->zmax = (box->zmax > tmp->zmax) ? box->zmax : tmp->zmax;
-
-                LWDEBUGF(4, "curve %d x=(%.16f,%.16f) y=(%.16f,%.16f) z=(%.16f,%.16f)", i/2, box->xmin, box->xmax, box->ymin, box->ymax, box->zmin, box->zmax);
-        }
-
-        
-        return box;
-}
-
-int
-lwcurve_compute_box2d_p(LWCURVE *curve, BOX2DFLOAT4 *result)
-{
-        BOX3D *box = lwcurve_compute_box3d(curve);
-        LWDEBUG(2, "lwcurve_compute_box2d_p called.");
-
-        if(box == NULL) return 0;
-        box3d_to_box2df_p(box, result);
-        return 1;
-}
-
-void pfree_curve(LWCURVE *curve)
-{
-        lwfree(curve->points);
-        lwfree(curve);
-}
-
-/* find length of this serialized curve */
-size_t
-lwgeom_size_curve(const uchar *serialized_curve)
-{
-        int type = (uchar)serialized_curve[0];
-        uint32 result = 1; /* type */
-        const uchar *loc;
-        uint32 npoints;
-
-        LWDEBUG(2, "lwgeom_size_curve called");
-
-        if(lwgeom_getType(type) != CURVETYPE)
-                lwerror("lwgeom_size_curve::attempt to find the length of a non-curve");
-
-        loc = serialized_curve + 1;
-        if(lwgeom_hasBBOX(type))
-        {
-                loc += sizeof(BOX2DFLOAT4);
-                result += sizeof(BOX2DFLOAT4);
-        }
-
-        if(lwgeom_hasSRID(type))
-        {
-                loc += 4; /* type + SRID */
-                result += 4;
-        }
-
-        /* we've read the type (1 byte) and SRID (4 bytes, if present) */
-        npoints = lw_get_uint32(loc);
-        result += sizeof(uint32); /* npoints */
-
-        result += TYPE_NDIMS(type) * sizeof(double) * npoints;
-
-        LWDEBUGF(3, "lwgeom_size_curve returning %d", result);
-
-        return result;
-}
-
-void printLWCURVE(LWCURVE *curve)
-{
-        lwnotice("LWCURVE {");
-        lwnotice("    ndims = %i", (int)TYPE_NDIMS(curve->type));
-        lwnotice("    SRID = %i", (int)curve->SRID);
-        printPA(curve->points);
-        lwnotice("}");
-}
-
-/* Clone LWCURVE object.  POINTARRAY is not copied. */
-LWCURVE *
-lwcurve_clone(const LWCURVE *g)
-{
-        LWCURVE *ret = lwalloc(sizeof(LWCURVE));
-        memcpy(ret, g, sizeof(LWCURVE));
-        if(g->bbox) ret->bbox = box2d_clone(g->bbox);
-        return ret;
-}
-
-/*
- * Add 'what' to this curve at position 'where'.
- * where=0 == prepend
- * where=-1 == append
- * Returns a MULTICURVE or a GEOMETRYCOLLECTION
- */
-LWGEOM *
-lwcurve_add(const LWCURVE *to, uint32 where, const LWGEOM *what)
-{
-        LWCOLLECTION *col;
-        LWGEOM **geoms;
-        int newtype;
-        
-        if(where != -1 && where != 0)
-        {
-                lwerror("lwcurve_add only supports 0 or -1 as second argument %d", where);
-                return NULL;
-        }
-
-        /* dimensions compatibility are checked by caller */
-
-        /* Construct geoms array */
-        geoms = lwalloc(sizeof(LWGEOM *)*2);
-        if(where == -1) /* append */
-        {
-                geoms[0] = lwgeom_clone((LWGEOM *)to);
-                geoms[1] = lwgeom_clone(what);
-        }
-        else /* prepend */
-        {
-                geoms[0] = lwgeom_clone(what);
-                geoms[1] = lwgeom_clone((LWGEOM *)to);
-        }
-        
-        /* reset SRID and wantbbox flag from component types */
-        geoms[0]->SRID = geoms[1]->SRID = -1;
-        TYPE_SETHASSRID(geoms[0]->type, 0);
-        TYPE_SETHASSRID(geoms[1]->type, 0);
-        TYPE_SETHASBBOX(geoms[0]->type, 0);
-        TYPE_SETHASBBOX(geoms[1]->type, 0);
-
-        /* Find appropriate geom type */
-        if(TYPE_GETTYPE(what->type) == CURVETYPE || TYPE_GETTYPE(what->type) == LINETYPE) newtype = MULTICURVETYPE;
-        else newtype = COLLECTIONTYPE;
-
-        col = lwcollection_construct(newtype, 
-                to->SRID, NULL, 
-                2, geoms);
-
-        return (LWGEOM *)col;
-}
-
-void lwcurve_reverse(LWCURVE *curve)
-{
-        ptarray_reverse(curve->points);
-}
-
-/*
- * TODO: Invalid segmentization.  This should accomodate the curvature.
- */
-LWCURVE *
-lwcurve_segmentize2d(LWCURVE *curve, double dist)
-{
-        return lwcurve_construct(curve->SRID, NULL,
-                ptarray_segmentize2d(curve->points, dist));
-}
-                    
-/* check coordinate equality */
-char
-lwcurve_same(const LWCURVE *me, const LWCURVE *you)
-{
-        return ptarray_same(me->points, you->points);
-}
-
-/*
- * Construct a LWCURVE from an array of LWPOINTs
- * LWCURVE dimensions are large enough to host all input dimensions.
- */
-LWCURVE *
-lwcurve_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points)
-{
-        int zmflag=0;
-        unsigned int i;
-        POINTARRAY *pa;
-        uchar *newpoints, *ptr;
-        size_t ptsize, size;
-
-        /*
-         * Find output dimensions, check integrity
-         */
-        for(i = 0; i < npoints; i++)
-        {
-                if(TYPE_GETTYPE(points[i]->type) != POINTTYPE)
-                {
-                        lwerror("lwcurve_from_lwpointarray: invalid input type: %s",
-                            lwgeom_typename(TYPE_GETTYPE(points[i]->type)));
-                        return NULL;
-                }
-                if(TYPE_HASZ(points[i]->type)) zmflag |= 2;
-                if(TYPE_HASM(points[i]->type)) zmflag |=1;
-                if(zmflag == 3) break;
-        }
-
-        if(zmflag == 0) ptsize = 2 * sizeof(double);
-        else if(zmflag == 3) ptsize = 4 * sizeof(double);
-        else ptsize = 3 * sizeof(double);
-
-        /*
-         * Allocate output points array
-         */
-        size = ptsize * npoints;
-        newpoints = lwalloc(size);
-        memset(newpoints, 0, size);
-
-        ptr = newpoints;
-        for(i = 0; i < npoints; i++)
-        {
-                size = pointArray_ptsize(points[i]->point);
-                memcpy(ptr, getPoint_internal(points[i]->point, 0), size);
-                ptr += ptsize;
-        }
-        pa = pointArray_construct(newpoints, zmflag&2, zmflag&1, npoints);
-
-        return lwcurve_construct(SRID, NULL, pa);
-}
-
-/*
- * Construct a LWCURVE from a LWMPOINT
- */
-LWCURVE *
-lwcurve_from_lwmpoint(int SRID, LWMPOINT *mpoint)
-{
-        unsigned int i;
-        POINTARRAY *pa;
-        char zmflag = TYPE_GETZM(mpoint->type);
-        size_t ptsize, size;
-        uchar *newpoints, *ptr;
-
-        if(zmflag == 0) ptsize = 2 * sizeof(double);
-        else if(zmflag == 3) ptsize = 4 * sizeof(double);
-        else ptsize = 3 * sizeof(double);
-
-        /* Allocate space for output points */
-        size = ptsize * mpoint->ngeoms;
-        newpoints = lwalloc(size);
-        memset(newpoints, 0, size);
-
-        ptr = newpoints;
-        for(i = 0; i < mpoint->ngeoms; i++)
-        {
-                memcpy(ptr,
-                        getPoint_internal(mpoint->geoms[i]->point, 0),
-                        ptsize);
-                ptr += ptsize;
-        }
-
-        pa = pointArray_construct(newpoints, zmflag&2, zmflag&1,
-                mpoint->ngeoms);
-
-        LWDEBUGF(3, "lwcurve_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag);
-        
-        return lwcurve_construct(SRID, NULL, pa);
-}
-
-LWCURVE *
-lwcurve_addpoint(LWCURVE *curve, LWPOINT *point, unsigned int where)
-{
-        POINTARRAY *newpa;
-        LWCURVE *ret;
-
-        newpa = ptarray_addPoint(curve->points, 
-                getPoint_internal(point->point, 0),
-                TYPE_NDIMS(point->type), where);
-        ret = lwcurve_construct(curve->SRID, NULL, newpa);
-
-        return ret;
-}
-
-LWCURVE *
-lwcurve_removepoint(LWCURVE *curve, unsigned int index)
-{
-        POINTARRAY *newpa;
-        LWCURVE *ret;
-
-        newpa = ptarray_removePoint(curve->points, index);
-        ret = lwcurve_construct(curve->SRID, NULL, newpa);
-
-        return ret;
-}
-
-/*
- * Note: input will be changed, make sure you have permissions for this.
- * */
-void
-lwcurve_setPoint4d(LWCURVE *curve, unsigned int index, POINT4D *newpoint)
-{
-        setPoint4d(curve->points, index, newpoint);
-}
-
-

Deleted: trunk/lwgeom/lwcurvepoly.c
===================================================================
--- trunk/lwgeom/lwcurvepoly.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwcurvepoly.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,86 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-/* basic LWCURVEPOLY manipulation */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "liblwgeom.h"
-
-
-LWCURVEPOLY *
-lwcurvepoly_deserialize(uchar *srl)
-{
-        LWCURVEPOLY *result;
-        LWGEOM_INSPECTED *insp;
-        int type = lwgeom_getType(srl[0]);
-        int i;
-
-        LWDEBUG(3, "lwcurvepoly_deserialize called.");
-
-        if(type != CURVEPOLYTYPE)
-        {
-                lwerror("lwcurvepoly_deserialize called on NON curvepoly: %d",
-                        type);
-                return NULL;
-        }
-
-        insp = lwgeom_inspect(srl);
-
-        result = lwalloc(sizeof(LWCURVEPOLY));
-        result->type = insp->type;
-        result->SRID = insp->SRID;
-        result->nrings = insp->ngeometries;
-        result->rings = lwalloc(sizeof(LWGEOM *)*insp->ngeometries);
-
-        if(lwgeom_hasBBOX(srl[0]))
-        {
-                result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-                memcpy(result->bbox, srl + 1, sizeof(BOX2DFLOAT4));
-        }
-        else result->bbox = NULL;
-
-        for(i = 0; i < insp->ngeometries; i++)
-        {
-                result->rings[i] = lwgeom_deserialize(insp->sub_geoms[i]);
-                if(lwgeom_getType(result->rings[i]->type) != CURVETYPE 
-                        && lwgeom_getType(result->rings[i]->type) != LINETYPE)
-                {
-                        lwerror("Only Circular curves and Linestrings are currently supported as rings, not %s (%d)", lwgeom_typename(result->rings[i]->type), result->rings[i]->type);
-                        lwfree(result);
-                        lwfree(insp);
-                        return NULL;
-                }
-                if(TYPE_NDIMS(result->rings[i]->type) != TYPE_NDIMS(result->type))
-                {
-                        lwerror("Mixed dimensions (curvepoly %d, ring %d)",
-                                TYPE_NDIMS(result->type), i, 
-                                TYPE_NDIMS(result->rings[i]->type));
-                        lwfree(result);
-                        lwfree(insp);
-                        return NULL;
-                }
-        }
-        return result;
-}
-
-LWGEOM *
-lwcurvepoly_add(const LWCURVEPOLY *to, uint32 where, const LWGEOM *what)
-{
-        /* TODO */
-        lwerror("lwcurvepoly_add not yet implemented.");
-        return NULL;
-}
-
-
-

Deleted: trunk/lwgeom/lwgeom.c
===================================================================
--- trunk/lwgeom/lwgeom.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgeom.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,696 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-/*#include "lwgeom_pg.h"*/
-#include "liblwgeom.h"
-#include "wktparse.h"
-
-
-LWGEOM *
-lwgeom_deserialize(uchar *srl)
-{
-	int type = lwgeom_getType(srl[0]);
-
-	LWDEBUGF(2, "lwgeom_deserialize got %d - %s", type, lwgeom_typename(type));
-
-	switch (type)
-	{
-		case POINTTYPE:
-			return (LWGEOM *)lwpoint_deserialize(srl);
-		case LINETYPE:
-			return (LWGEOM *)lwline_deserialize(srl);
-                case CURVETYPE:
-                        return (LWGEOM *)lwcurve_deserialize(srl);
-		case POLYGONTYPE:
-			return (LWGEOM *)lwpoly_deserialize(srl);
-		case MULTIPOINTTYPE:
-			return (LWGEOM *)lwmpoint_deserialize(srl);
-		case MULTILINETYPE:
-			return (LWGEOM *)lwmline_deserialize(srl);
-		case MULTIPOLYGONTYPE:
-			return (LWGEOM *)lwmpoly_deserialize(srl);
-		case COLLECTIONTYPE:
-			return (LWGEOM *)lwcollection_deserialize(srl);
-                case COMPOUNDTYPE:
-                        return (LWGEOM *)lwcompound_deserialize(srl);
-                case CURVEPOLYTYPE:
-                        return (LWGEOM *)lwcurvepoly_deserialize(srl);
-                case MULTICURVETYPE:
-                        return (LWGEOM *)lwmcurve_deserialize(srl);
-                case MULTISURFACETYPE:
-                        return (LWGEOM *)lwmsurface_deserialize(srl);
-		default:
-			lwerror("Unknown geometry type: %d", type);
-
-			return NULL;
-	}
-
-}
-
-size_t
-lwgeom_serialize_size(LWGEOM *lwgeom)
-{
-	int type = TYPE_GETTYPE(lwgeom->type);
-
-	LWDEBUGF(2, "lwgeom_serialize_size(%s) called", lwgeom_typename(type));
-
-	switch (type)
-	{
-		case POINTTYPE:
-			return lwpoint_serialize_size((LWPOINT *)lwgeom);
-		case LINETYPE:
-			return lwline_serialize_size((LWLINE *)lwgeom);
-		case POLYGONTYPE:
-			return lwpoly_serialize_size((LWPOLY *)lwgeom);
-                case CURVETYPE:
-                        return lwcurve_serialize_size((LWCURVE *)lwgeom);
-                case CURVEPOLYTYPE:
-                case COMPOUNDTYPE:
-		case MULTIPOINTTYPE:
-		case MULTILINETYPE:
-                case MULTICURVETYPE:
-		case MULTIPOLYGONTYPE:
-                case MULTISURFACETYPE:
-		case COLLECTIONTYPE:
-			return lwcollection_serialize_size((LWCOLLECTION *)lwgeom);
-		default:
-			lwerror("Unknown geometry type: %d", type);
-
-			return 0;
-	}
-}
-
-void
-lwgeom_serialize_buf(LWGEOM *lwgeom, uchar *buf, size_t *retsize)
-{
-	int type = TYPE_GETTYPE(lwgeom->type);
-
-	LWDEBUGF(2, "lwgeom_serialize_buf called with a %s",
-			lwgeom_typename(type));
-
-	switch (type)
-	{
-		case POINTTYPE:
-			lwpoint_serialize_buf((LWPOINT *)lwgeom, buf, retsize);
-			break;
-		case LINETYPE:
-			lwline_serialize_buf((LWLINE *)lwgeom, buf, retsize);
-			break;
-		case POLYGONTYPE:
-			lwpoly_serialize_buf((LWPOLY *)lwgeom, buf, retsize);
-			break;
-                case CURVETYPE:
-                        lwcurve_serialize_buf((LWCURVE *)lwgeom, buf, retsize);
-                        break;
-                case CURVEPOLYTYPE:
-                case COMPOUNDTYPE:
-		case MULTIPOINTTYPE:
-		case MULTILINETYPE:
-                case MULTICURVETYPE:
-		case MULTIPOLYGONTYPE:
-                case MULTISURFACETYPE:
-		case COLLECTIONTYPE:
-			lwcollection_serialize_buf((LWCOLLECTION *)lwgeom, buf,
-				retsize);
-			break;
-		default:
-			lwerror("Unknown geometry type: %d", type);
-			return;
-	}
-	return;
-}
-
-uchar *
-lwgeom_serialize(LWGEOM *lwgeom)
-{
-	size_t size = lwgeom_serialize_size(lwgeom);
-	size_t retsize;
-	uchar *serialized = lwalloc(size);
-
-	lwgeom_serialize_buf(lwgeom, serialized, &retsize);
-
-#if POSTGIS_DEBUG_LEVEL > 0
-	if ( retsize != size )
-	{
-		lwerror("lwgeom_serialize: computed size %d, returned size %d",
-			size, retsize);
-	}
-#endif
-
-	return serialized;
-}
-
-/* Force Right-hand-rule on LWGEOM polygons */
-void
-lwgeom_forceRHR(LWGEOM *lwgeom)
-{
-	LWCOLLECTION *coll;
-	int i;
-
-	switch (TYPE_GETTYPE(lwgeom->type))
-	{
-		case POLYGONTYPE:
-			lwpoly_forceRHR((LWPOLY *)lwgeom);
-			return;
-
-		case MULTIPOLYGONTYPE:
-		case COLLECTIONTYPE:
-			coll = (LWCOLLECTION *)lwgeom;
-			for (i=0; i<coll->ngeoms; i++)
-				lwgeom_forceRHR(coll->geoms[i]);
-			return;
-	}
-}
-
-/* Reverse vertex order of LWGEOM */
-void
-lwgeom_reverse(LWGEOM *lwgeom)
-{
-	int i;
-	LWCOLLECTION *col;
-
-	switch (TYPE_GETTYPE(lwgeom->type))
-	{
-		case LINETYPE:
-			lwline_reverse((LWLINE *)lwgeom);
-			return;
-		case POLYGONTYPE:
-			lwpoly_reverse((LWPOLY *)lwgeom);
-			return;
-		case MULTILINETYPE:
-		case MULTIPOLYGONTYPE:
-		case COLLECTIONTYPE:
-			col = (LWCOLLECTION *)lwgeom;
-			for (i=0; i<col->ngeoms; i++)
-				lwgeom_reverse(col->geoms[i]);
-			return;
-	}
-}
-
-int
-lwgeom_compute_box2d_p(LWGEOM *lwgeom, BOX2DFLOAT4 *buf)
-{
-        LWDEBUGF(2, "lwgeom_compute_box2d_p called of %p of type %d.", lwgeom, TYPE_GETTYPE(lwgeom->type));
-
-	switch(TYPE_GETTYPE(lwgeom->type))
-	{
-		case POINTTYPE:
-			return lwpoint_compute_box2d_p((LWPOINT *)lwgeom, buf);
-		case LINETYPE:
-			return lwline_compute_box2d_p((LWLINE *)lwgeom, buf);
-                case CURVETYPE:
-                        return lwcurve_compute_box2d_p((LWCURVE *)lwgeom, buf);
-		case POLYGONTYPE:
-			return lwpoly_compute_box2d_p((LWPOLY *)lwgeom, buf);
-                case COMPOUNDTYPE:
-                case CURVEPOLYTYPE:
-		case MULTIPOINTTYPE:
-		case MULTILINETYPE:
-                case MULTICURVETYPE:
-		case MULTIPOLYGONTYPE:
-                case MULTISURFACETYPE:
-		case COLLECTIONTYPE:
-			return lwcollection_compute_box2d_p((LWCOLLECTION *)lwgeom, buf);
-	}
-	return 0;
-}
-
-/*
- * dont forget to lwfree() result
- */
-BOX2DFLOAT4 *
-lwgeom_compute_box2d(LWGEOM *lwgeom)
-{
-	BOX2DFLOAT4 *result = lwalloc(sizeof(BOX2DFLOAT4));
-	if ( lwgeom_compute_box2d_p(lwgeom, result) ) return result;
-	else  {
-		lwfree(result);
-		return NULL;
-	}
-}
-
-LWPOINT *
-lwgeom_as_lwpoint(LWGEOM *lwgeom)
-{
-	if ( TYPE_GETTYPE(lwgeom->type) == POINTTYPE )
-		return (LWPOINT *)lwgeom;
-	else return NULL;
-}
-
-LWLINE *
-lwgeom_as_lwline(LWGEOM *lwgeom)
-{
-	if ( TYPE_GETTYPE(lwgeom->type) == LINETYPE )
-		return (LWLINE *)lwgeom;
-	else return NULL;
-}
-
-LWCURVE *
-lwgeom_as_lwcurve(LWGEOM *lwgeom)
-{
-        if( TYPE_GETTYPE(lwgeom->type) == CURVETYPE )
-                return (LWCURVE *)lwgeom;
-        else return NULL;
-}
-
-LWPOLY *
-lwgeom_as_lwpoly(LWGEOM *lwgeom)
-{
-	if ( TYPE_GETTYPE(lwgeom->type) == POLYGONTYPE )
-		return (LWPOLY *)lwgeom;
-	else return NULL;
-}
-
-LWCOLLECTION *
-lwgeom_as_lwcollection(LWGEOM *lwgeom)
-{
-	if ( TYPE_GETTYPE(lwgeom->type) >= MULTIPOINTTYPE 
-            && TYPE_GETTYPE(lwgeom->type) <= COLLECTIONTYPE)
-		return (LWCOLLECTION *)lwgeom;
-	else return NULL;
-}
-
-LWMPOINT *
-lwgeom_as_lwmpoint(LWGEOM *lwgeom)
-{
-	if ( TYPE_GETTYPE(lwgeom->type) == MULTIPOINTTYPE )
-		return (LWMPOINT *)lwgeom;
-	else return NULL;
-}
-
-LWMLINE *
-lwgeom_as_lwmline(LWGEOM *lwgeom)
-{
-	if ( TYPE_GETTYPE(lwgeom->type) == MULTILINETYPE )
-		return (LWMLINE *)lwgeom;
-	else return NULL;
-}
-
-LWMPOLY *
-lwgeom_as_lwmpoly(LWGEOM *lwgeom)
-{
-	if ( TYPE_GETTYPE(lwgeom->type) == MULTIPOLYGONTYPE )
-		return (LWMPOLY *)lwgeom;
-	else return NULL;
-}
-
-LWGEOM *lwmpoly_as_lwgeom(LWMPOLY *obj) { return (LWGEOM *)obj; }
-LWGEOM *lwmline_as_lwgeom(LWMLINE *obj) { return (LWGEOM *)obj; }
-LWGEOM *lwmpoint_as_lwgeom(LWMPOINT *obj) { return (LWGEOM *)obj; }
-LWGEOM *lwcollection_as_lwgeom(LWCOLLECTION *obj) { return (LWGEOM *)obj; }
-LWGEOM *lwpoly_as_lwgeom(LWPOLY *obj) { return (LWGEOM *)obj; }
-LWGEOM *lwline_as_lwgeom(LWLINE *obj) { return (LWGEOM *)obj; }
-LWGEOM *lwpoint_as_lwgeom(LWPOINT *obj) { return (LWGEOM *)obj; }
-
-void
-lwgeom_release(LWGEOM *lwgeom)
-{
-	uint32 i;
-	LWCOLLECTION *col;
-
-#ifdef INTEGRITY_CHECKS
-	if ( ! lwgeom )
-		lwerror("lwgeom_release: someone called on 0x0");
-#endif
-
-	/* Drop bounding box (always a copy) */
-	if ( lwgeom->bbox ) {
-                LWDEBUG(3, "lwgeom_release: releasing bbox.");
-
-                lwfree(lwgeom->bbox);
-        }
-
-	/* Collection */
-	if ( (col=lwgeom_as_lwcollection(lwgeom)) )
-	{
-                LWDEBUG(3, "lwgeom_release: Releasing collection.");
-
-		for (i=0; i<col->ngeoms; i++)
-		{
-			lwgeom_release(col->geoms[i]);
-		}
-		lwfree(lwgeom);
-	}
-
-	/* Single element */
-	else lwfree(lwgeom);
-
-}
-
-/* Clone an LWGEOM object. POINTARRAY are not copied. */
-LWGEOM *
-lwgeom_clone(const LWGEOM *lwgeom)
-{
-        LWDEBUGF(2, "lwgeom_clone called with %p, %d", lwgeom, TYPE_GETTYPE(lwgeom->type));
-
-	switch(TYPE_GETTYPE(lwgeom->type))
-	{
-		case POINTTYPE:
-			return (LWGEOM *)lwpoint_clone((LWPOINT *)lwgeom);
-		case LINETYPE:
-			return (LWGEOM *)lwline_clone((LWLINE *)lwgeom);
-                case CURVETYPE:
-                        return (LWGEOM *)lwcurve_clone((LWCURVE *)lwgeom);
-		case POLYGONTYPE:
-			return (LWGEOM *)lwpoly_clone((LWPOLY *)lwgeom);
-                case COMPOUNDTYPE:
-                case CURVEPOLYTYPE:
-		case MULTIPOINTTYPE:
-		case MULTILINETYPE:
-                case MULTICURVETYPE:
-		case MULTIPOLYGONTYPE:
-                case MULTISURFACETYPE:
-		case COLLECTIONTYPE:
-			return (LWGEOM *)lwcollection_clone((LWCOLLECTION *)lwgeom);
-		default:
-			return NULL;
-	}
-}
-
-/*
- * Add 'what' to 'to' at position 'where'
- *
- * where=0 == prepend
- * where=-1 == append
- * Appended-to LWGEOM gets a new type based on new condition.
- * Mix of dimensions is not allowed (TODO: allow it?).
- */
-LWGEOM *
-lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what)
-{
-	if ( TYPE_NDIMS(what->type) != TYPE_NDIMS(to->type) )
-	{
-		lwerror("lwgeom_add: mixed dimensions not supported");
-		return NULL;
-	}
-
-	LWDEBUGF(2, "lwgeom_add(%s, %d, %s) called",
-		lwgeom_typename(TYPE_GETTYPE(to->type)),
-		where,
-		lwgeom_typename(TYPE_GETTYPE(what->type)));
-
-	switch(TYPE_GETTYPE(to->type))
-	{
-		case POINTTYPE:
-			return (LWGEOM *)lwpoint_add((const LWPOINT *)to, where, what);
-		case LINETYPE:
-			return (LWGEOM *)lwline_add((const LWLINE *)to, where, what);
-
-                case CURVETYPE:
-                        return (LWGEOM *)lwcurve_add((const LWCURVE *)to, where, what);
-
-		case POLYGONTYPE:
-			return (LWGEOM *)lwpoly_add((const LWPOLY *)to, where, what);
-
-                case COMPOUNDTYPE:
-                        return (LWGEOM *)lwcompound_add((const LWCOMPOUND *)to, where, what);
-
-                case CURVEPOLYTYPE:
-                        return (LWGEOM *)lwcurvepoly_add((const LWCURVEPOLY *)to, where, what);
-
-		case MULTIPOINTTYPE:
-			return (LWGEOM *)lwmpoint_add((const LWMPOINT *)to,
-				where, what);
-
-		case MULTILINETYPE:
-			return (LWGEOM *)lwmline_add((const LWMLINE *)to,
-				where, what);
-
-                case MULTICURVETYPE:
-                        return (LWGEOM *)lwmcurve_add((const LWMCURVE *)to,
-                                where, what);
-
-		case MULTIPOLYGONTYPE:
-			return (LWGEOM *)lwmpoly_add((const LWMPOLY *)to,
-				where, what);
-
-                case MULTISURFACETYPE:
-                        return (LWGEOM *)lwmsurface_add((const LWMSURFACE *)to,
-                                where, what);
-
-		case COLLECTIONTYPE:
-			return (LWGEOM *)lwcollection_add(
-				(const LWCOLLECTION *)to, where, what);
-
-		default:
-			lwerror("lwgeom_add: unknown geometry type: %d",
-				TYPE_GETTYPE(to->type));
-			return NULL;
-	}
-}
-
-/*
- * Return an alloced string
- */
-char *
-lwgeom_to_ewkt(LWGEOM *lwgeom)
-{
-	uchar *serialized = lwgeom_serialize(lwgeom);
-	char *ret;
-	if ( ! serialized ) {
-		lwerror("Error serializing geom %p", lwgeom);
-	}
-	ret = unparse_WKT(serialized, lwalloc, lwfree);
-	lwfree(serialized);
-	return ret;
-}
-
-/*
- * Return an alloced string
- */
-char *
-lwgeom_to_hexwkb(LWGEOM *lwgeom, unsigned int byteorder)
-{
-	uchar *serialized = lwgeom_serialize(lwgeom);
-	char *hexwkb = unparse_WKB(serialized, lwalloc, lwfree, byteorder,NULL,1);
-	lwfree(serialized);
-	return hexwkb;
-}
-
-/*
- * Return an alloced string
- */
-uchar *
-lwgeom_to_ewkb(LWGEOM *lwgeom, char byteorder, size_t *outsize)
-{
-	uchar *serialized = lwgeom_serialize(lwgeom);
-
-	/*
-	 * We cast return to "unsigned" char as we are
-	 * requesting a "binary" output, not HEX
-	 * (last argument set to 0)
-	 */
-	uchar *hexwkb = (uchar *)unparse_WKB(serialized, lwalloc, lwfree,
-		byteorder, outsize, 0);
-	lwfree(serialized);
-	return hexwkb;
-}
-
-/*
- * Make an LWGEOM object from a EWKB binary representation.
- * Currently highly unoptimized as it:
- * 	- convert EWKB to HEXEWKB 
- *	- construct PG_LWGEOM
- *	- deserialize it
- */
-LWGEOM *
-lwgeom_from_ewkb(uchar *ewkb, size_t size)
-{
-	size_t hexewkblen = size*2;
-	char *hexewkb;
-	long int i;
-	LWGEOM *ret;
-	SERIALIZED_LWGEOM *serialized_lwgeom;
-
-	/* "HEXify" the EWKB */
-	hexewkb = lwalloc(hexewkblen+1);
-	for (i=0; i<size; ++i) deparse_hex(ewkb[i], &hexewkb[i*2]);
-	hexewkb[hexewkblen] = '\0';
-
-	/* Rely on grammar parser to construct a LWGEOM */
-	serialized_lwgeom = parse_lwgeom_wkt(hexewkb);
-
-	/* Free intermediate HEXified representation */
-	lwfree(hexewkb);
-
-	/* Deserialize */
-	ret = lwgeom_deserialize(serialized_lwgeom->lwgeom);
-
-	return ret;
-}
-
-/*
- * geom1 same as geom2
- *  iff
- *      + have same type 
- *	+ have same # objects
- *      + have same bvol
- *      + each object in geom1 has a corresponding object in geom2 (see above)
- */
-char
-lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
-{
-	LWDEBUGF(2, "lwgeom_same(%s, %s) called",
-		lwgeom_typename(TYPE_GETTYPE(lwgeom1->type)),
-		lwgeom_typename(TYPE_GETTYPE(lwgeom2->type)));
-
-	if ( TYPE_GETTYPE(lwgeom1->type) != TYPE_GETTYPE(lwgeom2->type) )
-	{
-		LWDEBUG(3, " type differ");
-
-		return 0;
-	}
-
-	if ( TYPE_GETZM(lwgeom1->type) != TYPE_GETZM(lwgeom2->type) )
-	{
-		LWDEBUG(3, " ZM flags differ");
-
-		return 0;
-	}
-
-	/* Check boxes if both already computed  */
-	if ( lwgeom1->bbox && lwgeom2->bbox )
-	{
-		/*lwnotice("bbox1:%p, bbox2:%p", lwgeom1->bbox, lwgeom2->bbox);*/
-		if ( ! box2d_same(lwgeom1->bbox, lwgeom2->bbox) )
-		{
-			LWDEBUG(3, " bounding boxes differ");
-
-			return 0;
-		}
-	}
-
-	/* geoms have same type, invoke type-specific function */
-	switch(TYPE_GETTYPE(lwgeom1->type))
-	{
-		case POINTTYPE:
-			return lwpoint_same((LWPOINT *)lwgeom1,
-				(LWPOINT *)lwgeom2);
-		case LINETYPE:
-			return lwline_same((LWLINE *)lwgeom1,
-				(LWLINE *)lwgeom2);
-		case POLYGONTYPE:
-			return lwpoly_same((LWPOLY *)lwgeom1,
-				(LWPOLY *)lwgeom2);
-		case MULTIPOINTTYPE:
-		case MULTILINETYPE:
-		case MULTIPOLYGONTYPE:
-		case COLLECTIONTYPE:
-			return lwcollection_same((LWCOLLECTION *)lwgeom1,
-				(LWCOLLECTION *)lwgeom2);
-		default:
-			lwerror("lwgeom_same: unknown geometry type: %d",
-				TYPE_GETTYPE(lwgeom1->type));
-			return 0;
-	}
-
-}
-
-void
-lwgeom_changed(LWGEOM *lwgeom)
-{
-	if ( lwgeom->bbox ) lwfree(lwgeom->bbox);
-	lwgeom->bbox = NULL;
-	TYPE_SETHASBBOX(lwgeom->type, 0);
-}
-
-void
-lwgeom_dropBBOX(LWGEOM *lwgeom)
-{
-	if ( lwgeom->bbox ) lwfree(lwgeom->bbox);
-	lwgeom->bbox = NULL;
-	TYPE_SETHASBBOX(lwgeom->type, 0);
-}
-
-/*
- * Ensure there's a box in the LWGEOM.
- * If the box is already there just return,
- * else compute it.
- */
-void
-lwgeom_addBBOX(LWGEOM *lwgeom)
-{
-	if ( lwgeom->bbox ) return;
-	lwgeom->bbox = lwgeom_compute_box2d(lwgeom);
-	TYPE_SETHASBBOX(lwgeom->type, 1);
-}
-
-void
-lwgeom_dropSRID(LWGEOM *lwgeom)
-{
-	TYPE_SETHASSRID(lwgeom->type, 0);
-	lwgeom->SRID = -1;
-}
-
-LWGEOM *
-lwgeom_segmentize2d(LWGEOM *lwgeom, double dist)
-{
-	switch(TYPE_GETTYPE(lwgeom->type))
-	{
-		case LINETYPE:
-			return (LWGEOM *)lwline_segmentize2d((LWLINE *)lwgeom,
-				dist);
-		case POLYGONTYPE:
-			return (LWGEOM *)lwpoly_segmentize2d((LWPOLY *)lwgeom,
-				dist);
-		case MULTILINETYPE:
-		case MULTIPOLYGONTYPE:
-		case COLLECTIONTYPE:
-			return (LWGEOM *)lwcollection_segmentize2d(
-				(LWCOLLECTION *)lwgeom, dist);
-
-		default:
-			return lwgeom_clone(lwgeom);
-	}
-}
-
-void
-lwgeom_longitude_shift(LWGEOM *lwgeom)
-{
-	int i;
-	switch(TYPE_GETTYPE(lwgeom->type))
-	{
-		LWPOINT *point;
-		LWLINE *line;
-		LWPOLY *poly;
-		LWCOLLECTION *coll;
-
-		case POINTTYPE:
-			point = (LWPOINT *)lwgeom;
-			ptarray_longitude_shift(point->point);
-			return;
-		case LINETYPE:
-			line = (LWLINE *)lwgeom;
-			ptarray_longitude_shift(line->points);
-			return;
-		case POLYGONTYPE:
-			poly = (LWPOLY *)lwgeom;
-			for (i=0; i<poly->nrings; i++)
-				ptarray_longitude_shift(poly->rings[i]);
-			return;
-		case MULTILINETYPE:
-		case MULTIPOLYGONTYPE:
-		case COLLECTIONTYPE:
-			coll = (LWCOLLECTION *)lwgeom;
-			for (i=0; i<coll->ngeoms; i++)
-				lwgeom_longitude_shift(coll->geoms[i]);
-			return;
-		default:
-			lwerror("%s:%d: unknown geom type: %d",
-				__FILE__, __LINE__,
-				TYPE_GETTYPE(lwgeom->type));
-	}
-}

Deleted: trunk/lwgeom/lwgeom_api.c
===================================================================
--- trunk/lwgeom/lwgeom_api.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgeom_api.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,2185 +0,0 @@
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "liblwgeom.h"
-#include "wktparse.h"
-
-/*
- * Lower this to reduce integrity checks
- */
-#define PARANOIA_LEVEL 1
-
-
-
-/**********************************************************************
- * BOX routines
- *
- * returns the float thats very close to the input, but <=
- *  handles the funny differences in float4 and float8 reps.
- **********************************************************************/
-
-
-/*
- * These are taken from glibc
- * some machines do *not* have these functions defined, so we give
- *  an implementation of them here.
- */
-typedef int int32_tt;
-typedef unsigned int u_int32_tt;
-
-typedef union
-{
-  float value;
-  u_int32_tt word;
-} ieee_float_shape_type;
-
-#define GET_FLOAT_WORD(i,d)			\
-	do {					\
-		ieee_float_shape_type gf_u;	\
-		gf_u.value = (d);		\
-		(i) = gf_u.word;		\
-	} while (0)
-
-
-#define SET_FLOAT_WORD(d,i)			\
-	do {					\
-		ieee_float_shape_type sf_u;	\
-		sf_u.word = (i);		\
-		(d) = sf_u.value;		\
-	} while (0)
-
-
-/*
- * Returns the next smaller or next larger float
- * from x (in direction of y).
- */
-float
-nextafterf_custom(float x, float y)
-{
-        int32_tt hx,hy,ix,iy;
-
-        GET_FLOAT_WORD(hx,x);
-        GET_FLOAT_WORD(hy,y);
-        ix = hx&0x7fffffff;             /* |x| */
-        iy = hy&0x7fffffff;             /* |y| */
-
-        if((ix>0x7f800000) ||   /* x is nan */
-           (iy>0x7f800000))     /* y is nan */
-           return x+y;
-        if(x==y) return y;              /* x=y, return y */
-        if(ix==0) {                             /* x == 0 */
-            SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */
-            y = x*x;
-            if(y==x) return y; else return x;   /* raise underflow flag */
-        }
-        if(hx>=0) {                             /* x > 0 */
-            if(hx>hy) {                         /* x > y, x -= ulp */
-                hx -= 1;
-            } else {                            /* x < y, x += ulp */
-                hx += 1;
-            }
-        } else {                                /* x < 0 */
-            if(hy>=0||hx>hy){                   /* x < y, x -= ulp */
-                hx -= 1;
-            } else {                            /* x > y, x += ulp */
-                hx += 1;
-            }
-        }
-        hy = hx&0x7f800000;
-        if(hy>=0x7f800000) return x+x;  /* overflow  */
-        if(hy<0x00800000) {             /* underflow */
-            y = x*x;
-            if(y!=x) {          /* raise underflow flag */
-                SET_FLOAT_WORD(y,hx);
-                return y;
-            }
-        }
-        SET_FLOAT_WORD(x,hx);
-        return x;
-}
-
-
-float nextDown_f(double d)
-{
-	float result  = d;
-
-	if ( ((double) result) <=d)
-		return result;
-
-	return nextafterf_custom(result, result - 1000000);
-
-}
-
-/*
- * Returns the float thats very close to the input, but >=.
- * handles the funny differences in float4 and float8 reps.
- */
-float
-nextUp_f(double d)
-{
-	float result  = d;
-
-	if ( ((double) result) >=d)
-		return result;
-
-	return nextafterf_custom(result, result + 1000000);
-}
-
-
-/*
- * Returns the double thats very close to the input, but <.
- * handles the funny differences in float4 and float8 reps.
- */
-double
-nextDown_d(float d)
-{
-	double result  = d;
-
-	if ( result < d)
-		return result;
-
-	return nextafterf_custom(result, result - 1000000);
-}
-
-/*
- * Returns the double thats very close to the input, but >
- * handles the funny differences in float4 and float8 reps.
- */
-double
-nextUp_d(float d)
-{
-	double result  = d;
-
-	if ( result > d)
-		return result;
-
-	return nextafterf_custom(result, result + 1000000);
-}
-
-
-
-/*
- * Convert BOX3D to BOX2D
- * returned box2d is allocated with 'lwalloc'
- */
-BOX2DFLOAT4 *
-box3d_to_box2df(BOX3D *box)
-{
-	BOX2DFLOAT4 *result = (BOX2DFLOAT4*) lwalloc(sizeof(BOX2DFLOAT4));
-
-#if PARANOIA_LEVEL > 0
-	if (box == NULL)
-	{
-		lwerror("box3d_to_box2df got NUL box");
-		return NULL;
-	}
-#endif
-
-	result->xmin = nextDown_f(box->xmin);
-	result->ymin = nextDown_f(box->ymin);
-
-	result->xmax = nextUp_f(box->xmax);
-	result->ymax = nextUp_f(box->ymax);
-
-	return result;
-}
-
-/*
- * Convert BOX3D to BOX2D using pre-allocated BOX2D
- * returned box2d is allocated with 'lwalloc'
- * return 0 on error (NULL input box)
- */
-int
-box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *result)
-{
-#if PARANOIA_LEVEL > 0
-	if (box == NULL)
-	{
-		lwerror("box3d_to_box2df got NUL box");
-		return 0;
-	}
-#endif
-
-	result->xmin = nextDown_f(box->xmin);
-	result->ymin = nextDown_f(box->ymin);
-
-	result->xmax = nextUp_f(box->xmax);
-	result->ymax = nextUp_f(box->ymax);
-
-	return 1;
-}
-
-
-
-/*
- * Convert BOX2D to BOX3D
- * zmin and zmax are set to NO_Z_VALUE
- */
-BOX3D
-box2df_to_box3d(BOX2DFLOAT4 *box)
-{
-	BOX3D result;
-
-#if PARANOIA_LEVEL > 0
-	if (box == NULL)
-		lwerror("box2df_to_box3d got NULL box");
-#endif
-
-	result.xmin = box->xmin;
-	result.ymin = box->ymin;
-
-	result.xmax = box->xmax;
-	result.ymax = box->ymax;
-
-	result.zmin = result.zmax = NO_Z_VALUE;
-
-	return result;
-}
-
-/*
- * Convert BOX2D to BOX3D, using pre-allocated BOX3D as output
- * Z values are set to NO_Z_VALUE.
- */
-void
-box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *out)
-{
-	if (box == NULL) return;
-
-	out->xmin = box->xmin;
-	out->ymin = box->ymin;
-
-	out->xmax = box->xmax;
-	out->ymax = box->ymax;
-
-	out->zmin = out->zmax = NO_Z_VALUE;
-}
-
-
-
-/*
- * Returns a BOX3D that encloses b1 and b2
- * box3d_union(NULL,A) --> A
- * box3d_union(A,NULL) --> A
- * box3d_union(A,B) --> A union B
- */
-BOX3D *
-box3d_union(BOX3D *b1, BOX3D *b2)
-{
-	BOX3D *result;
-
-	result = lwalloc(sizeof(BOX3D));
-
-	if ( (b1 == NULL) && (b2 == NULL) )
-	{
-		return NULL;
-	}
-
-	if  (b1 == NULL)
-	{
-		/*return b2 */
-		memcpy(result, b2, sizeof(BOX3D));
-		return result;
-	}
-	if (b2 == NULL)
-	{
-		/*return b1 */
-		memcpy(result, b1, sizeof(BOX3D));
-		return result;
-	}
-
-	if (b1->xmin < b2->xmin)
-		result->xmin = b1->xmin;
-	else
-		result->xmin = b2->xmin;
-
-	if (b1->ymin < b2->ymin)
-			result->ymin = b1->ymin;
-	else
-		result->ymin = b2->ymin;
-
-
-	if (b1->xmax > b2->xmax)
-		result->xmax = b1->xmax;
-	else
-		result->xmax = b2->xmax;
-
-	if (b1->ymax > b2->ymax)
-		result->ymax = b1->ymax;
-	else
-		result->ymax = b2->ymax;
-
-	if (b1->zmax > b2->zmax)
-			result->zmax = b1->zmax;
-	else
-			result->zmax = b2->zmax;
-
-	if (b1->zmin > b2->zmin)
-		result->zmin = b1->zmin;
-	else
-		result->zmin = b2->zmin;
-
-	return result;
-}
-
-/* Make given ubox a union of b1 and b2 */
-int
-box3d_union_p(BOX3D *b1, BOX3D *b2, BOX3D *ubox)
-{
-
-        LWDEBUG(2, "box3d_union_p called: (xmin, xmax), (ymin, ymax), (zmin, zmax)");
-        LWDEBUGF(4, "b1: (%.16f, %.16f),(%.16f, %.16f),(%.16f, %.16f)", b1->xmin, b1->xmax, b1->ymin, b1->ymax, b1->zmin, b1->zmax);
-        LWDEBUGF(4, "b2: (%.16f, %.16f),(%.16f, %.16f),(%.16f, %.16f)", b2->xmin, b2->xmax, b2->ymin, b2->ymax, b2->zmin, b2->zmax);
-
-	if ( (b1 == NULL) && (b2 == NULL) )
-	{
-		return 0;
-	}
-
-	if  (b1 == NULL)
-	{
-		memcpy(ubox, b2, sizeof(BOX3D));
-		return 1;
-	}
-	if (b2 == NULL)
-	{
-		memcpy(ubox, b1, sizeof(BOX3D));
-		return 1;
-	}
-
-	if (b1->xmin < b2->xmin)
-		ubox->xmin = b1->xmin;
-	else
-		ubox->xmin = b2->xmin;
-
-	if (b1->ymin < b2->ymin)
-		ubox->ymin = b1->ymin;
-	else
-		ubox->ymin = b2->ymin;
-
-
-	if (b1->xmax > b2->xmax)
-		ubox->xmax = b1->xmax;
-	else
-		ubox->xmax = b2->xmax;
-
-	if (b1->ymax > b2->ymax)
-		ubox->ymax = b1->ymax;
-	else
-		ubox->ymax = b2->ymax;
-
-	if (b1->zmax > b2->zmax)
-		ubox->zmax = b1->zmax;
-	else
-		ubox->zmax = b2->zmax;
-
-	if (b1->zmin < b2->zmin)
-		ubox->zmin = b1->zmin;
-	else
-		ubox->zmin = b2->zmin;
-
-	return 1;
-}
-
-#if 0 /* UNUSED */
-/*
- * Returns a pointer to internal storage, or NULL
- * if the serialized form does not have a BBOX.
- */
-BOX2DFLOAT4 *
-getbox2d_internal(uchar *srl)
-{
-	if (TYPE_HASBBOX(srl[0])) return (BOX2DFLOAT4 *)(srl+1);
-	else return NULL;
-}
-#endif /* UNUSED */
-
-/*
- * Same as getbox2d, but modifies box instead of returning result on the stack
- */
-int
-getbox2d_p(uchar *srl, BOX2DFLOAT4 *box)
-{
-	uchar type = srl[0];
-	uchar *loc;
-	BOX3D box3d;
-
-	LWDEBUG(2, "getbox2d_p call");
-
-	loc = srl+1;
-
-	if (lwgeom_hasBBOX(type))
-	{
-		/*woot - this is easy */
-		LWDEBUG(4, "getbox2d_p: has box");
-		memcpy(box, loc, sizeof(BOX2DFLOAT4));
-		return 1;
-	}
-
-	LWDEBUG(4, "getbox2d_p: has no box - computing");
-
-	/* We have to actually compute it! */
-	if ( ! compute_serialized_box3d_p(srl, &box3d) ) return 0;
-
-	LWDEBUGF(4, "getbox2d_p: compute_serialized_box3d returned %p", box3d);
-
-	if ( ! box3d_to_box2df_p(&box3d, box) ) return 0;
-
-	LWDEBUG(4, "getbox2d_p: box3d converted to box2d");
-
-	return 1;
-}
-
-/************************************************************************
- * POINTARRAY support functions
- *
- * TODO: should be moved to ptarray.c probably
- *
- ************************************************************************/
-
-/*
- * Copies a point from the point array into the parameter point
- * will set point's z=NO_Z_VALUE if pa is 2d
- * will set point's m=NO_M_VALUE if pa is 3d or 2d
- *
- * NOTE: point is a real POINT3D *not* a pointer
- */
-POINT4D
-getPoint4d(const POINTARRAY *pa, int n)
-{
-	POINT4D result;
-	getPoint4d_p(pa, n, &result);
-	return result;
-}
-
-/*
- * Copies a point from the point array into the parameter point
- * will set point's z=NO_Z_VALUE  if pa is 2d
- * will set point's m=NO_M_VALUE  if pa is 3d or 2d
- *
- * NOTE: this will modify the point4d pointed to by 'point'.
- */
-int
-getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *op)
-{
-	uchar *ptr;
-	int zmflag;
-
-#if PARANOIA_LEVEL > 0
-	if ( ! pa ) lwerror("getPoint4d_p: NULL pointarray");
-
-	if ( (n<0) || (n>=pa->npoints))
-	{
-		lwerror("getPoint4d_p: point offset out of range");
-	}
-#endif
-
-        LWDEBUG(4, "getPoint4d_p called.");
-
-	/* Get a pointer to nth point offset and zmflag */
-	ptr=getPoint_internal(pa, n);
-	zmflag=TYPE_GETZM(pa->dims);
-
-        LWDEBUGF(4, "ptr %p, zmflag %d", ptr, zmflag);
-
-	switch (zmflag)
-	{
-		case 0: /* 2d  */
-			memcpy(op, ptr, sizeof(POINT2D));
-			op->m=NO_M_VALUE;
-			op->z=NO_Z_VALUE;
-			break;
-
-		case 3: /* ZM */
-			memcpy(op, ptr, sizeof(POINT4D));
-			break;
-
-		case 2: /* Z */
-			memcpy(op, ptr, sizeof(POINT3DZ));
-			op->m=NO_M_VALUE;
-			break;
-
-		case 1: /* M */
-			memcpy(op, ptr, sizeof(POINT3DM));
-			op->m=op->z; /* we use Z as temporary storage */
-			op->z=NO_Z_VALUE;
-			break;
-
-		default:
-			lwerror("Unknown ZM flag ??");
-	}
-	return 1;
-
-}
-
-
-
-/*
- * Copy a point from the point array into the parameter point
- * will set point's z=NO_Z_VALUE if pa is 2d
- * NOTE: point is a real POINT3DZ *not* a pointer
- */
-POINT3DZ
-getPoint3dz(const POINTARRAY *pa, int n)
-{
-	POINT3DZ result;
-	getPoint3dz_p(pa, n, &result);
-	return result;
-}
-
-/*
- * Copy a point from the point array into the parameter point
- * will set point's z=NO_Z_VALUE if pa is 2d
- *
- * NOTE: point is a real POINT3DZ *not* a pointer
- */
-POINT3DM
-getPoint3dm(const POINTARRAY *pa, int n)
-{
-	POINT3DM result;
-	getPoint3dm_p(pa, n, &result);
-	return result;
-}
-
-/*
- * Copy a point from the point array into the parameter point
- * will set point's z=NO_Z_VALUE if pa is 2d
- * 
- * NOTE: this will modify the point3dz pointed to by 'point'.
- */
-int
-getPoint3dz_p(const POINTARRAY *pa, int n, POINT3DZ *op)
-{
-	uchar *ptr;
-
-#if PARANOIA_LEVEL > 0
-	if ( ! pa ) return 0;
-
-	if ( (n<0) || (n>=pa->npoints))
-	{
-		LWDEBUGF(4, "%d out of numpoint range (%d)", n, pa->npoints);
-		return 0; /*error */
-	}
-#endif
-
-	LWDEBUGF(2, "getPoint3dz_p called on array of %d-dimensions / %u pts",
-		TYPE_NDIMS(pa->dims), pa->npoints);
-
-	/* Get a pointer to nth point offset */
-	ptr=getPoint_internal(pa, n);
-
-	/*
-	 * if input POINTARRAY has the Z, it is always
-	 * at third position so make a single copy
-	 */
-	if ( TYPE_HASZ(pa->dims) )
-	{
-		memcpy(op, ptr, sizeof(POINT3DZ));
-	}
-
-	/*
-	 * Otherwise copy the 2d part and initialize
-	 * Z to NO_Z_VALUE
-	 */
-	else
-	{
-		memcpy(op, ptr, sizeof(POINT2D));
-		op->z=NO_Z_VALUE;
-	}
-
-	return 1;
-
-}
-
-/*
- * Copy a point from the point array into the parameter point
- * will set point's m=NO_Z_VALUE if pa has no M
- * 
- * NOTE: this will modify the point3dm pointed to by 'point'.
- */
-int
-getPoint3dm_p(const POINTARRAY *pa, int n, POINT3DM *op)
-{
-	uchar *ptr;
-	int zmflag;
-
-#if PARANOIA_LEVEL > 0
-	if ( ! pa ) return 0;
-
-	if ( (n<0) || (n>=pa->npoints))
-	{
-		lwerror("%d out of numpoint range (%d)", n, pa->npoints);
-		return 0; /*error */
-	}
-#endif 
-
-	LWDEBUGF(2, "getPoint3dm_p(%d) called on array of %d-dimensions / %u pts",
-		n, TYPE_NDIMS(pa->dims), pa->npoints);
-
-
-	/* Get a pointer to nth point offset and zmflag */
-	ptr=getPoint_internal(pa, n);
-	zmflag=TYPE_GETZM(pa->dims);
-
-	/*
-	 * if input POINTARRAY has the M and NO Z,
-	 * we can issue a single memcpy
-	 */
-	if ( zmflag == 1 )
-	{
-		memcpy(op, ptr, sizeof(POINT3DM));
-		return 1;
-	}
-
-	/*
-	 * Otherwise copy the 2d part and 
-	 * initialize M to NO_M_VALUE
-	 */
-	memcpy(op, ptr, sizeof(POINT2D));
-
-	/*
-	 * Then, if input has Z skip it and
-	 * copy next double, otherwise initialize
-	 * M to NO_M_VALUE
-	 */
-	if ( zmflag == 3 )
-	{
-		ptr+=sizeof(POINT3DZ);
-		memcpy(&(op->m), ptr, sizeof(double));
-	}
-	else
-	{
-		op->m=NO_M_VALUE;
-	}
-
-	return 1;
-}
-
-
-/*
- * Copy a point from the point array into the parameter point
- * z value (if present) is not returned.
- *
- * NOTE: point is a real POINT2D *not* a pointer
- */
-POINT2D
-getPoint2d(const POINTARRAY *pa, int n)
-{
-	POINT2D result;
-	getPoint2d_p(pa, n, &result);
-	return result;
-}
-
-/*
- * Copy a point from the point array into the parameter point
- * z value (if present) is not returned.
- *
- * NOTE: this will modify the point2d pointed to by 'point'.
- */
-int
-getPoint2d_p(const POINTARRAY *pa, int n, POINT2D *point)
-{
-#if PARANOIA_LEVEL > 0
-	if ( ! pa ) return 0;
-
-	if ( (n<0) || (n>=pa->npoints))
-	{
-		lwerror("getPoint2d_p: point offset out of range");
-		return 0; /*error */
-	}
-#endif
-
-	/* this does x,y */
-	memcpy(point, getPoint_internal(pa, n), sizeof(POINT2D));
-	return 1;
-}
-
-/*
- * set point N to the given value
- * NOTE that the pointarray can be of any
- * dimension, the appropriate ordinate values
- * will be extracted from it
- *
- */
-void
-setPoint4d(POINTARRAY *pa, int n, POINT4D *p4d)
-{
-	uchar *ptr=getPoint_internal(pa, n);
-	switch ( TYPE_GETZM(pa->dims) )
-	{
-		case 3:
-			memcpy(ptr, p4d, sizeof(POINT4D));
-			break;
-		case 2:
-			memcpy(ptr, p4d, sizeof(POINT3DZ));
-			break;
-		case 1:
-			memcpy(ptr, p4d, sizeof(POINT2D));
-			ptr+=sizeof(POINT2D);
-			memcpy(ptr, &(p4d->m), sizeof(double));
-			break;
-		case 0:
-			memcpy(ptr, p4d, sizeof(POINT2D));
-			break;
-	}
-}
-
-
-/*
- * Get a pointer to nth point of a POINTARRAY.
- * You cannot safely cast this to a real POINT, due to memory alignment
- * constraints. Use getPoint*_p for that.
- */
-uchar *
-getPoint_internal(const POINTARRAY *pa, int n)
-{
-	int size;
-
-#if PARANOIA_LEVEL > 0
-	if ( pa == NULL ) {
-		lwerror("getPoint got NULL pointarray");
-		return NULL;
-	}
-
-	if ( (n<0) || (n>=pa->npoints))
-	{
-		return NULL; /*error */
-	}
-#endif
-
-	size = pointArray_ptsize(pa);
-
-	return &(pa->serialized_pointlist[size*n]);
-}
-
-
-
-/*
- * Constructs a POINTARRAY.
- *
- * NOTE: points is *not* copied, so be careful about modification
- * (can be aligned/missaligned).
- *
- * NOTE: ndims is descriptive - it describes what type of data 'points'
- *       points to.  No data conversion is done.
- */
-POINTARRAY *
-pointArray_construct(uchar *points, char hasz, char hasm,
-	uint32 npoints)
-{
-	POINTARRAY  *pa;
-	
-	LWDEBUG(2, "pointArray_construct called.");
-
-	pa = (POINTARRAY*)lwalloc(sizeof(POINTARRAY));
-
-	pa->dims = 0;
-	TYPE_SETZM(pa->dims, hasz?1:0, hasm?1:0);
-	pa->npoints = npoints;
-
-	pa->serialized_pointlist = points;
-
-	LWDEBUGF(4, "pointArray_construct returning %p", pa);
-
-	return pa;
-}
-
-
-/*
- * Size of point represeneted in the POINTARRAY
- * 16 for 2d, 24 for 3d, 32 for 4d
- */
-int
-pointArray_ptsize(const POINTARRAY *pa)
-{
-	LWDEBUGF(2, "pointArray_ptsize: TYPE_NDIMS(pa->dims)=%x\n",
-		TYPE_NDIMS(pa->dims));
-
-	return sizeof(double)*TYPE_NDIMS(pa->dims);
-}
-
-
-/***************************************************************************
- * Basic type handling
- ***************************************************************************/
-
-
-/* Returns true if this type says it has an SRID (S bit set) */
-char
-lwgeom_hasSRID(uchar type)
-{
-	return TYPE_HASSRID(type);
-}
-
-/* Returns either 2,3, or 4 -- 2=2D, 3=3D, 4=4D */
-int
-lwgeom_ndims(uchar type)
-{
-	return TYPE_NDIMS(type);
-}
-
-/* has M ? */
-int lwgeom_hasM(uchar type)
-{
-	return  ( (type & 0x10) >>4);
-}
-
-/* has Z ? */
-int lwgeom_hasZ(uchar type)
-{
-	return  ( (type & 0x20) >>5);
-}
-
-
-/* get base type (ie. POLYGONTYPE) */
-int
-lwgeom_getType(uchar type)
-{
-        LWDEBUGF(2, "lwgeom_getType %d", type);
-
-	return (type & 0x0F);
-}
-
-
-/* Construct a type (hasBOX=false) */
-uchar
-lwgeom_makeType(char hasz, char hasm, char hasSRID, int type)
-{
-	return lwgeom_makeType_full(hasz, hasm, hasSRID, type, 0);
-}
-
-/*
- * Construct a type
- * TODO: needs to be expanded to accept explicit MZ type
- */
-uchar
-lwgeom_makeType_full(char hasz, char hasm, char hasSRID, int type, char hasBBOX)
-{
-	uchar result = (char)type;
-
-	TYPE_SETZM(result, hasz, hasm);
-	TYPE_SETHASSRID(result, hasSRID);
-	TYPE_SETHASBBOX(result, hasBBOX);
-
-	return result;
-}
-
-/* Returns true if there's a bbox in this LWGEOM (B bit set) */
-char
-lwgeom_hasBBOX(uchar type)
-{
-	return TYPE_HASBBOX(type);
-}
-
-/*****************************************************************************
- * Basic sub-geometry types
- *****************************************************************************/
-
-/* handle missaligned unsigned int32 data */
-uint32
-lw_get_uint32(const uchar *loc)
-{
-	uint32 result;
-
-	memcpy(&result, loc, sizeof(uint32));
-	return result;
-}
-
-/* handle missaligned signed int32 data */
-int32
-lw_get_int32(const uchar *loc)
-{
-	int32 result;
-
-	memcpy(&result,loc, sizeof(int32));
-	return result;
-}
-
-
-/*************************************************************************
- *
- * Multi-geometry support
- *
- * Note - for a simple type (ie. point), this will have
- * sub_geom[0] = serialized_form.
- *
- * For multi-geomtries sub_geom[0] will be a few bytes
- * into the serialized form.
- *
- * This function just computes the length of each sub-object and
- * pre-caches this info.
- *
- * For a geometry collection of multi* geometries, you can inspect
- * the sub-components
- * as well.
- */
-LWGEOM_INSPECTED *
-lwgeom_inspect(const uchar *serialized_form)
-{
-	LWGEOM_INSPECTED *result = lwalloc(sizeof(LWGEOM_INSPECTED));
-	uchar typefl = (uchar)serialized_form[0];
-	uchar type;
-	uchar **sub_geoms;
-	const uchar *loc;
-	int 	t;
-
-	LWDEBUGF(2, "lwgeom_inspect: serialized@%p", serialized_form);
-
-	if (serialized_form == NULL)
-		return NULL;
-
-	result->serialized_form = serialized_form; 
-	result->type = (uchar) serialized_form[0];
-	result->SRID = -1; /* assume */
-
-	type = lwgeom_getType(typefl);
-
-	loc = serialized_form+1;
-
-	if ( lwgeom_hasBBOX(typefl) )
-	{
-		loc += sizeof(BOX2DFLOAT4);
-	}
-
-	if ( lwgeom_hasSRID(typefl) )
-	{
-		result->SRID = lw_get_int32(loc);
-		loc += 4;
-	}
-
-	if ( (type==POINTTYPE) || (type==LINETYPE) || (type==POLYGONTYPE) || (type == CURVETYPE))
-	{
-		/* simple geometry (point/line/polygon)-- not multi! */
-		result->ngeometries = 1;
-		sub_geoms = (uchar**) lwalloc(sizeof(char*));
-		sub_geoms[0] = (uchar *)serialized_form;
-		result->sub_geoms = (uchar **)sub_geoms;
-		return result;
-	}
-
-	/* its a GeometryCollection or multi* geometry */
-
-	result->ngeometries = lw_get_uint32(loc);
-	loc +=4;
-
-	LWDEBUGF(3, "lwgeom_inspect: geometry is a collection of %d elements",
-		result->ngeometries);
-
-	if ( ! result->ngeometries ) return result;
-
-	sub_geoms = lwalloc(sizeof(uchar*) * result->ngeometries );
-	result->sub_geoms = sub_geoms;
-	sub_geoms[0] = (uchar *)loc;
-
-	LWDEBUGF(3, "subgeom[0] @ %p (+%d)", sub_geoms[0], sub_geoms[0]-serialized_form);
-
-	for (t=1;t<result->ngeometries; t++)
-	{
-		/* -1 = entire object */
-		int sub_length = lwgeom_size_subgeom(sub_geoms[t-1], -1);
-		sub_geoms[t] = sub_geoms[t-1] + sub_length;
-                
-		LWDEBUGF(3, "subgeom[%d] @ %p (+%d)",
-			t, sub_geoms[t], sub_geoms[0]-serialized_form);
-	}
-
-	return result;
-
-}
-
-
-/*
- * 1st geometry has geom_number = 0
- * if the actual sub-geometry isnt a POINT, null is returned (see _gettype()).
- * if there arent enough geometries, return null.
- * this is fine to call on a point (with geom_num=0),
- * multipoint or geometrycollection
- */
-LWPOINT *
-lwgeom_getpoint(uchar *serialized_form, int geom_number)
-{
-	int type = lwgeom_getType((uchar)serialized_form[0]);
-	uchar *sub_geom;
-
-	if ((type == POINTTYPE)  && (geom_number == 0))
-	{
-		/* Be nice and do as they want instead of what they say */
-		return lwpoint_deserialize(serialized_form);
-	}
-
-	if ((type != MULTIPOINTTYPE) && (type != COLLECTIONTYPE) )
-		return NULL;
-
-	sub_geom = lwgeom_getsubgeometry(serialized_form, geom_number);
-	if (sub_geom == NULL)
-		return NULL;
-
-	type = lwgeom_getType(sub_geom[0]);
-	if (type != POINTTYPE)
-		return NULL;
-
-	return lwpoint_deserialize(sub_geom);
-}
-
-/*
- * 1st geometry has geom_number = 0
- * if the actual sub-geometry isnt a POINT, null is returned (see _gettype()).
- * if there arent enough geometries, return null.
- * this is fine to call on a point (with geom_num=0), multipoint
- * or geometrycollection
- */
-LWPOINT *lwgeom_getpoint_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
-{
-	uchar *sub_geom;
-	uchar type;
-
-	sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number);
-
-	if (sub_geom == NULL) return NULL;
-
-	type = lwgeom_getType(sub_geom[0]);
-	if (type != POINTTYPE) return NULL;
-
-	return lwpoint_deserialize(sub_geom);
-}
-
-
-/*
- * 1st geometry has geom_number = 0
- * if the actual geometry isnt a LINE, null is returned (see _gettype()).
- * if there arent enough geometries, return null.
- * this is fine to call on a line, multiline or geometrycollection
- */
-LWLINE *
-lwgeom_getline(uchar *serialized_form, int geom_number)
-{
-	uchar type = lwgeom_getType( (uchar) serialized_form[0]);
-	uchar *sub_geom;
-
-	if ((type == LINETYPE)  && (geom_number == 0))
-	{
-		/* be nice and do as they want instead of what they say */
-		return lwline_deserialize(serialized_form);
-	}
-
-	if ((type != MULTILINETYPE) && (type != COLLECTIONTYPE) )
-		return NULL;
-
-	sub_geom = lwgeom_getsubgeometry(serialized_form, geom_number);
-	if (sub_geom == NULL) return NULL;
-
-	type = lwgeom_getType((uchar) sub_geom[0]);
-	if (type != LINETYPE) return NULL;
-
-	return lwline_deserialize(sub_geom);
-}
-
-/*
- * 1st geometry has geom_number = 0
- * if the actual geometry isnt a LINE, null is returned (see _gettype()).
- * if there arent enough geometries, return null.
- * this is fine to call on a line, multiline or geometrycollection
- */
-LWLINE *
-lwgeom_getline_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
-{
-	uchar *sub_geom;
-	uchar type;
-
-	sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number);
-
-	if (sub_geom == NULL) return NULL;
-
-	type = lwgeom_getType((uchar) sub_geom[0]);
-	if (type != LINETYPE) return NULL;
-
-	return lwline_deserialize(sub_geom);
-}
-
-/*
- * 1st geometry has geom_number = 0
- * if the actual geometry isnt a POLYGON, null is returned (see _gettype()).
- * if there arent enough geometries, return null.
- * this is fine to call on a polygon, multipolygon or geometrycollection
- */
-LWPOLY *
-lwgeom_getpoly(uchar *serialized_form, int geom_number)
-{
-	uchar type = lwgeom_getType((uchar)serialized_form[0]);
-	uchar *sub_geom;
-
-	if ((type == POLYGONTYPE)  && (geom_number == 0))
-	{
-		/* Be nice and do as they want instead of what they say */
-		return lwpoly_deserialize(serialized_form);
-	}
-
-	if ((type != MULTIPOLYGONTYPE) && (type != COLLECTIONTYPE) )
-		return NULL;
-
-	sub_geom = lwgeom_getsubgeometry(serialized_form, geom_number);
-	if (sub_geom == NULL) return NULL;
-
-	type = lwgeom_getType(sub_geom[0]);
-	if (type != POLYGONTYPE) return NULL;
-
-	return lwpoly_deserialize(sub_geom);
-}
-
-/*
- * 1st geometry has geom_number = 0
- * if the actual geometry isnt a POLYGON, null is returned (see _gettype()).
- * if there arent enough geometries, return null.
- * this is fine to call on a polygon, multipolygon or geometrycollection
- */
-LWPOLY *
-lwgeom_getpoly_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
-{
-	uchar *sub_geom;
-	uchar type;
-
-	sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number);
-
-	if (sub_geom == NULL) return NULL;
-
-	type = lwgeom_getType(sub_geom[0]);
-	if (type != POLYGONTYPE) return NULL;
-
-	return lwpoly_deserialize(sub_geom);
-}
-
-/*
- * 1st geometry has geom_number = 0
- * if there arent enough geometries, return null.
- */
-LWGEOM *lwgeom_getgeom_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
-{
-	uchar *sub_geom;
-	uchar type;
-
-	sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number);
-
-	if (sub_geom == NULL) return NULL;
-
-	type = lwgeom_getType(sub_geom[0]);
-
-	return lwgeom_deserialize(sub_geom);
-}
-
-
-/*
- * This gets the serialized form of a sub-geometry
- *
- * 1st geometry has geom_number = 0
- * if this isnt a multi* geometry, and geom_number ==0 then it returns
- * itself.
- *
- * Returns null on problems.
- *
- * In the future this is how you would access a muli* portion of a
- * geometry collection.
- *    GEOMETRYCOLLECTION(MULTIPOINT(0 0, 1 1), LINESTRING(0 0, 1 1))
- *   ie. lwgeom_getpoint( lwgeom_getsubgeometry( serialized, 0), 1)
- *           --> POINT(1 1)
- *
- * You can inspect the sub-geometry as well if you wish.
- *
- */
-uchar *
-lwgeom_getsubgeometry(const uchar *serialized_form, int geom_number)
-{
-	uchar *result;
-	/*major cheat!! */
-	LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized_form);
-
-	result = lwgeom_getsubgeometry_inspected(inspected, geom_number);
-	pfree_inspected(inspected);
-	return result;
-}
-
-uchar *
-lwgeom_getsubgeometry_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
-{
-	if ((geom_number <0) || (geom_number >= inspected->ngeometries) )
-	{
-		lwerror("lwgeom_getsubgeometry_inspected: geom_number out of range");
-		return NULL;
-	}
-
-	return inspected->sub_geoms[geom_number];
-}
-
-
-/*
- * 1st geometry has geom_number = 0
- *  use geom_number = -1 to find the actual type of the serialized form.
- *    ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, -1)
- *                 --> multipoint
- *   ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, 0)
- *                 --> point
- * gets the 8bit type of the geometry at location geom_number
- */
-uchar
-lwgeom_getsubtype(uchar *serialized_form, int geom_number)
-{
-	char  result;
-	/*major cheat!! */
-	LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized_form);
-
-	result = lwgeom_getsubtype_inspected(inspected, geom_number);
-	pfree_inspected(inspected);
-	return result;
-}
-
-uchar
-lwgeom_getsubtype_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
-{
-	if ((geom_number <0) || (geom_number >= inspected->ngeometries) )
-		return 99;
-
-	return inspected->sub_geoms[geom_number][0]; /* 1st byte is type */
-}
-
-
-/*
- * How many sub-geometries are there?
- * for point,line,polygon will return 1.
- */
-int
-lwgeom_getnumgeometries(uchar *serialized_form)
-{
-	uchar type = lwgeom_getType((uchar)serialized_form[0]);
-	uchar *loc;
-
-	if ( (type==POINTTYPE) || (type==LINETYPE) || (type==POLYGONTYPE) ||
-            (type==CURVETYPE) || (type==COMPOUNDTYPE) || (type==CURVEPOLYTYPE) )
-	{
-		return 1;
-	}
-
-	loc = serialized_form+1;
-
-	if (lwgeom_hasBBOX((uchar) serialized_form[0]))
-	{
-		loc += sizeof(BOX2DFLOAT4);
-	}
-
-	if (lwgeom_hasSRID((uchar) serialized_form[0]) )
-	{
-		loc += 4;
-	}
-	/* its a GeometryCollection or multi* geometry */
-	return lw_get_uint32(loc);
-}
-
-/*
- * How many sub-geometries are there?
- * for point,line,polygon will return 1.
- */
-int
-lwgeom_getnumgeometries_inspected(LWGEOM_INSPECTED *inspected)
-{
-	return inspected->ngeometries;
-}
-
-
-/*
- * Set finalType to COLLECTIONTYPE or 0 (0 means choose a best type)
- *   (ie. give it 2 points and ask it to be a multipoint)
- *  use SRID=-1 for unknown SRID  (will have 8bit type's S = 0)
- * all subgeometries must have the same SRID
- * if you want to construct an inspected, call this then inspect the result...
- */
-uchar *
-lwgeom_serialized_construct(int SRID, int finalType, char hasz, char hasm,
-	int nsubgeometries, uchar **serialized_subs)
-{
-	uint32 *lengths;
-	int t;
-	int total_length = 0;
-	char type = (char)-1;
-	char this_type = -1;
-	uchar *result;
-	uchar *loc;
-
-	if (nsubgeometries == 0)
-		return lwgeom_constructempty(SRID, hasz, hasm);
-
-	lengths = lwalloc(sizeof(int32) * nsubgeometries);
-
-	for (t=0;t<nsubgeometries;t++)
-	{
-		lengths[t] = lwgeom_size_subgeom(serialized_subs[t],-1);
-		total_length += lengths[t];
-		this_type = lwgeom_getType((uchar) (serialized_subs[t][0]));
-		if (type == (char)-1)
-		{
-			type = this_type;
-		}
-		else if (type == COLLECTIONTYPE)
-		{
-				/* still a collection type... */
-		}
-		else
-		{
-			if ( (this_type == MULTIPOINTTYPE) || (this_type == MULTILINETYPE)  || (this_type == MULTIPOLYGONTYPE) || (this_type == COLLECTIONTYPE) )
-			{
-				type = COLLECTIONTYPE;
-			}
-			else
-			{
-				if ( (this_type == POINTTYPE)  && (type==POINTTYPE) )
-					type=MULTIPOINTTYPE;
-				else if ( (this_type == LINETYPE)  && (type==LINETYPE) )
-					type=MULTILINETYPE;
-				else if ( (this_type == POLYGONTYPE)  && (type==POLYGONTYPE) )
-					type=MULTIPOLYGONTYPE;
-				else if ( (this_type == POLYGONTYPE)  && (type==MULTIPOLYGONTYPE) )
-					; /* nop */
-				else if ( (this_type == LINETYPE)  && (type==MULTILINETYPE) )
-					; /* nop */
-				else if ( (this_type == POINTTYPE)  && (type==MULTIPOINTTYPE) )
-					; /* nop */
-				else
-					type = COLLECTIONTYPE;
-			}
-		}
-	}
-
-	if (type == POINTTYPE)
-		type = MULTIPOINTTYPE;
-	if (type == LINETYPE)
-		type = MULTILINETYPE;
-	if (type == POINTTYPE)
-		type = MULTIPOINTTYPE;
-
-	if (finalType == COLLECTIONTYPE)
-		type = COLLECTIONTYPE;
-
-	/* now we have a multi* or GEOMETRYCOLLECTION, let's serialize it */
-
-	if (SRID != -1)
-		total_length +=4; /* space for SRID */
-
-	total_length +=1 ;   /* main type; */
-	total_length +=4 ;   /* nsubgeometries */
-
-	result = lwalloc(total_length);
-	result[0] = (uchar) lwgeom_makeType(hasz, hasm, SRID != -1,  type);
-	if (SRID != -1)
-	{
-		memcpy(&result[1],&SRID,4);
-		loc = result+5;
-	}
-	else
-		loc = result+1;
-
-	memcpy(loc,&nsubgeometries,4);
-	loc +=4;
-
-	for (t=0;t<nsubgeometries;t++)
-	{
-		memcpy(loc, serialized_subs[t], lengths[t] );
-		loc += lengths[t] ;
-	}
-
-	lwfree(lengths);
-	return result;
-}
-
-
-/*
- * Construct the empty geometry (GEOMETRYCOLLECTION(EMPTY)).
- *
- * Returns serialized form
- */
-uchar *
-lwgeom_constructempty(int SRID, char hasz, char hasm)
-{
-	int size = 0;
-	uchar *result;
-	int ngeoms = 0;
-	uchar *loc;
-
-	if (SRID != -1)
-		size +=4;
-
-	size += 5;
-
-	result = lwalloc(size);
-
-	result[0] = lwgeom_makeType(hasz, hasm, SRID != -1,  COLLECTIONTYPE);
-	if (SRID != -1)
-	{
-		memcpy(&result[1],&SRID,4);
-		loc = result+5;
-	}
-	else
-		loc = result+1;
-
-	memcpy(loc,&ngeoms,4);
-	return result;
-}
-
-size_t
-lwgeom_empty_length(int SRID)
-{
-	int size = 5;
-	if ( SRID != 1 ) size += 4;
-	return size;
-}
-
-/*
- * Construct the empty geometry (GEOMETRYCOLLECTION(EMPTY))
- * writing it into the provided buffer.
- */
-void
-lwgeom_constructempty_buf(int SRID, char hasz, char hasm,
-	uchar *buf, size_t *retsize)
-{
-	int ngeoms = 0;
-
-	buf[0] =(uchar) lwgeom_makeType( hasz, hasm, SRID != -1,  COLLECTIONTYPE);
-	if (SRID != -1)
-	{
-		memcpy(&buf[1],&SRID,4);
-		buf += 5;
-	}
-	else
-		buf += 1;
-
-	memcpy(buf, &ngeoms, 4);
-
-	if (retsize) *retsize = lwgeom_empty_length(SRID);
-}
-
-/*
- * helper function (not for general use)
- * find the size a geometry (or a sub-geometry)
- * 1st geometry has geom_number = 0
- *  use geom_number = -1 to find the actual type of the serialized form.
- *    ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, -1)
- *                 --> size of the multipoint
- *   ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, 0)
- *         --> size of the point
- * take a geometry, and find its length
- */
-size_t
-lwgeom_size(const uchar *serialized_form)
-{
-	uchar type = lwgeom_getType((uchar) serialized_form[0]);
-	int t;
-	const uchar *loc;
-	uint32 ngeoms;
-	int sub_size;
-	int result = 1; /* type */
-
-	LWDEBUG(2, "lwgeom_size called");
-
-	if (type == POINTTYPE)
-	{
-		LWDEBUG(3, "lwgeom_size: is a point");
-
-		return lwgeom_size_point(serialized_form);
-	}
-	else if (type == LINETYPE)
-	{
-		LWDEBUG(3, "lwgeom_size: is a line");
-
-		return lwgeom_size_line(serialized_form);
-	}
-        else if(type == CURVETYPE)
-        {
-                LWDEBUG(3, "lwgeom_size: is a curve");
-
-                return lwgeom_size_curve(serialized_form);
-        }
-	else if (type == POLYGONTYPE)
-	{
-		LWDEBUG(3, "lwgeom_size: is a polygon");
-
-		return lwgeom_size_poly(serialized_form);
-	} 
-        else if (type == COMPOUNDTYPE)
-        {
-                LWDEBUG(3, "lwgeom_size: is a compound curve");
-        }
-
-	if ( type == 0 )
-	{
-		lwerror("lwgeom_size called with unknown-typed serialized geometry");
-		return 0;
-	}
-
-	/*
-	 * Handle all the multi* and geometrycollections the same
-	 *
-	 * NOTE: for a geometry collection of GC of GC of GC we will
-	 *       be recursing...
-	 */
-
-	LWDEBUGF(3, "lwgeom_size called on a geoemtry with type %d", type);
-
-	loc = serialized_form+1;
-
-	if (lwgeom_hasBBOX((uchar) serialized_form[0]))
-	{
-		LWDEBUG(3, "lwgeom_size: has bbox");
-
-		loc += sizeof(BOX2DFLOAT4);
-		result +=sizeof(BOX2DFLOAT4);
-	}
-
-	if (lwgeom_hasSRID( (uchar) serialized_form[0]) )
-	{
-		LWDEBUG(3, "lwgeom_size: has srid");
-
-		result +=4;
-		loc +=4;
-	}
-
-
-	ngeoms = lw_get_uint32(loc);
-	loc +=4;
-	result += 4; /* numgeoms */
-
-	LWDEBUGF(3, "lwgeom_size called on a geoemtry with %d elems (result so far: %d)", ngeoms, result);
-
-	for (t=0;t<ngeoms;t++)
-	{
-		sub_size = lwgeom_size(loc);
-
-		LWDEBUGF(3, " subsize %d", sub_size);
-
-		loc += sub_size;
-		result += sub_size;
-	}
-
-	LWDEBUGF(3, "lwgeom_size returning %d", result);
-
-	return result;
-}
-
-size_t
-lwgeom_size_subgeom(const uchar *serialized_form, int geom_number)
-{
-	if (geom_number == -1)
-	{
-		return lwgeom_size(serialized_form);
-	}
-	return lwgeom_size( lwgeom_getsubgeometry(serialized_form,geom_number));
-}
-
-
-
-int
-lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected, int geom_number)
-{
-	return lwgeom_size(inspected->sub_geoms[geom_number]);
-}
-
-int
-compute_serialized_box3d_p(uchar *srl, BOX3D *out)
-{
-	BOX3D *box = compute_serialized_box3d(srl);
-	if ( ! box ) return 0;
-	out->xmin = box->xmin;
-	out->ymin = box->ymin;
-	out->zmin = box->zmin;
-	out->xmax = box->xmax;
-	out->ymax = box->ymax;
-	out->zmax = box->zmax;
-	lwfree(box);
-
-	return 1;
-}
-
-/*
- * Compute bounding box of a serialized LWGEOM, even if it is
- * already cached. The computed BOX2DFLOAT4 is stored at
- * the given location, the function returns 0 is the geometry
- * does not have a bounding box (EMPTY GEOM)
- */
-int
-compute_serialized_box2d_p(uchar *srl, BOX2DFLOAT4 *out)
-{
-	  BOX3D *result = compute_serialized_box3d(srl);
-	  if ( ! result ) return 0;
-	  out->xmin = result->xmin;
-	  out->xmax = result->xmax;
-	  out->ymin = result->ymin;
-	  out->ymax = result->ymax;
-	  lwfree(result);
-
-	  return 1;
-}
-
-/*
- * Don't forget to lwfree() result !
- */
-BOX3D *
-compute_serialized_box3d(uchar *srl)
-{
-	int type = lwgeom_getType(srl[0]);
-	int t;
-	uchar *loc;
-	uint32 ngeoms;
-	BOX3D *result;
-	BOX3D b1;
-	int sub_size;
-	char nboxes=0;
-
-	LWDEBUGF(2, "compute_serialized_box3d called on type %d", type);
-
-	if (type == POINTTYPE)
-	{
-		LWPOINT *pt = lwpoint_deserialize(srl);
-
-		LWDEBUG(3, "compute_serialized_box3d: lwpoint deserialized");
-
-		result = lwpoint_compute_box3d(pt);
-
-		LWDEBUG(3, "compute_serialized_box3d: bbox found");
-
-		pfree_point(pt);
-		return result;
-	}
-
-	else if (type == LINETYPE)
-	{
-		LWLINE *line = lwline_deserialize(srl);
-		result = lwline_compute_box3d(line);
-		pfree_line(line);
-		return result;
-
-	}
-        else if (type == CURVETYPE)
-        {
-                LWCURVE *curve = lwcurve_deserialize(srl);
-                result = lwcurve_compute_box3d(curve);
-                pfree_curve(curve);
-                return result;
-        }
-	else if (type == POLYGONTYPE)
-	{
-		LWPOLY *poly = lwpoly_deserialize(srl);
-		result = lwpoly_compute_box3d(poly);
-		pfree_polygon(poly);
-		return result;
-	}
-
-	if ( ! ( type == MULTIPOINTTYPE || type == MULTILINETYPE ||
-		type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE ||
-                type == COMPOUNDTYPE || type == CURVEPOLYTYPE ||
-                type == MULTICURVETYPE || type == MULTISURFACETYPE) )
-	{
-		lwnotice("compute_serialized_box3d called on unknown type %d", type);
-		return NULL;
-	}
-
-	loc = srl+1;
-
-	if (lwgeom_hasBBOX(srl[0]))
-	{
-		loc += sizeof(BOX2DFLOAT4);
-	}
-
-	if (lwgeom_hasSRID(srl[0]) )
-	{
-		loc +=4;
-	}
-
-	ngeoms = lw_get_uint32(loc);
-	loc += 4;
-
-	/* each sub-type */
-	result = NULL;
-	for (t=0; t<ngeoms; t++)
-	{
-		if ( compute_serialized_box3d_p(loc, &b1) ) 
-		{
-			LWDEBUG(3, "Geom %d have box:"); 
-#if POSTGIS_DEBUG_LEVEL >= 3
-			printBOX3D(&b1);
-#endif
-
-			if (result)
-			{
-				nboxes += box3d_union_p(result, &b1, result);
-			}
-			else
-			{ 
-				result = lwalloc(sizeof(BOX3D));
-				memcpy(result, &b1, sizeof(BOX3D));
-			}
-		}
-
-		sub_size = lwgeom_size(loc);
-		loc += sub_size;
-	}
-
-	return result;
-
-}
-
-/****************************************************************
- * memory management 
- *
- *  these only delete the memory associated
- *  directly with the structure - NOT the stuff pointing into
- *  the original de-serialized info
- *
- ****************************************************************/
-
-void
-pfree_inspected(LWGEOM_INSPECTED *inspected)
-{
-	if ( inspected->ngeometries )
-		lwfree(inspected->sub_geoms);
-	lwfree(inspected);
-}
-
-
-void pfree_POINTARRAY(POINTARRAY *pa)
-{
-	lwfree(pa);
-}
-
-
-
-
-/************************************************
- * debugging routines
- ************************************************/
-
-
-void printBOX3D(BOX3D *box)
-{
-	lwnotice("BOX3D: %g %g, %g %g", box->xmin, box->ymin,
-		box->xmax, box->ymax);
-}
-
-void printPA(POINTARRAY *pa)
-{
-	int t;
-	POINT4D pt;
-	char *mflag;
-
-
-	if ( TYPE_HASM(pa->dims) ) mflag = "M";
-	else mflag = "";
-
-	lwnotice("      POINTARRAY%s{", mflag);
-	lwnotice("                 ndims=%i,   ptsize=%i",
-		TYPE_NDIMS(pa->dims), pointArray_ptsize(pa));
-	lwnotice("                 npoints = %i", pa->npoints);
-
-	for (t =0; t<pa->npoints;t++)
-	{
-		getPoint4d_p(pa, t, &pt);
-		if (TYPE_NDIMS(pa->dims) == 2)
-		{
-			lwnotice("                    %i : %lf,%lf",t,pt.x,pt.y);
-		}
-		if (TYPE_NDIMS(pa->dims) == 3)
-		{
-			lwnotice("                    %i : %lf,%lf,%lf",t,pt.x,pt.y,pt.z);
-		}
-		if (TYPE_NDIMS(pa->dims) == 4)
-		{
-			lwnotice("                    %i : %lf,%lf,%lf,%lf",t,pt.x,pt.y,pt.z,pt.m);
-		}
-	}
-
-	lwnotice("      }");
-}
-
-void printBYTES(uchar *a, int n)
-{
-	int t;
-	char buff[3];
-
-	buff[2] = 0; /* null terminate */
-
-	lwnotice(" BYTE ARRAY (n=%i) IN HEX: {", n);
-	for (t=0;t<n;t++)
-	{
-		deparse_hex(a[t], buff);
-		lwnotice("    %i : %s", t,buff );
-	}
-	lwnotice("  }");
-}
-
-
-void
-printMULTI(uchar *serialized)
-{
-	LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized);
-	LWLINE  *line;
-	LWPOINT *point;
-	LWPOLY  *poly;
-	int t;
-
-	lwnotice("MULTI* geometry (type = %i), with %i sub-geoms",lwgeom_getType((uchar)serialized[0]), inspected->ngeometries);
-
-	for (t=0;t<inspected->ngeometries;t++)
-	{
-		lwnotice("      sub-geometry %i:", t);
-		line = NULL; point = NULL; poly = NULL;
-
-		line = lwgeom_getline_inspected(inspected,t);
-		if (line !=NULL)
-		{
-			printLWLINE(line);
-		}
-		poly = lwgeom_getpoly_inspected(inspected,t);
-		if (poly !=NULL)
-		{
-			printLWPOLY(poly);
-		}
-		point = lwgeom_getpoint_inspected(inspected,t);
-		if (point !=NULL)
-		{
-			printPA(point->point);
-		}
-    }
-
-    lwnotice("end multi*");
-
-	pfree_inspected(inspected);
-}
-
-void
-printType(uchar type)
-{
-	lwnotice("type 0x%x ==> hasBBOX=%i, hasSRID=%i, ndims=%i, type=%i",(unsigned int) type, lwgeom_hasBBOX(type), lwgeom_hasSRID(type),lwgeom_ndims(type), lwgeom_getType(type));
-}
-
-/*
- * Get the SRID from the LWGEOM.
- * None present => -1
- */
-int
-lwgeom_getsrid(uchar *serialized)
-{
-	uchar type = serialized[0];
-	uchar *loc = serialized+1;
-
-	if ( ! lwgeom_hasSRID(type)) return -1;
-
-	if (lwgeom_hasBBOX(type))
-	{
-		loc += sizeof(BOX2DFLOAT4);
-	}
-
-	return lw_get_int32(loc);
-}
-
-char
-ptarray_isccw(const POINTARRAY *pa)
-{
-	int i;
-	double area = 0;
-	POINT2D p1, p2;
-
-	for (i=0; i<pa->npoints-1; i++)
-	{
-		getPoint2d_p(pa, i, &p1);
-		getPoint2d_p(pa, i+1, &p2);
-		area += (p1.y * p2.x) - (p1.x * p2.y);
-	}
-	if ( area > 0 ) return 0;
-	else return 1;
-}
-
-/*
- * Returns a BOX2DFLOAT4 that encloses b1 and b2
- *
- * box2d_union(NULL,A) --> A
- * box2d_union(A,NULL) --> A
- * box2d_union(A,B) --> A union B
- */
-BOX2DFLOAT4 *
-box2d_union(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2)
-{
-	BOX2DFLOAT4 *result;
-
-	if ( (b1 == NULL) && (b2 == NULL) )
-	{
-		return NULL;
-	}
-
-	result = lwalloc(sizeof(BOX2DFLOAT4));
-
-	if  (b1 == NULL)
-	{
-		memcpy(result, b2, sizeof(BOX2DFLOAT4));
-		return result;
-	}
-	if (b2 == NULL)
-	{
-		memcpy(result, b1, sizeof(BOX2DFLOAT4));
-		return result;
-	}
-
-	if (b1->xmin < b2->xmin) result->xmin = b1->xmin;
-	else result->xmin = b2->xmin;
-
-	if (b1->ymin < b2->ymin) result->ymin = b1->ymin;
-	else result->ymin = b2->ymin;
-
-	if (b1->xmax > b2->xmax) result->xmax = b1->xmax;
-	else result->xmax = b2->xmax;
-
-	if (b1->ymax > b2->ymax) result->ymax = b1->ymax;
-	else result->ymax = b2->ymax;
-
-	return result;
-}
-
-/*
- * ubox may be one of the two args...
- * return 1 if done something to ubox, 0 otherwise.
- */
-int
-box2d_union_p(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2, BOX2DFLOAT4 *ubox)
-{
-	if ( (b1 == NULL) && (b2 == NULL) )
-	{
-		return 0;
-	}
-
-	if  (b1 == NULL)
-	{
-		memcpy(ubox, b2, sizeof(BOX2DFLOAT4));
-		return 1;
-	}
-	if (b2 == NULL)
-	{
-		memcpy(ubox, b1, sizeof(BOX2DFLOAT4));
-		return 1;
-	}
-
-	if (b1->xmin < b2->xmin) ubox->xmin = b1->xmin;
-	else ubox->xmin = b2->xmin;
-
-	if (b1->ymin < b2->ymin) ubox->ymin = b1->ymin;
-	else ubox->ymin = b2->ymin;
-
-	if (b1->xmax > b2->xmax) ubox->xmax = b1->xmax;
-	else ubox->xmax = b2->xmax;
-
-	if (b1->ymax > b2->ymax) ubox->ymax = b1->ymax;
-	else ubox->ymax = b2->ymax;
-
-	return 1;
-}
-
-const char *
-lwgeom_typeflags(uchar type)
-{
-	static char flags[5];
-	int flagno=0;
-	if ( TYPE_HASZ(type) ) flags[flagno++] = 'Z';
-	if ( TYPE_HASM(type) ) flags[flagno++] = 'M';
-	if ( TYPE_HASBBOX(type) ) flags[flagno++] = 'B';
-	if ( TYPE_HASSRID(type) ) flags[flagno++] = 'S';
-	flags[flagno] = '\0';
-
-	LWDEBUGF(4, "Flags: %s - returning %p", flags, flags);
-
-	return flags;
-}
-
-/*
- * Given a string with at least 2 chars in it, convert them to
- * a byte value.  No error checking done!
- */
-uchar
-parse_hex(char *str)
-{
-	/* do this a little brute force to make it faster */
-
-	uchar		result_high = 0;
-	uchar		result_low = 0;
-
-	switch (str[0])
-	{
-		case '0' :
-			result_high = 0;
-			break;
-		case '1' :
-			result_high = 1;
-			break;
-		case '2' :
-			result_high = 2;
-			break;
-		case '3' :
-			result_high = 3;
-			break;
-		case '4' :
-			result_high = 4;
-			break;
-		case '5' :
-			result_high = 5;
-			break;
-		case '6' :
-			result_high = 6;
-			break;
-		case '7' :
-			result_high = 7;
-			break;
-		case '8' :
-			result_high = 8;
-			break;
-		case '9' :
-			result_high = 9;
-			break;
-		case 'A' :
-			result_high = 10;
-			break;
-		case 'B' :
-			result_high = 11;
-			break;
-		case 'C' :
-			result_high = 12;
-			break;
-		case 'D' :
-			result_high = 13;
-			break;
-		case 'E' :
-			result_high = 14;
-			break;
-		case 'F' :
-			result_high = 15;
-			break;
-	}
-	switch (str[1])
-	{
-		case '0' :
-			result_low = 0;
-			break;
-		case '1' :
-			result_low = 1;
-			break;
-		case '2' :
-			result_low = 2;
-			break;
-		case '3' :
-			result_low = 3;
-			break;
-		case '4' :
-			result_low = 4;
-			break;
-		case '5' :
-			result_low = 5;
-			break;
-		case '6' :
-			result_low = 6;
-			break;
-		case '7' :
-			result_low = 7;
-			break;
-		case '8' :
-			result_low = 8;
-			break;
-		case '9' :
-			result_low = 9;
-			break;
-		case 'A' :
-			result_low = 10;
-			break;
-		case 'B' :
-			result_low = 11;
-			break;
-		case 'C' :
-			result_low = 12;
-			break;
-		case 'D' :
-			result_low = 13;
-			break;
-		case 'E' :
-			result_low = 14;
-			break;
-		case 'F' :
-			result_low = 15;
-			break;
-	}
-	return (uchar) ((result_high<<4) + result_low);
-}
-
-
-/*
- * Given one byte, populate result with two byte representing
- * the hex number.
- *
- * Ie. deparse_hex( 255, mystr)
- *		-> mystr[0] = 'F' and mystr[1] = 'F'
- *
- * No error checking done
- */
-void
-deparse_hex(uchar str, char *result)
-{
-	int	input_high;
-	int  input_low;
-	static char outchr[]={"0123456789ABCDEF" };
-
-	input_high = (str>>4);
-	input_low = (str & 0x0F);
-
-	result[0] = outchr[input_high];
-	result[1] = outchr[input_low];
-
-}
-
-SERIALIZED_LWGEOM *
-parse_lwgeom_wkt(char *wkt_input)
-{
-	SERIALIZED_LWGEOM *serialized_form = parse_lwg(wkt_input,
-		lwalloc, lwerror);
-
-
-	LWDEBUGF(2, "parse_lwgeom_wkt with %s",wkt_input);
-
-	if (serialized_form == NULL)
-	{
-		lwerror("parse_WKT:: couldnt parse!");
-		return NULL;
-	}
-
-	return serialized_form;
-
-}
-
-/*
- * Find interpolation point I
- * between point A and point B 
- * so that the len(AI) == len(AB)*F
- * and I falls on AB segment.
- *
- * Example:
- *
- *   F=0.5  :    A----I----B 
- *   F=1    :    A---------B==I 
- *   F=0    : A==I---------B
- *   F=.2   :    A-I-------B
- */
-void
-interpolate_point4d(POINT4D *A, POINT4D *B, POINT4D *I, double F)
-{
-#if PARANOIA_LEVEL > 0
-	double absF=fabs(F);
-	if ( absF < 0 || absF > 1 )
-	{
-		lwerror("interpolate_point4d: invalid F (%g)", F);
-	}
-#endif
-	I->x=A->x+((B->x-A->x)*F);
-	I->y=A->y+((B->y-A->y)*F);
-	I->z=A->z+((B->z-A->z)*F);
-	I->m=A->m+((B->m-A->m)*F);
-}

Modified: trunk/lwgeom/lwgeom_dump.c
===================================================================
--- trunk/lwgeom/lwgeom_dump.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgeom_dump.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -17,9 +17,7 @@
 #include "liblwgeom.h"
 #include "lwgeom_pg.h"
 #include "profile.h"
-#include "wktparse.h"
 
-
 Datum LWGEOM_dump(PG_FUNCTION_ARGS);
 Datum LWGEOM_dump_rings(PG_FUNCTION_ARGS);
 

Modified: trunk/lwgeom/lwgeom_functions_basic.c
===================================================================
--- trunk/lwgeom/lwgeom_functions_basic.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgeom_functions_basic.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -25,9 +25,7 @@
 #include "liblwgeom.h"
 #include "lwgeom_pg.h"
 #include "profile.h"
-#include "wktparse.h"
 
-
 Datum LWGEOM_mem_size(PG_FUNCTION_ARGS);
 Datum LWGEOM_summary(PG_FUNCTION_ARGS);
 Datum LWGEOM_npoints(PG_FUNCTION_ARGS);
@@ -112,8 +110,6 @@
 	text *mytext;
 	LWGEOM *lwgeom;
 
-	init_pg_func();
-
 	lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom));
 
 	result = lwgeom_summary(lwgeom, 0);
@@ -2910,11 +2906,9 @@
 	PG_LWGEOM *lwgeom;
 	char *result_cstring;
 	int len;
-    char *result,*loc_wkt;
+	char *result,*loc_wkt;
 	/*char *semicolonLoc; */
 
-	init_pg_func();
-
 	lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
 	result_cstring =  unparse_WKT(SERIALIZED_FORM(lwgeom),lwalloc,lwfree);
 
@@ -2954,8 +2948,6 @@
 	double result;
 	int SRID;
 
-	init_pg_func();
-
 	/* Extract first point */
 	geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
 	lwpoint = lwpoint_deserialize(SERIALIZED_FORM(geom));

Modified: trunk/lwgeom/lwgeom_geos_c.c
===================================================================
--- trunk/lwgeom/lwgeom_geos_c.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgeom_geos_c.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -8,7 +8,7 @@
 #include "lwgeom_pg.h"
 #include "liblwgeom.h"
 #include "profile.h"
-#include "wktparse.h"
+
 #include "geos_c.h"
 #include "lwgeom_rtree.h"
 

Modified: trunk/lwgeom/lwgeom_gist.c
===================================================================
--- trunk/lwgeom/lwgeom_gist.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgeom_gist.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -19,11 +19,7 @@
 #include "lwgeom_pg.h"
 #include "stringBuffer.h"
 
-#if POSTGIS_DEBUG_LEVEL > 0
-#include "wktparse.h"
-#endif
 
-
 /*
  * implementation GiST support and basic LWGEOM operations (like &&)
  */

Modified: trunk/lwgeom/lwgeom_inout.c
===================================================================
--- trunk/lwgeom/lwgeom_inout.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgeom_inout.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -24,7 +24,6 @@
 
 
 #include "lwgeom_pg.h"
-#include "wktparse.h"
 #include "profile.h"
 
 void elog_ERROR(const char* string);
@@ -97,8 +96,6 @@
 	PG_LWGEOM *lwgeom;
 	char *result;
 
-	init_pg_func();
-
 	lwgeom = (PG_LWGEOM *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
 	result = unparse_WKB(SERIALIZED_FORM(lwgeom),lwalloc,lwfree,-1,NULL,1);
 
@@ -118,8 +115,6 @@
 	text *type;
 	unsigned int byteorder=-1;
 
-	init_pg_func();
-
 	lwgeom = (PG_LWGEOM *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
 
 	if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) )
@@ -169,8 +164,6 @@
 	text *text_result;
 	size_t size;
 
-	init_pg_func();
-
 	lwgeom = (PG_LWGEOM *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
 	result = unparse_WKB(SERIALIZED_FORM(lwgeom),lwalloc,lwfree,-1,&size,1);
 
@@ -250,8 +243,6 @@
 	profstart(PROF_QRUN);
 #endif
 
-	init_pg_func();
-
 	if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) )
 	{
 		type = PG_GETARG_TEXT_P(1);
@@ -479,8 +470,6 @@
 	char *wkt;
 	int wkt_size ;
 
-	init_pg_func();
-
 	wkt_size = VARSIZE(wkt_input)-VARHDRSZ; /* actual letters */
 
 	wkt = palloc( wkt_size+1); /* +1 for null */
@@ -490,7 +479,7 @@
 
 	POSTGIS_DEBUGF(3, "in parse_WKT_lwgeom with input: '%s'",wkt);
 
-	serialized_lwgeom = parse_lwg((const char *)wkt, (allocator)lwalloc, (report_error)elog_ERROR);
+	serialized_lwgeom = parse_lwgeom_wkt(wkt);
 	lwgeom = lwgeom_deserialize(serialized_lwgeom->lwgeom);
     
 	ret = pglwgeom_serialize(lwgeom);

Modified: trunk/lwgeom/lwgeom_ogc.c
===================================================================
--- trunk/lwgeom/lwgeom_ogc.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgeom_ogc.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -28,9 +28,6 @@
 #include "lwgeom_pg.h"
 
 
-
-#include "wktparse.h"
-
 /* ---- SRID(geometry) */
 Datum LWGEOM_getSRID(PG_FUNCTION_ARGS);
 /* ---- SetSRID(geometry, integer) */
@@ -121,8 +118,6 @@
 	int32 size;
 	uchar type;
 
-	init_pg_func();
-
 	lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
 	text_ob = lwalloc(20+VARHDRSZ);
 	result = text_ob+VARHDRSZ;
@@ -1077,8 +1072,6 @@
         
 	POSTGIS_DEBUG(2, "LWGEOM_asText called.");
 
-	init_pg_func();
-
 	lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
 
 	/* Force to 2d */
@@ -1113,8 +1106,6 @@
 	PG_LWGEOM *ogclwgeom;
 	char *result;
 
-	init_pg_func();
-
 	/* Force to 2d */
 	ogclwgeom = (PG_LWGEOM *)DatumGetPointer(DirectFunctionCall1(
 		LWGEOM_force_2d, PG_GETARG_DATUM(0)));

Modified: trunk/lwgeom/lwgeom_pg.c
===================================================================
--- trunk/lwgeom/lwgeom_pg.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgeom_pg.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -8,16 +8,13 @@
 #include <executor/spi.h>
 #include "liblwgeom.h"
 #include "lwgeom_pg.h"
-#include "wktparse.h"
 
 
-
 #define PARANOIA_LEVEL 1
 
 /*
  * This is required for builds against pgsql 8.2
  */
-/*#include "pgmagic.h"*/
 #ifdef PG_MODULE_MAGIC
 PG_MODULE_MAGIC;
 #endif
@@ -100,8 +97,9 @@
 }
 
 void
-init_pg_func(void)
+lwgeom_init_allocators(void)
 {
+	/* liblwgeom callback - install PostgreSQL handlers */
 	lwalloc_var = pg_alloc;
 	lwrealloc_var = pg_realloc;
 	lwfree_var = pg_free;

Modified: trunk/lwgeom/lwgeom_pg.h
===================================================================
--- trunk/lwgeom/lwgeom_pg.h	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgeom_pg.h	2008-06-29 19:11:48 UTC (rev 2815)
@@ -67,9 +67,6 @@
 
 extern Oid getGeometryOID(void);
 
-/* call this as first thing of any PG function */
-void init_pg_func(void);
-
 /* PG-dependant */
 /* BOX is postgresql standard type */
 extern void box_to_box2df_p(BOX *box, BOX2DFLOAT4 *out);  

Modified: trunk/lwgeom/lwgeom_sqlmm.c
===================================================================
--- trunk/lwgeom/lwgeom_sqlmm.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgeom_sqlmm.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -19,7 +19,7 @@
 #include "postgres.h"
 #include "liblwgeom.h"
 #include "fmgr.h"
-#include "wktparse.h"
+
 #include "lwgeom_pg.h"
 
 

Deleted: trunk/lwgeom/lwgparse.c
===================================================================
--- trunk/lwgeom/lwgparse.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwgparse.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,1153 +0,0 @@
-/*
- * Written by Ralph Mason ralph.mason<at>telogis.com
- *
- * Copyright Telogis 2004
- * www.telogis.com
- *
- */
-#include <string.h>
-#include <stdio.h>
-/* Solaris9 does not provide stdint.h */
-/* #include <stdint.h> */
-#include <inttypes.h>
-
-#include "liblwgeom.h"
-#include "wktparse.h"
-
-/*
- * To get byte order
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-*/
-
-void set_zm(char z, char m);
-void close_parser(void);
-
-typedef uint32_t int4;
-
-typedef struct tag_tuple tuple;
-
-struct tag_outputstate{
-	uchar*	pos;
-};
-
-typedef struct tag_outputstate output_state;
-typedef void (*output_func)(tuple* this, output_state* out);
-typedef void (*read_col_func)(const char **f);
-
-
-
-/* Globals */
-
-int srid=-1;
-
-static int ferror_occured;
-static allocator local_malloc;
-static report_error error_func;
-
-struct tag_tuple{
-	output_func   of;
-	union union_tag {
-		double points[4];
-		int4   pointsi[4];
-
-		struct struct_tag {
-			tuple* 	stack_next;
-			int	type;
-			int	num;
-			int	size_here;
-		} nn;
-	} uu;
-	struct tag_tuple *next;
-};
-
-struct {
-	int	type;
-	int	flags;
-	int	srid;
-	int	ndims;
-	int	hasZ;
-	int	hasM;
-	/* create integer version */
-	int lwgi;
-	/* input is integer (wkb only)*/
-	int from_lwgi;
-
-	int4 alloc_size;
-
-	/*
-		linked list of all tuples
-	*/
-	tuple*	first;
-	tuple*  last;
-
-	/*
-		stack of open geometries
-	*/
-	tuple*  stack;
-
-} the_geom;
-
-tuple* free_list=0;
-int minpoints;
-int checkclosed;
-
-/*
- * This inicates if the number of points in the geometry is required to
- * be odd (one) or even (zero, currently not enforced) or whatever (-one)
- */
-int isodd;
-double *first_point=NULL;
-double *last_point=NULL;
-
-/* External functions */
-extern void init_parser(const char *);
-
-/* Prototypes */
-tuple* alloc_tuple(output_func of,size_t size);
-static void error(const char* err);
-void free_tuple(tuple* to_free);
-void inc_num(void);
-void alloc_stack_tuple(int type,output_func of,size_t size);
-void check_dims(int num);
-void WRITE_DOUBLES(output_state* out,double* points, int cnt);
-#ifdef SHRINK_INTS
-void WRITE_INT4(output_state * out,int4 val);
-#endif
-void empty_stack(tuple* this,output_state* out);
-void alloc_lwgeom(int srid);
-void write_point_2(tuple* this,output_state* out);
-void write_point_3(tuple* this,output_state* out);
-void write_point_4(tuple* this,output_state* out);
-void write_point_2i(tuple* this,output_state* out);
-void write_point_3i(tuple* this,output_state* out);
-void write_point_4i(tuple* this,output_state* out);
-void alloc_point_2d(double x,double y);
-void alloc_point_3d(double x,double y,double z);
-void alloc_point_4d(double x,double y,double z,double m);
-void write_type(tuple* this,output_state* out);
-void write_count(tuple* this,output_state* out);
-void write_type_count(tuple* this,output_state* out);
-void alloc_point(void);
-void alloc_linestring(void);
-void alloc_linestring_closed(void);
-void alloc_circularstring(void);
-void alloc_circularstring_closed(void);
-void alloc_polygon(void);
-void alloc_multipoint(void);
-void alloc_multilinestring(void);
-void alloc_multicurve(void);
-void alloc_multipolygon(void);
-void alloc_multisurface(void);
-void alloc_geomertycollection(void);
-void alloc_counter(void);
-void alloc_empty(void);
-SERIALIZED_LWGEOM* make_serialized_lwgeom(void);
-uchar strhex_readbyte(const char *in);
-uchar read_wkb_byte(const char **in);
-void read_wkb_bytes(const char **in, uchar* out, int cnt);
-int4 read_wkb_int(const char **in);
-double read_wkb_double(const char **in, int convert_from_int);
-void read_wkb_point(const char **b);
-void read_wkb_polygon(const char **b);
-void read_wkb_linestring(const char **b);
-void read_wkb_curve(const char **b);
-void read_wkb_ordinate_array(const char **b);
-void read_collection(const char **b, read_col_func f);
-void parse_wkb(const char **b);
-void alloc_wkb(const char *parser);
-SERIALIZED_LWGEOM* parse_it(const char* geometry, allocator allocfunc, report_error errfunc);
-SERIALIZED_LWGEOM* parse_lwg(const char* geometry, allocator allocfunc, report_error errfunc);
-SERIALIZED_LWGEOM* parse_lwgi(const char* geometry, allocator allocfunc, report_error errfunc);
-
-void
-set_srid(double d_srid)
-{
-	if ( d_srid >= 0 )
-		d_srid+=0.1;
-	else
-		d_srid-=0.1;
-
-
-	srid=(int)(d_srid+0.1);
-}
-
-tuple *
-alloc_tuple(output_func of,size_t size)
-{
-	tuple* ret = free_list;
-
-	if ( ! ret ){
-		int toalloc = (ALLOC_CHUNKS /sizeof(tuple));
-		ret = malloc( toalloc *sizeof(tuple) );
-
-		free_list = ret;
-
-		while(--toalloc){
-			ret->next = ret+1;
-			ret++;
-		}
-
-		ret->next = NULL;
-
-		return alloc_tuple(of,size);
-	}
-
-	free_list = ret->next;
-	ret->of = of;
-	ret->next = NULL;
-
-	if ( the_geom.last ) {
-		the_geom.last->next = ret;
-		the_geom.last = ret;
-	}
-	else {
-		the_geom.first = the_geom.last = ret;
-	}
-
-	the_geom.alloc_size += size;
-	return ret;
-}
-
-static void
-error(const char* err)
-{
-	error_func(err);
-	ferror_occured=1;
-}
-
-void
-free_tuple(tuple* to_free)
-{
-
-	tuple* list_end = to_free;
-
-	if( !to_free)
-		return;
-
-	while(list_end->next){
-		list_end=list_end->next;
-	}
-
-	list_end->next = free_list;
-	free_list = to_free;
-}
-
-void
-inc_num(void)
-{
-	the_geom.stack->uu.nn.num++;
-}
-
-/*
-	Allocate a 'counting' tuple
-*/
-void
-alloc_stack_tuple(int type,output_func of,size_t size)
-{
-	tuple*	p;
-	inc_num();
-
-        LWDEBUGF(2, "alloc_stack_tuple %d, %d", type, size);
-	
-	p = alloc_tuple(of,size);
-	p->uu.nn.stack_next = the_geom.stack;
-	p->uu.nn.type = type;
-	p->uu.nn.size_here = the_geom.alloc_size;
-	p->uu.nn.num = 0;
-	the_geom.stack = p;
-}
-
-void
-pop(void)
-{
-	the_geom.stack = the_geom.stack->uu.nn.stack_next;
-}
-
-void
-popc(void)
-{
-
-	if ( the_geom.stack->uu.nn.num < minpoints){
-		error("geometry requires more points");
-	}
-        if(isodd != -1 && the_geom.stack->uu.nn.num % 2 != isodd) {
-                error("geometry must have an odd number of points");
-        }
-	if ( checkclosed && first_point && last_point) {
-		if ( memcmp(first_point, last_point,
-			sizeof(double)*the_geom.ndims) )
-		{
-			error("geometry contains non-closed rings");
-		}
-	}	
-
-	the_geom.stack = the_geom.stack->uu.nn.stack_next;
-}
-
-
-void
-check_dims(int num)
-{
-        LWDEBUGF(2, "check_dims the_geom.ndims = %d, num = %d", the_geom.ndims, num);
-
-	if( the_geom.ndims != num){
-		if (the_geom.ndims) {
-			error("Can not mix dimensionality in a geometry");
-		} else {
-
-                        LWDEBUGF(3, "check_dims: setting dim %d", num);
-
-			the_geom.ndims = num;
-			if ( num > 2 ) the_geom.hasZ = 1;
-			if ( num > 3 ) the_geom.hasM = 1;
-		}
-	}
-}
-
-#define WRITE_INT4_REAL(x,y) { memcpy(x->pos,&y,4); x->pos+=4;}
-#define WRITE_INT4_REAL_MULTIPLE(x,y,z) { memcpy(x->pos,&y,z*4); x->pos+=(z*4);}
-
-/*
-	we can shrink ints to one byte if they are less than 127
-	by setting the extra bit.  Because if the different byte
-	ordering possibilities we need to set the lsb on little
-	endian to show a packed one and the msb on a big endian
-	machine
-*/
-#ifdef SHRINK_INTS
-void
-WRITE_INT4(output_state * out,int4 val)
-{
-	if ( val <= 0x7f ){
-		if ( getMachineEndian() == NDR ){
-			val = (val<<1) | 1;
-		}
-		else{
-			val |=0x80;
-		}
-
-		*out->pos++ = (uchar)val;
-		the_geom.alloc_size-=3;
-	}
-	else{
-		if ( getMachineEndian() == NDR ){
-			val <<=1;
-		}
-		WRITE_INT4_REAL(out,val);
-	}
-}
-#else
-#define WRITE_INT4 WRITE_INT4_REAL
-#endif
-
-
-void
-WRITE_DOUBLES(output_state* out,double* points, int cnt)
-{
-	if ( the_geom.lwgi){
-		int4 vals[4];
-		int i;
-
-		for(i=0; i<cnt;i++){
-			vals[i] = (int4)(((points[i]+180.0)*0xB60B60)+.5);
-		}
-		memcpy(out->pos,vals,sizeof(int4)*cnt);
-		out->pos+=sizeof(int4)*cnt;
-	}
-	else{
-		memcpy(out->pos,points,sizeof(double)*cnt);
-		out->pos+=sizeof(double)*cnt;
-	}
-
-}
-
-void
-empty_stack(tuple *this,output_state* out)
-{
-    /* Do nothing but provide an empty base for the geometry stack */
-}
-
-void
-alloc_lwgeom(int srid)
-{
-        LWDEBUGF(2, "alloc_lwgeom %d", srid);
-
-	the_geom.srid=srid;
-	the_geom.alloc_size=0;
-	the_geom.stack=NULL;
-	the_geom.ndims=0;
-	the_geom.hasZ=0;
-	the_geom.hasM=0;
-
-	/* Free if used already */
-	if ( the_geom.first ){
-		free_tuple(the_geom.first);
-		the_geom.first=the_geom.last=NULL;
-	}
-
-	if ( srid != -1 ){
-		the_geom.alloc_size+=4;
-	}
-
-    /* Setup up an empty tuple as the stack base */
-    the_geom.stack = alloc_tuple(empty_stack, 0);
-}
-
-void
-write_point_2(tuple* this,output_state* out)
-{
-	WRITE_DOUBLES(out,this->uu.points,2);
-}
-
-void
-write_point_3(tuple* this,output_state* out)
-{
-	WRITE_DOUBLES(out,this->uu.points,3);
-}
-
-void
-write_point_4(tuple* this,output_state* out)
-{
-	WRITE_DOUBLES(out,this->uu.points,4);
-}
-
-void
-write_point_2i(tuple* this,output_state* out)
-{
-	WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,2);
-}
-
-void
-write_point_3i(tuple* this,output_state* out)
-{
-	WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,3);
-}
-
-void
-write_point_4i(tuple* this,output_state* out)
-{
-	WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,4);
-}
-
-void
-alloc_point_2d(double x,double y)
-{
-	tuple* p = alloc_tuple(write_point_2,the_geom.lwgi?8:16);
-	p->uu.points[0] = x;
-	p->uu.points[1] = y;
-
-        LWDEBUGF(2, "alloc_point_2d %f,%f", x, y);
-	
-	/* keep track of point */
-	if ( checkclosed ) {
-		if ( ! the_geom.stack->uu.nn.num )
-			first_point = p->uu.points;
-		last_point = p->uu.points;
-	}
-
-	inc_num();
-	check_dims(2);
-}
-
-void
-alloc_point_3d(double x,double y,double z)
-{
-	tuple* p = alloc_tuple(write_point_3,the_geom.lwgi?12:24);
-	p->uu.points[0] = x;
-	p->uu.points[1] = y;
-	p->uu.points[2] = z;
-
-        LWDEBUGF(2, "alloc_point_3d %f, %f, %f", x, y, z);
-	
-	/* keep track of point */
-	if ( checkclosed ) {
-		if ( ! the_geom.stack->uu.nn.num )
-			first_point = p->uu.points;
-		last_point = p->uu.points;
-	}
-
-	inc_num();
-	check_dims(3);
-}
-
-void
-alloc_point_4d(double x,double y,double z,double m)
-{
-	tuple* p = alloc_tuple(write_point_4,the_geom.lwgi?16:32);
-	p->uu.points[0] = x;
-	p->uu.points[1] = y;
-	p->uu.points[2] = z;
-	p->uu.points[3] = m;
-
-        LWDEBUGF(2, "alloc_point_4d %f, %f, %f, %f", x, y, z, m);
-
-	/* keep track of point */
-	if ( checkclosed ) {
-		if ( ! the_geom.stack->uu.nn.num )
-			first_point = p->uu.points;
-		last_point = p->uu.points;
-	}
-
-	inc_num();
-	check_dims(4);
-}
-
-void
-write_type(tuple* this,output_state* out)
-{
-	uchar type=0;
-
-	/* Empty handler - switch back */
-	if ( this->uu.nn.type == 0xff )
-		this->uu.nn.type = COLLECTIONTYPE;
-
-	type |= this->uu.nn.type;
-
-	if (the_geom.ndims) /* Support empty */
-	{
-		TYPE_SETZM(type, the_geom.hasZ, the_geom.hasM);
-	}
-
-	if ( the_geom.srid != -1 ){
-		type |= 0x40;
-	}
-
-	*(out->pos)=type;
-	out->pos++;
-
-	if ( the_geom.srid != -1 ){
-		/* Only the first geometry will have a srid attached */
-		WRITE_INT4(out,the_geom.srid);
-		the_geom.srid = -1;
-	}
-}
-
-void
-write_count(tuple* this,output_state* out)
-{
-	int num = this->uu.nn.num;
-	WRITE_INT4(out,num);
-}
-
-void
-write_type_count(tuple* this,output_state* out)
-{
-	write_type(this,out);
-	write_count(this,out);
-}
-
-void
-alloc_point(void)
-{
-        LWDEBUG(2, "alloc_point");
-
-	if( the_geom.lwgi)
-		alloc_stack_tuple(POINTTYPEI,write_type,1);
-	else
-		alloc_stack_tuple(POINTTYPE,write_type,1);
-
-	minpoints=1;
-	checkclosed=0;
-        isodd=-1;
-}
-
-void
-alloc_linestring(void)
-{
-        LWDEBUG(2, "alloc_linestring");
-
-	if( the_geom.lwgi)
-		alloc_stack_tuple(LINETYPEI,write_type,1);
-	else
-		alloc_stack_tuple(LINETYPE,write_type,1);
-
-	minpoints=2;
-	checkclosed=0;
-        isodd=-1;
-}
-
-void alloc_linestring_closed(void)
-{
-        LWDEBUG(2, "alloc_linestring_closed called.");
-
-        alloc_linestring();
-        checkclosed=1;
-}
-
-void
-alloc_circularstring(void)
-{
-        LWDEBUG(2, "alloc_circularstring");
-
-        alloc_stack_tuple(CURVETYPE,write_type,1);
-        minpoints=3;
-        checkclosed=0;
-        isodd=1;
-}
-
-void alloc_circularstring_closed(void)
-{
-        LWDEBUG(2, "alloc_circularstring_closed");
-
-        alloc_circularstring();
-        checkclosed=1;
-}
-
-void
-alloc_polygon(void)
-{
-        LWDEBUG(2, "alloc_polygon");
-
-	if( the_geom.lwgi)
-		alloc_stack_tuple(POLYGONTYPEI, write_type,1);
-	else
-		alloc_stack_tuple(POLYGONTYPE, write_type,1);
-
-	minpoints=3;
-	checkclosed=1;
-        isodd=-1;
-
-}
-
-void
-alloc_curvepolygon(void)
-{
-        LWDEBUG(2, "alloc_curvepolygon called.");
-
-        alloc_stack_tuple(CURVEPOLYTYPE, write_type, 1);
-        minpoints=3;
-        checkclosed=1;
-        isodd=-1;
-}
-
-void
-alloc_compoundcurve(void)
-{
-        LWDEBUG(2, "alloc_compoundcurve called.");
-
-        alloc_stack_tuple(COMPOUNDTYPE, write_type, 1);
-}
-
-void
-alloc_multipoint(void)
-{
-        LWDEBUG(2, "alloc_multipoint");
-
-	alloc_stack_tuple(MULTIPOINTTYPE,write_type,1);
-}
-
-void
-alloc_multilinestring(void)
-{
-        LWDEBUG(2, "alloc_multilinestring");
-
-	alloc_stack_tuple(MULTILINETYPE,write_type,1);
-}
-
-void
-alloc_multicurve(void)
-{
-        LWDEBUG(2, "alloc_multicurve");
-
-        alloc_stack_tuple(MULTICURVETYPE,write_type,1);
-}
-
-void
-alloc_multipolygon(void)
-{
-        LWDEBUG(2, "alloc_multipolygon");
-
-	alloc_stack_tuple(MULTIPOLYGONTYPE,write_type,1);
-}
-
-void
-alloc_multisurface(void)
-{
-        LWDEBUG(2, "alloc_multisurface called");
-
-        alloc_stack_tuple(MULTISURFACETYPE,write_type,1);
-}
-
-void
-alloc_geomertycollection(void)
-{
-        LWDEBUG(2, "alloc_geometrycollection");
-
-	alloc_stack_tuple(COLLECTIONTYPE,write_type,1);
-}
-
-void
-alloc_counter(void)
-{
-        LWDEBUG(2, "alloc_counter");
-
-	alloc_stack_tuple(0,write_count,4);
-}
-
-void
-alloc_empty(void)
-{
-	tuple* st = the_geom.stack;
-
-	LWDEBUG(2, "alloc_empty");
-
-	/* Find the last geometry */
-	while(st->uu.nn.type == 0){
-		st =st->uu.nn.stack_next;
-	}
-
-	/* Reclaim memory */
-	free_tuple(st->next);
-
-	/* Put an empty geometry collection on the top of the stack */
-	st->next=NULL;
-	the_geom.stack=st;
-	the_geom.alloc_size=st->uu.nn.size_here;
-
-	/* Mark as a empty stop */
-	if (st->uu.nn.type != 0xFF){
-		st->uu.nn.type=0xFF;
-		st->of = write_type_count;
-		the_geom.alloc_size+=4;
-		st->uu.nn.size_here=the_geom.alloc_size;
-	}
-
-	st->uu.nn.num=0;
-}
-
-SERIALIZED_LWGEOM *
-make_serialized_lwgeom(void)
-{
-	SERIALIZED_LWGEOM *out_serialized_lwgeom;
-	uchar* out_c;
-	output_state out;
-	tuple* cur;
-	
-	LWDEBUG(2, "make_serialized_lwgeom");
-
-	/* Allocate the SERIALIZED_LWGEOM structure */
-	out_serialized_lwgeom = (SERIALIZED_LWGEOM *)local_malloc(sizeof(SERIALIZED_LWGEOM));
-
-	/* Allocate the LWGEOM itself */
-	out_c = (uchar*)local_malloc(the_geom.alloc_size);
-	out.pos = out_c;
-	cur = the_geom.first ;
-
-	while(cur){
-		cur->of(cur,&out);
-		cur=cur->next;
-	}
-
-	/* Setup the SERIALIZED_LWGEOM structure */
-	out_serialized_lwgeom->lwgeom = out_c;
-	out_serialized_lwgeom->size = the_geom.alloc_size;
-
-	return out_serialized_lwgeom;
-}
-
-void
-lwg_parse_yynotice(char* s)
-{
-        lwnotice(s);
-}
-
-int
-lwg_parse_yyerror(char* s)
-{
-	error("parse error - invalid geometry");
-	/* error_func("parse error - invalid geometry"); */
-	return 1;
-}
-
-/*
- Table below generated using this ruby.
-
- a=(0..0xff).to_a.collect{|x|0xff};('0'..'9').each{|x|a[x[0]]=x[0]-'0'[0]}
- ('a'..'f').each{|x|v=x[0]-'a'[0]+10;a[x[0]]=a[x.upcase[0]]=v}
- puts '{'+a.join(",")+'}'
-
- */
-static const uchar to_hex[]  = {
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	0,1,2,3,4,5,6,7,8,9,255,255,255,255,255,255,255,10,11,12,13,14,
-	15,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,10,11,12,13,14,15,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255};
-
-uchar
-strhex_readbyte(const char* in)
-{
-	if ( *in == 0 ){
-		if ( ! ferror_occured){
-			error("invalid wkb");
-		}
-		return 0;
-	}
-	return to_hex[(int)*in]<<4 | to_hex[(int)*(in+1)];
-}
-
-uchar
-read_wkb_byte(const char** in)
-{
-	uchar ret = strhex_readbyte(*in);
-	(*in)+=2;
-	return ret;
-}
-
-int swap_order;
-
-void
-read_wkb_bytes(const char** in, uchar* out, int cnt)
-{
-	if ( ! swap_order ){
-		while(cnt--) *out++ = read_wkb_byte(in);
-	}
-	else{
-		out += (cnt-1);
-		while(cnt--) *out-- = read_wkb_byte(in);
-	}
-}
-
-int4
-read_wkb_int(const char** in)
-{
-	int4 ret=0;
-	read_wkb_bytes(in,(uchar*)&ret,4);
-	return ret;
-}
-
-double
-read_wkb_double(const char** in, int convert_from_int)
-{
-	double ret=0;
-
-	if ( ! convert_from_int){
-		read_wkb_bytes(in,(uchar*)&ret,8);
-		return ret;
-	}else{
-		ret  = read_wkb_int(in);
-		ret /= 0xb60b60;
-		return ret-180.0;
- 	}
-}
-
-void
-read_wkb_point(const char **b)
-{
-	int i;
-	tuple* p = NULL;
-
-
-	if(the_geom.lwgi && the_geom.from_lwgi ){
-		/*
-		 * Special case - reading from lwgi to lwgi
-		 * we don't want to go via doubles in the middle.
-		 */
-		switch(the_geom.ndims){
-			case 2: p=alloc_tuple(write_point_2i,8); break;
-			case 3: p=alloc_tuple(write_point_3i,12); break;
-			case 4: p=alloc_tuple(write_point_4i,16); break;
-		}
-
-		for(i=0;i<the_geom.ndims;i++){
-			p->uu.pointsi[i]=read_wkb_int(b);
-		}
-	}
-	else{
-		int mul = the_geom.lwgi ? 1 : 2;
-
-		switch(the_geom.ndims){
-			case 2: p=alloc_tuple(write_point_2,8*mul); break;
-			case 3: p=alloc_tuple(write_point_3,12*mul); break;
-			case 4: p=alloc_tuple(write_point_4,16*mul); break;
-		}
-
-		for(i=0;i<the_geom.ndims;i++){
-			p->uu.points[i]=read_wkb_double(b,the_geom.from_lwgi);
-		}
-	}
-
-
-	/* keep track of point */
-	if ( checkclosed ) {
-		if ( ! the_geom.stack->uu.nn.num )
-			first_point = p->uu.points;
-		last_point = p->uu.points;
-	}
-
-	inc_num();
-	check_dims(the_geom.ndims);
-}
-
-void
-read_wkb_polygon(const char **b)
-{
-	/* Stack the number of ORDINATE_ARRAYs (rings) */
-	int4 cnt=read_wkb_int(b);
-	alloc_counter();
-
-	/* Read through each ORDINATE_ARRAY in turn */
-	while(cnt--){
-		if ( ferror_occured )	return;
-
-		/* Things to check for POLYGON ORDINATE_ARRAYs */
-		minpoints=3;
-		checkclosed=1;
-		isodd=-1;
-
-		read_wkb_ordinate_array(b);
-	}
-
-	pop();
-}
-
-void
-read_wkb_linestring(const char **b)
-{
-
-	/* Things to check for LINESTRING ORDINATE_ARRAYs */
-	minpoints=2;
-	checkclosed=0;
-	isodd=-1;
-
-	read_wkb_ordinate_array(b);
-}
-
-
-void
-read_wkb_curve(const char **b)
-{
-
-	/* Things to check for CURVE ORDINATE_ARRAYs */
-	minpoints=3;
-	checkclosed=0;
-	isodd=-1;
-
-	read_wkb_ordinate_array(b);
-}
-
-void
-read_wkb_ordinate_array(const char **b)
-{
-	/* Read through a WKB ordinate array */
-	int4 cnt=read_wkb_int(b);
-	alloc_counter();
-
-	while(cnt--){
-		if ( ferror_occured )	return;
-		read_wkb_point(b);
-	}
-
-	/* Perform a check of the ordinate array */
-	popc();
-}
-
-void
-read_collection(const char **b, read_col_func f)
-{
-	/* Read through a COLLECTION or an EWKB */
-	int4 cnt=read_wkb_int(b);
-	alloc_counter();
-
-	while(cnt--){
-		if ( ferror_occured )	return;
-		f(b);
-	}
-
-	pop();
-}
-
-void
-parse_wkb(const char **b)
-{
-	int4 type;
-	uchar xdr = read_wkb_byte(b);
-	int4 localsrid;
-
-        LWDEBUG(2, "parse_wkb");
-
-	swap_order=0;
-
-	if ( xdr != getMachineEndian() )
-	{
-		swap_order=1;
-	}
-
-	type = read_wkb_int(b);
-
-	/* quick exit on error */
-	if ( ferror_occured ) return;
-
-	the_geom.ndims=2;
-	if (type & WKBZOFFSET)
-	{
-		the_geom.hasZ = 1;
-		the_geom.ndims++;
-	}
-	else the_geom.hasZ = 0;
-	if (type & WKBMOFFSET)
-	{
-		the_geom.hasM = 1;
-		the_geom.ndims++;
-	}
-	else the_geom.hasM = 0;
-
-	if (type & WKBSRIDFLAG )
-	{
-		/* local (in-EWKB) srid spec overrides SRID=#; */
-		localsrid = read_wkb_int(b);
-		if ( localsrid != -1 )
-		{
-			if ( the_geom.srid == -1 ) the_geom.alloc_size += 4;
-			the_geom.srid = localsrid;
-		}
-	}
-
-	type &=0x0f;
-
-	if ( the_geom.lwgi  ){
-
-		if ( type<= POLYGONTYPE )
-			alloc_stack_tuple(type +9,write_type,1);
-		else
-			alloc_stack_tuple(type,write_type,1);
-	}
-	else{
-		/* If we are writing lwg and are reading wbki */
-		int4 towrite=type;
-		if (towrite >= POINTTYPEI && towrite <= POLYGONTYPEI){
-			towrite-=9;
-		}
-		alloc_stack_tuple(towrite,write_type,1);
-	}
-
-	switch(type ){
-		case	POINTTYPE:
-			read_wkb_point(b);
-			break;
-
-		case	LINETYPE:
-			read_wkb_linestring(b);
-			break;
-
-                case    CURVETYPE:
-                        read_wkb_curve(b);
-                        break;
-
-		case	POLYGONTYPE:
-			read_wkb_polygon(b);
-			break;
-
-                case    COMPOUNDTYPE:
-                        read_collection(b,parse_wkb);
-                        break;
-
-                case    CURVEPOLYTYPE:
-                        read_collection(b,parse_wkb);
-                        break;
-
-		case	MULTIPOINTTYPE:
-		case	MULTILINETYPE:
-                case    MULTICURVETYPE:
-		case	MULTIPOLYGONTYPE:
-                case    MULTISURFACETYPE:
-		case	COLLECTIONTYPE:
-			read_collection(b,parse_wkb);
-			break;
-
-		case	POINTTYPEI:
-			the_geom.from_lwgi=1;
-			read_wkb_point(b);
-			break;
-
-		case	LINETYPEI:
-			the_geom.from_lwgi=1;
-			read_wkb_linestring(b);
-			break;
-
-		case	POLYGONTYPEI:
-			the_geom.from_lwgi=1;
-			read_wkb_polygon(b);
-			break;
-
-		default:
-			error("Invalid type in wbk");
-	}
-
-	the_geom.from_lwgi=0;
-
-	pop();
-}
-
-
-void
-alloc_wkb(const char *parser)
-{
-        LWDEBUG(2, "alloc_wkb");
-
-	parse_wkb(&parser);
-}
-
-/*
-	Parse a string and return a LW_GEOM
-*/
-SERIALIZED_LWGEOM *
-parse_it(const char *geometry, allocator allocfunc, report_error errfunc)
-{
-        LWDEBUGF(2, "parse_it: %s", geometry);
-
-	local_malloc = allocfunc;
-	error_func=errfunc;
-
-	ferror_occured = 0;
-
-	init_parser(geometry);
-
-	lwg_parse_yyparse();
-
-	close_parser();
-
-	if (ferror_occured)
-		return NULL;
-
-	return make_serialized_lwgeom();
-}
-
-SERIALIZED_LWGEOM *
-parse_lwg(const char* geometry,allocator allocfunc,report_error errfunc)
-{
-	the_geom.lwgi=0;
-	return parse_it(geometry,allocfunc,errfunc);
-}
-
-SERIALIZED_LWGEOM *
-parse_lwgi(const char* geometry,allocator allocfunc,report_error errfunc)
-{
-	the_geom.lwgi=1;
-	return parse_it(geometry,allocfunc,errfunc);
-}
-
-void
-set_zm(char z, char m)
-{
-        LWDEBUGF(2, "set_zm %d, %d", z, m);
-
-	the_geom.hasZ = z;
-	the_geom.hasM = m;
-	the_geom.ndims = 2+z+m;
-}
-

Deleted: trunk/lwgeom/lwline.c
===================================================================
--- trunk/lwgeom/lwline.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwline.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,516 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-/* basic LWLINE functions */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "liblwgeom.h"
-
-
-
-/*
- * Construct a new LWLINE.  points will *NOT* be copied
- * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
- */
-LWLINE *
-lwline_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *points)
-{
-	LWLINE *result;
-	result = (LWLINE*) lwalloc(sizeof(LWLINE));
-
-        LWDEBUG(2, "lwline_construct called.");
-
-	result->type = lwgeom_makeType_full(
-		TYPE_HASZ(points->dims),
-		TYPE_HASM(points->dims),
-		(SRID!=-1), LINETYPE,
-		0);
-
-        LWDEBUGF(3, "lwline_construct type=%d", result->type);
-
-	result->SRID = SRID;
-	result->points = points;
-	result->bbox = bbox;
-
-	return result;
-}
-
-/*
- * given the LWGEOM serialized form (or a pointer into a muli* one)
- * construct a proper LWLINE.
- * serialized_form should point to the 8bit type format (with type = 2)
- * See serialized form doc
- */
-LWLINE *
-lwline_deserialize(uchar *serialized_form)
-{
-	uchar type;
-	LWLINE *result;
-	uchar *loc =NULL;
-	uint32 npoints;
-	POINTARRAY *pa;
-
-	type = (uchar) serialized_form[0];
-
-	if ( lwgeom_getType(type) != LINETYPE)
-	{
-		lwerror("lwline_deserialize: attempt to deserialize a line which is really a %s", lwgeom_typename(type));
-		return NULL;
-	}
-
-	result = (LWLINE*) lwalloc(sizeof(LWLINE)) ;
-	result->type = type;
-
-	loc = serialized_form+1;
-
-	if (lwgeom_hasBBOX(type))
-	{
-		LWDEBUG(3, "lwline_deserialize: input has bbox");
-
-		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-		memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
-		loc += sizeof(BOX2DFLOAT4);
-	}
-	else
-	{
-		result->bbox = NULL;
-		/*lwnotice("line has NO bbox"); */
-	}
-
-	if ( lwgeom_hasSRID(type))
-	{
-		/*lwnotice("line has srid"); */
-		result->SRID = lw_get_int32(loc);
-		loc +=4; /* type + SRID */
-	}
-	else
-	{
-		/*lwnotice("line has NO srid"); */
-		result->SRID = -1;
-	}
-
-	/* we've read the type (1 byte) and SRID (4 bytes, if present) */
-
-	npoints = lw_get_uint32(loc);
-	/*lwnotice("line npoints = %d", npoints); */
-	loc +=4;
-	pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), npoints);
-	result->points = pa;
-
-	return result;
-}
-
-/*
- * convert this line into its serialize form
- * result's first char will be the 8bit type.  See serialized form doc
- */
-uchar *
-lwline_serialize(LWLINE *line)
-{
-	size_t size, retsize;
-	uchar * result;
-
-	if (line == NULL) lwerror("lwline_serialize:: given null line");
-
-	size = lwline_serialize_size(line);
-	result = lwalloc(size);
-	lwline_serialize_buf(line, result, &retsize);
-
-	if ( retsize != size )
-	{
-		lwerror("lwline_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
-	}
-
-	return result;
-}
-
-/*
- * convert this line into its serialize form writing it into
- * the given buffer, and returning number of bytes written into
- * the given int pointer.
- * result's first char will be the 8bit type.  See serialized form doc
- */
-void
-lwline_serialize_buf(LWLINE *line, uchar *buf, size_t *retsize)
-{
-	char hasSRID;
-	uchar *loc;
-	int ptsize;
-	size_t size;
-
-	LWDEBUGF(2, "lwline_serialize_buf(%p, %p, %p) called",
-		line, buf, retsize);
-
-	if (line == NULL)
-		lwerror("lwline_serialize:: given null line");
-
-	if ( TYPE_GETZM(line->type) != TYPE_GETZM(line->points->dims) )
-		lwerror("Dimensions mismatch in lwline");
-
-	ptsize = pointArray_ptsize(line->points);
-
-	hasSRID = (line->SRID != -1);
-
-	buf[0] = (uchar) lwgeom_makeType_full(
-		TYPE_HASZ(line->type), TYPE_HASM(line->type),
-		hasSRID, LINETYPE, line->bbox ? 1 : 0);
-	loc = buf+1;
-
-	LWDEBUGF(3, "lwline_serialize_buf added type (%d)", line->type);
-
-	if (line->bbox)
-	{
-		memcpy(loc, line->bbox, sizeof(BOX2DFLOAT4));
-		loc += sizeof(BOX2DFLOAT4);
-
-		LWDEBUG(3, "lwline_serialize_buf added BBOX");
-	}
-
-	if (hasSRID)
-	{
-		memcpy(loc, &line->SRID, sizeof(int32));
-		loc += sizeof(int32);
-
-		LWDEBUG(3, "lwline_serialize_buf added SRID");
-	}
-
-	memcpy(loc, &line->points->npoints, sizeof(uint32));
-	loc += sizeof(uint32);
-
-	LWDEBUGF(3, "lwline_serialize_buf added npoints (%d)",
-		line->points->npoints);
-
-	/*copy in points */
-	size = line->points->npoints*ptsize;
-	memcpy(loc, getPoint_internal(line->points, 0), size);
-	loc += size;
-
-	LWDEBUGF(3, "lwline_serialize_buf copied serialized_pointlist (%d bytes)",
-		ptsize * line->points->npoints);
-
-	if (retsize) *retsize = loc-buf;
-
-	/*printBYTES((uchar *)result, loc-buf); */
-
-	LWDEBUGF(3, "lwline_serialize_buf returning (loc: %p, size: %d)",
-		loc, loc-buf);
-}
-
-/*
- * Find bounding box (standard one) 
- * zmin=zmax=NO_Z_VALUE if 2d 
- */
-BOX3D *
-lwline_compute_box3d(LWLINE *line)
-{
-	BOX3D *ret;
-
-	if (line == NULL) return NULL;
-
-	ret = ptarray_compute_box3d(line->points);
-	return ret;
-}
-
-/* find length of this deserialized line */
-size_t
-lwline_serialize_size(LWLINE *line)
-{
-	size_t size = 1;  /* type */
-
-	LWDEBUG(2, "lwline_serialize_size called");
-
-	if ( line->SRID != -1 ) size += 4; /* SRID */
-	if ( line->bbox ) size += sizeof(BOX2DFLOAT4);
-
-	size += 4; /* npoints */
-	size += pointArray_ptsize(line->points)*line->points->npoints;
-
-	LWDEBUGF(3, "lwline_serialize_size returning %d", size);
-
-	return size;
-}
-
-void pfree_line (LWLINE  *line)
-{
-	lwfree(line->points);
-	lwfree(line);
-}
-
-/* find length of this serialized line */
-size_t
-lwgeom_size_line(const uchar *serialized_line)
-{
-	int type = (uchar) serialized_line[0];
-	uint32 result = 1;  /*type */
-	const uchar *loc;
-	uint32 npoints;
-
-	LWDEBUG(2, "lwgeom_size_line called");
-
-	if ( lwgeom_getType(type) != LINETYPE)
-		lwerror("lwgeom_size_line::attempt to find the length of a non-line");
-
-
-	loc = serialized_line+1;
-
-	if (lwgeom_hasBBOX(type))
-	{
-		loc += sizeof(BOX2DFLOAT4);
-		result +=sizeof(BOX2DFLOAT4);
-	}
-
-	if ( lwgeom_hasSRID(type))
-	{
-		loc += 4; /* type + SRID */
-		result +=4;
-	}
-
-	/* we've read the type (1 byte) and SRID (4 bytes, if present) */
-	npoints = lw_get_uint32(loc);
-	result += sizeof(uint32); /* npoints */
-
-	result += TYPE_NDIMS(type) * sizeof(double) * npoints;
-
-	LWDEBUGF(3, "lwgeom_size_line returning %d", result);
-
-	return result;
-}
-
-void printLWLINE(LWLINE *line)
-{
-	lwnotice("LWLINE {");
-	lwnotice("    ndims = %i", (int)TYPE_NDIMS(line->type));
-	lwnotice("    SRID = %i", (int)line->SRID);
-	printPA(line->points);
-	lwnotice("}");
-}
-
-int
-lwline_compute_box2d_p(LWLINE *line, BOX2DFLOAT4 *box)
-{
-	return ptarray_compute_box2d_p(line->points, box);
-}
-
-/* Clone LWLINE object. POINTARRAY is not copied. */
-LWLINE *
-lwline_clone(const LWLINE *g)
-{
-	LWLINE *ret = lwalloc(sizeof(LWLINE));
-       
-	LWDEBUGF(2, "lwline_clone called with %p", g);
-
-	memcpy(ret, g, sizeof(LWLINE));
-	if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
-	return ret;
-}
-
-/*
- * Add 'what' to this line at position 'where'.
- * where=0 == prepend
- * where=-1 == append
- * Returns a MULTILINE or a GEOMETRYCOLLECTION
- */
-LWGEOM *
-lwline_add(const LWLINE *to, uint32 where, const LWGEOM *what)
-{
-	LWCOLLECTION *col;
-	LWGEOM **geoms;
-	int newtype;
-
-	if ( where != -1 && where != 0 )
-	{
-		lwerror("lwline_add only supports 0 or -1 as second argument, got %d", where);
-		return NULL;
-	}
-
-	/* dimensions compatibility are checked by caller */
-
-	/* Construct geoms array */
-	geoms = lwalloc(sizeof(LWGEOM *)*2);
-	if ( where == -1 ) /* append */
-	{
-		geoms[0] = lwgeom_clone((LWGEOM *)to);
-		geoms[1] = lwgeom_clone(what);
-	}
-	else /* prepend */
-	{
-		geoms[0] = lwgeom_clone(what);
-		geoms[1] = lwgeom_clone((LWGEOM *)to);
-	}
-
-	/* reset SRID and wantbbox flag from component types */
-	geoms[0]->SRID = geoms[1]->SRID = -1;
-	TYPE_SETHASSRID(geoms[0]->type, 0);
-	TYPE_SETHASSRID(geoms[1]->type, 0);
-	TYPE_SETHASBBOX(geoms[0]->type, 0);
-	TYPE_SETHASBBOX(geoms[1]->type, 0);
-
-	/* Find appropriate geom type */
-	if ( TYPE_GETTYPE(what->type) == LINETYPE ) newtype = MULTILINETYPE;
-	else newtype = COLLECTIONTYPE;
-
-	col = lwcollection_construct(newtype,
-		to->SRID, NULL,
-		2, geoms);
-	
-	return (LWGEOM *)col;
-}
-
-void
-lwline_reverse(LWLINE *line)
-{
-	ptarray_reverse(line->points);
-}
-
-LWLINE *
-lwline_segmentize2d(LWLINE *line, double dist)
-{
-	return lwline_construct(line->SRID, NULL,
-		ptarray_segmentize2d(line->points, dist));
-}
-
-/* check coordinate equality  */
-char
-lwline_same(const LWLINE *l1, const LWLINE *l2)
-{
-	return ptarray_same(l1->points, l2->points);
-}
-
-/*
- * Construct a LWLINE from an array of LWPOINTs
- * LWLINE dimensions are large enough to host all input dimensions.
- */
-LWLINE *
-lwline_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points)
-{
-	int zmflag=0;
-	unsigned int i;
-	POINTARRAY *pa;
-	uchar *newpoints, *ptr;
-	size_t ptsize, size;
-
-	/*
-	 * Find output dimensions, check integrity
-	 */
-	for (i=0; i<npoints; i++)
-	{
-		if ( TYPE_GETTYPE(points[i]->type) != POINTTYPE )
-		{
-			lwerror("lwline_from_lwpointarray: invalid input type: %s",
-				lwgeom_typename(TYPE_GETTYPE(points[i]->type)));
-			return NULL;
-		}
-		if ( TYPE_HASZ(points[i]->type) ) zmflag |= 2;
-		if ( TYPE_HASM(points[i]->type) ) zmflag |= 1;
-		if ( zmflag == 3 ) break;
-	}
-
-	if ( zmflag == 0 ) ptsize=2*sizeof(double);
-	else if ( zmflag == 3 ) ptsize=4*sizeof(double);
-	else ptsize=3*sizeof(double);
-
-	/*
-	 * Allocate output points array
-	 */
-	size = ptsize*npoints;
-	newpoints = lwalloc(size);
-	memset(newpoints, 0, size);
-
-	ptr=newpoints;
-	for (i=0; i<npoints; i++)
-	{
-		size=pointArray_ptsize(points[i]->point);
-		memcpy(ptr, getPoint_internal(points[i]->point, 0), size);
-		ptr+=ptsize;
-	}
-
-	pa = pointArray_construct(newpoints, zmflag&2, zmflag&1, npoints);
-
-	return lwline_construct(SRID, NULL, pa);
-}
-
-/*
- * Construct a LWLINE from a LWMPOINT
- */
-LWLINE *
-lwline_from_lwmpoint(int SRID, LWMPOINT *mpoint)
-{
-	unsigned int i;
-	POINTARRAY *pa;
-	char zmflag = TYPE_GETZM(mpoint->type);
-	size_t ptsize, size;
-	uchar *newpoints, *ptr;
-
-	if ( zmflag == 0 ) ptsize=2*sizeof(double);
-	else if ( zmflag == 3 ) ptsize=4*sizeof(double);
-	else ptsize=3*sizeof(double);
-
-	/* Allocate space for output points */
-	size = ptsize*mpoint->ngeoms;
-	newpoints = lwalloc(size);
-	memset(newpoints, 0, size);
-
-	ptr=newpoints;
-	for (i=0; i<mpoint->ngeoms; i++)
-	{
-		memcpy(ptr,
-			getPoint_internal(mpoint->geoms[i]->point, 0),
-			ptsize);
-		ptr+=ptsize;
-	}
-
-	pa = pointArray_construct(newpoints, zmflag&2, zmflag&1,
-		mpoint->ngeoms);
-
-	LWDEBUGF(3, "lwline_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag);
-
-	return lwline_construct(SRID, NULL, pa);
-}
-
-LWLINE *
-lwline_addpoint(LWLINE *line, LWPOINT *point, unsigned int where)
-{
-	POINTARRAY *newpa;
-	LWLINE *ret;
-
-	newpa = ptarray_addPoint(line->points,
-		getPoint_internal(point->point, 0),
-		TYPE_NDIMS(point->type), where);
-
-	ret = lwline_construct(line->SRID, NULL, newpa);
-
-	return ret;
-}
-
-LWLINE *
-lwline_removepoint(LWLINE *line, unsigned int index)
-{
-	POINTARRAY *newpa;
-	LWLINE *ret;
-
-	newpa = ptarray_removePoint(line->points, index);
-
-	ret = lwline_construct(line->SRID, NULL, newpa);
-
-	return ret;
-}
-
-/*
- * Note: input will be changed, make sure you have permissions for this.
- */
-void
-lwline_setPoint4d(LWLINE *line, unsigned int index, POINT4D *newpoint)
-{
-	setPoint4d(line->points, index, newpoint);
-}

Deleted: trunk/lwgeom/lwmcurve.c
===================================================================
--- trunk/lwgeom/lwmcurve.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwmcurve.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,125 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "liblwgeom.h"
-
-LWMCURVE *
-lwmcurve_deserialize(uchar *srl)
-{
-        LWMCURVE *result;
-        LWGEOM_INSPECTED *insp;
-        int stype;
-        int type = lwgeom_getType(srl[0]);
-        int i;
-
-        if(type != MULTICURVETYPE)
-        {
-                lwerror("lwmcurve_deserialize called on NON multicurve: %d", type);
-                return NULL;
-        }
-
-        insp = lwgeom_inspect(srl);
-
-        result = lwalloc(sizeof(LWMCURVE));
-        result->type = insp->type;
-        result->SRID = insp->SRID;
-        result->ngeoms = insp->ngeometries;
-        result->geoms = lwalloc(sizeof(LWCURVE *)*insp->ngeometries);
-
-        if(lwgeom_hasBBOX(srl[0]))
-        {
-                result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-                memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4));
-        }
-        else result->bbox = NULL;
-
-        for(i = 0; i < insp->ngeometries; i++)
-        {
-                stype = lwgeom_getType(insp->sub_geoms[i][0]);
-                if(stype == CURVETYPE)
-                {
-                        result->geoms[i] = (LWGEOM *)lwcurve_deserialize(insp->sub_geoms[i]);
-                }
-                else if(stype == LINETYPE)
-                {
-                        result->geoms[i] = (LWGEOM *)lwline_deserialize(insp->sub_geoms[i]);
-                }
-                else
-                {
-                        lwerror("Only Circular and Line strings are currenly permitted in a MultiCurve.");
-                        free(result);
-                        free(insp);
-                        return NULL;
-                }
-                        
-                if(TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type))
-                {
-                        lwerror("Mixed diminsions (multicurve: %d, curve %d:%d)",
-                                TYPE_NDIMS(result->type), i,
-                                TYPE_NDIMS(result->geoms[i]->type));
-                        free(result);
-                        free(insp);
-                        return NULL;
-                }
-        }
-        return result;
-}
-
-/*
- * Add 'what' to this multicurve at position 'where'.
- * where=0 == prepend
- * where=-1 == append
- * Returns a MULTICURVE or a COLLECTION
- */
-LWGEOM *
-lwmcurve_add(const LWMCURVE *to, uint32 where, const LWGEOM *what)
-{
-        LWCOLLECTION *col;
-        LWGEOM **geoms;
-        int newtype;
-        uint32 i;
-
-        if(where == -1) where = to->ngeoms;
-        else if(where < -1 || where > to->ngeoms)
-        {
-                lwerror("lwmcurve_add: add position out of range %d..%d",
-                        -1, to->ngeoms);
-                return NULL;
-        }
-
-        /* dimensions compatibility are checked by caller */
-
-        /* Construct geoms array */
-        geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
-        for(i = 0; i < where; i++)
-        {
-                geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
-        }
-        geoms[where] = lwgeom_clone(what);
-        for(i = where; i < to->ngeoms; i++) 
-        {
-                geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
-        }
-
-        if(TYPE_GETTYPE(what->type) == CURVETYPE) newtype = MULTICURVETYPE;
-        else newtype = COLLECTIONTYPE;
-
-        col = lwcollection_construct(newtype,
-                to->SRID, NULL,
-                to->ngeoms + 1, geoms);
-
-        return (LWGEOM *)col;
-}
-        

Deleted: trunk/lwgeom/lwmline.c
===================================================================
--- trunk/lwgeom/lwmline.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwmline.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,110 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "liblwgeom.h"
-
-LWMLINE *
-lwmline_deserialize(uchar *srl)
-{
-	LWMLINE *result;
-	LWGEOM_INSPECTED *insp;
-	int type = lwgeom_getType(srl[0]);
-	int i;
-
-	if ( type != MULTILINETYPE ) 
-	{
-		lwerror("lwmline_deserialize called on NON multiline: %d",
-			type);
-		return NULL;
-	}
-
-	insp = lwgeom_inspect(srl);
-
-	result = lwalloc(sizeof(LWMLINE));
-	result->type = insp->type;
-	result->SRID = insp->SRID;
-	result->ngeoms = insp->ngeometries;
-	result->geoms = lwalloc(sizeof(LWLINE *)*insp->ngeometries);
-
-	if (lwgeom_hasBBOX(srl[0]))
-	{
-		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-		memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4));
-	}
-	else result->bbox = NULL;
-
-
-	for (i=0; i<insp->ngeometries; i++)
-	{
-		result->geoms[i] = lwline_deserialize(insp->sub_geoms[i]);
-		if ( TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type) )
-		{
-			lwerror("Mixed dimensions (multiline:%d, line%d:%d)",
-				TYPE_NDIMS(result->type), i,
-				TYPE_NDIMS(result->geoms[i]->type)
-			);
-			return NULL;
-		}
-	}
-
-	return result;
-}
-
-/*
- * Add 'what' to this multiline at position 'where'.
- * where=0 == prepend
- * where=-1 == append
- * Returns a MULTILINE or a COLLECTION
- */
-LWGEOM *
-lwmline_add(const LWMLINE *to, uint32 where, const LWGEOM *what)
-{
-	LWCOLLECTION *col;
-	LWGEOM **geoms;
-	int newtype;
-	uint32 i;
-
-	if ( where == -1 ) where = to->ngeoms;
-	else if ( where < -1 || where > to->ngeoms )
-	{
-		lwerror("lwmline_add: add position out of range %d..%d",
-			-1, to->ngeoms);
-		return NULL;
-	}
-
-	/* dimensions compatibility are checked by caller */
-
-	/* Construct geoms array */
-	geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
-	for (i=0; i<where; i++)
-	{
-		geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
-	}
-	geoms[where] = lwgeom_clone(what);
-	for (i=where; i<to->ngeoms; i++)
-	{
-		geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
-	}
-
-	if ( TYPE_GETTYPE(what->type) == LINETYPE ) newtype = MULTILINETYPE;
-	else newtype = COLLECTIONTYPE;
-
-	col = lwcollection_construct(newtype,
-		to->SRID, NULL,
-		to->ngeoms+1, geoms);
-	
-	return (LWGEOM *)col;
-
-}

Deleted: trunk/lwgeom/lwmpoint.c
===================================================================
--- trunk/lwgeom/lwmpoint.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwmpoint.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,109 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "liblwgeom.h"
-
-LWMPOINT *
-lwmpoint_deserialize(uchar *srl)
-{
-	LWMPOINT *result;
-	LWGEOM_INSPECTED *insp;
-	int type = lwgeom_getType(srl[0]);
-	int i;
-
-	if ( type != MULTIPOINTTYPE ) 
-	{
-		lwerror("lwmpoint_deserialize called on NON multipoint: %d",
-			type);
-		return NULL;
-	}
-
-	insp = lwgeom_inspect(srl);
-
-	result = lwalloc(sizeof(LWMPOINT));
-	result->type = insp->type;
-	result->SRID = insp->SRID;
-	result->ngeoms = insp->ngeometries;
-	result->geoms = lwalloc(sizeof(LWPOINT *)*result->ngeoms);
-
-	if (lwgeom_hasBBOX(srl[0]))
-	{
-		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-		memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4));
-	}
-	else result->bbox = NULL;
-
-	for (i=0; i<insp->ngeometries; i++)
-	{
-		result->geoms[i] = lwpoint_deserialize(insp->sub_geoms[i]);
-		if ( TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type) )
-		{
-			lwerror("Mixed dimensions (multipoint:%d, point%d:%d)",
-				TYPE_NDIMS(result->type), i,
-				TYPE_NDIMS(result->geoms[i]->type)
-			);
-			return NULL;
-		}
-	}
-
-	return result;
-}
-
-/*
- * Add 'what' to this multipoint at position 'where'.
- * where=0 == prepend
- * where=-1 == append
- * Returns a MULTIPOINT or a COLLECTION
- */
-LWGEOM *
-lwmpoint_add(const LWMPOINT *to, uint32 where, const LWGEOM *what)
-{
-	LWCOLLECTION *col;
-	LWGEOM **geoms;
-	int newtype;
-	uint32 i;
-
-	if ( where == -1 ) where = to->ngeoms;
-	else if ( where < -1 || where > to->ngeoms )
-	{
-		lwerror("lwmpoint_add: add position out of range %d..%d",
-			-1, to->ngeoms);
-		return NULL;
-	}
-
-	/* dimensions compatibility are checked by caller */
-
-	/* Construct geoms array */
-	geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
-	for (i=0; i<where; i++)
-	{
-		geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
-	}
-	geoms[where] = lwgeom_clone(what);
-	for (i=where; i<to->ngeoms; i++)
-	{
-		geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
-	}
-
-	if ( TYPE_GETTYPE(what->type) == POINTTYPE ) newtype = MULTIPOINTTYPE;
-	else newtype = COLLECTIONTYPE;
-
-	col = lwcollection_construct(newtype,
-		to->SRID, NULL,
-		to->ngeoms+1, geoms);
-	
-	return (LWGEOM *)col;
-
-}

Deleted: trunk/lwgeom/lwmpoly.c
===================================================================
--- trunk/lwgeom/lwmpoly.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwmpoly.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,112 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "liblwgeom.h"
-
-
-LWMPOLY *
-lwmpoly_deserialize(uchar *srl)
-{
-	LWMPOLY *result;
-	LWGEOM_INSPECTED *insp;
-	int type = lwgeom_getType(srl[0]);
-	int i;
-
-	LWDEBUG(2, "lwmpoly_deserialize called");
-
-	if ( type != MULTIPOLYGONTYPE ) 
-	{
-		lwerror("lwmpoly_deserialize called on NON multipoly: %d",
-			type);
-		return NULL;
-	}
-
-	insp = lwgeom_inspect(srl);
-
-	result = lwalloc(sizeof(LWMPOLY));
-	result->type = insp->type;
-	result->SRID = insp->SRID;
-	result->ngeoms = insp->ngeometries;
-	result->geoms = lwalloc(sizeof(LWPOLY *)*insp->ngeometries);
-
-	if (lwgeom_hasBBOX(srl[0]))
-	{
-		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-		memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4));
-	}
-	else result->bbox = NULL;
-
-	for (i=0; i<insp->ngeometries; i++)
-	{
-		result->geoms[i] = lwpoly_deserialize(insp->sub_geoms[i]);
-		if ( TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type) )
-		{
-			lwerror("Mixed dimensions (multipoly:%d, poly%d:%d)",
-				TYPE_NDIMS(result->type), i,
-				TYPE_NDIMS(result->geoms[i]->type)
-			);
-			return NULL;
-		}
-	}
-
-	return result;
-}
-
-/*
- * Add 'what' to this multiline at position 'where'.
- * where=0 == prepend
- * where=-1 == append
- * Returns a MULTIPOLY or a COLLECTION
- */
-LWGEOM *
-lwmpoly_add(const LWMPOLY *to, uint32 where, const LWGEOM *what)
-{
-	LWCOLLECTION *col;
-	LWGEOM **geoms;
-	int newtype;
-	uint32 i;
-
-	if ( where == -1 ) where = to->ngeoms;
-	else if ( where < -1 || where > to->ngeoms )
-	{
-		lwerror("lwmline_add: add position out of range %d..%d",
-			-1, to->ngeoms);
-		return NULL;
-	}
-
-	/* dimensions compatibility are checked by caller */
-
-	/* Construct geoms array */
-	geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
-	for (i=0; i<where; i++)
-	{
-		geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
-	}
-	geoms[where] = lwgeom_clone(what);
-	for (i=where; i<to->ngeoms; i++)
-	{
-		geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
-	}
-
-	if ( TYPE_GETTYPE(what->type) == POLYGONTYPE ) newtype = MULTIPOLYGONTYPE;
-	else newtype = COLLECTIONTYPE;
-
-	col = lwcollection_construct(newtype,
-		to->SRID, NULL,
-		to->ngeoms+1, geoms);
-	
-	return (LWGEOM *)col;
-
-}

Deleted: trunk/lwgeom/lwmsurface.c
===================================================================
--- trunk/lwgeom/lwmsurface.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwmsurface.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,129 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "liblwgeom.h"
-
-
-LWMSURFACE *
-lwmsurface_deserialize(uchar *srl)
-{
-        LWMSURFACE *result;
-        LWGEOM_INSPECTED *insp;
-        int stype;
-        int type = lwgeom_getType(srl[0]);
-        int i;
-
-        LWDEBUG(2, "lwmsurface_deserialize called");
-
-        if(type != MULTISURFACETYPE)
-        {
-                lwerror("lwmsurface_deserialize called on a non-multisurface: %d", type);
-                return NULL;
-        }
-
-        insp = lwgeom_inspect(srl);
-
-        result = lwalloc(sizeof(LWMSURFACE));
-        result->type = insp->type;
-        result->SRID = insp->SRID;
-        result->ngeoms = insp->ngeometries;
-        result->geoms = lwalloc(sizeof(LWPOLY *)*insp->ngeometries);
-
-        if(lwgeom_hasBBOX(srl[0]))
-        {
-                result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-                memcpy(result->bbox, srl + 1, sizeof(BOX2DFLOAT4));
-        }
-        else result->bbox = NULL;
-
-        for(i = 0; i < insp->ngeometries; i++)
-        {
-                stype = lwgeom_getType(insp->sub_geoms[i][0]);
-                if(stype == POLYGONTYPE) 
-                {
-                        result->geoms[i] = (LWGEOM *)lwpoly_deserialize(insp->sub_geoms[i]);
-                }
-                else if(stype == CURVEPOLYTYPE)
-                {
-                        result->geoms[i] = (LWGEOM *)lwcurvepoly_deserialize(insp->sub_geoms[i]);
-                }
-                else
-                {
-                        lwerror("Only Polygons and Curved Polygons are supported in a MultiSurface.");
-                        lwfree(result);
-                        lwfree(insp);
-                        return NULL;
-                }
-
-                if(TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type))
-                {
-                        lwerror("Mixed dimensions (multisurface: %d, surface %d:%d", 
-                                TYPE_NDIMS(result->type), i, 
-                                TYPE_NDIMS(result->geoms[i]->type));
-                        lwfree(result);
-                        lwfree(insp);
-                        return NULL;
-                }
-        }
-        return result;
-}
-
-/*
- * Add 'what' to this multisurface at position 'where'
- * where=0 == prepend
- * where=-1 == append
- * Returns a MULTISURFACE or a COLLECTION
- */
-LWGEOM *
-lwmsurface_add(const LWMSURFACE *to, uint32 where, const LWGEOM *what)
-{
-        LWCOLLECTION *col;
-        LWGEOM **geoms;
-        int newtype;
-        uint32 i;
-        
-        if(where == -1) where = to->ngeoms;
-        else if(where < -1 || where > to->ngeoms)
-        {
-                lwerror("lwmsurface_add: add position out of range %d..%d",
-                        -1, to->ngeoms);
-                return NULL;
-        }
-
-        /* dimensions compatibility are checked by caller */
-
-        /* Construct geoms array */
-        geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
-        for(i = 0; i < where; i++)
-        {
-                geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
-        }
-        geoms[where] = lwgeom_clone(what);
-        for(i = where; i < to->ngeoms; i++)
-        {
-                geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
-        }
-
-        if(TYPE_GETTYPE(what->type) == POLYGONTYPE 
-                || TYPE_GETTYPE(what->type) == CURVEPOLYTYPE) 
-            newtype = MULTISURFACETYPE;
-        else newtype = COLLECTIONTYPE;
-
-        col = lwcollection_construct(newtype,
-            to->SRID, NULL, to->ngeoms + 1, geoms);
-
-        return (LWGEOM *)col;
-}
-

Deleted: trunk/lwgeom/lwpoint.c
===================================================================
--- trunk/lwgeom/lwpoint.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwpoint.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,431 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "liblwgeom.h"
-
-
-/*
- * Convert this point into its serialize form
- * result's first char will be the 8bit type.  See serialized form doc
- */
-uchar *
-lwpoint_serialize(LWPOINT *point)
-{
-	size_t size, retsize;
-	uchar *result;
-
-	size = lwpoint_serialize_size(point);
-	result = lwalloc(size);
-	lwpoint_serialize_buf(point, result, &retsize);
-
-	if ( retsize != size )
-	{
-		lwerror("lwpoint_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
-	}
-
-	return result;
-}
-
-/*
- * Convert this point into its serialize form writing it into
- * the given buffer, and returning number of bytes written into
- * the given int pointer.
- * result's first char will be the 8bit type.  See serialized form doc
- */
-void
-lwpoint_serialize_buf(LWPOINT *point, uchar *buf, size_t *retsize)
-{
-	int size=1;
-	char hasSRID;
-	uchar *loc;
-	int ptsize = pointArray_ptsize(point->point);
-
-	if ( TYPE_GETZM(point->type) != TYPE_GETZM(point->point->dims) )
-		lwerror("Dimensions mismatch in lwpoint");
-
-	LWDEBUGF(2, "lwpoint_serialize_buf(%p, %p) called", point, buf);
-	/*printLWPOINT(point); */
-
-	hasSRID = (point->SRID != -1);
-
-	if (hasSRID) size +=4;  /*4 byte SRID */
-	if (point->bbox) size += sizeof(BOX2DFLOAT4); /* bvol */
-
-	size += sizeof(double)*TYPE_NDIMS(point->type);
-
-	buf[0] = (uchar) lwgeom_makeType_full(
-		TYPE_HASZ(point->type), TYPE_HASM(point->type),
-		hasSRID, POINTTYPE, point->bbox?1:0);
-	loc = buf+1;
-
-	if (point->bbox)
-	{
-		memcpy(loc, point->bbox, sizeof(BOX2DFLOAT4));
-		loc += sizeof(BOX2DFLOAT4);
-	}
-
-	if (hasSRID)
-	{
-		memcpy(loc, &point->SRID, sizeof(int32));
-		loc += 4;
-	}
-
-	/* copy in points */
-	memcpy(loc, getPoint_internal(point->point, 0), ptsize);
-
-	if (retsize) *retsize = size;
-}
-
-/*
- * Find bounding box (standard one) 
- *   zmin=zmax=NO_Z_VALUE if 2d 
- */
-BOX3D *
-lwpoint_compute_box3d(LWPOINT *point)
-{
-	LWDEBUGF(2, "lwpoint_compute_box3d called with point %p", point);
-
-	if (point == NULL)
-	{
-		LWDEBUG(3, "lwpoint_compute_box3d returning NULL");
-
-		return NULL;
-	}
-
-	LWDEBUG(3, "lwpoint_compute_box3d returning ptarray_compute_box3d return");
-
-	return ptarray_compute_box3d(point->point);
-}
-
-/*
- * Convenience functions to hide the POINTARRAY
- * TODO: obsolete this
- */
-int
-lwpoint_getPoint2d_p(const LWPOINT *point, POINT2D *out)
-{
-	return getPoint2d_p(point->point, 0, out);
-}
-
-/* convenience functions to hide the POINTARRAY */
-int
-lwpoint_getPoint3dz_p(const LWPOINT *point, POINT3DZ *out)
-{
-	return getPoint3dz_p(point->point,0,out);
-}
-int
-lwpoint_getPoint3dm_p(const LWPOINT *point, POINT3DM *out)
-{
-	return getPoint3dm_p(point->point,0,out);
-}
-int
-lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
-{
-	return getPoint4d_p(point->point,0,out);
-}
-
-/* find length of this deserialized point */
-size_t
-lwpoint_serialize_size(LWPOINT *point)
-{
-	size_t size = 1; /* type */
-
-	LWDEBUG(2, "lwpoint_serialize_size called");
-
-	if ( point->SRID != -1 ) size += 4; /* SRID */
-	if ( point->bbox ) size += sizeof(BOX2DFLOAT4);
-
-	size += TYPE_NDIMS(point->type) * sizeof(double); /* point */
-
-	LWDEBUGF(3, "lwpoint_serialize_size returning %d", size);
-
-	return size; 
-}
-
-/*
- * Construct a new point.  point will not be copied
- * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
- */
-LWPOINT *
-lwpoint_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *point)
-{
-	LWPOINT *result ;
-
-	if (point == NULL)
-		return NULL; /* error */
-
-	result = lwalloc(sizeof(LWPOINT));
-	result->type = lwgeom_makeType_full(TYPE_HASZ(point->dims), TYPE_HASM(point->dims), (SRID!=-1), POINTTYPE, 0);
-	result->SRID = SRID;
-	result->point = point;
-	result->bbox = bbox;
-
-	return result;
-}
-
-LWPOINT *
-make_lwpoint2d(int SRID, double x, double y)
-{
-	POINT2D p;
-	POINTARRAY *pa = ptarray_construct(0, 0, 1);
-
-	p.x = x;
-	p.y = y;
-
-	memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT2D));
-
-	return lwpoint_construct(SRID, NULL, pa);
-}
-
-LWPOINT *
-make_lwpoint3dz(int SRID, double x, double y, double z)
-{
-	POINT3DZ p;
-	POINTARRAY *pa = ptarray_construct(1, 0, 1);
-
-	p.x = x;
-	p.y = y;
-	p.z = z;
-
-	memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT3DZ));
-
-	return lwpoint_construct(SRID, NULL, pa);
-}
-
-LWPOINT *
-make_lwpoint3dm(int SRID, double x, double y, double m)
-{
-	POINTARRAY *pa = ptarray_construct(0, 1, 1);
-	POINT3DM p;
-
-	p.x = x;
-	p.y = y;
-	p.m = m;
-
-	memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT3DM));
-
-	return lwpoint_construct(SRID, NULL, pa);
-}
-
-LWPOINT *
-make_lwpoint4d(int SRID, double x, double y, double z, double m)
-{
-	POINTARRAY *pa = ptarray_construct(1, 1, 1);
-	POINT4D p;
-	
-	p.x = x;
-	p.y = y;
-	p.z = z;
-	p.m = m;
-
-	memcpy(getPoint_internal(pa, 0), &p, sizeof(POINT4D));
-
-	return lwpoint_construct(SRID, NULL, pa);
-}
-
-/*
- * Given the LWPOINT serialized form (or a pointer into a muli* one)
- * construct a proper LWPOINT.
- * serialized_form should point to the 8bit type format (with type = 1)
- * See serialized form doc
- */
-LWPOINT *
-lwpoint_deserialize(uchar *serialized_form)
-{
-	uchar type;
-	int geom_type;
-	LWPOINT *result;
-	uchar *loc = NULL;
-	POINTARRAY *pa;
-
-	LWDEBUG(2, "lwpoint_deserialize called");
-
-	result = (LWPOINT*) lwalloc(sizeof(LWPOINT)) ;
-
-	type = serialized_form[0];
-	geom_type = lwgeom_getType(type);
-
-	if ( geom_type != POINTTYPE)
-	{
-		lwerror("lwpoint_deserialize: attempt to deserialize a point which is really a %s", lwgeom_typename(geom_type));
-		return NULL;
-	}
-	result->type = type;
-
-	loc = serialized_form+1;
-
-	if (lwgeom_hasBBOX(type))
-	{
-		LWDEBUG(3, "lwpoint_deserialize: input has bbox");
-
-		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-		memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
-		loc += sizeof(BOX2DFLOAT4);
-	}
-	else
-	{
-		result->bbox = NULL;
-	}
-
-	if ( lwgeom_hasSRID(type))
-	{
-		LWDEBUG(3, "lwpoint_deserialize: input has SRID");
-
-		result->SRID = lw_get_int32(loc);
-		loc += 4; /* type + SRID */
-	}
-	else
-	{
-		result->SRID = -1;
-	}
-
-	/* we've read the type (1 byte) and SRID (4 bytes, if present) */
-
-	pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), 1);
-
-	result->point = pa;
-
-	return result;
-}
-
-void pfree_point    (LWPOINT *pt)
-{
-	pfree_POINTARRAY(pt->point);
-	lwfree(pt);
-}
-
-void printLWPOINT(LWPOINT *point)
-{
-	lwnotice("LWPOINT {");
-	lwnotice("    ndims = %i", (int)TYPE_NDIMS(point->type));
-	lwnotice("    BBOX = %i", TYPE_HASBBOX(point->type) ? 1 : 0 );
-	lwnotice("    SRID = %i", (int)point->SRID);
-	printPA(point->point);
-	lwnotice("}");
-}
-
-int
-lwpoint_compute_box2d_p(LWPOINT *point, BOX2DFLOAT4 *box)
-{
-	return ptarray_compute_box2d_p(point->point, box);
-}
-
-/* Clone LWPOINT object. POINTARRAY is not copied. */
-LWPOINT *
-lwpoint_clone(const LWPOINT *g)
-{
-	LWPOINT *ret = lwalloc(sizeof(LWPOINT));
-
-	LWDEBUG(2, "lwpoint_clone called");
-
-	memcpy(ret, g, sizeof(LWPOINT));
-	if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
-	return ret;
-}
-
-/*
- * Add 'what' to this point at position 'where'.
- * where=0 == prepend
- * where=-1 == append
- * Returns a MULTIPOINT or a GEOMETRYCOLLECTION
- */
-LWGEOM *
-lwpoint_add(const LWPOINT *to, uint32 where, const LWGEOM *what)
-{
-	LWCOLLECTION *col;
-	LWGEOM **geoms;
-	int newtype;
-
-	if ( where != -1 && where != 0 )
-	{
-		lwerror("lwpoint_add only supports 0 or -1 as second argument, got %d", where);
-		return NULL;
-	}
-
-	/* dimensions compatibility are checked by caller */
-
-
-	/* Construct geoms array */
-	geoms = lwalloc(sizeof(LWGEOM *)*2);
-	if ( where == -1 ) /* append */
-	{
-		geoms[0] = lwgeom_clone((LWGEOM *)to);
-		geoms[1] = lwgeom_clone(what);
-	}
-	else /* prepend */
-	{
-		geoms[0] = lwgeom_clone(what);
-		geoms[1] = lwgeom_clone((LWGEOM *)to);
-	}
-	/* reset SRID and wantbbox flag from component types */
-	lwgeom_dropSRID(geoms[0]);
-	lwgeom_dropBBOX(geoms[0]);
-	lwgeom_dropSRID(geoms[1]);
-	lwgeom_dropBBOX(geoms[1]);
-
-	/* Find appropriate geom type */
-	if ( TYPE_GETTYPE(what->type) == POINTTYPE ) newtype = MULTIPOINTTYPE;
-	else newtype = COLLECTIONTYPE;
-
-	col = lwcollection_construct(newtype,
-		to->SRID, NULL,
-		2, geoms);
-	
-	return (LWGEOM *)col;
-}
-
-/* Find length of this serialized point */
-size_t
-lwgeom_size_point(const uchar *serialized_point)
-{
-	uint32  result = 1;
-	uchar type;
-	const uchar *loc;
-
-	type = serialized_point[0];
-
-	if ( lwgeom_getType(type) != POINTTYPE) return 0;
-
-	LWDEBUGF(2, "lwgeom_size_point called (%d)", result);
-
-	loc = serialized_point+1;
-
-	if (lwgeom_hasBBOX(type))
-	{
-		loc += sizeof(BOX2DFLOAT4);
-		result +=sizeof(BOX2DFLOAT4);
-
-		LWDEBUGF(3, "lwgeom_size_point: has bbox (%d)", result);
-	}
-
-	if ( lwgeom_hasSRID(type))
-	{
-		LWDEBUGF(3, "lwgeom_size_point: has srid (%d)", result);
-
-		loc +=4; /* type + SRID */
-		result +=4;
-	}
-
-	result += lwgeom_ndims(type)*sizeof(double);
-
-	return result;
-}
-
-/* check coordinate equality  */
-char
-lwpoint_same(const LWPOINT *p1, const LWPOINT *p2)
-{
-	return ptarray_same(p1->point, p2->point);
-}

Deleted: trunk/lwgeom/lwpoly.c
===================================================================
--- trunk/lwgeom/lwpoly.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/lwpoly.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,567 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-/* basic LWPOLY manipulation */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "liblwgeom.h"
-
-
-#define CHECK_POLY_RINGS_ZM 1
-
-/* construct a new LWPOLY.  arrays (points/points per ring) will NOT be copied
- * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
- */
-LWPOLY *
-lwpoly_construct(int SRID, BOX2DFLOAT4 *bbox, unsigned int nrings, POINTARRAY **points)
-{
-	LWPOLY *result;
-	int hasz, hasm;
-#ifdef CHECK_POLY_RINGS_ZM
-	char zm;
-	unsigned int i;
-#endif
-
-	if ( nrings < 1 ) lwerror("lwpoly_construct: need at least 1 ring");
-
-	hasz = TYPE_HASZ(points[0]->dims);
-	hasm = TYPE_HASM(points[0]->dims);
-
-#ifdef CHECK_POLY_RINGS_ZM
-	zm = TYPE_GETZM(points[0]->dims);
-	for (i=1; i<nrings; i++)
-	{
-		if ( zm != TYPE_GETZM(points[i]->dims) )
-			lwerror("lwpoly_construct: mixed dimensioned rings");
-	}
-#endif
-
-	result = (LWPOLY*) lwalloc(sizeof(LWPOLY));
-	result->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1), POLYGONTYPE,
-		0);
-	result->SRID = SRID;
-	result->nrings = nrings;
-	result->rings = points;
-	result->bbox = bbox;
-
-	return result;
-}
-
-
-/*
- * given the LWPOLY serialized form (or a pointer into a muli* one)
- * construct a proper LWPOLY.
- * serialized_form should point to the 8bit type format (with type = 3)
- * See serialized form doc
- */
-LWPOLY *
-lwpoly_deserialize(uchar *serialized_form)
-{
-
-	LWPOLY *result;
-	uint32 nrings;
-	int ndims, hasz, hasm;
-	uint32 npoints;
-	uchar type;
-	uchar *loc;
-	int t;
-
-	if (serialized_form == NULL)
-	{
-		lwerror("lwpoly_deserialize called with NULL arg");
-		return NULL;
-	}
-
-	result = (LWPOLY*) lwalloc(sizeof(LWPOLY));
-
-	type = serialized_form[0];
-	result->type = type;
-
-	ndims = TYPE_NDIMS(type);
-	hasz = TYPE_HASZ(type);
-	hasm = TYPE_HASM(type);
-	loc = serialized_form;
-
-	if ( TYPE_GETTYPE(type) != POLYGONTYPE)
-	{
-		lwerror("lwpoly_deserialize: attempt to deserialize a poly which is really a %s", lwgeom_typename(type));
-		return NULL;
-	}
-
-
-	loc = serialized_form+1;
-
-	if (lwgeom_hasBBOX(type)) {
-		LWDEBUG(3, "lwpoly_deserialize: input has bbox");
-
-		result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
-		memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
-		loc += sizeof(BOX2DFLOAT4);
-	} else {
-		result->bbox = NULL;
-	}
-
-	if ( lwgeom_hasSRID(type))
-	{
-		result->SRID = lw_get_int32(loc);
-		loc +=4; /* type + SRID */
-	}
-	else
-	{
-		result->SRID = -1;
-	}
-
-	nrings = lw_get_uint32(loc);
-	result->nrings = nrings;
-	loc +=4;
-	result->rings = (POINTARRAY**) lwalloc(nrings* sizeof(POINTARRAY*));
-
-	for (t =0;t<nrings;t++)
-	{
-		/* read in a single ring and make a PA */
-		npoints = lw_get_uint32(loc);
-		loc +=4;
-
-		result->rings[t] = pointArray_construct(loc, hasz, hasm, npoints);
-		loc += sizeof(double)*ndims*npoints;
-	}
-
-	return result;
-}
-
-/*
- * create the serialized form of the polygon
- * result's first char will be the 8bit type.  See serialized form doc
- * points copied
- */
-uchar *
-lwpoly_serialize(LWPOLY *poly)
-{
-	size_t size, retsize;
-	uchar *result;
-
-	size = lwpoly_serialize_size(poly);
-	result = lwalloc(size);
-	lwpoly_serialize_buf(poly, result, &retsize);
-	
-	if ( retsize != size )
-	{
-		lwerror("lwpoly_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
-	}
-
-	return result;
-}
-
-/*
- * create the serialized form of the polygon writing it into the
- * given buffer, and returning number of bytes written into
- * the given int pointer.
- * result's first char will be the 8bit type.  See serialized form doc
- * points copied
- */
-void
-lwpoly_serialize_buf(LWPOLY *poly, uchar *buf, size_t *retsize)
-{
-	size_t size=1;  /* type byte */
-	char hasSRID;
-	int t;
-	uchar *loc;
-	int ptsize;
-
-	LWDEBUG(2, "lwpoly_serialize_buf called");
-
-	ptsize = sizeof(double)*TYPE_NDIMS(poly->type);
-
-	hasSRID = (poly->SRID != -1);
-
-	size += 4; /* nrings */
-	size += 4*poly->nrings; /* npoints/ring */
-
-	buf[0] = (uchar) lwgeom_makeType_full(
-		TYPE_HASZ(poly->type), TYPE_HASM(poly->type),
-		hasSRID, POLYGONTYPE, poly->bbox ? 1 : 0);
-	loc = buf+1;
-
-	if (poly->bbox)
-	{
-		memcpy(loc, poly->bbox, sizeof(BOX2DFLOAT4));
-		size += sizeof(BOX2DFLOAT4); /* bvol */
-		loc += sizeof(BOX2DFLOAT4);
-	}
-
-	if (hasSRID)
-	{
-		memcpy(loc, &poly->SRID, sizeof(int32));
-		loc += 4;
-		size +=4;  /* 4 byte SRID */
-	}
-
-	memcpy(loc, &poly->nrings, sizeof(int32));  /* nrings */
-	loc+=4;
-
-	for (t=0;t<poly->nrings;t++)
-	{
-		POINTARRAY *pa = poly->rings[t];
-		size_t pasize;
-		uint32 npoints;
-
-		if ( TYPE_GETZM(poly->type) != TYPE_GETZM(pa->dims) )
-			lwerror("Dimensions mismatch in lwpoly");
-
-		npoints = pa->npoints;
-
-		memcpy(loc, &npoints, sizeof(uint32)); /* npoints this ring */
-		loc+=4;
-
-		pasize = npoints*ptsize;
-		size += pasize;
-
-		/* copy points */
-		memcpy(loc, getPoint_internal(pa, 0), pasize);
-		loc += pasize;
-
-	}
-
-	if (retsize) *retsize = size;
-}
-
-
-/* find bounding box (standard one)  zmin=zmax=0 if 2d (might change to NaN) */
-BOX3D *
-lwpoly_compute_box3d(LWPOLY *poly)
-{
-	BOX3D *result;
-
-	/* just need to check outer ring -- interior rings are inside */
-	POINTARRAY *pa = poly->rings[0];  
-	result  = ptarray_compute_box3d(pa);
-
-	return result;
-}
-
-/* find length of this serialized polygon */
-size_t
-lwgeom_size_poly(const uchar *serialized_poly)
-{
-	uint32 result = 1; /* char type */
-	uint32 nrings;
-	int ndims;
-	int t;
-	uchar type;
-	uint32 npoints;
-	const uchar *loc;
-
-	if (serialized_poly == NULL)
-		return -9999;
-
-
-	type = (uchar) serialized_poly[0];
-	ndims = lwgeom_ndims(type);
-
-	if ( lwgeom_getType(type) != POLYGONTYPE)
-		return -9999;
-
-
-	loc = serialized_poly+1;
-
-	if (lwgeom_hasBBOX(type))
-	{
-		LWDEBUG(3, "lwgeom_size_poly: has bbox");
-
-		loc += sizeof(BOX2DFLOAT4);
-		result +=sizeof(BOX2DFLOAT4);
-	}
-
-
-	if ( lwgeom_hasSRID(type))
-	{
-		LWDEBUG(3, "lwgeom_size_poly: has srid");
-
-		loc +=4; /* type + SRID */
-		result += 4;
-	}
-
-
-	nrings = lw_get_uint32(loc);
-	loc +=4;
-	result +=4;
-
-        LWDEBUGF(3, "lwgeom_size_poly contains %d rings", nrings);
-
-	for (t =0;t<nrings;t++)
-	{
-		/* read in a single ring and make a PA */
-		npoints = lw_get_uint32(loc);
-		loc += 4;
-		result += 4;
-
-		if (ndims == 3)
-		{
-			loc += 24*npoints;
-			result += 24*npoints;
-		}
-		else if (ndims == 2)
-		{
-			loc += 16*npoints;
-			result += 16*npoints;
-		}
-		else if (ndims == 4)
-		{
-			loc += 32*npoints;
-			result += 32*npoints;
-		}
-	}
-
-        LWDEBUGF(3, "lwgeom_size_poly returning %d", result);
-
-	return result;
-}
-
-/* find length of this deserialized polygon */
-size_t
-lwpoly_serialize_size(LWPOLY *poly)
-{
-	size_t size = 1; /* type */
-	uint32 i;
-
-	if ( poly->SRID != -1 ) size += 4; /* SRID */
-	if ( poly->bbox ) size += sizeof(BOX2DFLOAT4);
-
-	LWDEBUGF(2, "lwpoly_serialize_size called with poly[%p] (%d rings)",
-			poly, poly->nrings);
-
-	size += 4; /* nrings */
-
-	for (i=0; i<poly->nrings; i++)
-	{
-		size += 4; /* npoints */
-		size += poly->rings[i]->npoints*TYPE_NDIMS(poly->type)*sizeof(double);
-	}
-
-	LWDEBUGF(3, "lwpoly_serialize_size returning %d", size);
-
-	return size;
-}
-
-void pfree_polygon  (LWPOLY  *poly)
-{
-	int t;
-
-	for (t=0;t<poly->nrings;t++)
-	{
-		pfree_POINTARRAY(poly->rings[t]);
-	}
-
-	lwfree(poly);
-}
-
-void printLWPOLY(LWPOLY *poly)
-{
-	int t;
-	lwnotice("LWPOLY {");
-	lwnotice("    ndims = %i", (int)TYPE_NDIMS(poly->type));
-	lwnotice("    SRID = %i", (int)poly->SRID);
-	lwnotice("    nrings = %i", (int)poly->nrings);
-	for (t=0;t<poly->nrings;t++)
-	{
-		lwnotice("    RING # %i :",t);
-		printPA(poly->rings[t]);
-	}
-	lwnotice("}");
-}
-
-int
-lwpoly_compute_box2d_p(LWPOLY *poly, BOX2DFLOAT4 *box)
-{
-	BOX2DFLOAT4 boxbuf;
-	uint32 i;
-
-	if ( ! poly->nrings ) return 0;
-	if ( ! ptarray_compute_box2d_p(poly->rings[0], box) ) return 0;
-	for (i=1; i<poly->nrings; i++)
-	{
-		if ( ! ptarray_compute_box2d_p(poly->rings[0], &boxbuf) )
-			return 0;
-		if ( ! box2d_union_p(box, &boxbuf, box) )
-			return 0;
-	}
-	return 1;
-}
-
-/* Clone LWLINE object. POINTARRAY are not copied, it's ring array is. */
-LWPOLY *
-lwpoly_clone(const LWPOLY *g)
-{
-	LWPOLY *ret = lwalloc(sizeof(LWPOLY));
-	memcpy(ret, g, sizeof(LWPOLY));
-	ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
-	memcpy(ret->rings, g->rings, sizeof(POINTARRAY *)*g->nrings);
-	if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
-	return ret;
-}
-
-/*
- * Add 'what' to this poly at position 'where'.
- * where=0 == prepend
- * where=-1 == append
- * Returns a MULTIPOLYGON or a GEOMETRYCOLLECTION
- */
-LWGEOM *
-lwpoly_add(const LWPOLY *to, uint32 where, const LWGEOM *what)
-{
-	LWCOLLECTION *col;
-	LWGEOM **geoms;
-	int newtype;
-
-	if ( where != -1 && where != 0 )
-	{
-		lwerror("lwpoly_add only supports 0 or -1 as second argument, got %d", where);
-		return NULL;
-	}
-
-	/* dimensions compatibility are checked by caller */
-
-	/* Construct geoms array */
-	geoms = lwalloc(sizeof(LWGEOM *)*2);
-	if ( where == -1 ) /* append */
-	{
-		geoms[0] = lwgeom_clone((LWGEOM *)to);
-		geoms[1] = lwgeom_clone(what);
-	}
-	else /* prepend */
-	{
-		geoms[0] = lwgeom_clone(what);
-		geoms[1] = lwgeom_clone((LWGEOM *)to);
-	}
-
-	/* reset SRID and wantbbox flag from component types */
-	geoms[0]->SRID = geoms[1]->SRID = -1;
-	TYPE_SETHASSRID(geoms[0]->type, 0);
-	TYPE_SETHASSRID(geoms[1]->type, 0);
-	TYPE_SETHASBBOX(geoms[0]->type, 0);
-	TYPE_SETHASBBOX(geoms[1]->type, 0);
-
-	/* Find appropriate geom type */
-	if ( TYPE_GETTYPE(what->type) == POLYGONTYPE ) newtype = MULTIPOLYGONTYPE;
-	else newtype = COLLECTIONTYPE;
-
-	col = lwcollection_construct(newtype,
-		to->SRID, NULL,
-		2, geoms);
-	
-	return (LWGEOM *)col;
-}
-
-void
-lwpoly_forceRHR(LWPOLY *poly)
-{
-	int i;
-
-	if ( ptarray_isccw(poly->rings[0]) )
-	{
-		ptarray_reverse(poly->rings[0]);
-	}
-
-	for (i=1; i<poly->nrings; i++)
-	{
-		if ( ! ptarray_isccw(poly->rings[i]) )
-		{
-			ptarray_reverse(poly->rings[i]);
-		}
-	}
-}
-
-
-void
-lwpoly_reverse(LWPOLY *poly)
-{
-	int i;
-
-	for (i=0; i<poly->nrings; i++)
-		ptarray_reverse(poly->rings[i]);
-}
-
-LWPOLY *
-lwpoly_segmentize2d(LWPOLY *poly, double dist)
-{
-	POINTARRAY **newrings;
-	unsigned int i;
-	
-	newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
-	for (i=0; i<poly->nrings; i++)
-	{
-		newrings[i] = ptarray_segmentize2d(poly->rings[i], dist);
-	}
-	return lwpoly_construct(poly->SRID, NULL,
-		poly->nrings, newrings);
-}
-
-/*
- * check coordinate equality 
- * ring and coordinate order is considered
- */
-char
-lwpoly_same(const LWPOLY *p1, const LWPOLY *p2)
-{
-	unsigned int i;
-
-	if ( p1->nrings != p2->nrings ) return 0;
-	for (i=0; i<p1->nrings; i++)
-	{
-		if ( ! ptarray_same(p1->rings[i], p2->rings[i]) )
-			return 0;
-	}
-	return 1;
-}
-
-/*
- * Construct a polygon from a LWLINE being
- * the shell and an array of LWLINE (possibly NULL) being holes.
- * Pointarrays from intput geoms are cloned.
- * SRID must be the same for each input line.
- * Input lines must have at least 4 points, and be closed.
- */
-LWPOLY *
-lwpoly_from_lwlines(const LWLINE *shell,
-	unsigned int nholes, const LWLINE **holes)
-{
-	unsigned int nrings;
-	POINTARRAY **rings = lwalloc((nholes+1)*sizeof(POINTARRAY *));
-	int SRID = shell->SRID;
-	LWPOLY *ret;
-
-	if ( shell->points->npoints < 4 )
-		lwerror("lwpoly_from_lwlines: shell must have at least 4 points");
-	if ( ! ptarray_isclosed2d(shell->points) )
-		lwerror("lwpoly_from_lwlines: shell must be closed");
-	rings[0] = ptarray_clone(shell->points);
-
-	for (nrings=1; nrings<=nholes; nrings++)
-	{
-		const LWLINE *hole = holes[nrings-1];
-
-		if ( hole->SRID != SRID )
-			lwerror("lwpoly_from_lwlines: mixed SRIDs in input lines");
-
-		if ( hole->points->npoints < 4 )
-			lwerror("lwpoly_from_lwlines: holes must have at least 4 points");
-		if ( ! ptarray_isclosed2d(hole->points) )
-			lwerror("lwpoly_from_lwlines: holes must be closed");
-
-		rings[nrings] = ptarray_clone(hole->points);
-	}
-
-	ret = lwpoly_construct(SRID, NULL, nrings, rings);
-	return ret;
-}

Deleted: trunk/lwgeom/measures.c
===================================================================
--- trunk/lwgeom/measures.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/measures.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,845 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-#include <math.h>
-#include <string.h>
-
-#include "liblwgeom.h"
-
-
-/*
- * pt_in_ring_2d(): crossing number test for a point in a polygon
- *      input:   p = a point,
- *               pa = vertex points of a ring V[n+1] with V[n]=V[0]
- *      returns: 0 = outside, 1 = inside
- *
- *	Our polygons have first and last point the same,
- *
- */
-int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring)
-{
-	int cn = 0;    /* the crossing number counter */
-	int i;
-	POINT2D v1, v2;
-
-#if INTEGRITY_CHECKS
-	POINT2D first, last;
-
-	getPoint2d_p(ring, 0, &first);
-	getPoint2d_p(ring, ring->npoints-1, &last);
-	if ( memcmp(&first, &last, sizeof(POINT2D)) )
-	{
-		lwerror("pt_in_ring_2d: V[n] != V[0] (%g %g != %g %g)",
-			first.x, first.y, last.x, last.y);
-			
-	}
-#endif
-
-	LWDEBUGF(2, "pt_in_ring_2d called with point: %g %g", p->x, p->y);
-	/* printPA(ring); */
-
-	/* loop through all edges of the polygon */
-	getPoint2d_p(ring, 0, &v1);
-    	for (i=0; i<ring->npoints-1; i++)
-	{   
-		double vt;
-		getPoint2d_p(ring, i+1, &v2);
-
-		/* edge from vertex i to vertex i+1 */
-       		if
-		(
-			/* an upward crossing */
-			((v1.y <= p->y) && (v2.y > p->y))
-			/* a downward crossing */
-       		 	|| ((v1.y > p->y) && (v2.y <= p->y))
-		)
-	 	{
-
-			vt = (double)(p->y - v1.y) / (v2.y - v1.y);
-
-			/* P.x <intersect */
-			if (p->x < v1.x + vt * (v2.x - v1.x))
-			{
-				/* a valid crossing of y=p.y right of p.x */
-           	     		++cn;
-			}
-		}
-		v1 = v2;
-	}
-
-	LWDEBUGF(3, "pt_in_ring_2d returning %d", cn&1);
-
-	return (cn&1);    /* 0 if even (out), and 1 if odd (in) */
-}
-
-double distance2d_pt_pt(POINT2D *p1, POINT2D *p2)
-{
-	double hside = p2->x - p1->x;
-	double vside = p2->y - p1->y;
-
-	return sqrt ( hside*hside + vside*vside );
-
-	/* the above is more readable
-	   return sqrt(
-	  	(p2->x-p1->x) * (p2->x-p1->x) + (p2->y-p1->y) * (p2->y-p1->y)
-		);  */
-}
-
-/*distance2d from p to line A->B */
-double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B)
-{
-	double	r,s;
-
-	/*if start==end, then use pt distance */
-	if (  ( A->x == B->x) && (A->y == B->y) )
-		return distance2d_pt_pt(p,A);
-
-	/*
-	 * otherwise, we use comp.graphics.algorithms
-	 * Frequently Asked Questions method
-	 *
-	 *  (1)     	      AC dot AB
-         *         r = ---------
-         *               ||AB||^2
-	 *	r has the following meaning:
-	 *	r=0 P = A
-	 *	r=1 P = B
-	 *	r<0 P is on the backward extension of AB
-	 *	r>1 P is on the forward extension of AB
-	 *	0<r<1 P is interior to AB
-	 */
-
-	r = ( (p->x-A->x) * (B->x-A->x) + (p->y-A->y) * (B->y-A->y) )/( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
-
-	if (r<0) return distance2d_pt_pt(p,A);
-	if (r>1) return distance2d_pt_pt(p,B);
-
-
-	/*
-	 * (2)
-	 *	     (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
-	 *	s = -----------------------------
-	 *	             	L^2
-	 *
-	 *	Then the distance from C to P = |s|*L.
-	 *
-	 */
-
-	s = ( (A->y-p->y)*(B->x-A->x)- (A->x-p->x)*(B->y-A->y) ) /
-		( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
-
-	return LW_ABS(s) * sqrt(
-		(B->x-A->x)*(B->x-A->x) + (B->y-A->y)*(B->y-A->y)
-		);
-}
-
-/* find the minimum 2d distance from AB to CD */
-double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D)
-{
-
-	double	s_top, s_bot,s;
-	double	r_top, r_bot,r;
-
-	LWDEBUGF(2, "distance2d_seg_seg [%g,%g]->[%g,%g] by [%g,%g]->[%g,%g]",
-		A->x,A->y,B->x,B->y, C->x,C->y, D->x, D->y);
-
-
-	/*A and B are the same point */
-	if (  ( A->x == B->x) && (A->y == B->y) )
-		return distance2d_pt_seg(A,C,D);
-
-		/*U and V are the same point */
-
-	if (  ( C->x == D->x) && (C->y == D->y) )
-		return distance2d_pt_seg(D,A,B);
-
-	/* AB and CD are line segments */
-	/* from comp.graphics.algo
-
-	Solving the above for r and s yields
-				(Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy)
-	           r = ----------------------------- (eqn 1)
-				(Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
-
-		 	(Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
-		s = ----------------------------- (eqn 2)
-			(Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
-	Let P be the position vector of the intersection point, then
-		P=A+r(B-A) or
-		Px=Ax+r(Bx-Ax)
-		Py=Ay+r(By-Ay)
-	By examining the values of r & s, you can also determine some other limiting conditions:
-		If 0<=r<=1 & 0<=s<=1, intersection exists
-		r<0 or r>1 or s<0 or s>1 line segments do not intersect
-		If the denominator in eqn 1 is zero, AB & CD are parallel
-		If the numerator in eqn 1 is also zero, AB & CD are collinear.
-
-	*/
-	r_top = (A->y-C->y)*(D->x-C->x) - (A->x-C->x)*(D->y-C->y) ;
-	r_bot = (B->x-A->x)*(D->y-C->y) - (B->y-A->y)*(D->x-C->x) ;
-
-	s_top = (A->y-C->y)*(B->x-A->x) - (A->x-C->x)*(B->y-A->y);
-	s_bot = (B->x-A->x)*(D->y-C->y) - (B->y-A->y)*(D->x-C->x);
-
-	if  ( (r_bot==0) || (s_bot == 0) )
-	{
-		return (
-			LW_MIN(distance2d_pt_seg(A,C,D),
-				LW_MIN(distance2d_pt_seg(B,C,D),
-					LW_MIN(distance2d_pt_seg(C,A,B),
-						distance2d_pt_seg(D,A,B))
-				)
-			)
-		);
-	}
-	s = s_top/s_bot;
-	r=  r_top/r_bot;
-
-	if ((r<0) || (r>1) || (s<0) || (s>1) )
-	{
-		/*no intersection */
-		return (
-			LW_MIN(distance2d_pt_seg(A,C,D),
-				LW_MIN(distance2d_pt_seg(B,C,D),
-					LW_MIN(distance2d_pt_seg(C,A,B),
-						distance2d_pt_seg(D,A,B))
-				)
-			)
-		);
-
-	}
-	else
-		return -0; /*intersection exists */
-
-}
-
-/*
- * search all the segments of pointarray to see which one is closest to p1
- * Returns minimum distance between point and pointarray
- */
-double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa)
-{
-	double result = 0;
-	int t;
-	POINT2D	start, end;
-
-	getPoint2d_p(pa, 0, &start);
-
-	for (t=1; t<pa->npoints; t++)
-	{
-		double dist;
-		getPoint2d_p(pa, t, &end);
-		dist = distance2d_pt_seg(p, &start, &end);
-		if (t==1) result = dist;
-		else result = LW_MIN(result, dist);
-
-		if ( result == 0 ) return 0;
-
-		start = end;
-	}
-
-	return result;
-}
-
-/* test each segment of l1 against each segment of l2.  Return min */
-double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2)
-{
-	double 	result = 99999999999.9;
-	char result_okay = 0; /*result is a valid min */
-	int t,u;
-	POINT2D	start, end;
-	POINT2D	start2, end2;
-
-	LWDEBUGF(2, "distance2d_ptarray_ptarray called (points: %d-%d)",
-			l1->npoints, l2->npoints);
-
-	getPoint2d_p(l1, 0, &start);
-	for (t=1; t<l1->npoints; t++) /*for each segment in L1 */
-	{
-		getPoint2d_p(l1, t, &end);
-
-		getPoint2d_p(l2, 0, &start2);
-		for (u=1; u<l2->npoints; u++) /*for each segment in L2 */
-		{
-			double dist;
-
-			getPoint2d_p(l2, u, &end2);
-
-			dist = distance2d_seg_seg(&start, &end, &start2, &end2);
-
-			LWDEBUGF(4, "line_line; seg %i * seg %i, dist = %g\n",t,u,dist);
-
-			if (result_okay)
-				result = LW_MIN(result,dist);
-			else
-			{
-				result_okay = 1;
-				result = dist;
-			}
-
-			LWDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f",
-				t, u, dist, result);
-
-			if (result <= 0) return 0; /*intersection */
-
-			start2 = end2;
-		}
-		start = end;
-	}
-
-	return result;
-}
-
-/* true if point is in poly (and not in its holes) */
-int pt_in_poly_2d(POINT2D *p, LWPOLY *poly)
-{
-	int i;
-
-	/* Not in outer ring */
-	if ( ! pt_in_ring_2d(p, poly->rings[0]) ) return 0;
-
-	/* Check holes */
-	for (i=1; i<poly->nrings; i++)
-	{
-		/* Inside a hole */
-		if ( pt_in_ring_2d(p, poly->rings[i]) ) return 0;
-	}
-
-	return 1; /* In outer ring, not in holes */
-}
-
-/*
- * Brute force.
- * Test line-ring distance against each ring.
- * If there's an intersection (distance==0) then return 0 (crosses boundary).
- * Otherwise, test to see if any point is inside outer rings of polygon,
- * but not in inner rings.
- * If so, return 0  (line inside polygon),
- * otherwise return min distance to a ring (could be outside
- * polygon or inside a hole)
- */
-double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly)
-{
-	POINT2D pt;
-	int i;
-	double mindist = 0;
-
-	LWDEBUGF(2, "distance2d_ptarray_poly called (%d rings)", poly->nrings);
-
-	for (i=0; i<poly->nrings; i++)
-	{
-		double dist = distance2d_ptarray_ptarray(pa, poly->rings[i]);
-		if (i) mindist = LW_MIN(mindist, dist);
-		else mindist = dist;
-
-		LWDEBUGF(3, " distance from ring %d: %f, mindist: %f",
-			i, dist, mindist);
-
-		if ( mindist <= 0 ) return 0.0; /* intersection */
-	}
-
-	/*
-	 * No intersection, have to check if a point is
-	 * inside polygon
-	 */
-	getPoint2d_p(pa, 0, &pt);
-
-	/*
-	 * Outside outer ring, so min distance to a ring
-	 * is the actual min distance
-	 */
-	if ( ! pt_in_ring_2d(&pt, poly->rings[0]) ) return mindist;
-
-
-	/*
-	 * Its in the outer ring.
-	 * Have to check if its inside a hole
-	 */
-	for (i=1; i<poly->nrings; i++)
-	{
-		if ( pt_in_ring_2d(&pt, poly->rings[i]) )
-		{
-			/*
-			 * Its inside a hole, then the actual
-			 * distance is the min ring distance
-			 */
-			return mindist;
-		}
-	}
-
-	return 0.0; /* Not in hole, so inside polygon */
-}
-
-double distance2d_point_point(LWPOINT *point1, LWPOINT *point2)
-{
-	POINT2D p1;
-	POINT2D p2;
-
-	getPoint2d_p(point1->point, 0, &p1);
-	getPoint2d_p(point2->point, 0, &p2);
-
-	return distance2d_pt_pt(&p1, &p2);
-}
-
-double distance2d_point_line(LWPOINT *point, LWLINE *line)
-{
-	POINT2D p;
-	POINTARRAY *pa = line->points;
-	getPoint2d_p(point->point, 0, &p);
-	return distance2d_pt_ptarray(&p, pa);
-}
-
-double distance2d_line_line(LWLINE *line1, LWLINE *line2)
-{
-	POINTARRAY *pa1 = line1->points;
-	POINTARRAY *pa2 = line2->points;
-	return distance2d_ptarray_ptarray(pa1, pa2);
-}
-
-/*
- * 1. see if pt in outer boundary. if no, then treat the outer ring like a line
- * 2. if in the boundary, test to see if its in a hole.
- *    if so, then return dist to hole, else return 0 (point in polygon)
- */
-double distance2d_point_poly(LWPOINT *point, LWPOLY *poly)
-{
-	POINT2D p;
-	int i;
-
-	getPoint2d_p(point->point, 0, &p);
-
-	LWDEBUG(2, "distance2d_point_poly called");
-
-	/* Return distance to outer ring if not inside it */
-	if ( ! pt_in_ring_2d(&p, poly->rings[0]) )
-	{
-		LWDEBUG(3, " not inside outer-ring");
-
-		return distance2d_pt_ptarray(&p, poly->rings[0]);
-	}
-
-	/*
-	 * Inside the outer ring.
-	 * Scan though each of the inner rings looking to
-	 * see if its inside.  If not, distance==0.
-	 * Otherwise, distance = pt to ring distance
-	 */
-	for (i=1; i<poly->nrings; i++) 
-	{
-		/* Inside a hole. Distance = pt -> ring */
-		if ( pt_in_ring_2d(&p, poly->rings[i]) )
-		{
-			LWDEBUG(3, " inside an hole");
-
-			return distance2d_pt_ptarray(&p, poly->rings[i]);
-		}
-	}
-
-	LWDEBUG(3, " inside the polygon");
-
-	return 0.0; /* Is inside the polygon */
-}
-
-/*
- * Brute force.
- * Test to see if any rings intersect.
- * If yes, dist=0.
- * Test to see if one inside the other and if they are inside holes.
- * Find min distance ring-to-ring.
- */
-double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2)
-{
-	POINT2D pt;
-	double mindist = -1;
-	int i;
-
-	LWDEBUG(2, "distance2d_poly_poly called");
-
-	/* if poly1 inside poly2 return 0 */
-	getPoint2d_p(poly1->rings[0], 0, &pt);
-	if ( pt_in_poly_2d(&pt, poly2) ) return 0.0;  
-
-	/* if poly2 inside poly1 return 0 */
-	getPoint2d_p(poly2->rings[0], 0, &pt);
-	if ( pt_in_poly_2d(&pt, poly1) ) return 0.0;  
-
-	LWDEBUG(3, "  polys not inside each other");
-
-	/*
-	 * foreach ring in Poly1
-	 * foreach ring in Poly2
-	 *   if intersect, return 0
-	 */
-	for (i=0; i<poly1->nrings; i++)
-	{
-		int j;
-		for (j=0; j<poly2->nrings; j++)
-		{
-			double d = distance2d_ptarray_ptarray(poly1->rings[i],
-				poly2->rings[j]);
-			if ( d <= 0 ) return 0.0;
-
-			/* mindist is -1 when not yet set */
-			if (mindist > -1) mindist = LW_MIN(mindist, d);
-			else mindist = d;
-
-			LWDEBUGF(3, "  ring%i-%i dist: %f, mindist: %f", i, j, d, mindist);
-		}
-
-	}
-
-	/* otherwise return closest approach of rings (no intersection) */
-	return mindist;
-
-}
-
-double distance2d_line_poly(LWLINE *line, LWPOLY *poly)
-{
-	return distance2d_ptarray_poly(line->points, poly);
-}
-
-
-/*find the 2d length of the given POINTARRAY (even if it's 3d) */
-double lwgeom_pointarray_length2d(POINTARRAY *pts)
-{
-	double dist = 0.0;
-	int i;
-	POINT2D frm;
-	POINT2D to;
-
-	if ( pts->npoints < 2 ) return 0.0;
-	for (i=0; i<pts->npoints-1;i++)
-	{
-		getPoint2d_p(pts, i, &frm);
-		getPoint2d_p(pts, i+1, &to);
-		dist += sqrt( ( (frm.x - to.x)*(frm.x - to.x) )  +
-				((frm.y - to.y)*(frm.y - to.y) ) );
-	}
-	return dist;
-}
-
-/*
- * Find the 3d/2d length of the given POINTARRAY
- * (depending on its dimensions)
- */
-double
-lwgeom_pointarray_length(POINTARRAY *pts)
-{
-	double dist = 0.0;
-	int i;
-	POINT3DZ frm;
-	POINT3DZ to;
-
-	if ( pts->npoints < 2 ) return 0.0;
-
-	/* compute 2d length if 3d is not available */
-	if ( ! TYPE_HASZ(pts->dims) ) return lwgeom_pointarray_length2d(pts);
-
-	for (i=0; i<pts->npoints-1;i++)
-	{
-		getPoint3dz_p(pts, i, &frm);
-		getPoint3dz_p(pts, i+1, &to);
-		dist += sqrt( ( (frm.x - to.x)*(frm.x - to.x) )  +
-				((frm.y - to.y)*(frm.y - to.y) ) +
-				((frm.z - to.z)*(frm.z - to.z) ) );
-	}
-
-	return dist;
-}
-
-/*
- * This should be rewritten to make use of the curve itself.
- */
-double
-lwgeom_curvepolygon_area(LWCURVEPOLY *curvepoly)
-{
-        LWPOLY *poly = (LWPOLY *)lwgeom_segmentize((LWGEOM *)curvepoly, 32);
-        return lwgeom_polygon_area(poly);
-}
-
-/*
- * Find the area of the outer ring - sum (area of inner rings).
- * Could use a more numerically stable calculator...
- */
-double
-lwgeom_polygon_area(LWPOLY *poly)
-{
-	double poly_area=0.0;
-	int i;
-	POINT2D p1;
-	POINT2D p2;
-
-	LWDEBUGF(2, "in lwgeom_polygon_area (%d rings)", poly->nrings);
-
-	for (i=0; i<poly->nrings; i++)
-	{
-		int j;
-		POINTARRAY *ring = poly->rings[i];
-		double ringarea = 0.0;
-
-		LWDEBUGF(4, " rings %d has %d points", i, ring->npoints);
-
-		for (j=0; j<ring->npoints-1; j++)
-    		{
-			getPoint2d_p(ring, j, &p1);
-			getPoint2d_p(ring, j+1, &p2);
-			ringarea += ( p1.x * p2.y ) - ( p1.y * p2.x );
-		}
-
-		ringarea  /= 2.0;
-
-		LWDEBUGF(4, " ring 1 has area %lf",ringarea);
-
-		ringarea  = fabs(ringarea);
-		if (i != 0)	/*outer */
-			ringarea  = -1.0*ringarea ; /* its a hole */
-
-		poly_area += ringarea;
-	}
-
-	return poly_area;
-}
-
-/*
- * Compute the sum of polygon rings length.
- * Could use a more numerically stable calculator...
- */
-double lwgeom_polygon_perimeter(LWPOLY *poly)
-{
-	double result=0.0;
-	int i;
-
-	LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
-
-	for (i=0; i<poly->nrings; i++)
-		result += lwgeom_pointarray_length(poly->rings[i]);
-
-	return result;
-}
-
-/*
- * Compute the sum of polygon rings length (forcing 2d computation).
- * Could use a more numerically stable calculator...
- */
-double lwgeom_polygon_perimeter2d(LWPOLY *poly)
-{
-	double result=0.0;
-	int i;
-
-	LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
-
-	for (i=0; i<poly->nrings; i++)
-		result += lwgeom_pointarray_length2d(poly->rings[i]);
-
-	return result;
-}
-
-double
-lwgeom_mindistance2d_recursive(uchar *lw1, uchar *lw2)
-{
-  return lwgeom_mindistance2d_recursive_tolerance( lw1, lw2, 0.0 );
-}
-
-double
-lwgeom_mindistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance)
-{
-	LWGEOM_INSPECTED *in1, *in2;
-	int i, j;
-	double mindist = -1;
-
-	in1 = lwgeom_inspect(lw1);
-	in2 = lwgeom_inspect(lw2);
-
-	for (i=0; i<in1->ngeometries; i++)
-	{
-		uchar *g1 = lwgeom_getsubgeometry_inspected(in1, i);
-		int t1 = lwgeom_getType(g1[0]);
-		double dist=tolerance;
-
-		/* it's a multitype... recurse */
-		if ( t1 >= 4 )
-		{
-			dist = lwgeom_mindistance2d_recursive_tolerance(g1, lw2, tolerance);
-			if ( dist <= tolerance ) return tolerance; /* can't be closer */
-			if ( mindist == -1 ) mindist = dist;
-			else mindist = LW_MIN(dist, mindist);
-			continue;
-		}
-
-		for (j=0; j<in2->ngeometries; j++)
-		{
-			uchar *g2 = lwgeom_getsubgeometry_inspected(in2, j);
-			int t2 = lwgeom_getType(g2[0]);
-
-			if  ( t1 == POINTTYPE )
-			{
-				if  ( t2 == POINTTYPE )
-				{
-					dist = distance2d_point_point(
-						lwpoint_deserialize(g1),
-						lwpoint_deserialize(g2)
-					);
-				}
-				else if  ( t2 == LINETYPE )
-				{
-					dist = distance2d_point_line(
-						lwpoint_deserialize(g1),
-						lwline_deserialize(g2)
-					);
-				}
-				else if  ( t2 == POLYGONTYPE )
-				{
-					dist = distance2d_point_poly(
-						lwpoint_deserialize(g1),
-						lwpoly_deserialize(g2)
-					);
-				}
-			}
-			else if ( t1 == LINETYPE )
-			{
-				if ( t2 == POINTTYPE )
-				{
-					dist = distance2d_point_line(
-						lwpoint_deserialize(g2),
-						lwline_deserialize(g1)
-					);
-				}
-				else if ( t2 == LINETYPE )
-				{
-					dist = distance2d_line_line(
-						lwline_deserialize(g1),
-						lwline_deserialize(g2)
-					);
-				}
-				else if ( t2 == POLYGONTYPE )
-				{
-					dist = distance2d_line_poly(
-						lwline_deserialize(g1),
-						lwpoly_deserialize(g2)
-					);
-				}
-			}
-			else if ( t1 == POLYGONTYPE )
-			{
-				if ( t2 == POLYGONTYPE )
-				{
-					dist = distance2d_poly_poly(
-						lwpoly_deserialize(g2),
-						lwpoly_deserialize(g1)
-					);
-				}
-				else if ( t2 == POINTTYPE )
-				{
-					dist = distance2d_point_poly(
-						lwpoint_deserialize(g2),
-						lwpoly_deserialize(g1)
-					);
-				}
-				else if ( t2 == LINETYPE )
-				{
-					dist = distance2d_line_poly(
-						lwline_deserialize(g2),
-						lwpoly_deserialize(g1)
-					);
-				}
-			}
-			else /* it's a multitype... recurse */
-			{
-				dist = lwgeom_mindistance2d_recursive_tolerance(g1, g2, tolerance);
-			}
-
-			if (mindist == -1 ) mindist = dist;
-			else mindist = LW_MIN(dist, mindist);
-
-			LWDEBUGF(3, "dist %d-%d: %f - mindist: %f",
-				i, j, dist, mindist);
-
-
-			if (mindist <= tolerance) return tolerance; /* can't be closer */
-
-		}
-
-	}
-
-	if (mindist<0) mindist = 0; 
-
-	return mindist;
-}
-
-
-
-int
-lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad)
-{
-	POINT2D center;
-
-	center.x = cx;
-	center.y = cy;
-
-	if ( distance2d_pt_pt(p, &center) < rad ) return 1;
-	else return 0;
-
-}
-
-/*
- * Compute the azimuth of segment AB in radians.
- * Return 0 on exception (same point), 1 otherwise.
- */
-int
-azimuth_pt_pt(POINT2D *A, POINT2D *B, double *d)
-{
-	if ( A->x == B->x )
-	{
-		if ( A->y < B->y ) *d=0.0;
-		else if ( A->y > B->y ) *d=M_PI; 
-		else return 0;
-		return 1;
-	}
-
-	if ( A->y == B->y )
-	{
-		if ( A->x < B->x ) *d=M_PI/2; 
-		else if ( A->x > B->x ) *d=M_PI+(M_PI/2);
-		else return 0;
-		return 1;
-	}
-
-	if ( A->x < B->x )
-	{
-		if ( A->y < B->y )
-		{
-			*d=atan(fabs(A->x - B->x) / fabs(A->y - B->y) );
-		}
-		else /* ( A->y > B->y )  - equality case handled above */
-		{
-			*d=atan(fabs(A->y - B->y) / fabs(A->x - B->x) )
-				+ (M_PI/2);
-		}
-	}
-
-	else /* ( A->x > B->x ) - equality case handled above */
-	{
-		if ( A->y > B->y )
-		{
-			*d=atan(fabs(A->x - B->x) / fabs(A->y - B->y) )
-				+ M_PI;
-		}
-		else /* ( A->y < B->y )  - equality case handled above */
-		{
-			*d=atan(fabs(A->y - B->y) / fabs(A->x - B->x) )
-				+ (M_PI+(M_PI/2));
-		}
-	}
-
-	return 1;
-}
-

Deleted: trunk/lwgeom/ptarray.c
===================================================================
--- trunk/lwgeom/ptarray.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/ptarray.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,836 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-
-#include "liblwgeom.h"
-
-
-POINTARRAY *
-ptarray_construct(char hasz, char hasm, unsigned int npoints)
-{
-	uchar dims = 0;
-	size_t size; 
-	uchar *ptlist;
-	POINTARRAY *pa;
-	
-	TYPE_SETZM(dims, hasz?1:0, hasm?1:0);
-	size = TYPE_NDIMS(dims)*npoints*sizeof(double);
-
-	ptlist = (uchar *)lwalloc(size);
-	pa = lwalloc(sizeof(POINTARRAY));
-	pa->dims = dims;
-	pa->serialized_pointlist = ptlist;
-	pa->npoints = npoints;
-
-	return pa;
-
-}
-
-void
-ptarray_reverse(POINTARRAY *pa)
-{
-	POINT4D pbuf;
-	uint32 i;
-	int ptsize = pointArray_ptsize(pa);
-	int last = pa->npoints-1;
-	int mid = last/2;
-
-	for (i=0; i<=mid; i++)
-	{
-		uchar *from, *to;
-		from = getPoint_internal(pa, i);
-		to = getPoint_internal(pa, (last-i));
-		memcpy((uchar *)&pbuf, to, ptsize);
-		memcpy(to, from, ptsize);
-		memcpy(from, (uchar *)&pbuf, ptsize);
-	}
-
-}
-
-/*
- * calculate the 2d bounding box of a set of points
- * write result to the provided BOX2DFLOAT4
- * Return 0 if bounding box is NULL (empty geom)
- */
-int
-ptarray_compute_box2d_p(const POINTARRAY *pa, BOX2DFLOAT4 *result)
-{
-	int t;
-	POINT2D pt;
-	BOX3D box;
-
-	if (pa->npoints == 0) return 0;
-
-	getPoint2d_p(pa, 0, &pt);
-
-	box.xmin = pt.x;
-	box.xmax = pt.x;
-	box.ymin = pt.y;
-	box.ymax = pt.y;
-
-	for (t=1; t<pa->npoints; t++)
-	{
-		getPoint2d_p(pa, t, &pt);
-		if (pt.x < box.xmin) box.xmin = pt.x;
-		if (pt.y < box.ymin) box.ymin = pt.y;
-		if (pt.x > box.xmax) box.xmax = pt.x;
-		if (pt.y > box.ymax) box.ymax = pt.y;
-	}
-
-	box3d_to_box2df_p(&box, result);
-
-	return 1;
-}
-
-/*
- * Calculate the 2d bounding box of a set of points.
- * Return allocated BOX2DFLOAT4 or NULL (for empty array).
- */
-BOX2DFLOAT4 *
-ptarray_compute_box2d(const POINTARRAY *pa)
-{
-	int t;
-	POINT2D pt;
-	BOX2DFLOAT4 *result;
-
-	if (pa->npoints == 0) return NULL;
-
-	result = lwalloc(sizeof(BOX2DFLOAT4));
-
-	getPoint2d_p(pa, 0, &pt);
-
-	result->xmin = pt.x;
-	result->xmax = pt.x;
-	result->ymin = pt.y;
-	result->ymax = pt.y;
-
-	for (t=1;t<pa->npoints;t++)
-	{
-		getPoint2d_p(pa, t, &pt);
-		if (pt.x < result->xmin) result->xmin = pt.x;
-		if (pt.y < result->ymin) result->ymin = pt.y;
-		if (pt.x > result->xmax) result->xmax = pt.x;
-		if (pt.y > result->ymax) result->ymax = pt.y;
-	}
-
-	return result;
-}
-
-/*
- * Returns a modified POINTARRAY so that no segment is 
- * longer then the given distance (computed using 2d).
- * Every input point is kept.
- * Z and M values for added points (if needed) are set to 0.
- */
-POINTARRAY *
-ptarray_segmentize2d(POINTARRAY *ipa, double dist)
-{
-	double	segdist;
-	POINT4D	p1, p2;
-	void *ip, *op;
-	POINT4D pbuf;
-	POINTARRAY *opa;
-	int maxpoints = ipa->npoints;
-	int ptsize = pointArray_ptsize(ipa);
-	int ipoff=0; /* input point offset */
-
-	pbuf.x = pbuf.y = pbuf.z = pbuf.m = 0;
-
-	/* Initial storage */
-	opa = (POINTARRAY *)lwalloc(ptsize * maxpoints);
-	opa->dims = ipa->dims;
-	opa->npoints = 0;
-	opa->serialized_pointlist = (uchar *)lwalloc(maxpoints*ptsize);
-
-	/* Add first point */
-	opa->npoints++;
-	getPoint4d_p(ipa, ipoff, &p1);
-	op = getPoint_internal(opa, opa->npoints-1);
-	memcpy(op, &p1, ptsize); 
-	ipoff++;
-
-	while (ipoff<ipa->npoints)
-	{
-		/*
-		 * We use these pointers to avoid
-		 * "strict-aliasing rules break" warning raised
-		 * by gcc (3.3 and up).
-		 *
-		 * It looks that casting a variable address (also
-		 * referred to as "type-punned pointer")
-		 * breaks those "strict" rules.
-		 *
-		 */
-		POINT4D *p1ptr=&p1, *p2ptr=&p2;
-
-		getPoint4d_p(ipa, ipoff, &p2);
-
-		segdist = distance2d_pt_pt((POINT2D *)p1ptr, (POINT2D *)p2ptr);
-
-		if (segdist > dist) /* add an intermediate point */
-		{
-			pbuf.x = p1.x + (p2.x-p1.x)/segdist * dist;
-			pbuf.y = p1.y + (p2.y-p1.y)/segdist * dist;
-			/* might also compute z and m if available... */
-			ip = &pbuf;
-			memcpy(&p1, ip, ptsize);
-		}
-		else /* copy second point */
-		{
-			ip = &p2;
-			p1 = p2;
-			ipoff++;
-		}
-
-		/* Add point */
-		if ( ++(opa->npoints) > maxpoints ) {
-			maxpoints *= 1.5;
-			opa->serialized_pointlist = (uchar *)lwrealloc(
-				opa->serialized_pointlist,
-				maxpoints*ptsize
-			);
-		}
-		op = getPoint_internal(opa, opa->npoints-1);
-		memcpy(op, ip, ptsize); 
-	}
-
-	return opa;
-}
-
-char
-ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2)
-{
-	unsigned int i;
-	size_t ptsize;
-
-	if ( TYPE_GETZM(pa1->dims) != TYPE_GETZM(pa2->dims) ) return 0;
-
-	if ( pa1->npoints != pa2->npoints ) return 0;
-
-	ptsize = pointArray_ptsize(pa1);
-
-	for (i=0; i<pa1->npoints; i++)
-	{
-		if ( memcmp(getPoint_internal(pa1, i), getPoint_internal(pa2, i), ptsize) )
-			return 0;
-	}
-
-	return 1;
-}
-
-/*
- * Add a point in a pointarray.
- * 'where' is the offset (starting at 0)
- * if 'where' == -1 append is required.
- */
-POINTARRAY *
-ptarray_addPoint(POINTARRAY *pa, uchar *p, size_t pdims, unsigned int where)
-{
-	POINTARRAY *ret;
-	POINT4D pbuf;
-	size_t ptsize = pointArray_ptsize(pa);
-
-	LWDEBUGF(3, "pa %x p %x size %d where %d",
-		pa, p, pdims, where);
-
-	if ( pdims < 2 || pdims > 4 )
-	{
-		lwerror("ptarray_addPoint: point dimension out of range (%d)",
-			pdims);
-		return NULL;
-	}
-
-	if ( where > pa->npoints )
-	{
-		lwerror("ptarray_addPoint: offset out of range (%d)",
-			where);
-		return NULL;
-	}
-
-	LWDEBUG(3, "called with a %dD point");
-	
-	pbuf.x = pbuf.y = pbuf.z = pbuf.m = 0.0;
-	memcpy((uchar *)&pbuf, p, pdims*sizeof(double));
-
-	LWDEBUG(3, "initialized point buffer");
-
-	ret = ptarray_construct(TYPE_HASZ(pa->dims),
-		TYPE_HASM(pa->dims), pa->npoints+1);
-	
-	if ( where == -1 ) where = pa->npoints;
-
-	if ( where )
-	{
-		memcpy(getPoint_internal(ret, 0), getPoint_internal(pa, 0), ptsize*where);
-	}
-
-	memcpy(getPoint_internal(ret, where), (uchar *)&pbuf, ptsize);
-
-	if ( where+1 != ret->npoints )
-	{
-		memcpy(getPoint_internal(ret, where+1),
-			getPoint_internal(pa, where),
-			ptsize*(pa->npoints-where));
-	}
-
-	return ret;
-}
-
-/*
- * Remove a point from a pointarray.
- * 'which' is the offset (starting at 0)
- * Returned pointarray is newly allocated
- */
-POINTARRAY *
-ptarray_removePoint(POINTARRAY *pa, unsigned int which)
-{
-	POINTARRAY *ret;
-	size_t ptsize = pointArray_ptsize(pa);
-
-	LWDEBUGF(3, "pa %x which %d", pa, which);
-
-#if PARANOIA_LEVEL > 0
-	if ( which > pa->npoints-1 )
-	{
-		lwerror("ptarray_removePoint: offset (%d) out of range (%d..%d)",
-			which, 0, pa->npoints-1);
-		return NULL;
-	}
-
-	if ( pa->npoints < 3 )
-	{
-		lwerror("ptarray_removePointe: can't remove a point from a 2-vertex POINTARRAY");
-	}
-#endif
-
-	ret = ptarray_construct(TYPE_HASZ(pa->dims),
-		TYPE_HASM(pa->dims), pa->npoints-1);
-	
-	/* copy initial part */
-	if ( which )
-	{
-		memcpy(getPoint_internal(ret, 0), getPoint_internal(pa, 0), ptsize*which);
-	}
-
-	/* copy final part */
-	if ( which < pa->npoints-1 )
-	{
-		memcpy(getPoint_internal(ret, which), getPoint_internal(pa, which+1),
-			ptsize*(pa->npoints-which-1));
-	}
-
-	return ret;
-}
-
-/* 
- * Clone a pointarray 
- */
-POINTARRAY *
-ptarray_clone(const POINTARRAY *in)
-{
-	POINTARRAY *out = lwalloc(sizeof(POINTARRAY));
-	size_t size;
-
-        LWDEBUG(3, "ptarray_clone called.");
-
-	out->dims = in->dims;
-	out->npoints = in->npoints;
-
-	size = in->npoints*sizeof(double)*TYPE_NDIMS(in->dims);
-	out->serialized_pointlist = lwalloc(size);
-	memcpy(out->serialized_pointlist, in->serialized_pointlist, size);
-
-	return out;
-}
-
-int
-ptarray_isclosed2d(const POINTARRAY *in)
-{
-	if ( memcmp(getPoint_internal(in, 0), getPoint_internal(in, in->npoints-1), sizeof(POINT2D)) ) return 0;
-	return 1;
-}
-
-/*
- * calculate the BOX3D bounding box of a set of points
- * returns a lwalloced BOX3D, or NULL on empty array.
- * zmin/zmax values are set to NO_Z_VALUE if not available.
- */
-BOX3D *
-ptarray_compute_box3d(const POINTARRAY *pa)
-{
-	BOX3D *result = lwalloc(sizeof(BOX3D));
-
-	if ( ! ptarray_compute_box3d_p(pa, result) )
-	{
-		lwfree(result);
-		return NULL;
-	}
-
-	return result;
-}
-
-/*
- * calculate the BOX3D bounding box of a set of points
- * zmin/zmax values are set to NO_Z_VALUE if not available.
- * write result to the provided BOX3D
- * Return 0 if bounding box is NULL (empty geom)
- */
-int
-ptarray_compute_box3d_p(const POINTARRAY *pa, BOX3D *result)
-{
-	int t;
-	POINT3DZ pt;
-
-	LWDEBUGF(3, "ptarray_compute_box3d call (array has %d points)", pa->npoints);
-	
-	if (pa->npoints == 0) return 0;
-
-	getPoint3dz_p(pa, 0, &pt);
-
-	LWDEBUG(3, "got point 0");
-
-	result->xmin = pt.x;
-	result->xmax = pt.x;
-	result->ymin = pt.y;
-	result->ymax = pt.y;
-
-	if ( TYPE_HASZ(pa->dims) ) {
-		result->zmin = pt.z;
-		result->zmax = pt.z;
-	} else {
-		result->zmin = NO_Z_VALUE;
-		result->zmax = NO_Z_VALUE;
-	}
-
-	LWDEBUGF(3, "scanning other %d points", pa->npoints);
-
-	for (t=1; t<pa->npoints; t++)
-	{
-		getPoint3dz_p(pa,t,&pt);
-		if (pt.x < result->xmin) result->xmin = pt.x;
-		if (pt.y < result->ymin) result->ymin = pt.y;
-		if (pt.x > result->xmax) result->xmax = pt.x;
-		if (pt.y > result->ymax) result->ymax = pt.y;
-
-		if ( TYPE_HASZ(pa->dims) ) {
-			if (pt.z > result->zmax) result->zmax = pt.z;
-			if (pt.z < result->zmin) result->zmin = pt.z;
-		}
-	}
-
-	LWDEBUG(3, "returning box");
-
-	return 1;
-}
-
-/*
- * TODO: implement point interpolation
- */
-POINTARRAY *
-ptarray_substring(POINTARRAY *ipa, double from, double to)
-{
-	DYNPTARRAY *dpa;
-	POINTARRAY *opa;
-	POINT4D pt;
-	POINT4D p1, p2;
-	POINT4D *p1ptr=&p1; /* don't break strict-aliasing rule */
-	POINT4D *p2ptr=&p2;
-	int nsegs, i;
-	double length, slength, tlength;
-	int state = 0; /* 0=before, 1=inside */
-
-	/*
-	 * Create a dynamic pointarray with an initial capacity
-	 * equal to full copy of input points
-	 */
-	dpa = dynptarray_create(ipa->npoints, ipa->dims);
-
-	/* Compute total line length */
-	length = lwgeom_pointarray_length2d(ipa);
-
-
-	LWDEBUGF(3, "Total length: %g", length);
-
-
-	/* Get 'from' and 'to' lengths */
-	from = length*from;
-	to = length*to;
-
-
-	LWDEBUGF(3, "From/To: %g/%g", from, to);
-
-
-	tlength = 0;
-	getPoint4d_p(ipa, 0, &p1);
-	nsegs = ipa->npoints - 1;
-	for( i = 0; i < nsegs; i++ )
-	{
-		double dseg;
-
-		getPoint4d_p(ipa, i+1, &p2);
-
-
-		LWDEBUGF(3 ,"Segment %d: (%g,%g,%g,%g)-(%g,%g,%g,%g)",
-			i, p1.x, p1.y, p1.z, p1.m, p2.x, p2.y, p2.z, p2.m);
-
-
-		/* Find the length of this segment */
-		slength = distance2d_pt_pt((POINT2D *)p1ptr, (POINT2D *)p2ptr);
-
-		/*
-		 * We are before requested start.
-		 */
-		if ( state == 0 ) /* before */
-		{
-
-			LWDEBUG(3, " Before start");
-
-			/*
-			 * Didn't reach the 'from' point,
-			 * nothing to do
-			 */
-			if ( from > tlength + slength ) goto END;
-
-			else if ( from == tlength + slength )
-			{
-
-				LWDEBUG(3, "  Second point is our start");
-
-				/*
-				 * Second point is our start
-				 */
-				dynptarray_addPoint4d(dpa, &p2, 1);
-				state=1; /* we're inside now */
-				goto END;
-			}
-
-			else if ( from == tlength )
-			{
-
-				LWDEBUG(3, "  First point is our start");
-
-				/*
-				 * First point is our start
-				 */
-				dynptarray_addPoint4d(dpa, &p1, 1);
-
-				/*
-				 * We're inside now, but will check
-				 * 'to' point as well
-				 */
-				state=1;
-			}
-
-			else  /* tlength < from < tlength+slength */
-			{
-
-				LWDEBUG(3, "  Seg contains first point");
-
-				/*
-				 * Our start is between first and
-				 * second point
-				 */
-				dseg = (from - tlength) / slength;
-				interpolate_point4d(&p1, &p2, &pt, dseg);
-
-				dynptarray_addPoint4d(dpa, &pt, 1);
-
-				/*
-				 * We're inside now, but will check
-				 * 'to' point as well
-				 */
-				state=1;
-			}
-		}
-
-		if ( state == 1 ) /* inside */
-		{
-
-			LWDEBUG(3, " Inside");
-
-			/*
-			 * Didn't reach the 'end' point,
-			 * just copy second point
-			 */
-			if ( to > tlength + slength ) 
-			{
-				dynptarray_addPoint4d(dpa, &p2, 0);
-				goto END;
-			}
-
-			/*
-			 * 'to' point is our second point.
-			 */
-			else if ( to == tlength + slength )
-			{
-
-				LWDEBUG(3, " Second point is our end");
-
-				dynptarray_addPoint4d(dpa, &p2, 0);
-				break; /* substring complete */
-			}
-
-			/*
-			 * 'to' point is our first point.
-			 * (should only happen if 'to' is 0)
-			 */
-			else if ( to == tlength )
-			{
-
-				LWDEBUG(3, " First point is our end");
-
-				dynptarray_addPoint4d(dpa, &p1, 0);
-
-				break; /* substring complete */
-			}
-
-			/*
-			 * 'to' point falls on this segment
-			 * Interpolate and break.
-			 */
-			else if ( to < tlength + slength )
-			{
-
-				LWDEBUG(3, " Seg contains our end");
-
-				dseg = (to - tlength) / slength;
-				interpolate_point4d(&p1, &p2, &pt, dseg);
-
-				dynptarray_addPoint4d(dpa, &pt, 0);
-
-				break;
-			}
-
-			else
-			{
-				LWDEBUG(3, "Unhandled case");
-			}
-		}
-
-
-		END:
-
-		tlength += slength;
-		memcpy(&p1, &p2, sizeof(POINT4D));
-	}
-
-	/* Get constructed pointarray and release memory associated
-	 * with the dynamic pointarray
-	 */
-	opa = dpa->pa;
-	lwfree(dpa);
-
-	LWDEBUGF(3, "Out of loop, ptarray has %d points", opa->npoints);
-
-	return opa;
-}
-
-/*
- * Write into the *ret argument coordinates of the closes point on
- * the given segment to the reference input point.
- */
-void
-closest_point_on_segment(POINT2D *p, POINT2D *A, POINT2D *B, POINT2D *ret)
-{
-	double r;
-
-	if (  ( A->x == B->x) && (A->y == B->y) )
-	{
-		*ret = *A;
-		return;
-	}
-
-	/*
-	 * We use comp.graphics.algorithms Frequently Asked Questions method
-	 *
-	 * (1)           AC dot AB
-	 *           r = ----------
-	 *                ||AB||^2
-	 *	r has the following meaning:
-	 *	r=0 P = A
-	 *	r=1 P = B
-	 *	r<0 P is on the backward extension of AB
-	 *	r>1 P is on the forward extension of AB
-	 *	0<r<1 P is interior to AB
-	 *	
-	 */
-	r = ( (p->x-A->x) * (B->x-A->x) + (p->y-A->y) * (B->y-A->y) )/( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
-
-	if (r<0) {
-		*ret = *A; return;
-	}
-	if (r>1) {
-		*ret = *B;
-		return;
-	}
-
-	ret->x = A->x + ( (B->x - A->x) * r );
-	ret->y = A->y + ( (B->y - A->y) * r );
-}
-
-/*
- * Given a point, returns the location of closest point on pointarray
- */
-double
-ptarray_locate_point(POINTARRAY *pa, POINT2D *p)
-{
-	double mindist=-1;
-	double tlen, plen;
-	int t, seg=-1;
-	POINT2D	start, end;
-	POINT2D proj;
-
-	getPoint2d_p(pa, 0, &start);
-	for (t=1; t<pa->npoints; t++)
-	{
-		double dist;
-		getPoint2d_p(pa, t, &end);
-		dist = distance2d_pt_seg(p, &start, &end);
-
-		if (t==1 || dist < mindist ) {
-			mindist = dist;
-			seg=t-1;
-		}
-
-		if ( mindist == 0 ) break;
-
-		start = end;
-	}
-
-	LWDEBUGF(3, "Closest segment: %d", seg);
-
-	/*
-	 * If mindist is not 0 we need to project the 
-	 * point on the closest segment.
-	 */
-	if ( mindist > 0 )
-	{
-		getPoint2d_p(pa, seg, &start);
-		getPoint2d_p(pa, seg+1, &end);
-		closest_point_on_segment(p, &start, &end, &proj);
-	} else {
-		proj = *p;
-	}
-
-	LWDEBUGF(3, "Closest point on segment: %g,%g", proj.x, proj.y);
-
-	tlen = lwgeom_pointarray_length2d(pa);
-
-	LWDEBUGF(3, "tlen %g", tlen);
-
-	plen=0;
-	getPoint2d_p(pa, 0, &start);
-	for (t=0; t<seg; t++, start=end)
-	{
-		getPoint2d_p(pa, t+1, &end);
-		plen += distance2d_pt_pt(&start, &end);
-
-		LWDEBUGF(4, "Segment %d made plen %g", t, plen);
-	}
-
-	plen+=distance2d_pt_pt(&proj, &start);
-
-	LWDEBUGF(3, "plen %g, tlen %g", plen, tlen);
-	LWDEBUGF(3, "mindist: %g", mindist);
-
-	return plen/tlen;
-}
-
-/*
- * Longitude shift for a pointarray.
- *  Y remains the same
- *  X is converted:
- *	 from -180..180 to 0..360
- *	 from 0..360 to -180..180
- *  X < 0 becomes X + 360
- *  X > 180 becomes X - 360
- */
-void
-ptarray_longitude_shift(POINTARRAY *pa)
-{
-	int i;
-	double x;
-
-	for (i=0; i<pa->npoints; i++) {
-		memcpy(&x, getPoint_internal(pa, i), sizeof(double));
-		if ( x < 0 ) x+= 360;
-		else if ( x > 180 ) x -= 360;
-		memcpy(getPoint_internal(pa, i), &x, sizeof(double));
-	}
-}
-
-DYNPTARRAY *
-dynptarray_create(size_t initial_capacity, int dims)
-{
-	DYNPTARRAY *ret=lwalloc(sizeof(DYNPTARRAY));
-
-        LWDEBUGF(3, "dynptarray_create called, dims=%d.", dims);
-
-	if ( initial_capacity < 1 ) initial_capacity=1;
-
-	ret->pa=lwalloc(sizeof(POINTARRAY));
-	ret->pa->dims=dims;
-	ret->ptsize=pointArray_ptsize(ret->pa);
-	ret->capacity=initial_capacity;
-	ret->pa->serialized_pointlist=lwalloc(ret->ptsize*ret->capacity);
-	ret->pa->npoints=0;
-
-	return ret;
-}
-
-/*
- * Add a POINT4D to the dynamic pointarray.
- *
- * The dynamic pointarray may be of any dimension, only
- * accepted dimensions will be copied.
- *
- * If allow_duplicates is set to 0 (false) a check
- * is performed to see if last point in array is equal to the
- * provided one. NOTE that the check is 4d based, with missing
- * ordinates in the pointarray set to NO_Z_VALUE and NO_M_VALUE
- * respectively.
- */
-int
-dynptarray_addPoint4d(DYNPTARRAY *dpa, POINT4D *p4d, int allow_duplicates)
-{
-	POINTARRAY *pa=dpa->pa;
-	POINT4D tmp;
-
-        LWDEBUG(3, "dynptarray_addPoint4d called.");
-
-	if ( ! allow_duplicates && pa->npoints > 0 )
-	{
-		getPoint4d_p(pa, pa->npoints-1, &tmp);
-
-		/*
-		 * return 0 and do nothing else if previous point in list is
-		 * equal to this one  (4D equality)
-		 */
-		if ( ! memcmp(p4d, &tmp, sizeof(POINT4D)) ) return 0;
-	}
-
-	++pa->npoints;
-	if ( pa->npoints > dpa->capacity )
-	{
-		dpa->capacity*=2;
-		pa->serialized_pointlist = lwrealloc(
-			pa->serialized_pointlist,
-			dpa->capacity*dpa->ptsize);
-	}
-
-	setPoint4d(pa, pa->npoints-1, p4d);
-
-	return 1;
-}
-

Deleted: trunk/lwgeom/vsprintf.c
===================================================================
--- trunk/lwgeom/vsprintf.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/vsprintf.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,162 +0,0 @@
-/* Like vsprintf but provides a pointer to malloc'd storage, which must
-   be freed by the caller.
-   Copyright (C) 1994, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
-
-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, 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.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#if __STDC__
-# include <stdarg.h>
-#else
-# include <varargs.h>
-#endif
-
-#include <math.h>
-
-#ifdef TEST
-int global_total_width;
-#endif
-
-static int
-int_vasprintf (result, format, args)
-     char **result;
-     const char *format;
-     va_list *args;
-{
-  const char *p = format;
-  /* Add one to make sure that it is never zero, which might cause malloc
-     to return NULL.  */
-  int total_width = strlen (format) + 1;
-  va_list ap;
-
-  memcpy (&ap, args, sizeof (va_list));
-
-  while (*p != '\0')
-    {
-      if (*p++ == '%')
-	{
-	  while (strchr ("-+ #0", *p))
-	    ++p;
-	  if (*p == '*')
-	    {
-	      ++p;
-	      total_width += abs (va_arg (ap, int));
-	    }
-	  else
-	    total_width += strtoul (p, (char **) &p, 10);
-	  if (*p == '.')
-	    {
-	      ++p;
-	      if (*p == '*')
-		{
-		  ++p;
-		  total_width += abs (va_arg (ap, int));
-		}
-	      else
-		total_width += strtoul (p, (char **) &p, 10);
-	    }
-	  while (strchr ("hlLjtz", *p))
-	    ++p;
-	  /* Should be big enough for any format specifier except %s
-	     and floats.  */
-	  total_width += 30;
-	  switch (*p)
-	    {
-	    case 'd':
-	    case 'i':
-	    case 'o':
-	    case 'u':
-	    case 'x':
-	    case 'X':
-	    case 'c':
-	      (void) va_arg (ap, int);
-	      break;
-	    case 'f':
-	      {
-		double arg = va_arg (ap, double);
-		if (arg >= 1.0 || arg <= -1.0)
-		  /* Since an ieee double can have an exponent of 307, we'll
-		     make the buffer wide enough to cover the gross case. */
-		  total_width += 307;
-	      }
-	      break;
-	    case 'e':
-	    case 'E':
-	    case 'g':
-	    case 'G':
-	      (void) va_arg (ap, double);
-	      break;
-	    case 's':
-	      total_width += strlen (va_arg (ap, char *));
-	      break;
-	    case 'p':
-	    case 'n':
-	      (void) va_arg (ap, char *);
-	      break;
-	    }
-	  p++;
-	}
-    }
-#ifdef TEST
-  global_total_width = total_width;
-#endif
-  *result = malloc (total_width);
-  if (*result != NULL)
-    return vsprintf (*result, format, *args);
-  else
-    return 0;
-}
-
-int
-vasprintf (result, format, args)
-     char **result;
-     const char *format;
-     va_list args;
-{
-  return int_vasprintf (result, format, &args);
-}
-
-int
-asprintf
-#if __STDC__
-     (char **result, const char *format, ...)
-#else
-     (result, va_alist)
-     char **result;
-     va_dcl
-#endif
-{
-  va_list args;
-  int done;
-
-#if __STDC__
-  va_start (args, format);
-#else
-  char *format;
-  va_start (args);
-  format = va_arg (args, char *);
-#endif
-  done = vasprintf (result, format, args);
-  va_end (args);
-
-  return done;
-} 

Deleted: trunk/lwgeom/wktparse.h
===================================================================
--- trunk/lwgeom/wktparse.h	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/wktparse.h	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,106 +0,0 @@
-/*
- * Written by Ralph Mason ralph.mason<at>telogis.com
- *
- * Copyright Telogis 2004
- * www.telogis.com
- *
- */
-
-#ifndef _WKTPARSE_H
-#define _WKTPARSE_H
-
-#include <stdlib.h>
-
-
-#ifndef _LIBLWGEOM_H
-typedef unsigned char uchar;
-
-typedef struct serialized_lwgeom {
-    uchar *lwgeom;
-    int size;
-} SERIALIZED_LWGEOM;
-#endif
-typedef void* (*allocator)(size_t size);
-typedef void  (*freeor)(void* mem);
-typedef void  (*report_error)(const char* string, ...);
-
-/*typedef unsigned long int4;*/
-
-/* How much memory is allocated at a time(bytes) for tuples */
-#define ALLOC_CHUNKS 8192
-
-/* to shrink ints less than 0x7f to 1 byte */
-/* #define SHRINK_INTS */
-
-#define	POINTTYPE	1
-#define	LINETYPE	2
-#define	POLYGONTYPE	3
-#define	MULTIPOINTTYPE	4
-#define	MULTILINETYPE	5
-#define	MULTIPOLYGONTYPE	6
-#define	COLLECTIONTYPE	7
-
-/* Extended lwgeom integer types */
-#define POINTTYPEI    10
-#define LINETYPEI     11
-#define POLYGONTYPEI  12
-
-#define CURVETYPE       8
-#define COMPOUNDTYPE    9
-#define CURVEPOLYTYPE   13
-#define MULTICURVETYPE          14
-#define MULTISURFACETYPE        15
-
-extern int srid;
-
-/*
-
-   These functions are used by  the
-   generated parser and are not meant
-   for public use
-
-*/
-
-void set_srid(double srid);
-void alloc_lwgeom(int srid);
-
-void alloc_point_2d(double x,double y);
-void alloc_point_3d(double x,double y,double z);
-void alloc_point_4d(double x,double y,double z,double m);
-
-void alloc_point(void);
-void alloc_linestring(void);
-void alloc_linestring_closed(void);
-void alloc_circularstring(void);
-void alloc_circularstring_closed(void);
-void alloc_polygon(void);
-void alloc_compoundcurve(void);
-void alloc_curvepolygon(void);
-void alloc_multipoint(void);
-void alloc_multilinestring(void);
-void alloc_multicurve(void);
-void alloc_multipolygon(void);
-void alloc_multisurface(void);
-void alloc_geomertycollection(void);
-void alloc_empty();
-void alloc_counter(void);
-
-
-void pop(void);
-void popc(void);
-
-void alloc_wkb(const char* parser);
-
-/*
-	Use these functions to parse and unparse lwgeoms
-	You are responsible for freeing the returned memory.
-*/
-
-SERIALIZED_LWGEOM* parse_lwg(const char* wkt,allocator allocfunc,report_error errfunc);
-SERIALIZED_LWGEOM* parse_lwgi(const char* wkt,allocator allocfunc,report_error errfunc);
-char* unparse_WKT(uchar* serialized, allocator alloc,freeor free);
-char* unparse_WKB(uchar* serialized, allocator alloc,freeor free, char endian, size_t *outsize, uchar hexform);
-int lwg_parse_yyparse(void);
-int lwg_parse_yyerror(char* s);
-
-#endif /* _WKTPARSE_H */

Deleted: trunk/lwgeom/wktparse.lex
===================================================================
--- trunk/lwgeom/wktparse.lex	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/wktparse.lex	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,71 +0,0 @@
-/*
- * Written by Ralph Mason ralph.mason<at>telogis.com
- *
- * Copyright Telogis 2004
- * www.telogis.com
- *
- */
-
-%x vals_ok
-%{
-#include "wktparse.tab.h"
-#include <unistd.h>
-#include <stdlib.h> // need stdlib for atof() definition 
-
-void init_parser(const char *src);
-void close_parser(void);
-int lwg_parse_yywrap(void);
-int lwg_parse_yylex(void);
-
-static YY_BUFFER_STATE buf_state;
-   void init_parser(const char *src) { BEGIN(0);buf_state = lwg_parse_yy_scan_string(src); }
-   void close_parser() { lwg_parse_yy_delete_buffer(buf_state); }
-   int lwg_parse_yywrap(void){ return 1; }
-
-%}
-
-%%
-
-<vals_ok>[-|\+]?[0-9]+(\.[0-9]+)?([Ee](\+|-)?[0-9]+)? { lwg_parse_yylval.value=atof(lwg_parse_yytext); return VALUE; }
-<vals_ok>[-|\+]?(\.[0-9]+)([Ee](\+|-)?[0-9]+)? { lwg_parse_yylval.value=atof(lwg_parse_yytext); return VALUE; }
-
-<INITIAL>00[0-9A-F]* {  lwg_parse_yylval.wkb=lwg_parse_yytext; return WKB;}
-<INITIAL>01[0-9A-F]* {  lwg_parse_yylval.wkb=lwg_parse_yytext; return WKB;}
-
-<*>POINT 	{ return POINT; }
-<*>POINTM 	{ return POINTM; }
-<*>LINESTRING { return LINESTRING; }
-<*>LINESTRINGM { return LINESTRINGM; }
-<*>CIRCULARSTRING { return CIRCULARSTRING; }
-<*>CIRCULARSTRINGM { return CIRCULARSTRINGM; }
-<*>POLYGON { return POLYGON; }
-<*>POLYGONM { return POLYGONM; }
-<*>COMPOUNDCURVE { return COMPOUNDCURVE; }
-<*>COMPOUNDCURVEM { return COMPOUNDCURVEM; }
-<*>CURVEPOLYGON { return CURVEPOLYGON; }
-<*>CURVEPOLYGONM { return CURVEPOLYGONM; }
-<*>MULTIPOINT { return MULTIPOINT; }
-<*>MULTIPOINTM { return MULTIPOINTM; }
-<*>MULTILINESTRING { return MULTILINESTRING; }
-<*>MULTILINESTRINGM { return MULTILINESTRINGM; }
-<*>MULTICURVE { return MULTICURVE; }
-<*>MULTICURVEM { return MULTICURVEM; }
-<*>MULTIPOLYGON { return MULTIPOLYGON; }
-<*>MULTIPOLYGONM { return MULTIPOLYGONM; }
-<*>MULTISURFACE { return MULTISURFACE; }
-<*>MULTISURFACEM { return MULTISURFACEM; }
-<*>GEOMETRYCOLLECTION { return GEOMETRYCOLLECTION; }
-<*>GEOMETRYCOLLECTIONM { return GEOMETRYCOLLECTIONM; }
-<*>SRID { BEGIN(vals_ok); return SRID; }
-<*>EMPTY { return EMPTY; }
-
-<*>\(	{ BEGIN(vals_ok); return LPAREN; }
-<*>\)	{ return RPAREN; }
-<*>,	{ return COMMA ; }
-<*>=	{ return EQUALS ; }
-<*>;	{ BEGIN(0); return SEMICOLON; }
-<*>[ \t\n\r]+ /*eat whitespace*/
-<*>.	{ return lwg_parse_yytext[0]; }
-
-%%
-

Deleted: trunk/lwgeom/wktparse.tab.c
===================================================================
--- trunk/lwgeom/wktparse.tab.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/wktparse.tab.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,1991 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875c.  */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-
-   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, 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.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, when this file is copied by Bison into a
-   Bison output file, you may use that output file without restriction.
-   This special exception was added by the Free Software Foundation
-   in version 1.24 of Bison.  */
-
-/* Written by Richard Stallman by simplifying the original so called
-   ``semantic'' parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-/* If NAME_PREFIX is specified substitute the variables and functions
-   names.  */
-#define yyparse lwg_parse_yyparse
-#define yylex   lwg_parse_yylex
-#define yyerror lwg_parse_yyerror
-#define yylval  lwg_parse_yylval
-#define yychar  lwg_parse_yychar
-#define yydebug lwg_parse_yydebug
-#define yynerrs lwg_parse_yynerrs
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     POINT = 258,
-     LINESTRING = 259,
-     POLYGON = 260,
-     MULTIPOINT = 261,
-     MULTILINESTRING = 262,
-     MULTIPOLYGON = 263,
-     GEOMETRYCOLLECTION = 264,
-     CIRCULARSTRING = 265,
-     COMPOUNDCURVE = 266,
-     CURVEPOLYGON = 267,
-     MULTICURVE = 268,
-     MULTISURFACE = 269,
-     POINTM = 270,
-     LINESTRINGM = 271,
-     POLYGONM = 272,
-     MULTIPOINTM = 273,
-     MULTILINESTRINGM = 274,
-     MULTIPOLYGONM = 275,
-     GEOMETRYCOLLECTIONM = 276,
-     CIRCULARSTRINGM = 277,
-     COMPOUNDCURVEM = 278,
-     CURVEPOLYGONM = 279,
-     MULTICURVEM = 280,
-     MULTISURFACEM = 281,
-     SRID = 282,
-     EMPTY = 283,
-     VALUE = 284,
-     LPAREN = 285,
-     RPAREN = 286,
-     COMMA = 287,
-     EQUALS = 288,
-     SEMICOLON = 289,
-     WKB = 290
-   };
-#endif
-#define POINT 258
-#define LINESTRING 259
-#define POLYGON 260
-#define MULTIPOINT 261
-#define MULTILINESTRING 262
-#define MULTIPOLYGON 263
-#define GEOMETRYCOLLECTION 264
-#define CIRCULARSTRING 265
-#define COMPOUNDCURVE 266
-#define CURVEPOLYGON 267
-#define MULTICURVE 268
-#define MULTISURFACE 269
-#define POINTM 270
-#define LINESTRINGM 271
-#define POLYGONM 272
-#define MULTIPOINTM 273
-#define MULTILINESTRINGM 274
-#define MULTIPOLYGONM 275
-#define GEOMETRYCOLLECTIONM 276
-#define CIRCULARSTRINGM 277
-#define COMPOUNDCURVEM 278
-#define CURVEPOLYGONM 279
-#define MULTICURVEM 280
-#define MULTISURFACEM 281
-#define SRID 282
-#define EMPTY 283
-#define VALUE 284
-#define LPAREN 285
-#define RPAREN 286
-#define COMMA 287
-#define EQUALS 288
-#define SEMICOLON 289
-#define WKB 290
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 9 "wktparse.y"
-
-#include "wktparse.h"
-#include <unistd.h>
-#include <stdio.h>
-
-void set_zm(char z, char m);
-int lwg_parse_yylex(void);
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-#line 20 "wktparse.y"
-typedef union YYSTYPE {
-	double value;
-	const char* wkb;
-} YYSTYPE;
-/* Line 191 of yacc.c.  */
-#line 169 "y.tab.c"
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 214 of yacc.c.  */
-#line 181 "y.tab.c"
-
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
-
-# ifndef YYFREE
-#  define YYFREE free
-# endif
-# ifndef YYMALLOC
-#  define YYMALLOC malloc
-# endif
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   define YYSTACK_ALLOC alloca
-#  endif
-# else
-#  if defined (alloca) || defined (_ALLOCA_H)
-#   define YYSTACK_ALLOC alloca
-#  else
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning. */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-# else
-#  if defined (__STDC__) || defined (__cplusplus)
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   define YYSIZE_T size_t
-#  endif
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-# endif
-#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
-
-
-#if (! defined (yyoverflow) \
-     && (! defined (__cplusplus) \
-	 || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  short yyss;
-  YYSTYPE yyvs;
-  };
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (short) + sizeof (YYSTYPE))				\
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined (__GNUC__) && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)		\
-      do					\
-	{					\
-	  register YYSIZE_T yyi;		\
-	  for (yyi = 0; yyi < (Count); yyi++)	\
-	    (To)[yyi] = (From)[yyi];		\
-	}					\
-      while (0)
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)					\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack, Stack, yysize);				\
-	Stack = &yyptr->Stack;						\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (0)
-
-#endif
-
-#if defined (__STDC__) || defined (__cplusplus)
-   typedef signed char yysigned_char;
-#else
-   typedef short yysigned_char;
-#endif
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL  6
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   180
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS  36
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS  107
-/* YYNRULES -- Number of rules. */
-#define YYNRULES  169
-/* YYNRULES -- Number of states. */
-#define YYNSTATES  237
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   290
-
-#define YYTRANSLATE(YYX) 						\
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const unsigned char yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const unsigned short yyprhs[] =
-{
-       0,     0,     3,     4,     9,    10,    13,    15,    17,    19,
-      21,    23,    25,    27,    29,    31,    33,    35,    37,    39,
-      43,    45,    48,    49,    53,    55,    57,    58,    61,    62,
-      65,    69,    70,    74,    75,    79,    81,    82,    87,    89,
-      93,    95,    96,    99,   102,   103,   107,   109,   111,   112,
-     115,   116,   119,   120,   123,   124,   129,   131,   135,   138,
-     139,   143,   146,   147,   151,   153,   155,   157,   159,   160,
-     163,   164,   167,   168,   171,   172,   177,   179,   183,   184,
-     188,   189,   193,   195,   196,   201,   203,   205,   209,   213,
-     214,   218,   219,   223,   225,   226,   231,   233,   237,   238,
-     242,   243,   247,   249,   250,   255,   257,   259,   263,   267,
-     270,   271,   275,   277,   279,   280,   283,   284,   287,   288,
-     293,   295,   299,   300,   304,   305,   309,   311,   312,   317,
-     319,   321,   325,   329,   330,   334,   335,   339,   341,   342,
-     347,   349,   353,   354,   358,   359,   363,   365,   366,   371,
-     373,   375,   379,   383,   384,   388,   389,   393,   395,   396,
-     401,   403,   405,   409,   411,   413,   415,   418,   422,   427
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const short yyrhs[] =
-{
-      37,     0,    -1,    -1,    41,    34,    38,    40,    -1,    -1,
-      39,    40,    -1,    42,    -1,    43,    -1,    59,    -1,    71,
-      -1,   104,    -1,    86,    -1,   114,    -1,    51,    -1,    92,
-      -1,    98,    -1,   120,    -1,   126,    -1,   132,    -1,    27,
-      33,    29,    -1,    35,    -1,     3,    45,    -1,    -1,    15,
-      44,    45,    -1,    46,    -1,    48,    -1,    -1,    47,   142,
-      -1,    -1,    49,    50,    -1,    30,   138,    31,    -1,    -1,
-       6,    52,    54,    -1,    -1,    18,    53,    54,    -1,   142,
-      -1,    -1,    55,    30,    56,    31,    -1,    57,    -1,    56,
-      32,    57,    -1,    48,    -1,    -1,    58,   138,    -1,     4,
-      61,    -1,    -1,    16,    60,    61,    -1,    62,    -1,    64,
-      -1,    -1,    63,   142,    -1,    -1,    65,    68,    -1,    -1,
-      67,    68,    -1,    -1,    69,    30,    70,    31,    -1,   138,
-      -1,    70,    32,   138,    -1,    10,    75,    -1,    -1,    22,
-      72,    75,    -1,    10,    76,    -1,    -1,    22,    74,    76,
-      -1,    77,    -1,    79,    -1,    77,    -1,    81,    -1,    -1,
-      78,   142,    -1,    -1,    80,    83,    -1,    -1,    82,    83,
-      -1,    -1,    84,    30,    85,    31,    -1,   138,    -1,    85,
-      32,   138,    -1,    -1,    11,    87,    89,    -1,    -1,    23,
-      88,    89,    -1,   142,    -1,    -1,    90,    30,    91,    31,
-      -1,    64,    -1,    71,    -1,    91,    32,    64,    -1,    91,
-      32,    71,    -1,    -1,     7,    93,    95,    -1,    -1,    19,
-      94,    95,    -1,   142,    -1,    -1,    96,    30,    97,    31,
-      -1,    64,    -1,    97,    32,    64,    -1,    -1,    13,    99,
-     101,    -1,    -1,    25,   100,   101,    -1,   142,    -1,    -1,
-     102,    30,   103,    31,    -1,    64,    -1,    71,    -1,   103,
-      32,    64,    -1,   103,    32,    71,    -1,     5,   106,    -1,
-      -1,    17,   105,   106,    -1,   107,    -1,   109,    -1,    -1,
-     108,   142,    -1,    -1,   110,   111,    -1,    -1,   112,    30,
-     113,    31,    -1,    68,    -1,   113,    32,    68,    -1,    -1,
-      12,   115,   117,    -1,    -1,    24,   116,   117,    -1,   142,
-      -1,    -1,   118,    30,   119,    31,    -1,    66,    -1,    73,
-      -1,   119,    32,    66,    -1,   119,    32,    73,    -1,    -1,
-       8,   121,   123,    -1,    -1,    20,   122,   123,    -1,   142,
-      -1,    -1,   124,    30,   125,    31,    -1,   109,    -1,   125,
-      32,   109,    -1,    -1,    14,   127,   129,    -1,    -1,    26,
-     128,   129,    -1,   142,    -1,    -1,   130,    30,   131,    31,
-      -1,   109,    -1,   114,    -1,   131,    32,   109,    -1,   131,
-      32,   114,    -1,    -1,     9,   133,   135,    -1,    -1,    21,
-     134,   135,    -1,   142,    -1,    -1,   136,    30,   137,    31,
-      -1,   142,    -1,    40,    -1,   137,    32,    40,    -1,   139,
-      -1,   140,    -1,   141,    -1,    29,    29,    -1,    29,    29,
-      29,    -1,    29,    29,    29,    29,    -1,    28,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const unsigned short yyrline[] =
-{
-       0,    36,    36,    36,    38,    38,    41,    43,    45,    47,
-      49,    51,    53,    55,    57,    59,    61,    63,    65,    68,
-      71,    77,    79,    79,    82,    84,    87,    87,    90,    90,
-      93,    98,    98,   100,   100,   103,   105,   105,   108,   110,
-     113,   116,   116,   122,   124,   124,   127,   129,   132,   132,
-     135,   135,   138,   138,   141,   141,   144,   146,   151,   153,
-     153,   156,   158,   158,   161,   163,   166,   168,   171,   171,
-     174,   174,   177,   177,   180,   180,   183,   185,   190,   190,
-     192,   192,   195,   197,   197,   200,   202,   204,   206,   211,
-     211,   214,   214,   218,   220,   220,   223,   225,   230,   230,
-     233,   233,   237,   239,   239,   242,   244,   246,   248,   253,
-     255,   255,   258,   260,   263,   263,   266,   266,   269,   269,
-     272,   274,   279,   279,   281,   281,   285,   287,   287,   290,
-     292,   294,   296,   301,   301,   303,   303,   307,   309,   309,
-     312,   314,   319,   319,   321,   321,   325,   327,   327,   330,
-     332,   334,   336,   341,   341,   344,   344,   348,   350,   350,
-     354,   356,   358,   362,   364,   366,   369,   372,   375,   378
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE
-/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "POINT", "LINESTRING", "POLYGON",
-  "MULTIPOINT", "MULTILINESTRING", "MULTIPOLYGON", "GEOMETRYCOLLECTION",
-  "CIRCULARSTRING", "COMPOUNDCURVE", "CURVEPOLYGON", "MULTICURVE",
-  "MULTISURFACE", "POINTM", "LINESTRINGM", "POLYGONM", "MULTIPOINTM",
-  "MULTILINESTRINGM", "MULTIPOLYGONM", "GEOMETRYCOLLECTIONM",
-  "CIRCULARSTRINGM", "COMPOUNDCURVEM", "CURVEPOLYGONM", "MULTICURVEM",
-  "MULTISURFACEM", "SRID", "EMPTY", "VALUE", "LPAREN", "RPAREN", "COMMA",
-  "EQUALS", "SEMICOLON", "WKB", "$accept", "geometry", "@1", "@2",
-  "geometry_int", "srid", "geom_wkb", "geom_point", "@3", "point",
-  "empty_point", "@4", "nonempty_point", "@5", "point_int",
-  "geom_multipoint", "@6", "@7", "multipoint", "@8", "multipoint_int",
-  "mpoint_element", "@9", "geom_linestring", "@10", "linestring",
-  "empty_linestring", "@11", "nonempty_linestring", "@12",
-  "nonempty_linestring_closed", "@13", "linestring_1", "@14",
-  "linestring_int", "geom_circularstring", "@15",
-  "geom_circularstring_closed", "@16", "circularstring",
-  "circularstring_closed", "empty_circularstring", "@17",
-  "nonempty_circularstring", "@18", "nonempty_circularstring_closed",
-  "@19", "circularstring_1", "@20", "circularstring_int",
-  "geom_compoundcurve", "@21", "@22", "compoundcurve", "@23",
-  "compoundcurve_int", "geom_multilinestring", "@24", "@25",
-  "multilinestring", "@26", "multilinestring_int", "geom_multicurve",
-  "@27", "@28", "multicurve", "@29", "multicurve_int", "geom_polygon",
-  "@30", "polygon", "empty_polygon", "@31", "nonempty_polygon", "@32",
-  "polygon_1", "@33", "polygon_int", "geom_curvepolygon", "@34", "@35",
-  "curvepolygon", "@36", "curvepolygon_int", "geom_multipolygon", "@37",
-  "@38", "multipolygon", "@39", "multipolygon_int", "geom_multisurface",
-  "@40", "@41", "multisurface", "@42", "multisurface_int",
-  "geom_geometrycollection", "@43", "@44", "geometrycollection", "@45",
-  "geometrycollection_int", "a_point", "point_2d", "point_3d", "point_4d",
-  "empty", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const unsigned short yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const unsigned char yyr1[] =
-{
-       0,    36,    38,    37,    39,    37,    40,    40,    40,    40,
-      40,    40,    40,    40,    40,    40,    40,    40,    40,    41,
-      42,    43,    44,    43,    45,    45,    47,    46,    49,    48,
-      50,    52,    51,    53,    51,    54,    55,    54,    56,    56,
-      57,    58,    57,    59,    60,    59,    61,    61,    63,    62,
-      65,    64,    67,    66,    69,    68,    70,    70,    71,    72,
-      71,    73,    74,    73,    75,    75,    76,    76,    78,    77,
-      80,    79,    82,    81,    84,    83,    85,    85,    87,    86,
-      88,    86,    89,    90,    89,    91,    91,    91,    91,    93,
-      92,    94,    92,    95,    96,    95,    97,    97,    99,    98,
-     100,    98,   101,   102,   101,   103,   103,   103,   103,   104,
-     105,   104,   106,   106,   108,   107,   110,   109,   112,   111,
-     113,   113,   115,   114,   116,   114,   117,   118,   117,   119,
-     119,   119,   119,   121,   120,   122,   120,   123,   124,   123,
-     125,   125,   127,   126,   128,   126,   129,   130,   129,   131,
-     131,   131,   131,   133,   132,   134,   132,   135,   136,   135,
-     137,   137,   137,   138,   138,   138,   139,   140,   141,   142
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const unsigned char yyr2[] =
-{
-       0,     2,     0,     4,     0,     2,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     3,
-       1,     2,     0,     3,     1,     1,     0,     2,     0,     2,
-       3,     0,     3,     0,     3,     1,     0,     4,     1,     3,
-       1,     0,     2,     2,     0,     3,     1,     1,     0,     2,
-       0,     2,     0,     2,     0,     4,     1,     3,     2,     0,
-       3,     2,     0,     3,     1,     1,     1,     1,     0,     2,
-       0,     2,     0,     2,     0,     4,     1,     3,     0,     3,
-       0,     3,     1,     0,     4,     1,     1,     3,     3,     0,
-       3,     0,     3,     1,     0,     4,     1,     3,     0,     3,
-       0,     3,     1,     0,     4,     1,     1,     3,     3,     2,
-       0,     3,     1,     1,     0,     2,     0,     2,     0,     4,
-       1,     3,     0,     3,     0,     3,     1,     0,     4,     1,
-       1,     3,     3,     0,     3,     0,     3,     1,     0,     4,
-       1,     3,     0,     3,     0,     3,     1,     0,     4,     1,
-       1,     3,     3,     0,     3,     0,     3,     1,     0,     4,
-       1,     1,     3,     1,     1,     1,     2,     3,     4,     1
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const unsigned char yydefact[] =
-{
-       4,     0,     0,     0,     0,     0,     1,    26,    48,   114,
-      31,    89,   133,   153,    68,    78,   122,    98,   142,    22,
-      44,   110,    33,    91,   135,   155,    59,    80,   124,   100,
-     144,    20,     5,     6,     7,    13,     8,     9,    11,    14,
-      15,    10,    12,    16,    17,    18,     2,    19,    21,    24,
-       0,    25,     0,    43,    46,     0,    47,    54,   109,   112,
-       0,   113,   118,    36,    94,   138,   158,    58,    64,     0,
-      65,    74,    83,   127,   103,   147,    26,    48,   114,    36,
-      94,   138,   158,    68,    83,   127,   103,   147,     0,   169,
-      27,     0,    29,    49,    51,     0,   115,   117,     0,    32,
-       0,    35,    90,     0,    93,   134,     0,   137,   154,     0,
-     157,    69,    71,     0,    79,     0,    82,   123,     0,   126,
-      99,     0,   102,   143,     0,   146,    23,    45,   111,    34,
-      92,   136,   156,    60,    81,   125,   101,   145,     3,     0,
-       0,   163,   164,   165,     0,    54,    28,    50,   116,     0,
-       0,    50,    52,    50,   116,   166,    30,     0,    56,   120,
-       0,    40,     0,    38,     0,    96,     0,   140,     0,   161,
-       0,   160,     0,    76,    85,    86,     0,    68,    62,   129,
-      54,   130,     0,   105,   106,     0,   149,   150,     0,   167,
-      55,     0,   119,    54,    37,    28,    42,    95,    50,   139,
-     116,   159,     0,    75,     0,    84,    50,    61,    66,    67,
-      74,    68,    53,   128,    52,   104,    50,   148,   116,   168,
-      57,   121,    39,    97,   141,   162,    77,    87,    88,    73,
-      63,   131,   132,   107,   108,   151,   152
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const short yydefgoto[] =
-{
-      -1,     2,    88,     3,    32,     4,    33,    34,    76,    48,
-      49,    50,    51,    52,    92,    35,    63,    79,    99,   100,
-     162,   163,   164,    36,    77,    53,    54,    55,    56,    57,
-     179,   180,    94,    95,   157,    37,    83,   181,   211,    67,
-     207,    68,    69,    70,    71,   209,   210,   112,   113,   172,
-      38,    72,    84,   114,   115,   176,    39,    64,    80,   102,
-     103,   166,    40,    74,    86,   120,   121,   185,    41,    78,
-      58,    59,    60,    61,    62,    97,    98,   160,    42,    73,
-      85,   117,   118,   182,    43,    65,    81,   105,   106,   168,
-      44,    75,    87,   123,   124,   188,    45,    66,    82,   108,
-     109,   170,   140,   141,   142,   143,   101
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -166
-static const short yypact[] =
-{
-     -17,   -14,    21,   145,    -7,     5,  -166,    29,    30,    40,
-    -166,  -166,  -166,  -166,    51,  -166,  -166,  -166,  -166,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
-      23,  -166,    53,  -166,  -166,    23,  -166,  -166,  -166,  -166,
-      23,  -166,  -166,    23,    23,    23,    23,  -166,  -166,    23,
-    -166,  -166,    23,    23,    23,    23,    29,    30,    40,    23,
-      23,    23,    23,    51,    23,    23,    23,    23,   145,  -166,
-    -166,    55,  -166,  -166,  -166,    56,  -166,  -166,    57,  -166,
-      58,  -166,  -166,    59,  -166,  -166,    61,  -166,  -166,    62,
-    -166,  -166,  -166,    63,  -166,    64,  -166,  -166,    65,  -166,
-    -166,    66,  -166,  -166,    67,  -166,  -166,  -166,  -166,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,    70,
-      54,  -166,  -166,  -166,    55,  -166,    72,  -166,  -166,   112,
-      55,     8,    19,     8,    28,    73,  -166,   -18,  -166,  -166,
-      16,  -166,    18,  -166,    55,  -166,    24,  -166,    31,  -166,
-      33,  -166,    35,  -166,  -166,  -166,    42,    74,  -166,  -166,
-    -166,  -166,    44,  -166,  -166,    46,  -166,  -166,    48,    76,
-    -166,    55,  -166,  -166,  -166,    72,  -166,  -166,  -166,  -166,
-    -166,  -166,   145,  -166,    55,  -166,     8,  -166,  -166,  -166,
-    -166,    74,  -166,  -166,    19,  -166,     8,  -166,    28,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const short yypgoto[] =
-{
-    -166,  -166,  -166,  -166,   -88,  -166,  -166,  -166,  -166,    27,
-    -166,  -166,  -142,  -166,  -166,  -166,  -166,  -166,    32,  -166,
-    -166,   -89,  -166,  -166,  -166,    36,  -166,  -166,  -108,  -166,
-    -107,  -166,  -136,  -166,  -166,  -148,  -166,  -105,  -166,    60,
-    -101,  -165,  -166,  -166,  -166,  -166,  -166,   -98,  -166,  -166,
-    -166,  -166,  -166,    88,  -166,  -166,  -166,  -166,  -166,    93,
-    -166,  -166,  -166,  -166,  -166,    89,  -166,  -166,  -166,  -166,
-      68,  -166,  -166,  -146,  -166,  -166,  -166,  -166,  -147,  -166,
-    -166,    91,  -166,  -166,  -166,  -166,  -166,    96,  -166,  -166,
-    -166,  -166,  -166,    52,  -166,  -166,  -166,  -166,  -166,    92,
-    -166,  -166,  -122,  -166,  -166,  -166,   -49
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -117
-static const short yytable[] =
-{
-     138,    90,   167,   175,   161,   184,    93,   187,   186,   159,
-       1,    96,   208,   190,   191,   104,   107,   110,    14,     5,
-     111,     6,   158,   116,   119,   122,   125,    46,   173,   177,
-      26,   104,   107,   110,    47,   116,   119,   122,   125,   165,
-      16,   178,   196,   174,   212,   183,   208,   192,   193,   194,
-     195,    89,    28,   161,   224,   197,   198,   221,   228,   -28,
-     -50,   169,   199,   200,   201,   202,   203,   204,   234,   220,
-    -116,   236,   235,   205,   206,   213,   214,   215,   216,   217,
-     218,   -70,   226,    91,   139,   156,   144,   145,   146,   147,
-     223,   148,   149,   150,   151,   152,   153,   154,   227,   155,
-     171,   -41,   189,   126,   -72,   219,   222,   231,   233,   232,
-     230,   129,   229,   127,   225,     7,     8,     9,    10,    11,
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,   137,
-      89,     0,     0,   133,     0,     0,   128,    31,     7,     8,
-       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,   134,   130,   132,   136,   135,   131,     0,     0,
-      31
-};
-
-static const short yycheck[] =
-{
-      88,    50,   148,   151,   146,   153,    55,   154,   154,   145,
-      27,    60,   177,    31,    32,    64,    65,    66,    10,    33,
-      69,     0,   144,    72,    73,    74,    75,    34,   150,    10,
-      22,    80,    81,    82,    29,    84,    85,    86,    87,   147,
-      12,    22,   164,   151,   180,   153,   211,    31,    32,    31,
-      32,    28,    24,   195,   200,    31,    32,   193,   206,    30,
-      30,   149,    31,    32,    31,    32,    31,    32,   216,   191,
-      30,   218,   218,    31,    32,    31,    32,    31,    32,    31,
-      32,    30,   204,    30,    29,    31,    30,    30,    30,    30,
-     198,    30,    30,    30,    30,    30,    30,    30,   206,    29,
-     149,    29,    29,    76,    30,    29,   195,   214,   216,   214,
-     211,    79,   210,    77,   202,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    87,
-      28,    -1,    -1,    83,    -1,    -1,    78,    35,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    84,    80,    82,    86,    85,    81,    -1,    -1,
-      35
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const unsigned char yystos[] =
-{
-       0,    27,    37,    39,    41,    33,     0,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    35,    40,    42,    43,    51,    59,    71,    86,    92,
-      98,   104,   114,   120,   126,   132,    34,    29,    45,    46,
-      47,    48,    49,    61,    62,    63,    64,    65,   106,   107,
-     108,   109,   110,    52,    93,   121,   133,    75,    77,    78,
-      79,    80,    87,   115,    99,   127,    44,    60,   105,    53,
-      94,   122,   134,    72,    88,   116,   100,   128,    38,    28,
-     142,    30,    50,   142,    68,    69,   142,   111,   112,    54,
-      55,   142,    95,    96,   142,   123,   124,   142,   135,   136,
-     142,   142,    83,    84,    89,    90,   142,   117,   118,   142,
-     101,   102,   142,   129,   130,   142,    45,    61,   106,    54,
-      95,   123,   135,    75,    89,   117,   101,   129,    40,    29,
-     138,   139,   140,   141,    30,    30,    30,    30,    30,    30,
-      30,    30,    30,    30,    30,    29,    31,    70,   138,    68,
-     113,    48,    56,    57,    58,    64,    97,   109,   125,    40,
-     137,   142,    85,   138,    64,    71,    91,    10,    22,    66,
-      67,    73,   119,    64,    71,   103,   109,   114,   131,    29,
-      31,    32,    31,    32,    31,    32,   138,    31,    32,    31,
-      32,    31,    32,    31,    32,    31,    32,    76,    77,    81,
-      82,    74,    68,    31,    32,    31,    32,    31,    32,    29,
-     138,    68,    57,    64,   109,    40,   138,    64,    71,    83,
-      76,    66,    73,    64,    71,   109,   114
-};
-
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
-#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
-#endif
-#if ! defined (YYSIZE_T)
-# if defined (__STDC__) || defined (__cplusplus)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# endif
-#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
-#endif
-
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
-
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL		goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)					\
-do								\
-  if (yychar == YYEMPTY && yylen == 1)				\
-    {								\
-      yychar = (Token);						\
-      yylval = (Value);						\
-      yytoken = YYTRANSLATE (yychar);				\
-      YYPOPSTACK;						\
-      goto yybackup;						\
-    }								\
-  else								\
-    { 								\
-      yyerror ("syntax error: cannot back up");\
-      YYERROR;							\
-    }								\
-while (0)
-
-#define YYTERROR	1
-#define YYERRCODE	256
-
-/* YYLLOC_DEFAULT -- Compute the default location (before the actions
-   are run).  */
-
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)		\
-   ((Current).first_line   = (Rhs)[1].first_line,	\
-    (Current).first_column = (Rhs)[1].first_column,	\
-    (Current).last_line    = (Rhs)[N].last_line,	\
-    (Current).last_column  = (Rhs)[N].last_column)
-#endif
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (0)
-
-# define YYDSYMPRINT(Args)			\
-do {						\
-  if (yydebug)					\
-    yysymprint Args;				\
-} while (0)
-
-# define YYDSYMPRINTF(Title, Token, Value, Location)		\
-do {								\
-  if (yydebug)							\
-    {								\
-      YYFPRINTF (stderr, "%s ", Title);				\
-      yysymprint (stderr, 					\
-                  Token, Value);	\
-      YYFPRINTF (stderr, "\n");					\
-    }								\
-} while (0)
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_stack_print (short *bottom, short *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    short *bottom;
-    short *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (/* Nothing. */; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (0)
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_reduce_print (int yyrule)
-#else
-static void
-yy_reduce_print (yyrule)
-    int yyrule;
-#endif
-{
-  int yyi;
-  unsigned int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
-             yyrule - 1, yylno);
-  /* Print the symbols being reduced, and their result.  */
-  for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
-    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
-  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
-}
-
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (Rule);		\
-} while (0)
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YYDSYMPRINT(Args)
-# define YYDSYMPRINTF(Title, Token, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
-# undef YYMAXDEPTH
-#endif
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined (__GLIBC__) && defined (_STRING_H)
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-static YYSIZE_T
-#   if defined (__STDC__) || defined (__cplusplus)
-yystrlen (const char *yystr)
-#   else
-yystrlen (yystr)
-     const char *yystr;
-#   endif
-{
-  register const char *yys = yystr;
-
-  while (*yys++ != '\0')
-    continue;
-
-  return yys - yystr - 1;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-static char *
-#   if defined (__STDC__) || defined (__cplusplus)
-yystpcpy (char *yydest, const char *yysrc)
-#   else
-yystpcpy (yydest, yysrc)
-     char *yydest;
-     const char *yysrc;
-#   endif
-{
-  register char *yyd = yydest;
-  register const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-#endif /* !YYERROR_VERBOSE */
-
-
-
-#if YYDEBUG
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yysymprint (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  /* Pacify ``unused variable'' warnings.  */
-  (void) yyvaluep;
-
-  if (yytype < YYNTOKENS)
-    {
-      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-# ifdef YYPRINT
-      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
-    }
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  switch (yytype)
-    {
-      default:
-        break;
-    }
-  YYFPRINTF (yyoutput, ")");
-}
-
-#endif /* ! YYDEBUG */
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yydestruct (int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yytype, yyvaluep)
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  /* Pacify ``unused variable'' warnings.  */
-  (void) yyvaluep;
-
-  switch (yytype)
-    {
-
-      default:
-        break;
-    }
-}
-
-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM);
-# else
-int yyparse ();
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-/* The lookahead symbol.  */
-int yychar;
-
-/* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM)
-# else
-int yyparse (YYPARSE_PARAM)
-  void *YYPARSE_PARAM;
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-  
-  register int yystate;
-  register int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  short	yyssa[YYINITDEPTH];
-  short *yyss = yyssa;
-  register short *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  register YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK   (yyvsp--, yyssp--)
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* When reducing, the number of symbols on the RHS of the reduced
-     rule.  */
-  int yylen;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;		/* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed. so pushing a state here evens the stacks.
-     */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-	/* Give user a chance to reallocate the stack. Use copies of
-	   these so that the &'s don't force the real ones into
-	   memory.  */
-	YYSTYPE *yyvs1 = yyvs;
-	short *yyss1 = yyss;
-
-
-	/* Each stack pointer address is followed by the size of the
-	   data in use in that stack, in bytes.  This used to be a
-	   conditional around just the two extra args, but that might
-	   be undefined if yyoverflow is a macro.  */
-	yyoverflow ("parser stack overflow",
-		    &yyss1, yysize * sizeof (*yyssp),
-		    &yyvs1, yysize * sizeof (*yyvsp),
-
-		    &yystacksize);
-
-	yyss = yyss1;
-	yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyoverflowlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-	goto yyoverflowlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-	yystacksize = YYMAXDEPTH;
-
-      {
-	short *yyss1 = yyss;
-	union yyalloc *yyptr =
-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-	if (! yyptr)
-	  goto yyoverflowlab;
-	YYSTACK_RELOCATE (yyss);
-	YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-	if (yyss1 != yyssa)
-	  YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-		  (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-	YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-/* Do appropriate processing given the current state.  */
-/* Read a lookahead token if we need one and don't already have one.  */
-/* yyresume: */
-
-  /* First try to decide what to do without reference to lookahead token.  */
-
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a lookahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-	goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Shift the lookahead token.  */
-  YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
-
-  /* Discard the token being shifted unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  *++yyvsp = yylval;
-
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 2:
-#line 36 "wktparse.y"
-    { alloc_lwgeom(srid); }
-    break;
-
-  case 4:
-#line 38 "wktparse.y"
-    { alloc_lwgeom(-1); }
-    break;
-
-  case 19:
-#line 68 "wktparse.y"
-    { set_srid(yyvsp[0].value); }
-    break;
-
-  case 20:
-#line 71 "wktparse.y"
-    { alloc_wkb(yyvsp[0].wkb); }
-    break;
-
-  case 22:
-#line 79 "wktparse.y"
-    { set_zm(0, 1); }
-    break;
-
-  case 26:
-#line 87 "wktparse.y"
-    { alloc_point(); }
-    break;
-
-  case 27:
-#line 87 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 28:
-#line 90 "wktparse.y"
-    { alloc_point(); }
-    break;
-
-  case 29:
-#line 90 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 31:
-#line 98 "wktparse.y"
-    { alloc_multipoint(); }
-    break;
-
-  case 32:
-#line 98 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 33:
-#line 100 "wktparse.y"
-    { set_zm(0, 1); alloc_multipoint(); }
-    break;
-
-  case 34:
-#line 100 "wktparse.y"
-    {pop(); }
-    break;
-
-  case 36:
-#line 105 "wktparse.y"
-    { alloc_counter(); }
-    break;
-
-  case 37:
-#line 105 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 41:
-#line 116 "wktparse.y"
-    { alloc_point(); }
-    break;
-
-  case 42:
-#line 116 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 44:
-#line 124 "wktparse.y"
-    { set_zm(0, 1); }
-    break;
-
-  case 48:
-#line 132 "wktparse.y"
-    { alloc_linestring(); }
-    break;
-
-  case 49:
-#line 132 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 50:
-#line 135 "wktparse.y"
-    { alloc_linestring(); }
-    break;
-
-  case 51:
-#line 135 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 52:
-#line 138 "wktparse.y"
-    { alloc_linestring_closed(); }
-    break;
-
-  case 53:
-#line 138 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 54:
-#line 141 "wktparse.y"
-    { alloc_counter(); }
-    break;
-
-  case 55:
-#line 141 "wktparse.y"
-    { popc(); }
-    break;
-
-  case 59:
-#line 153 "wktparse.y"
-    {set_zm(0, 1); }
-    break;
-
-  case 62:
-#line 158 "wktparse.y"
-    {set_zm(0, 1); }
-    break;
-
-  case 68:
-#line 171 "wktparse.y"
-    { alloc_circularstring(); }
-    break;
-
-  case 69:
-#line 171 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 70:
-#line 174 "wktparse.y"
-    { alloc_circularstring(); }
-    break;
-
-  case 71:
-#line 174 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 72:
-#line 177 "wktparse.y"
-    { alloc_circularstring_closed(); }
-    break;
-
-  case 73:
-#line 177 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 74:
-#line 180 "wktparse.y"
-    { alloc_counter(); }
-    break;
-
-  case 75:
-#line 180 "wktparse.y"
-    { popc(); }
-    break;
-
-  case 78:
-#line 190 "wktparse.y"
-    { alloc_compoundcurve(); }
-    break;
-
-  case 79:
-#line 190 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 80:
-#line 192 "wktparse.y"
-    {set_zm(0, 1); alloc_compoundcurve(); }
-    break;
-
-  case 81:
-#line 192 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 83:
-#line 197 "wktparse.y"
-    { alloc_counter(); }
-    break;
-
-  case 84:
-#line 197 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 89:
-#line 211 "wktparse.y"
-    { alloc_multilinestring(); }
-    break;
-
-  case 90:
-#line 212 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 91:
-#line 214 "wktparse.y"
-    { set_zm(0, 1); alloc_multilinestring(); }
-    break;
-
-  case 92:
-#line 215 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 94:
-#line 220 "wktparse.y"
-    { alloc_counter(); }
-    break;
-
-  case 95:
-#line 220 "wktparse.y"
-    { pop();}
-    break;
-
-  case 98:
-#line 230 "wktparse.y"
-    { alloc_multicurve(); }
-    break;
-
-  case 99:
-#line 231 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 100:
-#line 233 "wktparse.y"
-    { set_zm(0, 1); alloc_multicurve(); }
-    break;
-
-  case 101:
-#line 234 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 103:
-#line 239 "wktparse.y"
-    { alloc_counter(); }
-    break;
-
-  case 104:
-#line 239 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 110:
-#line 255 "wktparse.y"
-    { set_zm(0, 1); }
-    break;
-
-  case 114:
-#line 263 "wktparse.y"
-    { alloc_polygon(); }
-    break;
-
-  case 115:
-#line 263 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 116:
-#line 266 "wktparse.y"
-    { alloc_polygon(); }
-    break;
-
-  case 117:
-#line 266 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 118:
-#line 269 "wktparse.y"
-    { alloc_counter(); }
-    break;
-
-  case 119:
-#line 269 "wktparse.y"
-    { pop();}
-    break;
-
-  case 122:
-#line 279 "wktparse.y"
-    { alloc_curvepolygon(); }
-    break;
-
-  case 123:
-#line 279 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 124:
-#line 281 "wktparse.y"
-    { set_zm(0, 1); alloc_curvepolygon(); }
-    break;
-
-  case 125:
-#line 282 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 127:
-#line 287 "wktparse.y"
-    { alloc_counter(); }
-    break;
-
-  case 128:
-#line 287 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 133:
-#line 301 "wktparse.y"
-    { alloc_multipolygon(); }
-    break;
-
-  case 134:
-#line 301 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 135:
-#line 303 "wktparse.y"
-    { set_zm(0, 1); alloc_multipolygon(); }
-    break;
-
-  case 136:
-#line 304 "wktparse.y"
-    { pop();}
-    break;
-
-  case 138:
-#line 309 "wktparse.y"
-    { alloc_counter(); }
-    break;
-
-  case 139:
-#line 309 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 142:
-#line 319 "wktparse.y"
-    {alloc_multisurface(); }
-    break;
-
-  case 143:
-#line 319 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 144:
-#line 321 "wktparse.y"
-    { set_zm(0, 1); alloc_multisurface(); }
-    break;
-
-  case 145:
-#line 322 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 147:
-#line 327 "wktparse.y"
-    { alloc_counter(); }
-    break;
-
-  case 148:
-#line 327 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 153:
-#line 341 "wktparse.y"
-    { alloc_geomertycollection(); }
-    break;
-
-  case 154:
-#line 342 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 155:
-#line 344 "wktparse.y"
-    { set_zm(0, 1); alloc_geomertycollection(); }
-    break;
-
-  case 156:
-#line 345 "wktparse.y"
-    { pop();}
-    break;
-
-  case 158:
-#line 350 "wktparse.y"
-    { alloc_counter(); }
-    break;
-
-  case 159:
-#line 350 "wktparse.y"
-    { pop(); }
-    break;
-
-  case 166:
-#line 369 "wktparse.y"
-    {alloc_point_2d(yyvsp[-1].value,yyvsp[0].value); }
-    break;
-
-  case 167:
-#line 372 "wktparse.y"
-    {alloc_point_3d(yyvsp[-2].value,yyvsp[-1].value,yyvsp[0].value); }
-    break;
-
-  case 168:
-#line 375 "wktparse.y"
-    {alloc_point_4d(yyvsp[-3].value,yyvsp[-2].value,yyvsp[-1].value,yyvsp[0].value); }
-    break;
-
-  case 169:
-#line 378 "wktparse.y"
-    { alloc_empty(); }
-    break;
-
-
-    }
-
-/* Line 1000 of yacc.c.  */
-#line 1761 "y.tab.c"
-
-  yyvsp -= yylen;
-  yyssp -= yylen;
-
-
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if YYERROR_VERBOSE
-      yyn = yypact[yystate];
-
-      if (YYPACT_NINF < yyn && yyn < YYLAST)
-	{
-	  YYSIZE_T yysize = 0;
-	  int yytype = YYTRANSLATE (yychar);
-	  const char* yyprefix;
-	  char *yymsg;
-	  int yyx;
-
-	  /* Start YYX at -YYN if negative to avoid negative indexes in
-	     YYCHECK.  */
-	  int yyxbegin = yyn < 0 ? -yyn : 0;
-
-	  /* Stay within bounds of both yycheck and yytname.  */
-	  int yychecklim = YYLAST - yyn;
-	  int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-	  int yycount = 0;
-
-	  yyprefix = ", expecting ";
-	  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-	      {
-		yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
-		yycount += 1;
-		if (yycount == 5)
-		  {
-		    yysize = 0;
-		    break;
-		  }
-	      }
-	  yysize += (sizeof ("syntax error, unexpected ")
-		     + yystrlen (yytname[yytype]));
-	  yymsg = (char *) YYSTACK_ALLOC (yysize);
-	  if (yymsg != 0)
-	    {
-	      char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
-	      yyp = yystpcpy (yyp, yytname[yytype]);
-
-	      if (yycount < 5)
-		{
-		  yyprefix = ", expecting ";
-		  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-		    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-		      {
-			yyp = yystpcpy (yyp, yyprefix);
-			yyp = yystpcpy (yyp, yytname[yyx]);
-			yyprefix = " or ";
-		      }
-		}
-	      yyerror (yymsg);
-	      YYSTACK_FREE (yymsg);
-	    }
-	  else
-	    yyerror ("syntax error; also virtual memory exhausted");
-	}
-      else
-#endif /* YYERROR_VERBOSE */
-	yyerror ("syntax error");
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse lookahead token after an
-	 error, discard it.  */
-
-      if (yychar <= YYEOF)
-        {
-          /* If at end of input, pop the error token,
-	     then the rest of the stack, then return failure.  */
-	  if (yychar == YYEOF)
-	     for (;;)
-	       {
-		 YYPOPSTACK;
-		 if (yyssp == yyss)
-		   YYABORT;
-		 YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
-		 yydestruct (yystos[*yyssp], yyvsp);
-	       }
-        }
-      else
-	{
-	  YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
-	  yydestruct (yytoken, &yylval);
-	  yychar = YYEMPTY;
-
-	}
-    }
-
-  /* Else will try to reuse lookahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-#ifdef __GNUC__
-  /* Pacify GCC when the user code never invokes YYERROR and the label
-     yyerrorlab therefore never appears in user code.  */
-  if (0)
-     goto yyerrorlab;
-#endif
-
-  yyvsp -= yylen;
-  yyssp -= yylen;
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-	{
-	  yyn += YYTERROR;
-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-	    {
-	      yyn = yytable[yyn];
-	      if (0 < yyn)
-		break;
-	    }
-	}
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-	YYABORT;
-
-      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
-      yydestruct (yystos[yystate], yyvsp);
-      YYPOPSTACK;
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  YYDPRINTF ((stderr, "Shifting error token, "));
-
-  *++yyvsp = yylval;
-
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here.  |
-`----------------------------------------------*/
-yyoverflowlab:
-  yyerror ("parser stack overflow");
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-  return yyresult;
-}
-
-
-#line 379 "wktparse.y"
-
-
-
-
-
-

Deleted: trunk/lwgeom/wktparse.tab.h
===================================================================
--- trunk/lwgeom/wktparse.tab.h	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/wktparse.tab.h	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,120 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875c.  */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-
-   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, 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.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, when this file is copied by Bison into a
-   Bison output file, you may use that output file without restriction.
-   This special exception was added by the Free Software Foundation
-   in version 1.24 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     POINT = 258,
-     LINESTRING = 259,
-     POLYGON = 260,
-     MULTIPOINT = 261,
-     MULTILINESTRING = 262,
-     MULTIPOLYGON = 263,
-     GEOMETRYCOLLECTION = 264,
-     CIRCULARSTRING = 265,
-     COMPOUNDCURVE = 266,
-     CURVEPOLYGON = 267,
-     MULTICURVE = 268,
-     MULTISURFACE = 269,
-     POINTM = 270,
-     LINESTRINGM = 271,
-     POLYGONM = 272,
-     MULTIPOINTM = 273,
-     MULTILINESTRINGM = 274,
-     MULTIPOLYGONM = 275,
-     GEOMETRYCOLLECTIONM = 276,
-     CIRCULARSTRINGM = 277,
-     COMPOUNDCURVEM = 278,
-     CURVEPOLYGONM = 279,
-     MULTICURVEM = 280,
-     MULTISURFACEM = 281,
-     SRID = 282,
-     EMPTY = 283,
-     VALUE = 284,
-     LPAREN = 285,
-     RPAREN = 286,
-     COMMA = 287,
-     EQUALS = 288,
-     SEMICOLON = 289,
-     WKB = 290
-   };
-#endif
-#define POINT 258
-#define LINESTRING 259
-#define POLYGON 260
-#define MULTIPOINT 261
-#define MULTILINESTRING 262
-#define MULTIPOLYGON 263
-#define GEOMETRYCOLLECTION 264
-#define CIRCULARSTRING 265
-#define COMPOUNDCURVE 266
-#define CURVEPOLYGON 267
-#define MULTICURVE 268
-#define MULTISURFACE 269
-#define POINTM 270
-#define LINESTRINGM 271
-#define POLYGONM 272
-#define MULTIPOINTM 273
-#define MULTILINESTRINGM 274
-#define MULTIPOLYGONM 275
-#define GEOMETRYCOLLECTIONM 276
-#define CIRCULARSTRINGM 277
-#define COMPOUNDCURVEM 278
-#define CURVEPOLYGONM 279
-#define MULTICURVEM 280
-#define MULTISURFACEM 281
-#define SRID 282
-#define EMPTY 283
-#define VALUE 284
-#define LPAREN 285
-#define RPAREN 286
-#define COMMA 287
-#define EQUALS 288
-#define SEMICOLON 289
-#define WKB 290
-
-
-
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-#line 20 "wktparse.y"
-typedef union YYSTYPE {
-	double value;
-	const char* wkb;
-} YYSTYPE;
-/* Line 1275 of yacc.c.  */
-#line 112 "y.tab.h"
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE lwg_parse_yylval;
-
-
-

Deleted: trunk/lwgeom/wktparse.y
===================================================================
--- trunk/lwgeom/wktparse.y	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/wktparse.y	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,383 +0,0 @@
-/*
- * Written by Ralph Mason ralph.mason<at>telogis.com
- *
- * Copyright Telogis 2004
- * www.telogis.com
- *
- */
-
-%{
-#include "wktparse.h"
-#include <unistd.h>
-#include <stdio.h>
-
-void set_zm(char z, char m);
-int lwg_parse_yylex(void);
-%}
-
-%start geometry
-
-%union {
-	double value;
-	const char* wkb;
-}
-
-%token POINT LINESTRING POLYGON MULTIPOINT MULTILINESTRING MULTIPOLYGON GEOMETRYCOLLECTION CIRCULARSTRING COMPOUNDCURVE CURVEPOLYGON MULTICURVE MULTISURFACE
-%token POINTM LINESTRINGM POLYGONM MULTIPOINTM MULTILINESTRINGM MULTIPOLYGONM GEOMETRYCOLLECTIONM CIRCULARSTRINGM COMPOUNDCURVEM CURVEPOLYGONM  MULTICURVEM MULTISURFACEM
-%token SRID      
-%token EMPTY
-%token <value> VALUE
-%token LPAREN RPAREN COMMA EQUALS SEMICOLON
-%token  <wkb> WKB
-
-%%
-
-geometry :
-	srid  SEMICOLON  { alloc_lwgeom(srid); } geometry_int 
-	|
-	{ alloc_lwgeom(-1); } geometry_int
-
-geometry_int :
-	geom_wkb
-	|
-	geom_point
-	|
-	geom_linestring
-	|
-        geom_circularstring
-        |
-	geom_polygon
-	|
-        geom_compoundcurve
-        |
-        geom_curvepolygon
-        |
-	geom_multipoint 
-	|
-	geom_multilinestring
-        |
-        geom_multicurve
-	|
-	geom_multipolygon
-	|
-        geom_multisurface
-        |
-	geom_geometrycollection
-
-srid :
-	SRID EQUALS VALUE { set_srid($3); } 
-
-geom_wkb :
-	WKB { alloc_wkb($1); }
-
-
-/* POINT */
-
-geom_point :
-	POINT point
-	|
-	POINTM { set_zm(0, 1); } point 
-
-point :
-	empty_point
-	|
-	nonempty_point
-
-empty_point :
-	{ alloc_point(); } empty { pop(); } 
-
-nonempty_point :
-	{ alloc_point(); } point_int { pop(); } 
-
-point_int :
-	LPAREN a_point RPAREN
-
-/* MULTIPOINT */
-
-geom_multipoint :
-	MULTIPOINT { alloc_multipoint(); } multipoint  { pop(); }
-	| 
-	MULTIPOINTM { set_zm(0, 1); alloc_multipoint(); } multipoint {pop(); }
-
-multipoint :
-	empty
-	|
-	{ alloc_counter(); } LPAREN multipoint_int RPAREN { pop(); } 
-
-multipoint_int :
-	mpoint_element
-	|
-	multipoint_int COMMA mpoint_element
-
-mpoint_element :
-	nonempty_point
-	|
-	/* this is to allow MULTIPOINT(0 0, 1 1) */
-	{ alloc_point(); } a_point { pop(); }
-
-
-/* LINESTRING */
-
-geom_linestring :
-	LINESTRING linestring
-	|
-	LINESTRINGM { set_zm(0, 1); } linestring
-
-linestring :
-	empty_linestring
-	|
-	nonempty_linestring
-
-empty_linestring :
-	{ alloc_linestring(); } empty { pop(); } 
-
-nonempty_linestring :
-	{ alloc_linestring(); } linestring_1 { pop(); } 
-
-nonempty_linestring_closed :
-        { alloc_linestring_closed(); } linestring_1 { pop(); }
-
-linestring_1 :
-	{ alloc_counter(); } LPAREN linestring_int RPAREN { popc(); }
-
-linestring_int :
-	a_point
-	|
-	linestring_int COMMA a_point;
-
-/* CIRCULARSTRING */
-
-geom_circularstring :
-        CIRCULARSTRING circularstring
-        |
-        CIRCULARSTRINGM {set_zm(0, 1); } circularstring
-
-geom_circularstring_closed :
-        CIRCULARSTRING circularstring_closed
-        |
-        CIRCULARSTRINGM {set_zm(0, 1); } circularstring_closed
-
-circularstring :
-        empty_circularstring
-        |
-        nonempty_circularstring
-
-circularstring_closed :
-        empty_circularstring
-        |
-        nonempty_circularstring_closed
-
-empty_circularstring :
-        { alloc_circularstring(); } empty { pop(); }
-
-nonempty_circularstring :
-        { alloc_circularstring(); } circularstring_1 { pop(); }
-
-nonempty_circularstring_closed :
-        { alloc_circularstring_closed(); } circularstring_1 { pop(); }
-
-circularstring_1 :
-        { alloc_counter(); } LPAREN circularstring_int RPAREN { popc(); }
-
-circularstring_int :
-        a_point
-        |
-        circularstring_int COMMA a_point;
-
-/* COMPOUNDCURVE */
-
-geom_compoundcurve:
-        COMPOUNDCURVE { alloc_compoundcurve(); } compoundcurve { pop(); }
-        |
-        COMPOUNDCURVEM {set_zm(0, 1); alloc_compoundcurve(); } compoundcurve { pop(); }
-
-compoundcurve:
-        empty
-        |
-        { alloc_counter(); } LPAREN compoundcurve_int RPAREN { pop(); }
-
-compoundcurve_int:
-        nonempty_linestring
-        |
-        geom_circularstring
-        |
-        compoundcurve_int COMMA nonempty_linestring
-        |
-        compoundcurve_int COMMA geom_circularstring
-
-/* MULTILINESTRING */
-
-geom_multilinestring :
-	MULTILINESTRING { alloc_multilinestring(); }
-		multilinestring  { pop(); }
-	|
-	MULTILINESTRINGM { set_zm(0, 1); alloc_multilinestring(); }
-		multilinestring { pop(); } 
-
-multilinestring :
-	empty
-	|
-	{ alloc_counter(); } LPAREN multilinestring_int RPAREN{ pop();}
-
-multilinestring_int :
-	nonempty_linestring
-	|
-	multilinestring_int COMMA nonempty_linestring
-
-/* MULTICURVESTRING */
-
-geom_multicurve :
-        MULTICURVE { alloc_multicurve(); }
-                multicurve { pop(); }
-        |
-        MULTICURVEM { set_zm(0, 1); alloc_multicurve(); }
-                multicurve { pop(); }
-
-multicurve :
-        empty
-        |
-        { alloc_counter(); } LPAREN multicurve_int RPAREN { pop(); }
-
-multicurve_int :
-        nonempty_linestring
-        |
-        geom_circularstring
-        |
-        multicurve_int COMMA nonempty_linestring
-        |
-        multicurve_int COMMA geom_circularstring
-
-/* POLYGON */
-
-geom_polygon :
-	POLYGON polygon
-	|
-	POLYGONM { set_zm(0, 1); } polygon 
-
-polygon :
-	empty_polygon
-	|
-	nonempty_polygon
-
-empty_polygon :
-	{ alloc_polygon(); } empty  { pop(); } 
-
-nonempty_polygon :
-	{ alloc_polygon(); } polygon_1  { pop(); } 
-
-polygon_1 :
-	{ alloc_counter(); } LPAREN polygon_int RPAREN { pop();} 
-
-polygon_int :
-	linestring_1
-	|
-	polygon_int COMMA linestring_1
-
-/* CURVEPOLYGON */
-
-geom_curvepolygon :
-        CURVEPOLYGON { alloc_curvepolygon(); } curvepolygon { pop(); }
-        |
-        CURVEPOLYGONM { set_zm(0, 1); alloc_curvepolygon(); } 
-                        curvepolygon { pop(); }
-
-curvepolygon :
-        empty
-        |
-        { alloc_counter(); } LPAREN curvepolygon_int RPAREN { pop(); }
-
-curvepolygon_int :
-        nonempty_linestring_closed
-        |
-        geom_circularstring_closed
-        |
-        curvepolygon_int COMMA nonempty_linestring_closed
-        |
-        curvepolygon_int COMMA geom_circularstring_closed
-
-/* MULTIPOLYGON */
-
-geom_multipolygon :
-	MULTIPOLYGON { alloc_multipolygon(); } multipolygon { pop(); }
-	|
-	MULTIPOLYGONM { set_zm(0, 1); alloc_multipolygon(); }
-		multipolygon { pop();} 
-
-multipolygon :
-	empty
-	|
-	{ alloc_counter(); } LPAREN multipolygon_int RPAREN { pop(); }
-
-multipolygon_int :
-	nonempty_polygon
-	|
-	multipolygon_int COMMA nonempty_polygon
-
-/* MULTISURFACE */
-
-geom_multisurface :
-        MULTISURFACE {alloc_multisurface(); } multisurface { pop(); }
-        |
-        MULTISURFACEM { set_zm(0, 1); alloc_multisurface(); }
-                multisurface { pop(); }
-
-multisurface :
-        empty
-        |
-        { alloc_counter(); } LPAREN multisurface_int RPAREN { pop(); }
-
-multisurface_int :
-        nonempty_polygon
-        |
-        geom_curvepolygon
-        |
-        multisurface_int COMMA nonempty_polygon
-        |
-        multisurface_int COMMA geom_curvepolygon
-
-/* GEOMETRYCOLLECTION */
-
-geom_geometrycollection :
-	GEOMETRYCOLLECTION { alloc_geomertycollection(); }
-		geometrycollection { pop(); }
-	|
-	GEOMETRYCOLLECTIONM { set_zm(0, 1); alloc_geomertycollection(); }
-		geometrycollection { pop();}
-
-geometrycollection :
-	empty
-	|
-	{ alloc_counter(); } LPAREN geometrycollection_int RPAREN { pop(); }
-
-geometrycollection_int :
-	/* to support GEOMETRYCOLLECTION(EMPTY) for backward compatibility */
-	empty
-	|
-	geometry_int
-	|
-	geometrycollection_int COMMA geometry_int
-
-
-a_point :
-	point_2d
-	|
-	point_3d
-	|
-	point_4d 
-
-point_2d :
-	VALUE VALUE {alloc_point_2d($1,$2); }
-
-point_3d :
-	VALUE VALUE VALUE {alloc_point_3d($1,$2,$3); }
-
-point_4d :
-	VALUE VALUE VALUE VALUE {alloc_point_4d($1,$2,$3,$4); }
-
-empty :
-	EMPTY { alloc_empty(); }
-%%
-
-
-
-

Deleted: trunk/lwgeom/wktunparse.c
===================================================================
--- trunk/lwgeom/wktunparse.c	2008-06-28 05:34:59 UTC (rev 2814)
+++ trunk/lwgeom/wktunparse.c	2008-06-29 19:11:48 UTC (rev 2815)
@@ -1,765 +0,0 @@
-/*
- * Written by Ralph Mason ralph.mason<at>telogis.com
- *
- * Copyright Telogis 2004
- * www.telogis.com
- *
- * $Id$
- */
-
-
-#include <string.h>
-#include <math.h>
-#include <stdio.h>
-/* TO get byte order */
-#include <sys/types.h>
-#include <sys/param.h>
-/* Solaris9 does not provide stdint.h */
-/* #include <stdint.h> */
-#include <inttypes.h>
-
-#include "liblwgeom.h"
-#include "wktparse.h"
-
-
-/*-- Typedefs ---------------------------------------------- */
-
-typedef uint32_t int4;
-typedef uchar* (*outfunc)(uchar*,int);
-typedef uchar* (*outwkbfunc)(uchar*);
-
-/*-- Prototypes -------------------------------------------- */
-
-void ensure(int chars);
-void to_end(void);
-void write_str(const char* str);
-void write_double(double val);
-void write_int(int i);
-int4 read_int(uchar** geom);
-double read_double(uchar** geom);
-uchar* output_point(uchar* geom,int supress);
-uchar* output_single(uchar* geom,int supress);
-uchar* output_collection(uchar* geom,outfunc func,int supress);
-uchar* output_collection_2(uchar* geom,int suppress);
-uchar* output_multipoint(uchar* geom,int suppress);
-uchar* output_compound(uchar* geom, int suppress);
-uchar* output_multisurface(uchar* geom, int suppress);
-
-void write_wkb_hex_bytes(uchar* ptr, unsigned int cnt, size_t size);
-void write_wkb_bin_bytes(uchar* ptr, unsigned int cnt, size_t size);
-void write_wkb_bin_flip_bytes(uchar* ptr, unsigned int cnt, size_t size);
-void write_wkb_hex_flip_bytes(uchar* ptr, unsigned int cnt, size_t size);
-
-void write_wkb_int(int i);
-uchar* output_wkb_collection(uchar* geom,outwkbfunc func);
-uchar* output_wkb_collection_2(uchar* geom);
-uchar* output_wkb_point(uchar* geom);
-uchar* output_wkb(uchar* geom);
-
-/*-- Globals ----------------------------------------------- */
-
-static int dims;
-static allocator local_malloc;
-static freeor local_free;
-static char*  out_start;
-static char*  out_pos;
-static int len;
-static int lwgi;
-static uchar endianbyte;
-void (*write_wkb_bytes)(uchar* ptr,unsigned int cnt,size_t size);
-
-/*---------------------------------------------------------- */
-
-
-
-/*
- * Ensure there is enough space for chars bytes.
- * Reallocate memory is this is not the case.
- */
-void
-ensure(int chars){
-
-	int pos = out_pos - out_start;
-
-	if (  (pos + chars) >= len ){
-		char* newp =(char*)local_malloc(len*2);
-		memcpy(newp,out_start,len);
-		local_free(out_start);
-		out_start = newp;
-		out_pos = newp + pos;
-		len *=2;
-	}
-}
-
-void
-to_end(void)
-{
-	while(*out_pos){
-		out_pos++;
-	}
-}
-
-void
-write_str(const char* str)
-{
-	ensure(32);
-	strcpy(out_pos,str);
-	to_end();
-}
-
-void
-write_double(double val){
-	ensure(32);
-	if (lwgi)
-		sprintf(out_pos,"%.8g",val);
-	else
-		sprintf(out_pos,"%.15g",val);
-	to_end();
-}
-
-void
-write_int(int i){
-	ensure(32);
-	sprintf(out_pos,"%i",i);
-	to_end();
-}
-
-int4
-read_int(uchar** geom)
-{
-	int4 ret;
-#ifdef SHRINK_INTS
-	if ( getMachineEndian() == NDR ){
-		if( (**geom)& 0x01){
-			ret = **geom >>1;
-			(*geom)++;
-			return ret;
-		}
-	}
-	else{
-		if( (**geom)& 0x80){
-			ret = **geom & ~0x80;
-			(*geom)++;
-			return ret;
-		}
-	}
-#endif
-	memcpy(&ret,*geom,4);
-
-#ifdef SHRINK_INTS
-	if ( getMachineEndian() == NDR ){
-		ret >>= 1;
-	}
-#endif
-
-	(*geom)+=4;
-	return ret;
-}
-
-double round(double);
-
-double read_double(uchar** geom){
-	if (lwgi){
-		double ret = *((int4*)*geom);
-		ret /= 0xb60b60;
-		(*geom)+=4;
-		return ret-180.0;
-	}
-	else{
-		double ret;
- 		memcpy(&ret, *geom, 8);
-		(*geom)+=8;
-		return ret;
-	}
-}
-           
-uchar *
-output_point(uchar* geom,int supress)
-{
-	int i;
-
-	for( i = 0 ; i < dims ; i++ ){
-		write_double(read_double(&geom));
-		if (i +1 < dims )
-			write_str(" ");
-	}
-	return geom;
-}
-
-uchar *
-output_single(uchar* geom,int supress)
-{
-	write_str("(");
-	geom=output_point(geom,supress);
-	write_str(")");
-	return geom;
-}
-
-uchar *
-output_collection(uchar* geom,outfunc func,int supress)
-{
-	int cnt = read_int(&geom);
-	if ( cnt == 0 ){
-		write_str(" EMPTY");
-	}
-	else{
-		write_str("(");
-		while(cnt--){
-			geom=func(geom,supress);
-			if ( cnt ){
-				write_str(",");
-			}
-		}
-		write_str(")");
-	}
-	return geom;
-}
-
-uchar *
-output_collection_2(uchar* geom,int suppress)
-{
-	return output_collection(geom,output_point,suppress);
-}
-
-uchar *output_wkt(uchar* geom, int supress);
-
-/* special case for multipoint to supress extra brackets */
-uchar *output_multipoint(uchar* geom,int suppress){
-	unsigned type = *geom & 0x0f;
-	
-	if ( type  == POINTTYPE )
-		return output_point(++geom,suppress);
-	else if ( type == POINTTYPEI ){
-		lwgi++;
-		geom=output_point(++geom,0);
-		lwgi--;
-		return geom;
-	}
-	
-	return output_wkt(geom,suppress);
-}
-
-/* special case for compound to suppress linestring but not circularstring */
-uchar *output_compound(uchar* geom, int suppress) {
-        unsigned type;
-
-#ifdef PGIS_DEBUG_CALLS
-        lwnotice("output_compound called.");
-#endif
-
-        type=*geom++;
-        switch(TYPE_GETTYPE(type)) 
-        {
-                case LINETYPE:
-                        geom = output_collection(geom,output_point,0);
-                        break;
-                case CURVETYPE:
-                        write_str("CIRCULARSTRING");
-                        geom = output_collection(geom,output_point,1);
-                        break;
-        }
-	return geom;
-}
-
-uchar *output_multisurface(uchar* geom, int suppress) {
-        unsigned type;
-
-#ifdef PGIS_DEBUG_CALLS
-        lwnotice("output_multisurface called.");
-#endif
-
-        type=*geom++;
-        switch(TYPE_GETTYPE(type))
-        {
-                case POLYGONTYPE:
-                        geom = output_collection(geom, output_collection_2,0);
-                        break;
-                case CURVEPOLYTYPE:
-                        write_str("CURVEPOLYGON");
-                        geom = output_collection(geom, output_compound,1);
-                        break;
-        }
-        return geom;
-}
-
-/*
- * Suppress=0 -- write TYPE, M, coords
- * Suppress=1 -- write TYPE, coords 
- * Suppress=2 -- write only coords
- */
-uchar *
-output_wkt(uchar* geom, int supress)
-{
-
-	unsigned type=*geom++;
-	char writeM=0;
-	dims = TYPE_NDIMS(type); /* ((type & 0x30) >> 4)+2; */
-
-#ifdef PGIS_DEBUG_CALLS
-        lwnotice("output_wkt called.");
-#endif
-
-	if ( ! supress && !TYPE_HASZ(type) && TYPE_HASM(type) ) writeM=1;
-
-
-	/* Skip the bounding box if there is one */
-	if ( TYPE_HASBBOX(type) )
-	{
-		geom+=16;
-	}
-
-	if ( TYPE_HASSRID(type) ) {
-		write_str("SRID=");write_int(read_int(&geom));write_str(";");
-	}
-
-	switch(TYPE_GETTYPE(type)) {
-		case POINTTYPE:
-			if ( supress < 2 )
-			{
-				if (writeM) write_str("POINTM");
-				else write_str("POINT");
-			}
-			geom=output_single(geom,0);
-			break;
-		case LINETYPE:
-			if ( supress < 2 )
-			{
-				if (writeM) write_str("LINESTRINGM");
-				else write_str("LINESTRING");
-			}
-			geom = output_collection(geom,output_point,0);
-			break;
-                case CURVETYPE:
-                        if ( supress < 2 )
-                        {
-                                if(writeM) write_str("CIRCULARSTRINGM");
-                                else write_str("CIRCULARSTRING");
-                        }
-                        geom = output_collection(geom,output_point,0);
-                        break;
-		case POLYGONTYPE:
-			if ( supress < 2 )
-			{
-				if (writeM) write_str("POLYGONM");
-				else write_str("POLYGON");
-			}
-			geom = output_collection(geom,output_collection_2,0);
-			break;
-                case COMPOUNDTYPE:
-                        if ( supress < 2 )
-                        {
-                                if (writeM) write_str("COMPOUNDCURVEM");
-                                else write_str("COMPOUNDCURVE");
-                        }
-                        geom = output_collection(geom, output_compound,1);
-                        break;
-                case CURVEPOLYTYPE:
-                        if (supress < 2)
-                        {
-                                if(writeM) write_str("CURVEPOLYGONM");
-                                else write_str("CURVEPOLYGON");
-                        }
-                        geom = output_collection(geom, output_compound,0);
-                        break;
-		case MULTIPOINTTYPE:
-			if ( supress < 2 )
-			{
-				if (writeM) write_str("MULTIPOINTM");
-				else write_str("MULTIPOINT");
-			}
-			geom = output_collection(geom,output_multipoint,2);
-			break;
-		case MULTILINETYPE:
-			if ( supress < 2 )
-			{
-				if (writeM) write_str("MULTILINESTRINGM");
-				else write_str("MULTILINESTRING");
-			}
-			geom = output_collection(geom,output_wkt,2);
-			break;
-                case MULTICURVETYPE:
-                        if ( supress < 2 )
-                        {
-                                if (writeM) write_str("MULTICURVEM");
-                                else write_str("MULTICURVE");
-                        }
-                        geom = output_collection(geom,output_compound,2);
-                        break;
-		case MULTIPOLYGONTYPE:
-			if ( supress < 2 )
-			{
-				if (writeM) write_str("MULTIPOLYGONM");
-				else write_str("MULTIPOLYGON");
-			}
-			geom = output_collection(geom,output_wkt,2);
-			break;
-                case MULTISURFACETYPE:
-                        if ( supress < 2)
-                        {
-                                if (writeM) write_str("MULTISURFACEM");
-                                else write_str("MULTISURFACE");
-                        } 
-                        geom = output_collection(geom,output_multisurface,2);
-                        break;
-		case COLLECTIONTYPE:
-			if ( supress < 2 )
-			{
-				if (writeM) write_str("GEOMETRYCOLLECTIONM");
-				else write_str("GEOMETRYCOLLECTION");
-			}
-			geom = output_collection(geom,output_wkt,1);
-			break;
-
-		case POINTTYPEI:
-			if ( supress < 2 )
-			{
-				if (writeM) write_str("POINTM");
-				else write_str("POINT");
-			}
-			lwgi++;
-			geom=output_single(geom,0);
-			lwgi--;
-			break;
-		case LINETYPEI:
-			if ( supress < 2 )
-			{
-				if (writeM) write_str("LINESTRINGM");
-				else write_str("LINESTRING");
-			}
-			lwgi++;
-			geom = output_collection(geom,output_point,0);
-			lwgi--;
-			break;
-		case POLYGONTYPEI:
-			if ( supress < 2 )
-			{
-				if (writeM) write_str("POLYGONM");
-				else write_str("POLYGON");
-			}
-			lwgi++;
-			geom =output_collection(geom,output_collection_2,0);
-			lwgi--;
-			break;
-	}
-	return geom;
-}
-
-char *
-unparse_WKT(uchar* serialized, allocator alloc, freeor free)
-{
-
-#ifdef PGIS_DEBUG_CALLS
-        lwnotice("unparse_WKT called.");
-#endif
-
-	if (serialized==NULL)
-		return NULL;
-
-	local_malloc=alloc;
-	local_free=free;
-	len = 128;
-	out_start = out_pos = alloc(len);
-	lwgi=0;
-
-	output_wkt(serialized, 0);
-
-	return out_start;
-}
-
-static char outchr[]={"0123456789ABCDEF" };
-
-/* Write HEX bytes flipping */
-void
-write_wkb_hex_flip_bytes(uchar* ptr, unsigned int cnt, size_t size)
-{
-	unsigned int bc; /* byte count */
-
-	ensure(cnt*2*size);
-
-	while(cnt--){
-		for(bc=size; bc; bc--)
-		{
-			*out_pos++ = outchr[ptr[bc-1]>>4];
-			*out_pos++ = outchr[ptr[bc-1]&0x0F];
-		}
-		ptr+=size;
-	}
-}
-
-/* Write HEX bytes w/out flipping */
-void
-write_wkb_hex_bytes(uchar* ptr, unsigned int cnt, size_t size)
-{
-	unsigned int bc; /* byte count */
-
-	ensure(cnt*2*size);
-
-	while(cnt--){
-		for(bc=0; bc<size; bc++)
-		{
-			*out_pos++ = outchr[ptr[bc]>>4];
-			*out_pos++ = outchr[ptr[bc]&0x0F];
-		}
-		ptr+=size;
-	}
-}
-
-/* Write BIN bytes flipping */
-void
-write_wkb_bin_flip_bytes(uchar* ptr, unsigned int cnt, size_t size)
-{
-	unsigned int bc; /* byte count */
-
-	ensure(cnt*size);
-
-	while(cnt--)
-	{
-		for(bc=size; bc; bc--)
-			*out_pos++ = ptr[bc-1];
-		ptr+=size;
-	}
-}
-
-
-/* Write BIN bytes w/out flipping */
-void
-write_wkb_bin_bytes(uchar* ptr, unsigned int cnt, size_t size)
-{
-	unsigned int bc; /* byte count */
-
-	ensure(cnt*size);
-
-	/* Could just use a memcpy here ... */
-	while(cnt--)
-	{
-		for(bc=0; bc<size; bc++)
-			*out_pos++ = ptr[bc];
-		ptr+=size;
-	}
-}
-
-uchar *
-output_wkb_point(uchar* geom)
-{
-	if ( lwgi ){
-		write_wkb_bytes(geom,dims,4);
-		return geom + (4*dims);
-	}
-	else{
-		write_wkb_bytes(geom,dims,8);
-		return geom + (8*dims);
-	}
-}
-
-void
-write_wkb_int(int i){
-	write_wkb_bytes((uchar*)&i,1,4);
-}
-
-uchar *
-output_wkb_collection(uchar* geom,outwkbfunc func)
-{
-	int cnt = read_int(&geom);
-#ifdef PGIS_DEBUG
-	lwnotice("output_wkb_collection: %d iterations loop", cnt);
-#endif
-	write_wkb_int(cnt);
-	while(cnt--) geom=func(geom);
-	return geom;
-}
-
-uchar *
-output_wkb_collection_2(uchar* geom){
-	return output_wkb_collection(geom,output_wkb_point);
-}
-
-uchar *
-output_wkb(uchar* geom)
-{
-	unsigned char type=*geom++;
-	int4 wkbtype;
-
-	dims = TYPE_NDIMS(type); 
-#ifdef PGIS_DEBUG
-	lwnotice("output_wkb: dims set to %d", dims);
-#endif
-
-	/* Skip the bounding box */
-	if ( TYPE_HASBBOX(type) ) { 
-		geom+=16;
-	}
-
-	wkbtype = TYPE_GETTYPE(type); 
-
-	if ( TYPE_HASZ(type) )
-		 wkbtype |= WKBZOFFSET;
-	if ( TYPE_HASM(type) )
-		 wkbtype |= WKBMOFFSET;
-	if ( TYPE_HASSRID(type) ) {
-		wkbtype |= WKBSRIDFLAG;
-	}
-
-
-	/* Write byteorder (as from WKB specs...) */
-	write_wkb_bytes(&endianbyte,1,1);
-
-	write_wkb_int(wkbtype);
-
-	if ( TYPE_HASSRID(type) ) {
-		write_wkb_int(read_int(&geom));
-	}
-
-	switch(TYPE_GETTYPE(type)){
-		case POINTTYPE:
-			geom=output_wkb_point(geom);
-			break;
-		case LINETYPE:
-			geom=output_wkb_collection(geom,output_wkb_point);
-			break;
-                case CURVETYPE:
-                        geom=output_wkb_collection(geom,output_wkb_point);
-                        break;
-		case POLYGONTYPE:
-			geom=output_wkb_collection(geom,output_wkb_collection_2);
-			break;
-                case COMPOUNDTYPE:
-                        geom=output_wkb_collection(geom,output_wkb);
-                        break;
-                case CURVEPOLYTYPE:
-                        geom=output_wkb_collection(geom,output_wkb);
-                        break;
-                case MULTICURVETYPE:
-                case MULTISURFACETYPE:
-		case MULTIPOINTTYPE:
-		case MULTILINETYPE:
-		case MULTIPOLYGONTYPE:
-		case COLLECTIONTYPE:
-			geom = output_wkb_collection(geom,output_wkb);
-			break;
-
-		/*
-			These don't output standard wkb at the moment
-			the output and integer version.
-
-			however you could run it through the wkt parser
-			for a lwg and then output that.  There should
-			also be a force_to_real_(lwgi)
-		*/
-		case POINTTYPEI:
-			lwgi++;
-			geom=output_wkb_point(geom);
-			lwgi--;
-			break;
-		case LINETYPEI:
-			lwgi++;
-			geom = output_wkb_collection(geom,output_wkb_point);
-			lwgi--;
-			break;
-		case POLYGONTYPEI:
-			lwgi++;
-			geom = output_wkb_collection(geom,output_wkb_collection_2);
-			lwgi--;
-			break;
-	}
-	return geom;
-}
-
-char *
-unparse_WKB(uchar* serialized, allocator alloc, freeor free, char endian, size_t *outsize, uchar hex)
-{
-#ifdef PGIS_DEBUG
-	lwnotice("unparse_WKB(%p,...) called", serialized);
-#endif
-
-	if (serialized==NULL)
-		return NULL;
-
-	local_malloc=alloc;
-	local_free=free;
-	len = 128;
-	out_start = out_pos = alloc(len);
-	lwgi=0;
-
-	if ( endian == (char)-1 )
-	{
-		endianbyte = getMachineEndian();
-		if ( hex ) write_wkb_bytes = write_wkb_hex_bytes;
-		else write_wkb_bytes = write_wkb_bin_bytes;
-	}
-	else
-	{
-		endianbyte = endian;
-		if ( endianbyte != getMachineEndian() )
-		{
-			if ( hex ) write_wkb_bytes = write_wkb_hex_flip_bytes;
-			else write_wkb_bytes = write_wkb_bin_flip_bytes;
-		}
-		else
-		{
-			if ( hex ) write_wkb_bytes = write_wkb_hex_bytes;
-			else write_wkb_bytes = write_wkb_bin_bytes;
-		}
-	}
-
-	output_wkb(serialized);
-
-	if ( hex ) {
-		ensure(1);
-		*out_pos=0;
-	}
-
-	if ( outsize ) *outsize = (out_pos-out_start);
-
-	return out_start;
-}
-
-
-/******************************************************************
- * $Log$
- * Revision 1.23  2006/02/06 11:12:22  strk
- * uint32_t typedef moved back from wktparse.h to lwgparse.c and wktunparse.c
- *
- * Revision 1.22  2006/02/03 20:53:37  strk
- * Swapped stdint.h (unavailable on Solaris9) with inttypes.h
- *
- * Revision 1.21  2006/02/03 09:52:14  strk
- * Changed int4 typedefs to use POSIX uint32_t
- *
- * Revision 1.20  2006/01/09 15:12:02  strk
- * ISO C90 comments
- *
- * Revision 1.19  2005/03/10 18:19:16  strk
- * Made void args explicit to make newer compilers happy
- *
- * Revision 1.18  2005/02/21 16:16:14  strk
- * Changed byte to uchar to avoid clashes with win32 headers.
- *
- * Revision 1.17  2005/02/07 13:21:10  strk
- * Replaced DEBUG* macros with PGIS_DEBUG*, to avoid clashes with postgresql DEBUG
- *
- * Revision 1.16  2005/01/18 09:32:03  strk
- * Changed unparse_WKB interface to take an output size pointer and an HEXFORM
- * specifier. Reworked code in wktunparse to use function pointers.
- *
- * Revision 1.15  2004/12/21 15:19:01  strk
- * Canonical binary reverted back to EWKB, now supporting SRID inclusion.
- *
- * Revision 1.14  2004/12/17 11:08:53  strk
- * Moved getMachineEndian from parser to liblwgeom.{h,c}.
- * Added XDR and NDR defines.
- * Fixed all usage of them.
- *
- * Revision 1.13  2004/10/25 12:27:33  strk
- * Removed useless network type includes,
- * Added param.h include for BYTE_ORDER defines under win32.
- *
- * Revision 1.12  2004/10/21 19:48:34  strk
- * Stricter syntax fixes. Reported by Sébastien NICAISE <snicaise at iciatechnologies.com>
- *
- * Revision 1.11  2004/10/15 07:35:41  strk
- * Fixed a bug introduced by me (byteorder skipped for inner geoms in WKB)
- *
- * Revision 1.10  2004/10/11 14:03:33  strk
- * Added endiannes specification to unparse_WKB, AsBinary, lwgeom_to_wkb.
- *
- ******************************************************************/



More information about the postgis-commits mailing list