@param WKBBuffer        $buffer
@param CoordinateSystem $cs

@return MultiPoint
493851
private function readMultiPoint(WKBBuffer $buffer, CoordinateSystem $cs) : MultiPoint
    {
        $numPoints = $buffer->readUnsignedLong();
        $points = [];

        for ($i = 0; $i < $numPoints; $i++) {
            $points[] = $this->readGeometry($buffer, $cs->SRID());
        }

        return new MultiPoint($cs, ...$points);
    }
1101023
private function readMultiLineString(WKBBuffer $buffer, CoordinateSystem $cs) : MultiLineString
    {
        $numLineStrings = $buffer->readUnsignedLong();
        $lineStrings = [];

        for ($i = 0; $i < $numLineStrings; $i++) {
            $lineStrings[] = $this->readGeometry($buffer, $cs->SRID());
        }

        return new MultiLineString($cs, ...$lineStrings);
    }
247647
private function readLineStringText(WKTParser $parser, CoordinateSystem $cs) : LineString
    {
        $points = $this->readMultiPoint($parser, $cs);

        return new LineString($cs, ...$points);
    }
89388
public function concat(Buffer $buffer)
    {
        // size-protected through Buffer class
        $this->buffer = $this->buffer . $buffer->getBinary();
        $this->size  += $buffer->getSize();
        return $this;
    }
113719
private function readTriangleText(WKTParser $parser, CoordinateSystem $cs) : Triangle
    {
        $rings = $this->readMultiLineString($parser, $cs);

        return new Triangle($cs, ...$rings);
    }
509896
public static int cs_fkeep(Dcs A, Dcs_ifkeep fkeep, Object other) {
        int j, p, nz = 0, n, Ap[], Ai[];
        double Ax[];
        if (!Dcs_util.CS_CSC(A))
            return (-1); /* check inputs */
        n = A.n;
        Ap = A.p;
        Ai = A.i;
        Ax = A.x;
        for (j = 0; j < n; j++) {
            p = Ap[j]; /* get current location of col j */
            Ap[j] = nz; /* record new location of col j */
            for (; p < Ap[j + 1]; p++) {
                if (fkeep.fkeep(Ai[p], j, Ax != null ? Ax[p] : 1, other)) {
                    if (Ax != null)
                        Ax[nz] = Ax[p]; /* keep A(i,j) */
                    Ai[nz++] = Ai[p];
                }
            }
        }
        Ap[n] = nz; /* finalize A */
        Dcs_util.cs_sprealloc(A, 0); /* remove extra space from A */
        return (nz);
    }
344640
public static int[] cs_post(int[] parent, int n)
	{
		int j, k = 0, post[], w[], head[], next[], stack[] ;
		if (parent == null) return (null) ;		/* check inputs */
		post = new int [n] ;				/* allocate result */
		w = new int [3*n] ;				/* get workspace */
		if (w == null || post == null) return (cs_idone (post, null, w, false)) ;
		head = w ; next = w ;
		int next_offset = n ;
		stack = w ;
		int stack_offset = 2*n ;
		for (j = 0 ; j < n ; j++) head [j] = -1 ;	/* empty linked lists */
		for (j = n-1 ; j >= 0 ; j--) /* traverse nodes in reverse order*/
		{
			if (parent [j] == -1) continue;		/* j is a root */
			next [next_offset + j] = head [parent [j]] ;  /* add j to list of its parent */
			head [parent [j]] = j ;
		}
		for (j = 0 ; j < n ; j++)
		{
			if (parent [j] != -1) continue ;	/* skip j if it is not a root */
			k = cs_tdfs(j, k, head, 0, next, next_offset, post, 0, stack, stack_offset) ;
		}
		return (post) ;
	}
599
protected function readGeometry(WKBBuffer $buffer, int $srid) : Geometry
    {
        $buffer->readByteOrder();

        $this->readGeometryHeader($buffer, $geometryType, $hasZ, $hasM, $srid);

        $cs = new CoordinateSystem($hasZ, $hasM, $srid);

        switch ($geometryType) {
            case Geometry::POINT:
                return $this->readPoint($buffer, $cs);

            case Geometry::LINESTRING:
                return $this->readLineString($buffer, $cs);

            case Geometry::CIRCULARSTRING:
                return $this->readCircularString($buffer, $cs);

            case Geometry::COMPOUNDCURVE:
                return $this->readCompoundCurve($buffer, $cs);

            case Geometry::POLYGON:
                return $this->readPolygon($buffer, $cs);

            case Geometry::CURVEPOLYGON:
                return $this->readCurvePolygon($buffer, $cs);

            case Geometry::MULTIPOINT:
                return $this->readMultiPoint($buffer, $cs);

            case Geometry::MULTILINESTRING:
                return $this->readMultiLineString($buffer, $cs);

            case Geometry::MULTIPOLYGON:
                return $this->readMultiPolygon($buffer, $cs);

            case Geometry::GEOMETRYCOLLECTION:
                return $this->readGeometryCollection($buffer, $cs);

            case Geometry::POLYHEDRALSURFACE:
                return $this->readPolyhedralSurface($buffer, $cs);

            case Geometry::TIN:
                return $this->readTIN($buffer, $cs);

            case Geometry::TRIANGLE:
                return $this->readTriangle($buffer, $cs);
        }

        throw GeometryIOException::unsupportedWKBType($geometryType);
    }
831405
function copyBuffer(buf) {
  var targetBuffer = new Buffer(buf.length);
  buf.copy(targetBuffer);
  return targetBuffer;
}
815150
public static Geometry computePositiveRingBuffer(Geometry geom, double bufferDistance,
            int numBuffer, BufferParameters bufferParameters, boolean doDifference) throws SQLException {
        Polygon[] buffers = new Polygon[numBuffer];        
        if (geom instanceof Polygon) {
            //Work arround to manage polygon with hole
            geom = geom.getFactory().createPolygon(((Polygon) geom).getExteriorRing().getCoordinateSequence());
        }
        Geometry previous = geom;
        double distance = 0;
        for (int i = 0; i < numBuffer; i++) {
            distance += bufferDistance;
            Geometry newBuffer = runBuffer(geom, distance, bufferParameters);
            if (doDifference) {
                buffers[i] = (Polygon) newBuffer.difference(previous);
            } else {
                buffers[i] = (Polygon) newBuffer;
            }
            previous = newBuffer;
        }
        return geom.getFactory().createMultiPolygon(buffers);
    }
1040794
private function readTIN(WKBBuffer $buffer, CoordinateSystem $cs) : TIN
    {
        $numPatches = $buffer->readUnsignedLong();
        $patches = [];

        for ($i = 0; $i < $numPatches; $i++) {
            $patches[] = $this->readGeometry($buffer, $cs->SRID());
        }

        return new TIN($cs, ...$patches);
    }
201802
public static int cusparseXcscsort_bufferSizeExt(
        cusparseHandle handle, 
        int m, 
        int n, 
        int nnz, 
        Pointer cscColPtrA, 
        Pointer cscRowIndA, 
        long[] pBufferSizeInBytes)
    {
        return checkResult(cusparseXcscsort_bufferSizeExtNative(handle, m, n, nnz, cscColPtrA, cscRowIndA, pBufferSizeInBytes));
    }
746131
public static int cusparseScsc2dense(
        cusparseHandle handle, 
        int m, 
        int n, 
        cusparseMatDescr descrA, 
        Pointer cscSortedValA, 
        Pointer cscSortedRowIndA, 
        Pointer cscSortedColPtrA, 
        Pointer A, 
        int lda)
    {
        return checkResult(cusparseScsc2denseNative(handle, m, n, descrA, cscSortedValA, cscSortedRowIndA, cscSortedColPtrA, A, lda));
    }
1354936
private function readMultiPolygonText(WKTParser $parser, CoordinateSystem $cs) : MultiPolygon
    {
        $parser->matchOpener();
        $polygons = [];

        do {
            $polygons[] = $this->readPolygonText($parser, $cs);
            $nextToken = $parser->getNextCloserOrComma();
        } while ($nextToken === ',');

        return new MultiPolygon($cs, ...$polygons);
    }
1178467
public static function rectangle(Point $a, Point $b) : LineString
    {
        $cs = $a->coordinateSystem();

        if ($cs != $b->coordinateSystem()) { // by-value comparison.
            throw CoordinateSystemException::dimensionalityMix($a, $b);
        }

        if ($cs->coordinateDimension() !== 2) {
            throw new CoordinateSystemException(__METHOD__ . ' expects 2D points.');
        }

        $x1 = min($a->x(), $b->x());
        $x2 = max($a->x(), $b->x());

        $y1 = min($a->y(), $b->y());
        $y2 = max($a->y(), $b->y());

        $p1 = new Point($cs, $x1, $y1);
        $p2 = new Point($cs, $x2, $y1);
        $p3 = new Point($cs, $x2, $y2);
        $p4 = new Point($cs, $x1, $y2);

        return new LineString($cs, $p1, $p2, $p3, $p4, $p1);
    }
598938
private MultiPoint parseMultiPoint(JsonParser jp) throws IOException, SQLException {
        jp.nextToken(); // FIELD_NAME coordinates        
        String coordinatesField = jp.getText();
        if (coordinatesField.equalsIgnoreCase(GeoJsonField.COORDINATES)) {
            jp.nextToken(); // START_ARRAY [ coordinates
            MultiPoint mPoint = GF.createMultiPoint(parseCoordinates(jp));
            jp.nextToken();//END_OBJECT } geometry
            return mPoint;
        } else {
            throw new SQLException("Malformed GeoJSON file. Expected 'coordinates', found '" + coordinatesField + "'");
        }
    }
86365
private static void cs_augment(int k, DZcs A, int[] jmatch, int jmatch_offset, int[] cheap, int cheap_offset,
		    int[] w, int w_offset, int[] js, int js_offset, int[] is, int is_offset, int[] ps, int ps_offset)
	{
		int p, i = -1, Ap[] = A.p, Ai[] = A.i, head = 0, j ;
		boolean found = false ;
		js [js_offset + 0] = k ;				/* start with just node k in jstack */
		while (head >= 0)
		{
			/* --- Start (or continue) depth-first-search at node j ------------- */
			j = js [js_offset + head] ;			/* get j from top of jstack */
			if (w [w_offset + j] != k)			/* 1st time j visited for kth path */
			{
				w [w_offset + j] = k ;			/* mark j as visited for kth path */
				for (p = cheap [cheap_offset + j] ; p < Ap [j+1] && !found ; p++)
				{
					i = Ai [p] ;			/* try a cheap assignment (i,j) */
					found = (jmatch [jmatch_offset + i] == -1) ;
				}
				cheap [cheap_offset + j] = p ;		/* start here next time j is traversed*/
				if (found)
				{
					is [is_offset + head] = i ;  	/* column j matched with row i */
					break ;				/* end of augmenting path */
				}
				ps [ps_offset + head] = Ap [j] ;	/* no cheap match: start dfs for j */
			}
			/* --- Depth-first-search of neighbors of j ------------------------- */
			for (p = ps [ps_offset + head] ; p < Ap [j+1] ; p++)
			{
				i = Ai [p] ;				/* consider row i */
				if (w [w_offset + jmatch [jmatch_offset + i]] == k)
					continue ;			/* skip jmatch [i] if marked */
				ps [ps_offset + head] = p + 1 ;		/* pause dfs of node j */
				is [is_offset + head] = i ;		/* i will be matched with j if found */
				js [js_offset + (++head)] = jmatch [jmatch_offset + i] ;  /* start dfs at column jmatch [i] */
				break;
			}
			if (p == Ap [j+1]) head-- ;			/* node j is done; pop from stack */
		} 							/* augment the match if path found: */
		if (found) for (p = head ; p >= 0 ; p--) jmatch [jmatch_offset + is [is_offset + p]] = js [js_offset + p] ;
	}