Есть много операторов для побитового арифметики:
Например, вы можете использовать
(logxor bit 1)
Это даст вам 0
если бит равен 1 и 1
если бит равен 0:
(logxor 0 1) ; => 1
(logxor 1 1) ; => 0
Конечно, вы можете положить часть bit
в качестве второго аргумента:
(logxor 1 bit)
Bonus:
Может быть, вы можете сделать функцию и оптимизировать его с типом декларации:
(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
С объявлением типа
; 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 указывает, что желательно, чтобы компилятор производил встроенные вызовы функций, названных именами функций; то есть код для указанного имени функции должен быть интегрирован в вызывающую подпрограмму, появляясь в строке `` in line '' вместо вызова процедуры.
«вызов инверсии», вероятно, компенсирует усиление в производительности »- вы можете использовать' (declaim (inline invert)) 'для встраивания вызова. – jkiiski
Добавлено! Спасибо! :) – tsikov
@tsikov: Спасибо, logxor был тем, что я искал, но упустил его значение. Предположим теперь, что я могу сделать '(определить изменение-макро invertf (& отдых арг) (лямбда (бит) (объявлять (бит бит типа)) (logxor бит 1)))' воспользоваться деклараций и встраивание ? – davypough