[英]Inversion of a bit
我一直無法找到簡單地反轉一下的common-lisp函數(或宏)。 有些函數可以對位數組進行操作,邏輯函數可以對數字進行操作,但這些函數似乎需要額外的步驟來反轉單個位變量。 一個暫時的解決方案是
(define-modify-macro invertf (&rest args)
(lambda (bit)
(if (= bit 0) 1 0)))
哪個有效,但我想知道是否有更優雅或更簡單的解決方案。
按位運算有很多運算符:
例如,您可以使用
(logxor bit 1)
這會給你0
如果該位是1, 1
,如果該位為0:
(logxor 0 1) ; => 1
(logxor 1 1) ; => 0
當然你可以將bit
部分作為第二個參數:
(logxor 1 bit)
獎金 :
也許您可以創建一個函數並使用類型聲明對其進行優化:
(defun invert (bit)
"Inverts a bit"
(declare (type bit bit))
(logxor bit 1))
運行后(disassemble 'invert)
我在SBCL上得到了以下結果:
沒有類型聲明:
; disassembly for INVERT
; Size: 56 bytes. Origin: #x10059E97FC
; 7FC: 498B4C2460 MOV RCX, [R12+96] ; thread.binding-stack-pointer
; no-arg-parsing entry point
; 801: 48894DF8 MOV [RBP-8], RCX
; 805: BF02000000 MOV EDI, 2
; 80A: 488BD3 MOV RDX, RBX
; 80D: 4883EC18 SUB RSP, 24
; 811: 48896C2408 MOV [RSP+8], RBP
; 816: 488D6C2408 LEA RBP, [RSP+8]
; 81B: B904000000 MOV ECX, 4
; 820: FF1425980B1020 CALL QWORD PTR [#x20100B98] ; TWO-ARG-XOR
; 827: 488B5DF0 MOV RBX, [RBP-16]
; 82B: 488BE5 MOV RSP, RBP
; 82E: F8 CLC
; 82F: 5D POP RBP
; 830: C3 RET
; 831: 0F0B10 BREAK 16 ; Invalid argument count trap
WITH類型聲明
; disassembly for INVERT
; Size: 25 bytes. Origin: #x1005767CA9
; A9: 498B4C2460 MOV RCX, [R12+96] ; thread.binding-stack-pointer
; no-arg-parsing entry point
; AE: 48894DF8 MOV [RBP-8], RCX
; B2: 488BD3 MOV RDX, RBX
; B5: 4883F202 XOR RDX, 2
; B9: 488BE5 MOV RSP, RBP
; BC: F8 CLC
; BD: 5D POP RBP
; BE: C3 RET
; BF: 0F0B10 BREAK 16 ; Invalid argument count trap
在我看來,類型聲明保存了一些操作。
讓我們衡量差異:
(defun invert (bit)
"Inverts a bit"
(declare (type bit bit))
(logxor bit 1))
(defun invert-no-dec (bit)
"Inverts a bit"
(logxor bit 1))
現在運行:
(time (loop repeat 1000000 do (invert 1)))
輸出:
Evaluation took:
0.007 seconds of real time
0.005164 seconds of total run time (0.005073 user, 0.000091 system)
71.43% CPU
14,060,029 processor cycles
0 bytes consed
在跑步的時候:
(time (loop repeat 1000000 do (invert-no-dec 1)))
輸出:
Evaluation took:
0.011 seconds of real time
0.011327 seconds of total run time (0.011279 user, 0.000048 system)
100.00% CPU
25,505,355 processor cycles
0 bytes consed
似乎類型聲明使函數的速度提高了一倍。 必須注意的是,對invert
的調用可能會抵消性能增益,除非你使用(declaim (inline invert))
。 來自CLHS :
inline指定編譯器需要對由function-names命名的函數進行內聯調用; 也就是說,指定函數名的代碼應該集成到調用例程中,顯示“在行中”代替過程調用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.