All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.ethz.globis.phtree.PhDistancePP Maven / Gradle / Ivy

There is a newer version: 2.8.1
Show newest version
/*
 * Copyright 2011-2016 ETH Zurich. All Rights Reserved.
 *
 * This software is the proprietary information of ETH Zurich.
 * Use is subject to license terms.
 */
package ch.ethz.globis.phtree;

import java.util.Arrays;

import ch.ethz.globis.phtree.pre.PreProcessorPointF;


/**
 * Calculate the euclidean distance for encoded {@code double} values.
 * 
 * @see PhDistance
 * 
 * @author ztilmann
 */
public class PhDistancePP implements PhDistance {

	/** Euclidean distance with standard `double` encoding. */ 
	public static final PhDistance DOUBLE = 
			new PhDistancePP(new PreProcessorPointF.IEEE());

	private final PreProcessorPointF pre;

	public PhDistancePP(PreProcessorPointF pre) {
		this.pre = pre;
	}

	
	/**
	 * Calculate the distance for encoded {@code double} values.
	 * 
	 * @see PhDistance#dist(long[], long[])
	 */
	@Override
	public double dist(long[] v1, long[] v2) {
		double d = 0;
		double[] d1 = new double[v1.length];
		double[] d2 = new double[v2.length];
		pre.post(v1, d1);
		pre.post(v2, d2);
		for (int i = 0; i < v1.length; i++) {
			double dl = d1[i] - d2[i];
			d += dl*dl;
		}
		return Math.sqrt(d);
	}

	
	@Override
	public void toMBB(double distance, long[] center, long[] outMin,
			long[] outMax) {
		double[] c = new double[center.length];
		double[] min = new double[outMin.length];
		double[] max = new double[outMax.length];
		pre.post(center, c);
		for (int i = 0; i < center.length; i++) {
			min[i] = c[i] - distance;
			max[i] = c[i] + distance;
		}
		pre.pre(min, outMin);
		pre.pre(max, outMax);
	}

	
	@Override
	public void knnCalcDistances(long[] kNNCenterIn, long[] prefixIn, int bitsToIgnore, double[] outDistances) {
		long maskSingleBit = 1L << (bitsToIgnore-1);
		if (maskSingleBit < 0) {
			//TODO
			//can't yet deal with negative/positive of postLen==63
			return;
		}
		long maskPrefix = (-1L) << bitsToIgnore;
		long maskPostFix = (~maskPrefix) >> 1;
		for (int i = 0; i < prefixIn.length; i++) {
			long nodeCenter = prefixIn[i] & maskPrefix;
			//find coordinate closest to the node's center, however the node-center should between the
			//resulting coordinate and the kNN-center.
			boolean isLarger = kNNCenterIn[i] > (nodeCenter | maskPostFix);
			nodeCenter |= isLarger ? 
				//kNN center is in 'upper' quadrant
				maskPostFix
				:
				//kNN Center is in 'lower' quadrant, move buf to 'upper' quadrant
				maskSingleBit;

			double dist = pre.post(nodeCenter) - pre.post(kNNCenterIn[i]);
			outDistances[i] = dist * dist;
		}
		
		Arrays.sort(outDistances);

		//create totals
		for (int i = 1; i < outDistances.length; i++) {
			outDistances[i] += outDistances[i-1];
		}
		for (int i = 0; i < outDistances.length; i++) {
			outDistances[i] = Math.sqrt(outDistances[i]);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy