# Lista 2 (11 marca 2021), grupa KBa
###### tags: `ask21` `ćwiczenia` `kba`
## Deklaracje
Gotowość rozwiązania zadania należy wyrazić poprzez postawienie X w odpowiedniej kolumnie! Jeśli pożądasz zreferować dane zadanie (co najwyżej jedno!) w trakcie dyskusji oznacz je znakiem ==X== na żółtym tle.
**UWAGA: Tabelkę wolno edytować tylko wtedy, gdy jest na zielonym tle!**
:::danger
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| --------------------:| --- | ----- | ----- | --- | --- | --- | ----- | ----- | --- |
| Andriy Bernad | X | X | X | |==X==| | X | X | X | 7
| Wojciech Bogucki | X | ==X== | X | | X | | X | X | | 6
| Michał Doros | X | X | X | X | X | X | ==X== | X | X | 9
| Marko Golovko | X | X | X | X | | | X | | | 5
| Magdalena Jarecka | | X | ==X== | | X | | X | X | | 5
| Szymon Jędras | X | X | X | X | X | X | X | X | X | 9
| Heorhii Karpenko | X | X | X | | X | | X | X | X | 7
| Szymon Kosakowski | X | X | X | | X | | X | X | X | 7
| Izabella Kozioł | | | | | | | | | | 0
| Franciszek Malinka | X | X | X | | X | X | X | X |==X==| 8
| Filip Pazera | | X | X | | | | X | | | 3
| Franciszek Pindel | X | X | X | | X | | X | ==X== | X | 7
| Kacper Puchalski | X | X | X | | X | | X | X | X | 7
| Kacper Solecki | X | X | X | X | X | X | X | ==X== | X | 9
| Andrzej Tkaczyk | X | X | X | | X | X | X | X | X | 8
| Łukasz Wasilewski | X | X | X | X | X | X | | | | 6
| Vladyslav Yablonskyi | X | X | X | | X | | ==X== | X | | 6
| Adam Zyzik | | X | X | | | | X | X | | 4
:::
## Zadanie 1
:::info
Autor: Łukasz Wasilewski
:::
(x>0) || (x-1 < 0) - nie zawsze prawda. Fałsz gdy x w zapisie bitowym jest równy 100...0 bo wtedy x<0 oraz x-1 wylicza się do 011...1 co dla zmiennych typu int32_t jest większe od 0
(x&7) != 7 <=>któryś z 3 ostatnich bitów x nie jest zapalony.
x << 29 < 0 <=> 3 ostatni bit jest zapalony
więc cały warunek jest fałszywy dla cokolwiek000, cokolwiek001, cokolwiek010, cokolwiek011
(x*x)>=0 fałsz gdy (pierwszy_bit*(2^32 )-x)^2 % 2^32 >=2^(31)
x<0 || -x<=0 zawsze
x > 0 || -x >= 0 fałsz dla 10000...0_2
(x | -x)>> 31 == -1 fałsz dla 10000...0_2
x + y == (uint32_t)y + (uint32_t)x zawsze
x * ~y + (uint32_t )y * (uint32_t)x == -x zawsze bo maszynowe l. całkowite z + i * są pierścieniem, oraz ~y+(uint32_t )y=~y+y=-1.
## Zadanie 2
:::info
Autor: Wojciech Bogucki
:::
```c=
void swap(int32_t * x, int32_t * y){
*x = *x + *y;
*y = *x - *y;
*x = *x - *y;
}
```
W lini nr. 3 efektywnie będzie y = x + y - y
=> y = x
W lini nr. 4 efektywnie będzie x = x + y - x
=> x = y
> [name=Andrzej Tkaczyk] z xorem w spoilerze
:::spoiler
```c=
x = x ^ y;
y = x ^ y;
x = x ^ y;
```
:::
## Zadanie 3
:::info
Autor: Magdalena Jarecka
:::
**Nadmiar** - gdy w reprezentacji liczb binarnych nie ma wystarczającej liczby bitów, aby przedstawić wynik operacji arytmetycznej.
**Niedomiar** - gdy w reprezentacji liczb binarnych ujemnych nie ma wystarczającej liczby bitów, aby przedstawić wynik operacji arytmetycznej.
```c=
s = x + y
bool is_overflow = ((s ^ y) & (s ^ x)) >> 31;
```
1) Jeśli x i y mają różne znaki nie może dojść do nadmiaru/niedomiaru
W tym momencie s będzie przyjmowało znak x lub y dzięki czemu (s ^ y) oraz (s ^ x) będzie różniło się najbardziej znaczącymi bitami. Czyli (s ^ y) & (s ^ x)) przy najstarszym bicie będzie miało 0.
(s ^ y) & (s ^ x)) >> 31) = 0
0 & 1 = 0
3) Jeśli mają te same znaki to może dojśc do nadmiaru/niedomiaru
Wtedy s będzie miało inny znak niż x i y.
- x, y < 0, s > 0:
Wtedy s ^ y będzie miało na początku 1 tak samo jak i s ^ x.
(s ^ y) & (s ^ x) -> również 1 na początku
Przesuwamy początkowy bit na pierwsze miejsce co sprawia że:
(s ^ y) & (s ^ x)) >> 31) = 1
1 & 1 = 1
- x, y > 0, s < 0:
Tak samo
> [name=Andrzej Tkaczyk]
> można bez & 1 na końcu
## Zadanie 4
:::info
Autor: Szymon Jędras
:::
```c=
//• ⊕ jest operacją dodawania,
z_i = (x_i ^ y_i) & 0x80 ^ ((x_i & 0x7f) + (y_i & 0x7f));
//• ⊕ jest operacją odejmowania.
z_i = ~(((x_i ^ y_i) | 0x7f) ^ ((x_i | 0x80) - (y_i & 0x7f));
```
Wizualizacja:
:::spoiler
$$
\begin{aligned}
&carry: &1\ 0\quad &1\ 0\quad &1\ 0\quad &1\ 0\\
&x: &1\ 1\quad &1\ 1\quad &0\ 0\quad &0\ 0\\
&y: &1\ 1\quad &0\ 0\quad &1\ 1\quad &0\ 0\\
&wynik\ pierwszy: &0\ 1\quad &0\ 1\quad &0\ 1\quad &0\ 1\\\\
¬\ x: &0\ 0\quad &0\ 0\quad &1\ 1\quad &1\ 1\\
&(not\ x)\oplus y: &1\ 1\quad &0\ 0\quad &0\ 0\quad &1\ 1\\
&koncowy\ wynik: &1\ 0\quad &0\ 1\quad &0\ 1\quad &1\ 0\\
&spodziewany\ wynik:\quad &1\ 0\quad &0\ 1\quad &0\ 1\quad &1\ 0
\end{aligned}
$$
:::
Fragment:
```c=
(x_i & 0x7f) + (y_i & 0x7f) // (1)
```
maskuje najbardziej znaczący bit w każdym bajcie, uniemożliwiając overflow. Następnie pozostała część to 1-bitowa suma, najpierw znajduje te bity które się różnią pomiędzy x i y, a potem je odwraca jeżeli jakiś bit "przelał się" z mniej znaczących bitów.
Żeby wynik nie był "zły", trzeba by było przechowywać carry bit w zewnętrznej zmiennej i dodać/odjąć go w fragmencie (1).
```c=
(x_i & 0x7f) + (y_i & 0x7f) + carry; // (1)
```
Carry bit można było by liczyć za pomocą takiego fragmentu kodu:
```c=
carry = (x_i & y_i ^ z_i)>>31 & 1;
```
:::spoiler
dodawanie:
```c=
z = (x & 0x7F7F7F7F) + (y & 0x7F7F7F7F);
z = ((x ^ y) & 0x80808080) ^ z;
```
odejmowanie:
```c=
z = (x | 0x80808080) - (y & 0x7F7F7F7F);
z = (((~x) ^ y) & 0x80808080) ^ z;
```
:::
## Zadanie 5
:::info
Autor: Andrzej Bernad
:::
$temp_{x} =\lfloor \frac{x}{2} \rfloor +\lfloor \frac{x}{4} \rfloor + \epsilon = \frac{x}{2} + \frac{x}{4}$
```c=
int32_t threefourths(int32_t x)
{
int32_t temp_x = (x >> 1) + (x >> 2);
// temp_x = x / 2 + x / 4 = 3/4 * x
int32_t overflow_bits = 0xC0000000 & temp_x;
// zapamiętujemy 2 najbardziej znaczące bity wyniku
/* obliczamy wynik z możliwą utratą dwóch najbardziej
* znaczących bitów, natomiast z dobrym zaokrągleniem */
int32_t temp = x;
temp <<= 1; // x * 2
temp += x; // x * 2 + x
temp >>= 2; // (x * 2 + x) / 4 , w tym miejscu zaokrąglamy wynik
// odzyskujemy dwa najbardziej znaczące bity wyniku
temp &= 0x3FFFFFFF //0b0011..11
temp |= overflow_bits;
return temp;
}
// 0xC0000000 = 0b11000000000000000000000000000000
```
> [name=Franciszek Pindel] może tak
:::spoiler
```c
r = (x & 0b11) + (x & 0b1) >> 2;
return (x >> 2) + (x >> 1) + r;
```
:::
> [name=Franciszek Malinka] mam jeszcze krócej
:::spoiler
```c=
/* Oblicz x * 3 / 4 zaokrąglając w dół */
int32_t threefourths(int32_t x) {
return (x>>1) + (x+1 >> 2);
}
```
1. $x = 0 \mod 4$, wtedy $$\lfloor 3x/4\rfloor = 3x/4 = x/2 + x/4 = \lfloor x/2 \rfloor + \lfloor (x+1)/4 \rfloor$$.
2. $x = 1 \mod 4$, wtedy $$\lfloor 3x/4\rfloor = (3x - 3)/4 = 3(x-1)/4 = (x-1)/2 + (x-1)/4 = \lfloor x/2 \rfloor + \lfloor (x+1)/4 \rfloor$$.
3. $x = 2 \mod 4$, wtedy $$\lfloor 3x/4\rfloor = (3x - 2)/4 = 3x/4 - 1/2 = x/2 + x/4 - 1/2 = \lfloor x/2 \rfloor + \lfloor x/4 \rfloor \\= \lfloor x/2 \rfloor + \lfloor (x+1)/4 \rfloor$$
4. $x = 3 \mod 4$, wtedy $$\lfloor 3x/4\rfloor = (3x - 1)/4 = x/2 + x/4 - 1/4 = \lfloor x/2 \rfloor + 1/2 + \lfloor (x+1)/4 \rfloor - 1/4 -1/4 \\= \lfloor x/2 \rfloor + \lfloor (x+1)/4 \rfloor$$
:::
## Zadanie 6
:::info
Autor: Andrzej Tkaczyk
:::
$x<y\ wtw. \frac{x}{2}<\frac{y}{2}\ wtw. \frac{x}{2}-\frac{y}{2}<0$
ale psuje się jak y = x+1 i 2|x (przez zaokrąglenie), dlatego jeśli nie wychodzi porównanie $\frac{x}{2}<\frac{y}{2}$, to sprawdzamy ten przypadek y = x+1 i 2|x
```c=
uint32_t lta(uint32_t x, uint32_t y){
return (x >> 1) - (y >> 1) >> 31 & 1 | (~x & y & 1) & (x >> 1) - ((y >> 1)+1) >> 31 & 1;
//(x >> 1) - (y >> 1) >> 31 & 1 -> sprawdzenie czy x/2 - y/2 < 0
//(~x & y & 1) -> sprawdzenie czy 2|x i czy y ma potencjał być x+1
//(x >> 1) - ((y >> 1)+1) >> 31 & 1 -> sprawdzenie czy x/2 - (y+1)/2 < 0
}
int32_t ltb(int32_t x, int32_t y){
return (x >> 1) - (y >> 1) >> 31 & 1 | (~x & y & 1) & (x >> 1) - ((y >> 1)+1) >> 31 & 1;
//(x >> 1) - (y >> 1) >> 31 & 1 -> sprawdzenie czy x/2 - y/2 < 0
//(~x & y & 1) -> sprawdzenie czy 2|x i czy y ma potencjał być x+1
//(x >> 1) - ((y >> 1)+1) >> 31 & 1 -> sprawdzenie czy x/2 - (y+1)/2 < 0
}
```
> [name=Krystian Bacławski] Rozwiązanie do rozważenia:
:::spoiler
```c=
((x >> 1) - (y >> 1) - (~x & y & 1)) >> 31
```
:::
## Zadanie 7
:::info
Autor: Władysław Jabłoński
:::
* $x < 0$: `x` na najbardziej znaczącym bicie ma wartość $1$, a więc maska ma wartość równą $111...111_{(2)}$. L = -x i R = 0.
* $x \geq 0$: Wartość `mask` będzie równa 0. L = 0 i R = x
```c=
int32_t mask = x >> 31;
return (mask & -x) + (~mask & x);
```
> [name=Franciszek Malinka] Mam krócej
:::spoiler
```c
int32_t y = x >> 31;
return (x ^ y) - y;
```
Jeśli `x < 0`, to `y = 0xffffffff = -1`, zatem `(x^y) = ~x`, a `~x + 1 = -x`. Jeśli `x >= 0`, to `y = 0` i działania z `y` nic nie robią.
:::
## Zadanie 8
:::info
Autor: Kacper Solecki
:::
```c=
// obliczanie sgn(x)
(x >> N-1) | (-x >> N-1 & 1)
```
- Dla x<0 to -1 | 0. (Dla x = INT_MIN to -1 | 1)
- Dla x=0 to 0 | 0.
- Dla x>0 to 0 | 1.
## Zadanie 9
:::info
Autor: Franciszek Malinka
:::
Pomysł jest podobny do zliczania liczby zapalonych bitów. Tym razem chcemy w kubełkach trzymać liczbę parzystą, jeśli w kubełku jest parzyście wiele bitów i l. nieparzystę w p.w.
$b = x_0 \oplus x_1 \oplus x_2 ... \oplus x_{31}$
`b = x ^ (x >> 16)`
$b_i = x_i \oplus x_{i+16}$, gdzie $i = 0..15$
```c=
int32_t odd_ones(uint32_t x) {
uint32_t y = x;
// na co drugim bicie jest zapalona 1 iff w kubełkach dwubitowych jest nieparzyście wiele zapalonych bitów
y = y ^ (x >> 1);
y = y ^ (y >> 2);
y = y ^ (y >> 4);
y = y ^ (y >> 8);
y = y ^ (y >> 16);
return y & 1;
}
```