Допустим есть такой код:
float op(float a, float p, float q) { return a * p * q; }
a, p, q дробные числа в диапазоне [0, 1]
нужно реализовать то же самое, но с unsigned short, т.е. fixed point:
u_int16_t op(u_int16_t a, u_int16_t p, u_int16_t q) { return a * p * q / (65535UL * 65535UL); }
я думал, что по логике оно должно без проблем скомпилиться в что-то типа:
mov ax, [arg_a] ; ax = a mov dx, [arg_p] ; dx = p imul dx ; dx:ax = a*p xor ecx, ecx mov cx, [arg_q] ; ecx = q imul ecx ; edx:eax = a*p*q idiv 0xfffe0001 ; eax = a*p*q/(65535*65535), edx = остаток ret ; результат в eax
Но op упорно возвращает 0 вместо 65535. Помогает смена типа аргументов на u_int64_t (с u_int32_t тоже возвращает 0).
Должен ли компилятор автоматически расширять операнды до 64 бит? Можно как-то заставить gcc (а в идеале, любой компилятор) юзать эти 64 бита? Или надо явно указывать преобразование в u_int64_t? Думаю, мне будет полезно посмотреть код какого-нибудь alpha blending'а в 16битах, никто не знает библиотеки, реализующей подобное?