2015-03-20 8 views
5

Sto provando a generare una tabella cosine/sinusoidale per aritmetica a virgola fissa utilizzando un formato firmato 2,14 (intero con segno a 2 bit, frazione a 14 bit). L'argomento di coseno/seno è normalizzato e piegato attorno a 180, 90 e 45 gradi, quindi ho solo bisogno di valori di coseno e seno compresi tra 0 e 45 gradi (o 12867 come punto fisso). Il codice calcola una tabella leggermente più grande che va da 0 a 1 radianti (o 16384 come punto fisso).Come creare una tabella cosine con i template compilati con meno di 8 gigabyte di ram?

Ho testato questo codice per 8,8, 7,9, 6,10, 5,11, 4,12 e 3,13 bit punto fisso ma non è possibile compilarlo per punto fisso a 2,14 bit. L'ho interrotto quando g ++ stava usando circa 7 GB di RAM e continua a crescere.

Quindi, come faccio a fare in modo che i modelli usino meno ram?

#include <stdint.h> 
#include <math.h> 

template <uint16_t...> struct IndexList {}; 

template <uint16_t left_base, typename LeftList, 
      uint16_t right_base, typename RightList> struct Merge; 

template <uint16_t left_base, uint16_t... left, 
      uint16_t right_base, uint16_t... right> 
struct Merge<left_base, IndexList<left...>, 
      right_base, IndexList<right...> > { 
    typedef IndexList<left..., right...> Result; 
}; 

template <uint16_t base, uint16_t n> struct Indexes { 
    static constexpr uint16_t left_base = base; 
    static constexpr uint16_t left = n/2; 
    static constexpr uint16_t right_base = base + n/2; 
    static constexpr uint16_t right = n - n/2; 
    typedef typename Merge<left_base, 
          typename Indexes<left_base, left>::Result, 
          right_base, 
          typename Indexes<right_base, right>::Result 
          >::Result Result; 
}; 

template <uint16_t base> struct Indexes<base, 0> { 
    typedef IndexList<> Result; 
}; 

template <uint16_t base> struct Indexes<base, 1> { 
    typedef IndexList<base> Result; 
}; 

template <uint16_t bits, uint16_t fraction> 
class FixedPoint { 
public: 
    constexpr FixedPoint(double x) : raw_(x * (1 << fraction)) { } 
private: 
    uint16_t raw_; 
}; 

template <uint16_t bits, uint16_t fraction, typename IndexList> struct TableEntries; 
template <uint16_t bits, uint16_t fraction, uint16_t... I> 
struct TableEntries<bits, fraction, IndexList<I...> > { 
    using FP = FixedPoint<bits, fraction>; 
    enum { N = sizeof...(I) }; 
    FP data[N]; 
    constexpr inline TableEntries() 
     : data({ FP(cos(double(I)/(1 << fraction)))... }) {} 
}; 

template<uint16_t bits, uint16_t fraction> 
class Table { 
public: 
    constexpr Table() { } 
private: 
    static constexpr uint16_t NUM = 1 << fraction; 
    typedef typename Indexes<0, NUM>::Result IndexList; 
    TableEntries<bits, fraction, IndexList> entries; 
}; 

Table<2, 14> table; 
+1

Questo è un po' un abuso di modelli variadici, direi che avere argomenti di template 16K richiede guai, perché pensi di dover specificare tutti gli indici come argomenti del template? Non potremmo usare 'TableEntries' solo gli argomenti' bits' e 'fraction', e quindi calcolare' N' (e quindi gli indici che ha bisogno di calcolare) da solo? Anche come nota a margine, l'uso di 'cos()' in una funzione 'constexpr' non è portabile, credo che funzioni in gcc, ma si veda [questa domanda SO] (http: // stackoverflow .com/questions/17347935/constexpr-math-functions) –

+0

Vorrei anche chiedervi se poteste semplicemente vivere con l'inizializzazione del runtime del tavolo .È la generazione della tabella in fase di compilazione comprando qualcosa di tangibile nella vostra applicazione? di la complessità del codice e il tempo di compilazione potrebbero rendere inutile l'inizializzazione di una tabella 'static' in fase di runtime. –

+0

Preferisco fare questo tipo di tabella nel costruttore della classe che lo usa. – user3528438

risposta

2

penso che si sarebbe molto meglio scrivendo un generatore di codice piccolo che può generare i file .c per tali tabelle.

Sfortunatamente, C++ si sforza molto di essere un puro linguaggio di programmazione in fase di compilazione, ma è anche molto difficile da implementare. I calcoli compilati in C++ sembrano ancora un po 'fantastici se stai cercando di essere pragmatico al riguardo :(

Problemi correlati