2010-07-10 71 views
4

我寫了一個Int128類型,它的效果很好。我認爲我可以通過一個簡單的想法來改善其表現:改善有點笨拙的輪班操作。MSIL是否有ROL和ROR指令?

因爲它們大量用於乘法和除法,所以改進會產生連鎖反應。所以我開始創建一個動態方法(將低位和高位旋轉),只是發現沒有OpCodes.Rol或OpCodes.Ror指令。

這在IL中可能嗎?

+0

即使事實證明沒有用於位旋轉的CIL操作碼,JIT編譯器仍然足夠聰明,可以將幾個CIL操作碼映射到底層機器指令集上的ROL和ROR指令。 (我實際上並不認爲JIT編譯器*很聰明,但至少可以)。我的意思是說:我不會太擔心。與真正的彙編語言相比,CIL代碼看起來效率非常低,但JIT編譯器很可能會有所緩解。 – stakx 2010-07-14 18:05:08

回答

4

您需要使用位來實現它轉移

UInt64 highBits = 0; 
UInt64 lowBits = 1; 
Int32 n = 63; 
var altShift = (n - 63); 

var lowShiftedOff = (n - 63) > 0 ? 0 : (lowBits << n); 
var highShiftedOff = (n - 63) > 0 ? 0 : (highBits << n); 

var highResult = (UInt64)(highShiftedOff | (altShift > 0 ? (lowBits << altShift - 1) : 0)); 
var lowResult= (UInt64)(lowShiftedOff | (altShift > 0 ? (highBits << altShift - 1) : 0)); 
+1

謝謝。你證實了我所擔心的。 我在.NET 4.0的BigInteger中挖掘,看看他們是如何做到的,現在我對我的感覺並不怎麼糟糕。 – Tergiver 2010-07-10 20:18:24

+1

這不僅不好,而且我忽略了SHL和SHR僅查看移位操作數的最後5位(對於U/Int32)或6位(對於U/Int64),有效地爲整個移位值創建模數。在嘗試轉換位時,這是一個很大的痛苦,我不明白爲什麼它是這樣實現的。 – codekaizen 2010-07-10 20:31:50

+0

移位操作數僅在小於所涉及類型大小的移位時定義,因爲對於* n *位類型移位多於* n *位沒有多大意義。標準(ECMA 335:§3.59)說:'如果'shiftAmount'大於或等於'value'的寬度,則返回值是未指定的。' – porges 2010-07-18 05:16:44

0

爲了部分7年後回答這個問題,萬一有人需要它。

您可以在.Net中使用ROR/ROL。

MSIL不直接包含ROR或ROL操作,但有一些模式會使JIT編譯器生成ROR和ROL。 RuyJIT(.Net和.Net核心)支持這一點。

使用此模式改進.Net Core的細節爲discussed here,一個月後.Net核心代碼爲updated to use it。在implementation of SHA512

尋找,我們發現ROR的例子:

public static UInt64 RotateRight(UInt64 x, int n) { 
     return (((x) >> (n)) | ((x) << (64-(n)))); 
    } 

而且通過同樣的模式延伸到ROL:

public static UInt64 RotateLeft(UInt64 x, int n) { 
     return (((x) << (n)) | ((x) >> (64-(n)))); 
    } 

要做到這一點對128位整數,你可以作爲兩個64處理然後AND提取「carry」,並清除目的地和OR來應用。這必須在兩個方向上進行鏡像(低>高和高>低)。由於這個問題有點老,我不想去打擾一個例子。