2011-12-09 26 views
8

में 128-बिट डिवीजन आंतरिक आंतरिक मैं दृश्य सी ++ में वास्तव में कोई 128-बिट डिवीजन आंतरिक कार्य नहीं कर रहा हूं?विजुअल सी ++

एक 64x64 = 128 बिट गुणात्मक आंतरिक फ़ंक्शन है जिसे _umul128() कहा जाता है, जो अच्छी तरह से एमयूएल x64 असेंबलर निर्देश से मेल खाता है।

स्वाभाविक रूप से, मुझे लगता है कि 128/64 = 64 बिट डिवीजन आंतरिक भी होगा (डीआईवी निर्देश मॉडलिंग), लेकिन मेरे विस्मय के लिए न तो दृश्य सी ++ और न ही इंटेल सी ++ में ऐसा प्रतीत होता है, कम से कम यह सूचीबद्ध नहीं है intrin.h।

क्या कोई इसकी पुष्टि कर सकता है? मैंने कंपाइलर निष्पादन योग्य फ़ाइलों में फ़ंक्शन नामों के लिए grep'ing करने का प्रयास किया, लेकिन पहली जगह _umul128 नहीं मिला, इसलिए मुझे लगता है कि मैंने गलत स्थान देखा है।

अद्यतन: कम से कम मुझे अब दृश्य सी ++ 2010 के c1.dll में "umul128" (अग्रणी अंडरस्कोर के बिना) पैटर्न मिला है। अन्य सभी अंतर्ज्ञान इसके चारों ओर सूचीबद्ध हैं, लेकिन दुर्भाग्यवश कोई "udiv128" या पसंद नहीं है :(तो ऐसा लगता है कि वे वास्तव में इसे लागू करने के लिए "भूल गए" हैं।

स्पष्टीकरण के लिए: मैं केवल 128 बिट डेटा प्रकार की तलाश नहीं कर रहा हूं, लेकिन 128 बिट स्केलर int को 64-बिट द्वारा विभाजित करने का एक तरीका है C++ int। या तो कोई आंतरिक समारोह या देशी 128 बिट पूर्णांक समर्थन मेरी समस्या का समाधान होगा।

एडी टी: जवाब नहीं है, वहाँ कोई _udiv128 दृश्य स्टूडियो 2010 या 2012

+1

यह सीआरटी का हिस्सा नहीं है। यह एक आंतरिक है, प्रोसेसर के साथ मुफ्त में आता है। लेकिन केवल 64-बिट मोड में। जब तक आपको 128-बिट प्रोसेसर नहीं मिलता है तब तक div के लिए कोई फ्रीबी नहीं। पाउ (2, 128) की हास्यास्पद रूप से विशाल श्रेणी को देखते हुए, आपको मनमाना सटीक पुस्तकालय की तलाश करनी चाहिए। आसपास के बहुत सारे। –

+0

@ ट्रीमोन्की: __int18 वीएस द्वारा समर्थित नहीं है, http://stackoverflow.com/questions/6759592/how-to-enable-int128-on-visual-studio – cxxl

+2

@ हंस: क्षमा करें, मुझे समझ में नहीं आता है। यह सिर्फ एक आंतरिक नहीं है, यहां तक ​​कि 64 बिट मोड में भी नहीं। और मुझे इसकी आवश्यकता है * लिखना * एक मनमाना सटीक lib :) – cxxl

उत्तर

1

में आंतरिक मैं कोई विशेषज्ञ हूँ, लेकिन मैं इस अप खोदा:

http://research.swtch.com/2008/01/division-via-multiplication.html

दिलचस्प सामान। आशा करता हूँ की ये काम करेगा।

संपादित करें: यह व्यावहारिक भी है: http://www.gamedev.net/topic/508197-x64-div-intrinsic/

+0

यह वास्तव में काफी दर्द है।यहां तक ​​कि यदि आपको पारस्परिक + शिफ्ट की आवश्यकता होती है, तो आपको अपने 128 बिट नाम को पारस्परिक रूप से गुणा करना होगा और परिणाम से शीर्ष 64 बिट्स लेना होगा, जो एक गंभीर पिटा – yonil

+0

है, मुझे यह भी विश्वास करना मुश्किल लगता है कि पूरी बात होगी किसी भी तरह एक डीआईवी/आईडीआईवी निर्देश बेहतर प्रदर्शन। – yonil

10

आप थोड़ा हैक्स कोई आपत्ति नहीं है, यह मदद मिल सकती है (64-बिट मोड केवल, परीक्षण नहीं):

#include <windows.h> 
#include <stdio.h> 

unsigned char udiv128Data[] = 
{ 
    0x48, 0x89, 0xD0, // mov rax,rdx 
    0x48, 0x89, 0xCA, // mov rdx,rcx 
    0x49, 0xF7, 0xF0, // div r8 
    0x49, 0x89, 0x11, // mov [r9],rdx 
    0xC3    // ret 
}; 

unsigned char sdiv128Data[] = 
{ 
    0x48, 0x89, 0xD0, // mov rax,rdx 
    0x48, 0x89, 0xCA, // mov rdx,rcx 
    0x49, 0xF7, 0xF8, // idiv r8 
    0x49, 0x89, 0x11, // mov [r9],rdx 
    0xC3    // ret 
}; 

unsigned __int64 (__fastcall *udiv128)(unsigned __int64 numhi, 
             unsigned __int64 numlo, 
             unsigned __int64 den, 
             unsigned __int64* rem) = 
    (unsigned __int64 (__fastcall *)(unsigned __int64, 
            unsigned __int64, 
            unsigned __int64, 
            unsigned __int64*))udiv128Data; 

__int64 (__fastcall *sdiv128)(__int64 numhi, 
           __int64 numlo, 
           __int64 den, 
           __int64* rem) = 
    (__int64 (__fastcall *)(__int64, 
          __int64, 
          __int64, 
          __int64*))sdiv128Data; 

int main(void) 
{ 
    DWORD dummy; 
    unsigned __int64 ur; 
    __int64 sr; 
    VirtualProtect(udiv128Data, sizeof(udiv128Data), PAGE_EXECUTE_READWRITE, &dummy); 
    VirtualProtect(sdiv128Data, sizeof(sdiv128Data), PAGE_EXECUTE_READWRITE, &dummy); 
    printf("0x0000ABCDEF000000000000/0x0001000000000000 = 0x%llX\n", 
     udiv128(0x0000AB, 0xCDEF000000000000, 0x0001000000000000, &ur)); 
    printf("-6/-2 = %lld\n", 
     sdiv128(-1, -6, -2, &sr)); 
    return 0; 
} 
+1

एमएसवीसी के लिए संकलन –

+0

@Maratyszcza के दौरान इन कार्यों को कोड सेगमेंट में रखने के लिए #pragma सेक्शन का उपयोग कर सकते हैं: आप सही हैं। –

+0

आप इनलाइन असेंबली का उपयोग क्यों नहीं कर सकते? –

2

एक छोटा सा सुधार - एक कम निर्देश

extern "C" digit64 udiv128(digit64 low, digit64 hi, digit64 divisor, digit64 *remainder); 

; Arguments 
; RCX  Low Digit 
; RDX  High Digit 
; R8  Divisor 
; R9  *Remainder 

; RAX  Quotient upon return 

.code 
udiv128 proc 
    mov rax, rcx ; Put the low digit in place (hi is already there) 
    div r8  ; 128 bit divide rdx-rax/r8 = rdx remainder, rax quotient 
    mov [r9], rdx ; Save the reminder 
    ret  ; Return the quotient 
udiv128 endp 
end