Example #1
0
  /**
   * Checks if the dividing record passed as arguments is in the multi-dimensional search range
   * defined by this class.
   */
  public boolean isInSearchRange(final byte[] dividingRecord) {

    final boolean dimShownToBeLargerThanMin[] = new boolean[numDimensions];
    final boolean dimShownToBeSmallerThanMax[] = new boolean[numDimensions];

    // get first byte in which the values differ
    int firstDifferingByte = 0;
    for (; firstDifferingByte < dividingRecord.length; firstDifferingByte++) {
      if (dividingRecord[firstDifferingByte] != searchMinZOrder[firstDifferingByte]
          || dividingRecord[firstDifferingByte] != searchMaxZOrder[firstDifferingByte]) {
        break;
      }
    }

    /**
     * We now scan sequentially over the bit array, starting with firstDifferingByte. Thereby, we
     * notice whenever we detect a smaller or greater situation (and make sure that, for the
     * dimension under investigation, we do not check again in future). Note that this operation
     * operates on top of the zOrder string, in which bits are interleaved.
     *
     * <p>The unsatisfiedConstraintsCtr is for performance optimizations. It is initialized with
     * numDimensions*2, and when its count reaches zero we know that all dimensions have to be shown
     * larger than min and smaller than max, i.e. that all constraints have been satisfied.
     */
    int unsatisfiedConstraintsCtr = numDimensions * 2;
    for (int i = firstDifferingByte * Byte.SIZE;
        i < dividingRecord.length * Byte.SIZE && unsatisfiedConstraintsCtr > 0;
        i++) {

      final int dimension = i % numDimensions;
      final boolean divRecordBitSet = BytesUtil.getBit(dividingRecord, i);

      if (!dimShownToBeLargerThanMin[dimension]) {

        final boolean searchMinBitSet = BytesUtil.getBit(searchMinZOrder, i);

        if (divRecordBitSet && !searchMinBitSet) {

          dimShownToBeLargerThanMin[dimension] = true;
          unsatisfiedConstraintsCtr--;

        } else if (!divRecordBitSet && searchMinBitSet) {

          return false; // conflict
        } // else: skip
      }

      if (!dimShownToBeSmallerThanMax[dimension]) {

        final boolean searchMaxBitSet = BytesUtil.getBit(searchMaxZOrder, i);

        if (!divRecordBitSet && searchMaxBitSet) {

          dimShownToBeSmallerThanMax[dimension] = true;
          unsatisfiedConstraintsCtr--;

        } else if (divRecordBitSet && !searchMaxBitSet) {

          return false;
        } // else: skip
      }
    }

    return true; // all is good
  }
Example #2
0
  /**
   * Returns the BIGMIN, i.e. the next relevant value in the search range. The value is returned as
   * unsigned, which needs to be converted into two's complement prior to appending as a key (see
   * {@link GeoSpatialLiteralExtension} for details).
   *
   * <p>This method implements the BIGMIN decision table as provided in
   * http://www.vision-tools.com/h-tropf/multidimensionalrangequery.pdf, see page 76.
   *
   * @param iv the IV of the dividing record
   * @return
   */
  public byte[] calculateBigMin(final byte[] dividingRecord) {

    if (dividingRecord.length != searchMinZOrder.length
        || dividingRecord.length != searchMaxZOrder.length) {

      // this should never happen, assuming correct configuration
      throw new RuntimeException("Key dimenisions differs");
    }

    final int numBytes = dividingRecord.length;

    System.arraycopy(searchMinZOrder, 0, min, 0, zOrderArrayLength);
    System.arraycopy(searchMaxZOrder, 0, max, 0, zOrderArrayLength);
    java.util.Arrays.fill(bigmin, (byte) 0); // reset bigmin

    boolean finished = false;
    for (int i = 0; i < numBytes * Byte.SIZE && !finished; i++) {

      final boolean divRecordBitSet = BytesUtil.getBit(dividingRecord, i);
      final boolean minBitSet = BytesUtil.getBit(min, i);
      final boolean maxBitSet = BytesUtil.getBit(max, i);

      if (!divRecordBitSet) {

        if (!minBitSet) {

          if (!maxBitSet) {

            // case 0 - 0 - 0: continue (nothing to do)

          } else {

            // case 0 - 0 - 1
            System.arraycopy(min, 0, bigmin, 0, zOrderArrayLength);
            load(true /* setFirst */, i, bigmin, numDimensions);
            load(false, i, max, numDimensions);
          }

        } else {

          if (!maxBitSet) {

            // case 0 - 1 - 0
            throw new RuntimeException("MIN must be <= MAX.");

          } else {

            // case 0 - 1 - 1
            System.arraycopy(min, 0, bigmin, 0, zOrderArrayLength);
            finished = true;
          }
        }
      } else {

        if (!minBitSet) {

          if (!maxBitSet) {

            // case 1 - 0 - 0
            finished = true;

          } else {

            // case 1 - 0 - 1
            load(true, i, min, numDimensions);
          }

        } else {

          if (!maxBitSet) {

            // case 1 - 1 - 0
            throw new RuntimeException("MIN must be <= MAX.");

          } else {

            // case 1 - 1 - 1: continue (nothing to do)

          }
        }
      }
    }

    return bigmin;
  }