2016-11-13 2 views
3

Я пытаюсь перевести позорный fast inverse square root техника на язык программирования D из C. Необходимого шага включает в себя хранение длинных бит в целом:Тип каламбурный в D

i = * (long *) &y; 

В разделе комментариев, Эндрю предлагает что эта операция называется типом punning. Кто-нибудь знает, как выполнить операцию кастомизации типа в D?

Для тех, кому любопытно, вот полный C представление кода:

float Q_rsqrt(float number) { 
long i; 
float x2, y; 
const float threehalfs = 1.5F; 
x2 = number * 0.5F; 
y = number; 
i = * (long *) &y; // the part in question 
i = 0x5f3759df - (i >> 1); 
y = * (float *) &i; // again, but for floating points 
y = y * (threehalfs - (x2 * y * y)); 
return y; 
} 
+1

Вы пробовали делать то же самое в D, что и в C? Он должен работать ... (ну, кроме C long, немного отличается, вы должны использовать D 'int' для' float') –

+0

Это отличное предложение. Я буду проверять и отвечать. Как люди обычно ссылаются на используемую операцию? –

+0

@ AdamD.Ruppe К сожалению, синтаксис \ * ( \ *), похоже, вызывает ошибку синтаксического анализа. Вы случайно знаете название этой операции? –

ответ

3

Все, что вам действительно нужно сделать, чтобы использовать отливку D-стиль - это единственное место, где D код отличается от C.

Вот рабочая программа:

import std.stdio; 

float Q_rsqrt(float number) { 
    int i; // we use int here because int.sizeof == float.sizeof 
    float x2, y; 
    const float threehalfs = 1.5F; 
    x2 = number * 0.5F; 
    y = number; 
    i = * cast(int*) &y; 
    i = 0x5f3759df - (i >> 1); 
    y = * cast(float*) &i; 
    y = y * (threehalfs - (x2 * y * y)); 
    y = y * (threehalfs - (x2 * y * y)); // 2nd iteration 

    return y; 
} 

int main() { 
    writeln(Q_rsqrt(0.15625f)); 
    // Output: 2.52981 

    return 0; 
} 
2

То же самое может быть достигнуто с union, с дополнительным преимуществом, что теперь это можно сделать @safe и немного легче на глазах:

float Q_rsqrt(float number) @safe { 
    union V { 
    int i; 
    float y; 
    } 
    V v; 
    float x2; 
    const float threehalfs = 1.5F; 
    x2 = number * 0.5F; 
    with (v) { 
    y = number; 
    i = 0x5f3759df - (i >> 1); 
    y = y * (threehalfs - (x2 * y * y)); 
    y = y * (threehalfs - (x2 * y * y)); // 2nd iteration 
    return y; 
    } 
} 

int main() { 
    writeln(Q_rsqrt(0.15625f)); 
    // Output: 2.52981 

    return 0; 
} 

С оптимизацией он генерирует ту же самую сборку, что и реализация, с помощью указателей (по крайней мере, в LDC и GDC).

Смежные вопросы