我寫了一個Int128類型,它的效果很好。我認爲我可以通過一個簡單的想法來改善其表現:改善有點笨拙的輪班操作。MSIL是否有ROL和ROR指令?
因爲它們大量用於乘法和除法,所以改進會產生連鎖反應。所以我開始創建一個動態方法(將低位和高位旋轉),只是發現沒有OpCodes.Rol或OpCodes.Ror指令。
這在IL中可能嗎?
我寫了一個Int128類型,它的效果很好。我認爲我可以通過一個簡單的想法來改善其表現:改善有點笨拙的輪班操作。MSIL是否有ROL和ROR指令?
因爲它們大量用於乘法和除法,所以改進會產生連鎖反應。所以我開始創建一個動態方法(將低位和高位旋轉),只是發現沒有OpCodes.Rol或OpCodes.Ror指令。
這在IL中可能嗎?
號
您需要使用位來實現它轉移
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));
謝謝。你證實了我所擔心的。 我在.NET 4.0的BigInteger中挖掘,看看他們是如何做到的,現在我對我的感覺並不怎麼糟糕。 – Tergiver 2010-07-10 20:18:24
這不僅不好,而且我忽略了SHL和SHR僅查看移位操作數的最後5位(對於U/Int32)或6位(對於U/Int64),有效地爲整個移位值創建模數。在嘗試轉換位時,這是一個很大的痛苦,我不明白爲什麼它是這樣實現的。 – codekaizen 2010-07-10 20:31:50
移位操作數僅在小於所涉及類型大小的移位時定義,因爲對於* n *位類型移位多於* n *位沒有多大意義。標準(ECMA 335:§3.59)說:'如果'shiftAmount'大於或等於'value'的寬度,則返回值是未指定的。' – porges 2010-07-18 05:16:44
爲了部分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來應用。這必須在兩個方向上進行鏡像(低>高和高>低)。由於這個問題有點老,我不想去打擾一個例子。
即使事實證明沒有用於位旋轉的CIL操作碼,JIT編譯器仍然足夠聰明,可以將幾個CIL操作碼映射到底層機器指令集上的ROL和ROR指令。 (我實際上並不認爲JIT編譯器*很聰明,但至少可以)。我的意思是說:我不會太擔心。與真正的彙編語言相比,CIL代碼看起來效率非常低,但JIT編譯器很可能會有所緩解。 – stakx 2010-07-14 18:05:08