2010-06-23 5 views
5

Mi piacerebbe creare una struttura vettore in D che funziona in questo modo:Strutturazione vettoriale veloce che consente operazioni [i] e .xyz in 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 

tardi Vorrei anche aggiungere cose come u = v * u ecc Ma quanto sopra farà per ora.
Questo è quanto sono venuto:

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

Ora, questo lo rende più o meno funziona come avrei voluto, ma mi sento molto sicuro di se questo è "giusto". L'opAssign() dovrebbe forse restituire qualche valore?

Mi chiedo anche se questo è veramente veloce come può essere? Ho provato ad aggiungere alias data[0] x; ecc. Ma non funziona. Qualche idea? O è questo "come è fatto"? Forse il compilatore è abbastanza intelligente da capire che le funzioni corrette sono più o meno alias?

risposta

5

Nel complesso, questo sembra abbastanza ragionevole. Per lo scopo del concatenamento dei compiti, opAssign dovrebbe probabilmente restituire v. Tuttavia, in pratica, questo è spesso trascurato e potrebbe causare un successo nelle prestazioni (non so). A differenza di D1, è possibile restituire array statici dalle funzioni in D2.

Per quanto riguarda le prestazioni, il modo migliore per pensarlo è a livello di assemblaggio. Supponendo che l'inlining sia abilitato, lo x() sarà quasi sicuramente in linea. Gli array statici sono memorizzati direttamente nella struttura senza uno strato aggiuntivo di riferimento indiretto. L'istruzione return data[0]; farà sì che il compilatore generi codice da leggere da un offset dall'inizio della struct. Questo offset sarà noto al momento della compilazione. Pertanto, molto probabilmente chiamando x() genererà esattamente le stesse istruzioni di assemblaggio come se x fosse in realtà una variabile membro pubblico.

un'altra possibilità, però, sarebbe quella di utilizzare un'unione anonima e struct:

struct vec3f 
{ 
    union { 
     float[3] vec; 

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

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

} 

nota, anche se questo alias this è abbastanza buggy in questo momento, e probabilmente non dovrebbe usare ancora meno che non si' sono disposto a presentare alcune segnalazioni di bug.

2

È possibile utilizzare opDispatch per la scia di profondità arbitraria. Ti suggerisco anche di definire la struttura vettoriale in base alla dimensione e al tipo. Ecco la mia versione per il confronto: tools.vector (D1, quindi lo swizzling è un po 'più ingombrante).

+1

+1, ho avuto la stessa idea per il swizzling con opDispatch. Sono ancora nelle prime fasi di D, quindi la mia soluzione probabilmente non è buona come potrebbe essere. Ma le cose in fase di compilazione che puoi fare sono sbalorditive! – shambulator

2

È possibile utilizzare un'operazione array per copiare l'intero array in un solo colpo in 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]; } 
    } 

Perché proprietà?

Vorrei suggerire di eliminare queste righe e creare i campi pubblici x, yez. Ciò migliorerà anche le prestazioni in modalità non in linea. Puoi usare union per avere un array di dati [3] comunque.