/* * Copyright (c) 2011 LinkedIn, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.flaptor.indextank.index.scorer; import java.util.Arrays; import com.flaptor.indextank.util.FormatLogger; public class CategoryEncoder { private static final FormatLogger logger = new FormatLogger(); /** * Precondition bitmask.length >= data.length */ public static int decode(int[] data, int dataOffset, int[] bitmask) { int retval = 0; for (int i = bitmask.length - 1; i >= 0 ; i--) { for (int j = 31; j >=0; j--) { if ((bitmask[i] & (1<<j)) != 0) { retval = retval << 1; if ((data.length - dataOffset > i) && ( (data[i+dataOffset] & (1<<j)) != 0)) { retval = retval | 1; } } } } return retval; } public static int[] encode(int[] oldData, int dataOffset, int[] bitmask, int value) { int[] data; if (oldData.length - dataOffset < bitmask.length) { data = new int[bitmask.length + dataOffset]; System.arraycopy(oldData, 0, data, 0, oldData.length); } else { data = oldData; } for (int i =dataOffset; i < data.length && i < bitmask.length + dataOffset; i++) { for (int j = 0; j < 32; j++) { if ((bitmask[i - dataOffset] & (1<<j)) != 0) { data[i] = data[i] & (~(1<<j)); if ((value & 1) != 0) { data[i] = data[i] | (1 << j); } value = value >>> 1; } } } if (value != 0) { throw new IllegalArgumentException("value too big to encode in bitmasked space"); } return data; } /** * Check if the dataBitmap masked with the categoriesBitmask is compliant with the valuesBitmap. * This implies anding every int in the dataBitmap with its correspoding int in the categoriesBitmask * and checking the result against the correspoding int in the valuesBitmap. In case the valuesBitmap * is larger than the dataBitmap, every extra position must be zero. * * @param dataBitmap the document data * @param offset the offset of the dataBitmap where the actual facets data begins (after the variables data) * @param categoriesBitmask mask to apply to the data for the category/ies to consider * @param valuesBitmap values to match * @return <code>true</code> if the values match */ public static boolean matches(int[] dataBitmap, int offset, int[] categoriesBitmask, int[] valuesBitmap) { if (valuesBitmap.length != categoriesBitmask.length) { throw new IllegalArgumentException("Values and mask must have the same size"); } for (int i = 0; i < valuesBitmap.length; i++) { if (i >= dataBitmap.length - offset) { if (valuesBitmap[i] != 0) { return false; } } else if ((dataBitmap[i + offset] & categoriesBitmask[i]) != valuesBitmap[i]) { return false; } } return true; } }