---
# System prepended metadata

title: Lista 2
tags: [ASK]

---

###### tags: `ASK`

# Lista 2


## Zadanie 1
```c
(x > 0) || (x - 1 < 0)
```
wyrażenie zwróci *fałsz* 

dla x = $INT32\_MIN$ (wartość możemy sprawdzić po dołączeniu biblioteki `stdint.h`), które jest równe $100...00_{(2)} = -2147483648$
$x > 0 \to false$
$x - 1 = 100...00_{(2)} - 1 = 011...11_{(2)} = 2147483647 = INT32\_MAX$
występuje *overflow*, więc $x - 1 < 0 \to false$

```c
(x & 7) != 7 || (x << 29 < 0)
```
wyrażenie zawsze zwróci *prawdę*

$(x \& 7) \ != 7 \to$ będzie fałszem, gdy wszystkie trzy skrajnie prawe bity $x$ będą równe $1$
weźmy $x =\  ...111{(2)}$
wtedy po przesunięciu $x << 29$ otrzymamy $111....00_{(2)}$
widzimy, że jest to liczba ujemna, czyli $(x << 29 < 0) \to true$


```c
(x * x) >= 0
```
wyrażenie zwróci *fałsz*

gdy w wyniku $x^2$ na 31 pozycji w reprezentacji binarnej będzie zapalony bit, znaleźć taką liczbę możemy w następujący sposób (uwzględniając dziedziny):
\begin{cases}
    x^2 = (2^t + 2^r)^2 = 2^{2t} + 2^{t+r + 1} + 2^{2r}\\
    t + r + 1 = 31
\end{cases}
weźmy np. $x = 2^{10} + 2^{20} = 1049600 = 00000000000100000000010000000000_{(2)}$
$x^2 = (2^{10} + 2^{20})^2 = 2^{20} + 2^{31} + 2^{40}$
po utracie bitów wyniku zapalone będą bity $31$ i $20 \to$ liczba ujemna

```c
x < 0 || -x <= 0
```
wyrażenie zawsze zwróci *prawdę*

ponieważ liczb ujemnych jest o jeden więcej
```c
x > 0 || -x >= 0
```
wyrażenie zwróci *fałsz*

dla $x = INT32\_MIN$

`-x = ~x + 1`
$-x = -INT32\_MIN = -(-2147483648) = 2147483648 =\\
= INT32\_MAX + 1 = 011...111 + 1 = 10...000 = INT32\_MIN$

```c
(x | -x) >> 31 == -1
```
wyrażenie zwróci *fałsz*

dla $x = 0$
$(x \ | -x)$ zwróci $0$, a $(0 >> 31)$ to też $0$

```c
x + y == (uint32_t)y + (uint32_t)x
```
wyrażenie zawsze zwróci *prawdę*

ponieważ `unsigned` jest zarażający to nastąpi niejawne rzutowanie, czyli tak naprawdę nasze wyrażenie będzie wyglądać tak:
`(uint32_t)(x + y) == (uint32_t)y + (uint32_t)x`

```c
x * ~y + (uint32_t)y * (uint32_t)x == -x
```
wyrażenie zawsze zwróci *prawdę*

`(uint32_t)x * (uint32_t)(~y) + (uint32_t)y * (uint32_t)x == (uint32_t)(-x)`

Lewa strona:
`(uint32_t)x * ((uint32_t)(~y) + (uint32_t)y)`
korzystając z : `-y = ~y + 1` $\to$ `-1 = ~y + y` mamy:
`(uint32_t)x * (-1)`
`(uint32_t)x * UINT32_MAX` $\to$ zwraca `(uint32_t)(-x)`

Prawa strona:
`(uint32_t)(-x)`
`(uint32_t)(~x + 1)`


## Zadanie 2

Sposób z dodawaniem:
```c=
void swap(int *x, int *y) {
  *x += *y;
  *y = *x - *y;
  *x -= *y;
}
```

Sposób z xorem:
```c=
void swap(int *x, int *y) {
  *x ^= *y;
  *y ^= *x;
  *x ^= *y;
}
```



## Zadanie 3

**Nadmiar (overflow)** - przekroczenie zakresu wartości, które może przyjąć zmienna (liczba zajmuje więcej bitów pamięci, niż zostało jej przydzielone)

**Niedomiar (underflow)** - dla liczb typu *integer* oznacza, że wartość wyniku jest bliższa minus nieskończoności niż minimalna wartość jaki może przyjąć dana zmienna

zakładam, że $x, y, s$ są typu `int32_t`



- jeżeli $x$ i $y$ mają rózne znaki to nie może wystąpić *overflow*
- jeżeli $x,y > 0$ to w wyniku 31 bit będzie zapalony
- jeżeli $x,y < 0$ to w wyniku 31 bit będzie zgaszony

```c=
(((s ^ y) & (s ^ x)) >> 31) & 1;
```

## Zadanie 4

```c=
uint32_t sum = (x & 0x7F7F7F7F) + (y & 0x7F7F7F7F);
sum ^= ((x ^ y) & 0x80808080);
    
uint32_t diff = (x | 0x80808080) - (y & 0x7F7F7F7F);
diff ^= ((0x80808080 ^ x) ^ y) & 0x80808080;
```

Przykład dodawania:
x = 1001
y = 1111
sum = (x & 0111) + (y & 0111) = 0001 + 0111 = 1000
sum ^= (x ^ y) & 1000

Przykład odejmowania:
x = 1001
y = 1111
diff = 1001 - 0111 = 0010

## Zadanie 5

$x * 3/4 = x * (1/2 + 1/4) = x * 1/2 + x * 1/4 = x / 2 + x/2^2$

```c=
int32_t threefourths(int32_t x){
    x = ((x >> 1) + (x >> 2)) + (1 & x & (x >> 1));
}
```
druga część sumy sprawdza czy dwa bity po prawej są oba zapalone $\to$ utrata bitu wyniku i trzeba dodać 1

## Zadanie 6

```c
((x >> 1) - (y >> 1) - (~x & y & 1) >> N - 1) & 1;
```

Sprawdzamy znak `x/2 - y/2`.

Jeśli najmniej znaczące bity `x` i `y` to odpowiednio `0` i `1`, odejmujemy jeszcze `1`.


Dla liczb bez znaku, jeśli `x < y`, to `x/2 - y/2` ma również zapalony najbardziej znaczący bit:

```
x/2 - y/2 = (2^N - 1) + 1 + x/2 - y/2 = 2^N - (y/2 - x/2) >= 2^(N-1)
```


## Zadanie 7

`-x = ~x + 1`
```c=
int abs(int x) {
  int64_t mask = x >> N - 1;
  return mask & ~x+1 + ~mask & x;
}
```




## Zadanie 8

`-x = ~x + 1`
```c=
int sign(int x){
  return (x >> N-1) | (~x+1 >> N-1 & 1);
}
```


## Zadanie 9

z xor'em:
```c=
int32_t odd_ones(uint32_t x) {
    x ^= x >> 1;
    x ^= x >> 2;
    x ^= x >> 4;
    x ^= x >> 8;
    x ^= x >> 16;
    return x & 1;
}
```
wykorzystując zadanie z poprzedniej listy zliczające liczbę zapalonych bitów:
```cpp=
int32_t odd_ones(uint32_t x) {
  x = (x & 0x55555555) + ((x >> 1) & 0x55555555); // 01010101010101010101010101010101
  x = (x & 0x33333333) + ((x >> 2) & 0x33333333); // 00110011001100110011001100110011
  x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F); // 00001111000011110000111100001111
  x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF); // 00000000111111110000000011111111
  x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF); // 00000000000000001111111111111111

  return x & 1;
}
```
