代码之家  ›  专栏  ›  技术社区  ›  0scar

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

  •  5
  • 0scar  · 技术社区  · 16 年前

    我想在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 回复  |  直到 16 年前
        1
  •  5
  •   dsimcha    16 年前

    总的来说,这看起来很合理。对于赋值链,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
  •  2
  •   FeepingCreature    16 年前

    你可以用 opDispatch 用于任意深度的旋转。我还建议根据大小和类型模板化向量结构。以下是我的比较版本: tools.vector (D1,所以旋转有点麻烦)。

        3
  •  2
  •   Michel Fortin    16 年前

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

    data[] = v[];
    
        4
  •  1
  •   ponce    16 年前
    @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来拥有数据[3]数组。