Быстрая векторная структура, которая позволяет [i] и .xyz-операции в D? - PullRequest
5 голосов
/ 23 июня 2010

Я хотел бы создать векторную структуру в D, которая работает следующим образом:

vec u, v;
vec w = [2,6,8];
v.x = 9; // Sets x
v[1] = w.y; // Sets y
u = v; // Should copy data

Позже я также хотел бы добавить такие вещи, как u = v * u и т. Д. Но вышеприведенное пока подойдет.
Вот как далеко я зашёл:

struct vec3f
{
    float[3] data;
    alias data this;
    @property
    {
        float x(float f) { return data[0] = f; }
        float y(float f) { return data[1] = f; }
        float z(float f) { return data[2] = f; }
        float x() { return data[0]; }
        float y() { return data[1]; }
        float z() { return data[2]; }
    }
    void opAssign(float[3] v)
    {
        data[0] = v[0];
        data[1] = v[1];
        data[2] = v[2];
    }
}

Теперь это в значительной степени заставляет это работать так, как я хотел, но я чувствую себя очень неуверенно относительно того, правильно ли это. Должно ли opAssign () возвращать какое-то значение?

Мне также интересно, действительно ли это так быстро, как только может быть? Я пытался добавить alias data[0] x; и т. Д., Но это не работает. Есть идеи? Или это "как это делается"? Возможно, компилятор достаточно умен, чтобы выяснить, какие функции являются более или менее псевдонимами?

Ответы [ 4 ]

5 голосов
/ 23 июня 2010

В целом, это выглядит довольно разумно. Для целей цепочки присваивания opAssign, вероятно, должен возвращать v. Однако на практике это часто упускается из виду и может привести к снижению производительности (я не знаю). В отличие от D1, вы можете возвращать статические массивы из функций в D2.

Что касается производительности, то лучше всего думать об этом на уровне сборки. Предполагая, что встраивание включено, x() почти наверняка будет встроено. Статические массивы хранятся непосредственно в структуре без дополнительного уровня косвенности. Инструкция return data[0]; заставит компилятор генерировать код для чтения со смещением от начала структуры. Это смещение будет известно во время компиляции. Поэтому, скорее всего, вызов x() сгенерирует точно такие же инструкции по сборке, как если бы x была на самом деле общедоступной переменной-членом.

Еще одна возможность - использовать анонимный союз и структуру:

struct vec3f
{
    union {
        float[3] vec;

        struct {
            float x;
            float y;
            float z;
        }
    }

    alias vec this;  // For assignment of a float[3].

}

Обратите внимание, что alias this в настоящее время довольно глючит, и вам, вероятно, не следует использовать его, пока вы не захотите подать несколько сообщений об ошибках.

2 голосов
/ 26 июня 2010

Вы можете использовать операцию массива для копирования всего массива за один снимок в opAssign:

data[] = v[];
2 голосов
/ 23 июня 2010

Вы можете использовать opDispatch для воспроизведения произвольной глубины. Я бы также порекомендовал шаблонную векторную структуру по размеру и типу. Вот моя версия для сравнения: tools.vector (D1, так что пьянство немного более громоздко).

1 голос
/ 28 июня 2010
@property
    {
        float x(float f) { return data[0] = f; }
        float y(float f) { return data[1] = f; }
        float z(float f) { return data[2] = f; }
        float x() { return data[0]; }
        float y() { return data[1]; }
        float z() { return data[2]; }
    }

Почему свойства?

Я бы предложил отбросить эти строки и сделать открытыми поля x, y и z. Это также улучшит производительность в не встроенном режиме. В любом случае вы можете использовать union, чтобы иметь массив data [3].

...