001/* 002 * Copyright 2013 Alex Kasko (alexkasko.com) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.alexkasko.unsafe.offheaplong; 018 019/** 020 * Contains static methods for packing two values with limited size (one long and one int) 021 * into one long value. May be used to pack values before placing them into {@link com.alexkasko.unsafe.offheaplong.OffHeapLongAddressable}. 022 * Values are stored using bit shifting as follows: 023 * <pre> 024 * {@code 025 * 0 32 64-bits 64 026 * +-----------------------------+-----------+------------------+ 027 * | first 32 bits of long value | int value | tail of long val | 028 * +-----------------------------+-----------+------------------+ 029 * } 030 * </pre> 031 * This class doesn't use {@code sun.misc.Unsafe} 032 * 033 * @author alexkasko 034 * Date: 1/14/13 035 */ 036public class LongPacker { 037 /** 038 * Packs one long value with limited size and one int value 039 * into one long value. 040 * Values limits are checking using {@code assert} 041 * keyword, java must be run with {@code -ea} switch to enable them. 042 * 043 * @param big long value 044 * @param little int value 045 * @param bits max size of long value in bits, max size of int value is {@code 64 - bits} 046 * @return packed long value 047 */ 048 public static long pack(long big, int little, int bits) { 049 assert bits > 32 && bits < 64; 050 assert big < (1L << bits); 051 assert little < (1 << (64 - bits)); 052 int ls = bits & 7; 053 int bm = (1 << ls) - 1; 054 long res = (big & ~bm) << (64 - bits); 055 res |= (little & ((1L << (64 - bits)) - 1)) << ls; 056 res |= big & bm; 057 return res; 058 } 059 060 /** 061 * Read long value from packed long. 062 * Values limits are checking using {@code assert} 063 * keyword, java must be run with {@code -ea} switch to enable them. 064 * 065 * @param pack packed long 066 * @param bits max size of long value in bits, max size of int value is {@code 64 - bits} 067 * @return source long value 068 */ 069 public static long big(long pack, int bits) { 070 assert bits > 32 && bits < 64; 071 int ls = bits & 7; 072 long res = (pack & (((1L << (bits - ls)) - 1) << (64 - bits + ls))) >>> (64 - bits); 073 return res | pack & ((1 << ls) - 1); 074 } 075 076 /** 077 * 078 * Values limits are checking using {@code assert} 079 * keyword, java must be run with {@code -ea} switch to enable them. 080 * 081 * @param pack packed long 082 * @param bits max size of long value in bits, max size of int value is {@code 64 - bits} 083 * @return source int value 084 */ 085 public static int little(long pack, int bits) { 086 assert bits > 32 && bits < 64; 087 int ls = bits & 7; 088 return (int) ((pack & (((1L << (64 - bits)) -1) << ls)) >> ls); 089 } 090}