2010-06-23 23 views
5

Me gustaría crear una estructura vectorial en D que funciona así:estructura vectorial rápida que permite [i] y .xyz-operaciones en 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 

Más tarde también me gustaría añadir cosas como u = v * u etc. Pero lo anterior va a hacer por ahora.
Esto es lo lejos que he llegado:

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

Ahora bien, esto hace que sea más o menos funciona como yo quería, pero me siento muy seguro de si esto es "correcto". ¿Debería el opAssign() devolver algo de valor?

¿Me pregunto si esto es realmente tan rápido como puede ser? He intentado agregar alias data[0] x; etc. pero eso no funciona. ¿Algunas ideas? ¿O es así "cómo se hace"? Tal vez el compilador es lo suficientemente inteligente como para descubrir que las funciones de propiedad son más o menos alias.

Respuesta

5

En general, esto se ve bastante razonable. A los efectos del encadenamiento de asignaciones, es probable que opAssign devuelva v. Sin embargo, en la práctica esto a menudo se pasa por alto y podría causar un golpe de rendimiento (no sé). A diferencia de D1, puede devolver matrices estáticas desde funciones en D2.

En cuanto al rendimiento, la mejor manera de pensar en esto es en el nivel de montaje. Suponiendo que la alineación está habilitada, x() casi con certeza estará en línea. Las matrices estáticas se almacenan directamente en la estructura sin una capa adicional de direccionamiento indirecto. La instrucción return data[0]; hará que el compilador genere código para leer desde un desplazamiento desde el comienzo de la estructura. Este desplazamiento se conocerá en tiempo de compilación. Por lo tanto, lo más probable es que llamar al x() generará exactamente las mismas instrucciones de ensamblaje que si x fuera realmente una variable de miembro público.

Otra posibilidad, sin embargo, sería el uso de una unión anónima y estructura:

struct vec3f 
{ 
    union { 
     float[3] vec; 

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

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

} 

Tenga en cuenta, sin embargo, que alias this es bastante buggy de este momento, y es probable que no se debe utilizar sin embargo, a menos que' Estoy dispuesto a presentar algunos informes de errores.

2

Puede usar opDispatch para oscilación de profundidad arbitraria. También recomendaría modelar tu estructura vectorial en tamaño y tipo. Aquí está mi versión para comparar: tools.vector (D1, por lo que el swizzling es un poco más engorroso).

+1

+1, tuve la misma idea de swizzling con opDispatch. Todavía estoy en las primeras etapas de D, por lo que mi solución probablemente no sea tan buena como podría ser. Sin embargo, ¡las cosas en tiempo de compilación que puedes hacer son alucinantes! – shambulator

2

Se puede utilizar una operación de matriz para copiar todo el conjunto en una sola toma en opAssign:

data[] = v[]; 
1
@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]; } 
    } 

¿Por qué propiedades?

Yo sugeriría soltar estas líneas y hacer campos públicos x, y y z. Esto también mejorará el rendimiento en modo no en línea. Puede usar union para tener una matriz de datos [3] de todos modos.