/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.lucene.util; public class TestBitUtil extends LuceneTestCase { private static int slowNlz(long x) { if (x == 0L) return 64; int nlz = 0; while ( ((x << nlz) & (1L << 63)) == 0) { nlz++; } return nlz; } private void checkNlz(long x) { assertEquals(slowNlz(x), BitUtil.nlz(x)); assertEquals(Long.numberOfLeadingZeros(x), BitUtil.nlz(x)); } public void testNlz() { checkNlz(0L); checkNlz(1L); checkNlz(-1L); for (int i = 1; i <= 63; i++) { checkNlz(1L << i); checkNlz((1L << i) + (1L << (i>>1))); } } public void testBitUtils() { long num = 100000; assertEquals( 5, BitUtil.ntz(num) ); assertEquals( 5, BitUtil.ntz2(num) ); assertEquals( 5, BitUtil.ntz3(num) ); num = 10; assertEquals( 1, BitUtil.ntz(num) ); assertEquals( 1, BitUtil.ntz2(num) ); assertEquals( 1, BitUtil.ntz3(num) ); for (int i=0; i<64; i++) { num = 1L << i; assertEquals( i, BitUtil.ntz(num) ); assertEquals( i, BitUtil.ntz2(num) ); assertEquals( i, BitUtil.ntz3(num) ); } } private long testArg(int shift) { return (1L << shift) + (1L << (shift>>1)); } private long nlzBitUtilBasicLoop(int iters) { long sumRes = 0; while (iters-- >= 0) { for (int i = 1; i <= 63; i++) { long a = testArg(i); sumRes += BitUtil.nlz(a); sumRes += BitUtil.nlz(a+1); sumRes += BitUtil.nlz(a-1); sumRes += BitUtil.nlz(a+10); sumRes += BitUtil.nlz(a-10); } } return sumRes; } private long nlzLongBasicLoop(int iters) { long sumRes = 0; while (iters-- >= 0) { for (int i = 1; i <= 63; i++) { long a = testArg(i); sumRes += Long.numberOfLeadingZeros(a); sumRes += Long.numberOfLeadingZeros(a+1); sumRes += Long.numberOfLeadingZeros(a-1); sumRes += Long.numberOfLeadingZeros(a+10); sumRes += Long.numberOfLeadingZeros(a-10); } } return sumRes; } public void tstPerfNlz() { // See LUCENE-3197, prefer to use Long.numberOfLeadingZeros() over BitUtil.nlz(). final long measureMilliSecs = 2000; final int basicIters = 100000; long startTime; long endTime; long curTime; long dummy = 0; // avoid optimizing away dummy = 0; int bitUtilLoops = 0; startTime = System.currentTimeMillis(); endTime = startTime + measureMilliSecs; do { dummy += nlzBitUtilBasicLoop(basicIters); bitUtilLoops++; curTime = System.currentTimeMillis(); } while (curTime < endTime); int bitUtilPsTime = (int) (1000000000 * (curTime - startTime) / (basicIters * 5 * 63 * (float) bitUtilLoops)); System.out.println("BitUtil nlz time: " + (bitUtilPsTime/1) + " picosec/call, dummy: " + dummy); dummy = 0; int longLoops = 0; startTime = System.currentTimeMillis(); endTime = startTime + measureMilliSecs; do { dummy += nlzLongBasicLoop(basicIters); longLoops++; curTime = System.currentTimeMillis(); } while (curTime < endTime); int longPsTime = (int) (1000000000 * (curTime - startTime) / (basicIters * 5 * 63 * (float) longLoops)); System.out.println("Long nlz time: " + longPsTime + " picosec/call, dummy: " + dummy); } }