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}