2011-03-11 12 views
5

क्या जावा में 128 बिट ऑब्जेक्ट बनाने का कोई तरीका है, जिसे थोड़ा या int के समान तरीके से छेड़छाड़ की जा सकती है? मैं 32 बिट बदलाव करना चाहता हूं और मैं पूरी 128 बिट संरचना पर थोड़ा सा या ऑपरेशन करने में सक्षम होना चाहता हूं।जावा 128 बिट स्ट्रक्चर बिट मैनिपुलेशन

उत्तर

2

यहां, मैं आपको एक पुराना विचार प्रस्तुत करता हूं। अब यह बेहद कम हो गया है (कोई कोड बढ़ाने वाला नहीं, कुछ भी नहीं) साधारण 128 बिट चीज़ों के लिए जो सुपर फास्ट होना चाहिए। मैं वास्तव में क्या चाहता हूं एक बाइटबफर आधारित सी के समान संरचना है लेकिन जावा में पूरी तरह उपयोग योग्य है।

मुख्य विचार एक समय में एक ही ऑब्जेक्ट को आवंटित करना और सरणी के लिए पॉइंटर का उपयोग करना है। इस प्रकार, यह स्मृति को बहुत संरक्षित करता है और स्मृति को निरंतर क्षेत्र में आवंटित किया जाता है, इसलिए कम कैश मिस (हमेशा अच्छा) होता है।

मैंने कुछ मामूली परीक्षण किया (लेकिन कोड अभी भी अनचाहे है)। यह 128 बिट संख्याओं के साथ जोड़ने, xor, या सेट/मूलभूत संचालन की अनुमति देता है। मानक नियम: दुर्भाग्य से अपेक्षित अपेक्षा से कम दस्तावेज। अतिरिक्त संचालन के लिए अतिरिक्त कोड जोड़ना सीधे आगे होना चाहिए।

यहां कोड है, कुछ उपयोग के लिए मुख्य विधि देखें। चीयर्स!

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); 
    } 
} 
1

सं

क्षमा वहाँ एक बेहतर जवाब नहीं है।

एक दृष्टिकोण दो लंबे मूल्यों के लिए एक रैपर ऑब्जेक्ट बनाने और प्रासंगिक ऑपरेटरों की हस्ताक्षर लेने के दौरान आवश्यक कार्यक्षमता को लागू करने के लिए हो सकता है। BigInteger भी है [rlibby के उत्तर से अपडेट किया गया], लेकिन यह आवश्यक समर्थन प्रदान नहीं करता है।

हैप्पी कोडिंग।

+0

यह वह दृष्टिकोण था जिस पर मैं – richs

1

वहाँ long से अब डेटा प्रकार है (मैं एक 128 बिट चल बिन्दु के साथ एक RFE के रूप में इस लॉग इन किया है;)

आप चार 32-बिट int मूल्यों के साथ एक वस्तु बना सकते हैं और काफी इन आपरेशनों का समर्थन कर सकते आसानी से।

1

आप जावा के अंतर्निहित बिटवाई ऑपरेटरों को लागू करने के लिए किसी भी नए प्रकार को परिभाषित नहीं कर सकते हैं।

हालांकि, क्या आप बस java.math.BigInteger का उपयोग कर सकते हैं? BigInteger सभी बिट-वार ऑपरेशंस को परिभाषित करता है जो अभिन्न प्रकारों (विधियों के रूप में) के लिए परिभाषित किए जाते हैं। इसमें, उदाहरण के लिए, BigInteger.or(BigInteger) शामिल है।

1

शायद BitSet आपके लिए उपयोगी होगा।

इसमें तार्किक परिचालन हैं, और मुझे लगता है कि स्थानांतरित करना उनके उपयोगिता विधियों को लागू करने के लिए कठिन नहीं होगा।

+0

पर विचार कर रहा था दरअसल, 'बिटकसेट' एपीआई का उपयोग करके शिफ्ट * कुशलतापूर्वक * लागू करना मुश्किल होगा। –

+0

@ स्टीफन यह सच है। – corsiKa

+0

@ स्टीफन - विचित्र रूप से पर्याप्त, दाएं शिफ्ट _is_ पहले ही कार्यान्वित किया गया है, 'बिट्ससेट.get (int, int)' देखें। कुछ कारणों से, हालांकि, उन्होंने बाएं शिफ्ट की उपेक्षा की। – jtahlborn

3

तीन संभावनाओं की पहचान की गई है:

  • BitSet वर्ग संचालन कि आप की आवश्यकता के कुछ प्रदान करता है, लेकिन कोई "बदलाव" विधि। इस लापता विधि को लागू करने के लिए, अगर आप इस तरह कुछ करने के लिए आवश्यकता होगी:

    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); 
    
  • BigInteger वर्ग विधियों (कम या ज्यादा) के सभी प्रदान करता है, लेकिन जब से BigInteger अपरिवर्तनीय है, यह में परिणाम सकता है एक अत्यधिक वस्तु निर्माण दर ... आप बिट्स का उपयोग कैसे करते हैं इस पर निर्भर करता है। (वहाँ भी मुद्दा यह है कि shiftLeft(32) वाम-पंथी बिट्स बंद काटना नहीं होगा ... लेकिन आप and का उपयोग कर सूचकांक 128 और उच्च पर बिट्स बाहर नकाब से इस समस्या से निपटने कर सकते हैं।)

  • यदि प्रदर्शन की कुंजी है चिंता, एक कस्टम वर्ग को 4 int या 2 long फ़ील्ड के साथ लागू करने से शायद सर्वश्रेष्ठ प्रदर्शन होगा। (जो वास्तव में दोनों का तेज विकल्प हार्डवेयर प्लेटफार्म, जेवीएम, आदि पर निर्भर करेगा। शायद मैं long संस्करण का चयन करूंगा क्योंकि यह कोड के लिए आसान होगा ... और प्रोफाइलिंग के संकेत देने पर केवल ऑप्टिमाइज़ करने का प्रयास करें यह एक संभावित सार्थक गतिविधि थी।)

    इसके अलावा, आप एपीआई को यथासंभव व्यवहार करने के लिए डिज़ाइन कर सकते हैं (जावा भाषा की बाधाओं को मॉड्यूल करें)। नकारात्मकता यह है कि आपको सब कुछ लागू करना और परीक्षण करना है, और आप अपने कोड-बेस में जादू संख्या 128 को हार्ड-वायरिंग करेंगे।

+0

32 बिट पर भी हमेशा बेहतर रहता है (एमएमएक्स रेग को एकल लोड करने के लिए इस्तेमाल किया जा सकता है) – bestsss

+0

@bestsss आप x86/x86-64 आर्किटेक्चर मान रहे हैं। –

+0

@ स्टीफन, x86, x64 के मूल 64 रजिस्ट्रार हैं, लेकिन यहां तक ​​कि 'छोटे' प्रोसेसर एक्सस्केल, एआरएमवी 7 में एक ही निर्देश में लोड को संभालने के लिए 64 बिट रजिस्ट्रार हैं।निश्चित रूप से, "हमेशा" बहुत आसानी से उपयोग किया जाता है क्योंकि सभी CPUs के उपयोग योग्य 64 बिट लोड निर्देश नहीं होंगे। – bestsss

0

अफैइक, जेवीएम जो कुछ भी आप करते हैं, 32 बिट भाग में जो कुछ भी आप कोड करते हैं उसे कनवर्ट करेंगे। जेवीएम 32 बिट है। मुझे लगता है कि जेवीएम का 64 बिट संस्करण बड़े पैमाने पर 32 बिट भाग में प्रक्रिया करता है। यह निश्चित रूप से स्मृति को संरक्षित करना चाहिए ... आप बस अपना कोड धीमा करने जा रहे हैं क्योंकि जेआईटी आपके द्वारा बनाई गई गड़बड़ी को अनुकूलित करने का प्रयास करता है। सी/सी ++ आदि में ऐसा करने का कोई मतलब नहीं है क्योंकि आप अभी भी इस तथ्य से प्रतिबाधा करेंगे कि हार्डवेयर में 32 या 64 बिट रजिस्टरों का उपयोग करने की संभावना है। यहां तक ​​कि इंटेल जेनॉन फाई (512 बिट वेक्टर रजिस्ट्रार भी हैं) 32 और 64 बिट तत्वों के बस हैं।

यदि आप ऐसा कुछ कार्यान्वित करना चाहते हैं, तो यदि आप GPU हार्डवेयर उपलब्ध हैं तो आप इसे जीएलएसएल या ओपनसीएल में करने का प्रयास कर सकते हैं। 2015 में जावा सुमात्रा जावा 9 के हिस्से के रूप में जारी किया जाएगा, कम से कम यह योजना है। फिर आपके पास बॉक्स से बाहर GPU कोड के साथ जावा को एकीकृत करने की क्षमता होगी। यह एक बड़ा सौदा है, इसलिए शानदार नाम!

संबंधित मुद्दे