简体   繁体   English

java 128位结构位maninpulation

[英]java 128 bit structure bit maninpulation

Is there a way to create a 128 bit object in java, that can be bit manipulated the same way as a long or int? 有没有办法在java中创建一个128位对象,可以像long或int那样进行位操作? I want to do 32 bit shifts and i want to be able to do a bit OR operation on the whole 128 bit structure. 我想做32位移位,我希望能够对整个128位结构进行一些OR运算。

Here, I present to you... an old idea. 在这里,我向你介绍......一个古老的想法。 Now it's awfully downgraded (no code enhancer, no nothing) to simple 128 bit thingie that should be super fast, though. 现在它被降级(没有代码增强器,没有任何东西)到简单的128位东西,应该超级快。 What I truly want is a ByteBuffer based array of C alike Struct but fully usable in java. 我真正想要的是一个基于ByteBuffer的C类似结构数组,但在java中完全可用。

The main idea is allocating more than a single object at a time and using a pointer to the array. 主要思想是一次分配多个对象并使用指向数组的指针。 Thus, it greatly conserves memory and the memory is allocated in continuous area, so less cache misses (always good). 因此,它极大地节省了内存,并且内存在连续区域中分配,因此缓存丢失较少(总是很好)。

I did some moderate testing (but the code is still untested). 我做了一些温和的测试(但代码仍未经过测试)。 It does allow basic operations like add, xor, or, set/get with 128 bit numbers. 它允许基本操作,如add,xor,或set / get,具有128位数字。 The standard rule: less documentation than expected applied unfortunately. 标准规则:遗憾的是,文档少于预期。 Adding extra code for extra operations should be straight forward. 为额外操作添加额外代码应该是直截了当的。

Here is the code, look at main method for some usage. 这是代码,看看主要方法的一些用法。 Cheers! 干杯!

package bestsss.util;

import java.util.Random;

public class Bitz {
    final int[] array;
    private Bitz(int n){
        array=new int[n<<2];
    }

    public int size(){
        return size(this.array);
    }

    private static int size(int[] array){
        return array.length>>2;
    }
    /**
     * allocates N 128bit elements. newIdx to create a pointer
     * @param n
     * @return
     */
    public static Bitz allocate(int n){
        return new Bitz(n);
    }
    /**
     * Main utility class - points to an index in the array
     * @param idx
     * @return
     */
    public Idx newIdx(int idx){     
        return new Idx(array).set(idx);
    }

    public static class Idx{
        private static final  long mask = 0xFFFFFFFFL;
        //dont make the field finals

        int idx;
        int[] array;//keep ref. here, reduce the indirection

        Idx(int[] array){
            this.array=array;
        }

        public Idx set(int idx) {
            if (Bitz.size(array)<=idx || idx<0)
                throw new IndexOutOfBoundsException(String.valueOf(idx));

            this.idx = idx<<2;
            return this;
        }

        public int index(){
            return idx>>2;
        }

        public Idx shl32(){
            final int[] array=this.array;
            int idx = this.idx;

            array[idx]=array[++idx];
            array[idx]=array[++idx];
            array[idx]=array[++idx];                 
            array[idx]=0;

            return this;
        }

        public Idx shr32(){
            final int[] array=this.array;
            int idx = this.idx+3;

            array[idx]=array[--idx];
            array[idx]=array[--idx];
            array[idx]=array[--idx];                 
            array[idx]=0;
            return this;
        }
        public Idx or(Idx src){         
            final int[] array=this.array;
            int idx = this.idx;

            int idx2 = src.idx;
            final int[] array2=src.array;

            array[idx++]|=array2[idx2++];
            array[idx++]|=array2[idx2++];
            array[idx++]|=array2[idx2++];
            array[idx++]|=array2[idx2++];

            return this;            
        }

        public Idx xor(Idx src){            
            final int[] array=this.array;
            int idx = this.idx;

            int idx2 = src.idx;
            final int[] array2=src.array;

            array[idx++]^=array2[idx2++];
            array[idx++]^=array2[idx2++];
            array[idx++]^=array2[idx2++];
            array[idx++]^=array2[idx2++];

            return this;            
        }

        public Idx add(Idx src){            
            final int[] array=this.array;
            int idx = this.idx+3;

            final int[] array2=src.array;
            int idx2 = src.idx+3;


            long l =0;

            l += array[idx]&mask;
            l += array2[idx2--]&mask;           
            array[idx--]=(int)(l&mask);
            l>>>=32;


            l += array[idx]&mask;
            l += array2[idx2--]&mask;           
            array[idx--]=(int)(l&mask);
            l>>>=32;

            l += array[idx]&mask;
            l += array2[idx2--]&mask;           
            array[idx--]=(int)(l&mask);
            l>>>=32;

            l += array[idx]&mask;
            l += array2[idx2--];            
            array[idx]=(int)(l&mask);
//          l>>>=32;

            return this;            
        }

        public Idx set(long high, long low){
            final int[] array=this.array;
            int idx = this.idx;
            array[idx+0]=(int) ((high>>>32)&mask);
            array[idx+1]=(int) ((high>>>0)&mask);


            array[idx+2]=(int) ((low>>>32)&mask);
            array[idx+3]=(int) ((low>>>0)&mask);
            return this;
        }


        public long high(){
            final int[] array=this.array;
            int idx = this.idx;
            long res = (array[idx]&mask)<<32 | (array[idx+1]&mask); 
            return res;
        }

        public long low(){
            final int[] array=this.array;
            int idx = this.idx;
            long res = (array[idx+2]&mask)<<32 | (array[idx+3]&mask); 
            return res;
        }

        //ineffective but well
        public String toString(){                   
            return String.format("%016x-%016x", high(), low());
        }
    }

    public static void main(String[] args) {
        Bitz bitz = Bitz.allocate(256);
        Bitz.Idx idx = bitz.newIdx(0);
        Bitz.Idx idx2 = bitz.newIdx(2);

        System.out.println(idx.set(0, 0xf));
        System.out.println(idx2.set(0, Long.MIN_VALUE).xor(idx));       

        System.out.println(idx.set(0, Long.MAX_VALUE).add(idx2.set(0, 1)));
        System.out.println("==");
        System.out.println(idx.add(idx));//can add itself

        System.out.println(idx.shl32());//left
        System.out.println(idx.shr32());//and right
        System.out.println(idx.shl32());//back left

        //w/ alloc
        System.out.println(idx.add(bitz.newIdx(4).set(0, Long.MAX_VALUE)));

        //self xor
        System.out.println(idx.xor(idx));
        //random xor

        System.out.println("===init random===");
        Random r = new Random(1112); 
        for (int i=0, s=bitz.size(); i<s; i++){
            idx.set(i).set(r.nextLong(), r.nextLong());
            System.out.println(idx);
        }
        Idx theXor = bitz.newIdx(0);
        for (int i=1, s=bitz.size(); i<s; i++){         
            theXor.xor(idx.set(i));
        }

        System.out.println("===XOR===");
        System.out.println(theXor);
    }
}

Three possibilities have been identified: 已经确定了三种可能性:

  • The BitSet class provides some of the operations that you need, but no "shift" method. BitSet类提供了您需要的一些操作,但没有“shift”方法。 To implement this missing method, you'd need to do something like this: 要实现这个缺少的方法,您需要执行以下操作:

     BitSet bits = new BitSet(128); ... // shift left by 32bits for (int i = 0; i < 96; i++) { bits.set(i, bits.get(i + 32)); } bits.set(96, 127, false); 
  • The BigInteger class provides all of the methods (more or less), but since BigInteger is immutable, it could result in an excessive object creation rate ... depending on how you use the bitsets. BigInteger类提供了所有方法(或多或少),但由于BigInteger是不可变的,因此可能导致过多的对象创建速率......取决于您如何使用位集。 (There is also the issue that shiftLeft(32) won't chop off the leftmost bits ... but you can deal with this by using and to mask out the bits at index 128 and higher.) (还有一个问题,即shiftLeft(32)不会切断最左边的位...但你可以通过使用and掩盖索引128及更高位的位来处理这个问题。)

  • If performance is your key concern, implementing a custom class with 4 int or 2 long fields will probably give best performance. 如果性能是您关注的主要问题,那么实现具有4个int或2个long字段的自定义类可能会提供最佳性能。 (Which is actually the faster option of the two will depend on the hardware platform, the JVM, etc. I'd probably choose the long version because it will be simpler to code ... and only try to optimize further if profiling indicated that it was a potentially worthwhile activity.) (实际上两者中更快的选择取决于硬件平台,JVM等等。我可能会选择long版本,因为编写代码会更简单...并且只有在分析表明这样做时才尝试进一步优化这是一项有潜在价值的活动。)

    Furthermore, you can design the APIs to behave exactly as you require (modulo the constraints of Java language). 此外,您可以设计API以完全按照您的要求运行(以Java语言的约束为模)。 The downside is that you have to implement and test everything, and you will be hard-wiring the magic number 128 into your code-base. 缺点是您必须实现并测试所有内容,并且您将把魔术数字128硬连接到您的代码库中。

There is no longer data type than long (I have logged this as an RFE along with a 128 bit floating point ;) 数据类型不再long (我将其记录为RFE以及128位浮点;)

You can create an object with four 32-bit int values and support these operations fairly easily. 您可以使用四个32位int值创建一个对象,并且相当容易地支持这些操作。

No. 没有。

Sorry there isn't a better answer. 对不起,没有更好的答案。

One approach may be to create a wrapper object for two long values and implement the required functionality while taking signedness of the relevant operators into account. 一种方法可以是为两个长值创建包装器对象,并在考虑相关运算符的签名的同时实现所需的功能。 There is also BigInteger [updated from rlibby's answer], but it doesn't provide the required support. 还有BigInteger [从rlibby的答案更新],但它没有提供所需的支持。

Happy coding. 快乐的编码。

You can't define any new types to which you could apply Java's built-in bitwise operators. 您无法定义可以应用Java内置按位运算符的任何新类型。

However, could you just use java.math.BigInteger ? 但是,你能使用java.math.BigInteger吗? BigInteger defines all of the bit-wise operations that are defined for integral types (as methods). BigInteger定义了为整数类型定义的所有按位操作(作为方法)。 This includes, for example, BigInteger.or(BigInteger) . 这包括,例如, BigInteger.or(BigInteger)

Perhaps BitSet would be useful to you. 也许BitSet会对你有用。

It has the logical operations, and I imagine shifting wouldn't be all that hard to implement given their utility methods. 它具有逻辑运算,我认为根据它们的实用方法,转换并不是那么难实现。

Afaik, the JVM will just convert whatever you code into 32 bit chunks whatever you do. Afaik,无论你做什么,JVM都会将你编码的任何内容转换为32位块。 JVM is 32 bit. JVM是32位。 I think even 64 bit version of JVM largely processes in 32 bit chunks. 我认为即使是64位版本的JVM也主要以32位块的形式处理。 It certainly should to conserve memory... You're just going to slow down your code as the JIT tries to optimise the mess you create. 它当然应该节省内存......当JIT试图优化您创建的混乱时,您只会减慢代码速度。 In C/C++ etc. there's no point doing this either as you will still have impedance from the fact that it's 32 or 64 bit registers in the hardware you're most likely using. 在C / C ++等中,没有必要这么做,因为你最有可能使用的硬件中的32位或64位寄存器仍会产生阻抗。 Even the Intel Xenon Phi (has 512bit vector registers) is just bunches of 32 and 64 bit elements. 即使是Intel Xenon Phi(具有512位向量寄存器)也只是32位和64位元素的串联。

If you want to implement something like that, you could try to do it in GLSL or OpenCL if you have GPU hardware available. 如果你想实现类似的东西,你可以尝试在GLSL或OpenCL中使用GPU硬件。 In 2015 Java Sumatra will be released as part of Java 9, at least that's the plan. 2015年Java Sumatra将作为Java 9的一部分发布,至少这是计划。 Then you will have the ability to integrate java with GPU code out of the box. 然后,您将能够将Java与GPU代码集成在一起。 That IS a big deal, hence the illustrious name! 这是一个大问题,因此这个杰出的名字!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM