https://forums.factorio.com/viewtopic.php?p=550049#p550049

[0.17.45] Arithmetic Combinator: right-shift (>>) not working correctly on negative numbers - Factorio Forums[0.17.45] Arithmetic Combinator: right-shift (>>) not working correctly on negative numbers - Factorio Forumsforums.factorio.com


논리 시프트를 1틱 구현하는건 정녕 불가능한건가 머리 싸매다가 포기하고 뒤져보니 이런게 있음(제일 밑 코멘트)





어떤 원리로 동작하는 건지 분석을 해보니 이거 만든 사람은 진짜 천재라는 생각밖에 안들더라


만약 입력 A가 음수일 경우 최상위 비트는 1이기 때문에

1abcde....uvwxyz 꼴의 비트라고 볼 수 있음 이게 산술연산조합기(>>)로 들어가게 되는데 그 위에 있는 상수 조합기에서는 A=0x80000000을 넣어 주고있음

그래서 실제로 산술 연산 조합기에 들어가는 A 값은

1abcde...uvwxzy +
100000...000000 =

0abcde...uvwzyx 가 된다

최상위비트만 1에서 0으로 바뀌고 이 상황에서 예를들어 B=3만큼 시프트>>한다면

0000abcde...uvw가 되어버림

근데 a 왼쪽에 있는 비트를 1에서 0으로 바꿨었단 말임. 그래서 이걸 복구해줘야함

이걸 상수조합기에 있는 회색신호=초록색신호=0x40000000이 가능하게 해준다


저 회색신호랑 초록신호도 A신호와 마찬가지로 산술연산조합기(>>)에 들어가는데

0x40000000 = 010000..000000을 B=3만큼 시프트한다면

000010000...000 이 되어서 A로 출력되게 됨, 근데 회색신호 초록신호가 각각 두종류니깐


000010000...000 +

000010000...000 =

000100000...000이 A에 더해지게 된다


왜 굳이 0x80000000>>B를 하는것이 아니라 0x40000000>>B 2개를 각각해서 더하는가 하면 0x80000000은 음수이기 때문에 쉬프트를 하면 처음 문제가 되었던것처럼(산술시프트) 상위비트들이 1로 바뀌게 됨

그래서 굳이 둘로 쪼개서 양수로 만들고 하게 되는 것



암튼 이걸 아까 A에 출력에 더해보면

0000abcde...uvw +

000100000...000 =

0001abcde...uvw


성공적으로 신호가 복구 되었다!



물론 입력 신호가 양수일때도 잘 동작함

입력이 양수 0abcde....uvwxyz 라고 하면 여기에 0x80000000을 더하기 때문에

0abcde...uvwxyz +

100000...000000 =

1abcde...uvwxyz 가 되고 이걸 B=3만큼 시프트>> 하면 부호 비트가 복사되면서

1111abcde...uvw 가 됨


여기에 아까 회색신호와 초록색 신호 덕분에 얻을 수 있었던 값 000100000...000을 더하면

1111abcde...uvw +

000100000...000 =

0000abcde...uvw

앞에 있던 1들이 전부 사라져서 0이 되었다!



이제 여기에 최후의 디테일로 B=31때 추가처리를 할 필요가 있음

회색신호랑 초록색신호를 이용해서 (0x40000000>>B)*2를 계산해주고 있는건데

B= 28일 때, (0x40000000>>28)*2 = 4 * 2 = 8

B= 29일 때, (0x40000000>>29)*2 = 2 * 2 = 4

B= 30일 때, (0x40000000>>30)*2 = 1 * 2 = 2

B가 1씩 증가할 때마다 계산 값은 /2로 감소하게 되는데 B가 31이라면

B= 30일 때, (0x40000000>>31)*2 = 0 * 2 = 0

1이 아니라 0이 나오게 되어버림. 0x80000000>>>B가 아니라 (0x40000000>>B)*2를 했기 때문에 비트를 좀더 빨리 손실하게 되는 것

그래서 이걸 매꾸기 위해 수량비교 조합기를 통해 B가 31일땐 그냥 A 1을 출력하도록 되어있다

그래서 결론적으론 잘 동작함



아 그리고 산술 조합기(>>)에서는 * >> B를 수행하고 있는데

노란 별에는 A, 회색신호, 초록신호가 대응하지만 B자체도 노란 별에 대응하기 때문에 B>>B결과 또한 출력 A로 나오게 됨

하지만 B가 0~31값이라면 B>>B값은 항상 0이기 때문에 결과적으로 문제는 되지 않는다




논리시프트를 1틱 구현하기 위해서는 결국 합선된 회로선에서는 제로틱에 덧셈이 된다는 걸 잘 활용해야 될 것 같긴 했는데 이 회로는 입력단과 출력단 둘다 이걸 잘 활용했기 때문에 최소의 조합기와 최소의 틱으로 논리시프트를 해낼 수 있었다


보다가 너무 감명받아서 설명 글을 주저리 주저리 써봤음. 팩토 회로의 세계는 진짜 너무 심오하고 썩은물들이 많다..