# Architektury systemów komputerowych ## Lista 10. ### Zadanie 1. - $T_{avg seek} = 576 / 24 / 3 \cdot 1ms = 8ms$ - $T_{avg rotation} = 1/7200RPM \cdot 60s/1min / 2 = 4.17ms$ - $T_{transfer} = 1/7200RPM \cdot 60s/1min / 32000 = 0.000026ms$ - $T_{access} = 8ms + 4.17ms + 0.000026ms = 12.17ms$ ## Lista 7. ### Zadanie 5. ```cpp union elem { struct { long *p; long y; } e1; struct { long x; union elem *next; } e2; }; elem* f(elem *el){ elem *next = el->e2.next; el->e2.x = *(next->e1.p) - next->e1.y; return next; } ``` ### Zadanie 6. ```cpp typedef struct A { ll u[2]; ll *v; } SA; typedef struct B { ll p[2]; ll q; } SB; SB eval(SA s){ SB ret = SB(); ret.p[0] = s.u[1] * *(s.v); ret.p[1] = s.u[0] - *(s.v); ret.q = s.u[0] - s.u[1]; return ret; } ll wrap(ll x, ll y, ll z){ SB s = eval({x,y,&z}); return s.q * (s.p[0] + s.p[1]); } ``` ### Zadanie 7. ```cpp struct P{ long sz; float *tab; }; float puzzle7(P *p, float x){ long sz = p->sz; float* tab = p->tab; float ret = 0; float bs = 1; for(int i=0;i<sz;i++){ ret = bs * tab[i]; bs *= x; } return ret; } ``` ### Zadanie 8. ``` Base::doit(int): movl %esi, %eax subl 8(%rdi), %eax ret Derived::doit(int): movl 8(%rdi), %eax imull %esi, %eax ret doit(Base*): movq (%rdi), %rax movl $1, %esi movq (%rax), %rax jmp *%rax main: pushq %rbx subq $32, %rsp movq %rsp, %rdi movq $vtable for Base+16, (%rsp) movl $10, 8(%rsp) movl $21, 24(%rsp) movq $vtable for Derived+16, 16(%rsp) call doit(Base*) leaq 16(%rsp), %rdi movl %eax, %ebx call doit(Base*) addq $32, %rsp addl %ebx, %eax popq %rbx ret vtable for Base: .quad 0 .quad 0 .quad Base::doit(int) vtable for Derived: .quad 0 .quad 0 .quad Derived::doit(int) ``` Wielomian ## Lista 6. ### Zadanie 1. ```cpp #include <iostream> #include <algorithm> using namespace std; using ll = long long; extern "C" long pointless(long n, long* p); long pointless2(long n, long* p) { if (n == 0) return 0; long result2 = 0; long result = pointless2(n+n, &result2); result += result2; n += result; *p = n; return result; } int main(){ for(int i=0;i<100;i++){ long res = 0; cout << pointless2(i, &res) << " "; res = 0; cout << pointless(i, &res) << "\n"; } return 0; } ``` ### Zadanie 2. ```cpp #include <iostream> #include <algorithm> #include <climits> using namespace std; using ll = long long; struct T{ ll a; ll b; ll c; }; ll a[5] = {6,7,8,10,9}; extern "C" T puzzle2(ll* a, ll n); T puzzle2hand(ll* a, ll n){ T ret; ll sum = 0; ll maxi = LONG_MIN; ll mini = LONG_MAX; for(ll i=0;i<n;i++){ ll rcx = a[i]; mini = min(mini, a[i]); maxi = max(maxi, a[i]); sum += a[i]; } ret.a = mini; ret.b = maxi; ret.c = sum / n; return ret; } int main(){ T res = puzzle2(&a[0], 5); T res2 = puzzle2hand(&a[0], 5); cout << res.a << " " << res.b << " " << res.c << "\n"; cout << res2.a << " " << res2.b << " " << res2.c << "\n"; return 0; } ``` ### Zadanie 3. ```cpp #include <iostream> using namespace std; int64_t fd(int64_t x){ return x+5; } int64_t f60(int64_t x){ return x*8; } int64_t f61(int64_t x){ return x*8; } int64_t f62(int64_t x){ return (x<<4) - x; } int64_t f64(int64_t x){ return x >> 3; } int64_t f65(int64_t x){ return x*x; } int64_t (*arr[])(int64_t) = {f60, f61, f62, fd, f64, f65}; int64_t switch_prob(int64_t x, int64_t n){ if(60 <= n && n <= 65){ return arr[n-60](x); } return fd(x); } int main(){ return 0; } ``` ### Zadanie 4. ```cpp #include <iostream> using namespace std; using ll = long long; extern "C" ll M(ll x); extern "C" ll F(ll x); ll Fhand(ll x); ll Mhand(ll x){ return (x ? x - Fhand(Mhand(x-1)) : 0); } ll Fhand(ll x){ return (x ? x - Mhand(Fhand(x-1)) : 1); } int main(){ for(int i=1;i<=10;i++){ cout << i << " " << M(i) << " " << Mhand(i) << " " << F(i) << " " << Fhand(i) << "\n"; } return 0; } ``` ## Lista 5. ### Zadanie 1. ```asm .section .text .global addu addu: add %rdi, %rsi sbb %rax, %rax or %rsi, %rax ret ``` ### Zadanie 2. ```asm .section .text .global cmp cmp: sub %rsi, %rdi sbb %rax, %rax neg %rdi adc %rax, %rax ret ``` ### Zadanie 3. ```cpp int puzzle(long x, unsigned n){ int eax = 0; if(n == 0) return n; for(int edx=0;edx!=n;edx++){ eax += x & 1; x /= 2; } return eax; } ``` Popcount na pierwszych na bitach (najniższych) ### Zadanie 4. ```cpp long puzzle2(char *s, char *d){ char* rax = d; do{ char* rdx = s; char c; do{ c = *(rdx++); if(c == 0){ return rax - d; } }while(c != *rax); rax++; }while(1); } ``` Liczenie najdłuższego prefiksu słowa d, które jest podsłowem słowa s. ### Zadanie 5. ```cpp #include <iostream> using namespace std; uint32_t puzzle3(uint32_t n, uint32_t d){ uint64_t n2 = n; uint64_t d2 = d; d2 <<= 32; uint32_t edx = 32; uint32_t ecx = 0x80000000; uint32_t eax = 0; do{ n2 += n2; int64_t r8 = n2; r8 -= d2; if(r8 >= 0){ eax |= ecx; n2 = r8; } ecx >>= 1; edx--; }while(edx); return eax; } int main(){ for(int i=1;i<=20;i++){ for(int j=1;j<=20;j++){ cout << puzzle3(i,j) << " "; } cout << "\n"; } return 0; } ``` Dzielenie całkowite liczb nieujemnych. ### Zadanie 6. ```cpp #include <iostream> using namespace std; uint32_t puzzle4(long *a, long v, uint64_t s, uint64_t e){ uint64_t mid = (e-s)/2 + s; if(s > e) return -1; uint64_t r8 = a[mid]; if(r8 == v) return mid; if(r8 > v) return puzzle4(a, v, s, mid-1); return puzzle4(a, v, mid+1, e); } long arr[] = {1, 5, 7, 8}; int main(){ int i = puzzle4(&arr[0], 7, 0, 3); cout << i << "\n"; return 0; } ``` ### Zadanie 7. ```cpp #include <iostream> using namespace std; int64_t switch_prob(int64_t x, int64_t n){ switch(n){ case 60: case 61: return x * 8; case 64: return x >> 3; case 62: x = (x << 4) - x; case 65: x = x * x; default: return x + 75; } } int main(){ return 0; } ``` ## Lista 4. ### Zadanie 1. - 256 - 19 - 264 - 255 - 171 - 17 - 255 - 17 - 17 ### Zadanie 2. - 0x100 = 256 - %rdx = -10 - %rax = 16 - 0x110 = 18 - %rcx = 0 - 0x108 = 43776 - %rdx = 16 - %rdx = 22 ### Zadanie 3. ```cpp #define ALPHA 0.7 #define Q16 ((uint16_t)(ALPHA * (1 << 16))) int16_t exp_smooth(int16_t xi, int16_t s_prev, uint16_t alpha) { int32_t si = (int32_t)alpha * xi + ((1 << 16) - alpha) * s_prev; return (int16_t)(si >> 16); } volatile int16_t x[] = {1, 4, 3, 2}; int16_t s[] = {0, 0, 0, 0}; int main() { s[0] = x[0]; for (int i = 1; i <= 10; ++i) { exp_smooth(x[i], s[i-1], Q16); } return 0; } ``` ## Zadanie 4. ```cpp long decode(long x, long y){ long z = x + y; y ^= z; x ^= z; z = x & y; return z >> 63; } ``` ## Zadanie 5. ``` ror $24,%edi rorq $8,%rdi ror $24,%edi rorq $8,%rdi ror $24,%edi rorq $8,%rdi ror $24,%edi rorq $8,%rdi mov %edi,%eax ``` ## Zadanie 6. ``` movq %rsi,%rax addq %rcx,%rax adcq %rdi,%rdx ``` ## Lista 3. ### Zadanie 1. ```cpp #include <iostream> #include <bitset> #include <cassert> using namespace std; int64_t third = 0x55555556; int64_t div3(int64_t x){ return ((x * third) >> 32) - (-1 & x>>63); } int main(){ for(int32_t i=-1e9;i<=1e9;i++){ assert(div3(i) == (i < 0 ? -abs(i)/3 : i/3)); } } ``` ### Zadanie 2. ```cpp #include <iostream> #include <bitset> using namespace std; int k = 2; int n = 4; uint64_t a[4] = {1LL<<31, 1LL<<31, 1LL<<30, 1LL<<30}; uint64_t b[4] = {1LL<<31, 1LL<<30, 1LL<<31, 1LL<<30};; int main(){ cin.tie(0); ios_base::sync_with_stdio(0); uint64_t tot = 0; uint64_t tot2 = 0; for(int i=0;i<n;i++){ uint64_t res = (a[i] > b[i] ? (a[i]-b[i])*(a[i]-b[i]) : (b[i]-a[i])*(b[i]-a[i])); tot += res & 0x0000FFFF; tot2 += res >> 32; } tot2 += tot >> 32; cout << bitset<32>(tot2 >> k) << "\n"; return 0; } ``` ### Zadanie 3. $0 01100 0100000000_{16bit float} = 0.15625$ ![obraz](https://hackmd.io/_uploads/rkfl1bSpa.png) Dla normalnych floatów pewnie podobnie subnormal min - $2^{-150}$? positive min - $2^{-126}$ maximum num - $(2-2^{-23})*2^{127}$ ### Zadanie 4. ### Zadanie 5. 1. TAK 2. NIE, MIN_INT i -1 3. TAK 4. NIE, kontrprzykład: -2147483625 -2147483415 -2147481315 5. NIE, kontrprzykład: 0 1 ### Zadanie 6. ```cpp #include <iostream> using namespace std; uint32_t sign(uint32_t x){ return x ^ 1<<31; } uint32_t log(uint32_t x){ return (x>>23)-127 & 0x000000FF; } uint32_t eq(uint32_t x, uint32_t y){ return ((x|y)==0x80000000) & (x==y); } int main(){ float a = 19.5; int x = * ( int * ) &a; cout << log(x) << "\n"; } ``` ![obraz](https://hackmd.io/_uploads/BJIeQXSaT.png) ![obraz](https://hackmd.io/_uploads/r1A-m7rTp.png) ### Zadanie 7. ```cpp uint32_t shift(uint32_t x, int32_t k){ int32_t e = (x>>23&0x000000FF) - 127; uint32_t man = 0x007FFFFF; uint32_t exp = 0x7F800000; uint32_t sgn = 0x80000000; if(k >= 0){ k = min(k, 255-e); x += k << 23; } else{ int32_t k2 = -k; if(k2 > e+127){ int32_t s = x & sgn; x &= ~exp | ~sgn; x >>= k2-e-127; x |= s; } else{ x -= k2 << 23; } } return x; } ``` ### Zadanie 8. ```cpp #include <iostream> #include <iomanip> #include <bitset> using namespace std; int32_t int2float(int32_t x){ if(x == 0) return 0; uint32_t sgn = x < 0; x = abs(x); uint32_t lb = __builtin_clz(x); uint32_t exp = 31 - lb; uint32_t man = ((uint32_t)(x & ((1<<(exp+1))-1)) << (32 - exp)) >> 9; uint32_t guard = (exp >= 23 ? (x >> exp-23 & 1) : 0); uint32_t round = (exp >= 24 ? (x >> exp-24 & 1) : 0); uint32_t stick = (exp >= 25 ? (x & (1<<(exp-24))-1) > 0 : 0); if(round && (guard || stick)) man++; if(man >> 23){ man &= (1<<23)-1; man >>= 1; exp++; } return (sgn << 31) | ((exp+127) << 23) | man; } int main(){ int32_t x = int2float((1<<30)-1); cout << (1<<30)-1 << "\n"; cout << *(float*)(&x) << "\n"; return 0; } ``` ### Zadanie 9. ```cpp #include <iostream> using namespace std; int32_t float2int(int32_t f) { int32_t s = f >> 31; /* -1 jeśli znak był ujemny */ int32_t e = (f >> 23 & 255) - 127; /* wykładnik po odjęciu bias */ uint32_t m = f << 8 | 0x80000000; /* mantysa 1.xxx... dosunięta do lewej */ m = (e > 31 ? 0x80000000 : (m>>max(0,(31-e)))); return m * (2*s+1); } int main(){ float x = 0x80000000; cout << float2int(*(int32_t*)&x) << "\n"; return 0; } ``` ### Zadanie 10. ## Lista 2. ### Zadanie 1. - NIE, bo $INT\_MIN < 0$ i $INT\_MIN - 1 > 0$ - TAK, jeśli pierwszy warunek jest spełniony to reprezentacją tej liczby po przesunięciu będzie $111000000\dots_2$ - NIE, $(2^{15} + 2^{14})^2 < 0$ - TAK, $0$ spełnia, wszystkie oprócz $INT\_MIN$a też i sam $INT\_MIN$ tak samo - TAK, bo tak powiedziałem - NIE, bo $0$ - TAK, typy signed i unsigned dodają się tak samo, przy porównaniu następuje konwersja typu (bez zmiany reprezentacji) - TAK, sumarycznie $y$ i $\neg y$ upraszczają się do mnożenia przez $-1$ ### Zadanie 2. ```cpp x ^= y ^= x ^= y; ``` ### Zadanie 3. ```cpp int32_t overflowcheck(int32_t x, int32_t y){ return (~(x^y)&(s^x))>>31&1; } ``` ### Zadanie 4. ```cpp uint32_t simdadd(uint32_t x, uint32_t y){ return (x & 0x7F7F7F7F) + (y & 0x7F7F7F7F) ^ (x ^ y) & 0x80808080; } uint32_t simdsub(uint32_t x, uint32_t y){ return ~((x ^ y | 0x7F7F7F7F) ^ (x | 0x80808080) - (y & 0x7F7F7F7F)); } ``` ### Zadanie 5. ```cpp int32_t threefourths(int32_t x){ return ((x>>2)<<1) + (x>>2) + ((((x&3)<<1)+(x&3))>>2); } ``` ### Zadanie 6. ```cpp uint32_t lesssigned(int32_t x, int32_t y){ return (~y&x|(~y|x)&(x^1<<31)-(y^1<<31))>>31&1; } uint32_t lessunsigned(uint32_t x, uint32_t y){ return (~x&y|(~x|y)&x-y)>>31&1; } ``` ### Zadanie 7. ```cpp int32_t abs(int32_t x){ return ~x>>31 & x | x>>31 & -x; } ``` ### Zadanie 8. ```cpp int32_t sgn(int32_t x){ return ~x>>31 & 1 & ~(~x>>31 & x-1>>31) | x>>31 & -1; } ``` ### Zadanie 9. ```cpp int32_t oddpop(uint32_t x){ x = (x & 0x55555555) + ((x>>1) & 0x55555555); x = (x & 0x33333333) + ((x>>2) & 0x33333333); x = (x & 0x0F0F0F0F) + ((x>>4) & 0x0F0F0F0F); x = (x & 0x00FF00FF) + ((x>>8) & 0x00FF00FF); x = (x & 0x0000FFFF) + ((x>>16) & 0x0000FFFF); return (x & 1); } ```