public function relativeTo($base, $schemaRelative = false)
    {
        if (false === ($base instanceof IRI)) {
            $base = new IRI($base);
        }
        $relative = clone $this;

        // Compare scheme
        if ($relative->scheme !== $base->scheme) {
            return $relative;
        }

        // Compare authority
        if ($relative->getAuthority() !== $base->getAuthority()) {
            if (true === $schemaRelative) {
                $relative->scheme = null;
            }

            return $relative;
        }
        $relative->scheme = null;
        $relative->host = null;
        $relative->userinfo = null;
        $relative->port = null;

        // Compare path
        $baseSegments     = explode('/', $base->path);
        $relativeSegments = explode('/', $relative->path);
        $len = min(count($baseSegments), count($relativeSegments)) - 1;  // do not move beyond last segment

        $pos = 0;

        while (($baseSegments[$pos] === $relativeSegments[$pos]) && ($pos < $len)) {
            $pos++;
        }

        $relative->path = '';
        $numBaseSegments = count($baseSegments) - $pos - 1;
        if ($numBaseSegments > 0) {
            $relative->path .= str_repeat('../', $numBaseSegments);
        }

        if (($baseSegments[$pos] !== $relativeSegments[$pos]) ||
            ((null === $relative->query) && (null === $relative->fragment)) ||
            ($base->path === '')) {
            // if the two paths differ or if there's neither a query component nor a fragment
            // or there is no base path, we need to consider this IRI's path

            if (($relative->path === '') && (false !== strpos($relativeSegments[$pos], ':'))) {
                // if the first path segment contains a colon, we need to
                // prepend a ./ to distinguish it from an absolute IRI
                $relative->path .= './';
            }

            $relative->path .= implode('/', array_slice($relativeSegments, $pos));

            // .. and ensure that the resulting path isn't empty
            if (($relative->path === '')) {
                $relative->path .= './';
            }
        }

        if ($relative->query !== $base->query) {
            return $relative;
        }

        if (null !== $relative->fragment) {
            $relative->query = null;
        }

        return $relative;
    }