По соображениям оптимизации я думал о вызове напрямую (с встроенным ассемблером)
к функциям «флдл» и «кулак». К сожалению, я не понимаю, как управлять этим, так как я не тот бог в ассемблере.
я не получил дальше, чем это:
double* input;
long long output;
__asm fldl input;
__asm fist output;
__asm fld input
на самом деле попытается прочитать ваш указатель значение, как если бы это было значение с плавающей запятой. Если вы хотите прочитать значение с плавающей точкой указал указателем, Вы должны пройти двухэтапный процесс: прочитать адрес в регистр, а затем прочитать данные, используя адрес в реестре. На 32-битной платформе это будет что-то вроде
__asm {
mov eax, input
fld qword ptr [eax]
fistp output
}
Я только попробовал это в VS2005, и это работает. (Обратите внимание, что, как и другие люди заявили в комментариях, fist
не поддерживает хранение в 64-битной версии long long
, в то время как fistp
делает. Но вам наверное нужно fistp
во всяком случае, т. е. в магазине.)
Самым простым, вероятно, является:
double input;
long long output;
__asm fld input
__asm fisttp output
Это делает «нормальное» двойное и длинное длинное преобразование, усекающееся до нуля, точно так же, как в C-броске. Очень старые (до Pentium4) процессоры не поддерживают fistpp
Впрочем, поэтому на таких машинах нужно использовать fistp
вместо этого, который использует текущий режим округления (обычно округление до ближайшего). Поэтому, если вы хотите, например, округлить в сторону -infinity, вам нужно сохранить текущий режим округления, установить его на то, что вы хотите, сделать fistp
и восстановить режим округления:
double input;
long long output;
unsigned short oldcw, cw;
__asm fld input
__asm fstcw oldcw
cw = (oldcw & ~0xc00) | 0x400; // round towards -infinity
__asm fldcw cw
__asm fistp output
__asm fldcw oldcw