允许在 D 中进行 [i] 和 .xyz 操作的快速向量结构?

发布于 2024-09-06 12:42:45 字数 891 浏览 7 评论 0原文

我想在 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; 等,但这不起作用。有什么想法吗?或者这就是“如何做到的”?也许编译器足够聪明,可以找出属性函数或多或少是别名?

I'd like to create a vector struct in D that works like this:

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

Later I'd also like to add stuff like u = v * u etc. But the above will do for now.
This is how far I've come:

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];
    }
}

Now this pretty much makes it work like I wanted, but I feel very unsure about if this is "right". Should the opAssign() perhaps return some value?

I'm also wondering if this is really as fast as it can be? Is I've tried adding alias data[0] x; etc. but that doesn't work. Any ideas? Or is this "how it's done"? Perhaps the compiler is smart enough to figure out the propery functions are more or less aliases?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

極樂鬼 2024-09-13 12:42:45

总的来说,这看起来相当合理。出于分配链的目的,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 目前存在相当多的错误,并且除非您愿意,否则您可能不应该使用它提交一些错误报告。

Overall, this looks pretty reasonable. For the purpose of assignment chaining, opAssign should arguably return v. However, in practice this is often overlooked and might cause a performance hit (I don't know). Unlike in D1, you can return static arrays from functions in D2.

As far as performance, the best way to think of this is at the assembly level. Assuming inlining is enabled, x() will almost certainly be inlined. Static arrays are stored directly in the struct without an extra layer of indirection. The instruction return data[0]; will cause the compiler to generate code to read from an offset from the beginning of the struct. This offset will be known at compile time. Therefore, most likely calling x() will generate exactly the same assembly instructions as if x were actually a public member variable.

One other possibility, though, would be to use an anonymous union and struct:

struct vec3f
{
    union {
        float[3] vec;

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

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

}

Note, though that alias this is fairly buggy right now, and you probably shouldn't use it yet unless you're willing to file some bug reports.

抠脚大汉 2024-09-13 12:42:45

您可以使用 opDispatch 进行任意深度的调配。我还建议根据大小和类型对向量结构进行模板化。这是我的比较版本: tools.vector ( D1,所以 swizzling 有点麻烦)。

You can use opDispatch for swizzling of arbitrary depth. I'd also recommend templating your vector struct on size and type. Here's my version for comparison: tools.vector (D1, so swizzling is a bit more cumbersome).

流星番茄 2024-09-13 12:42:45

您可以在 opAssign 中使用数组操作一次性复制整个数组:

data[] = v[];

You can use an array operation to copy the whole array in one shot in opAssign:

data[] = v[];
末蓝 2024-09-13 12:42:45
@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] 数组。

@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]; }
    }

Why properties ?

I would suggest to drop these lines and make x, y and z public fields.
This will also improve performance in non-inline mode. You can use union to have a data[3] array anyway.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文