www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Compiletime Table

reply "D_Learner" <johnsjdsd gmail.com> writes:
I was wondering how I could change the code below such the `bmBc` 
is computed at compile time . The one below works for runtime but 
it is not ideal since I need to know the  `bmBc` table at 
compile-time . I could appreciate advice on how I could improve 
on this.



     import std.conv:to;
     import std.stdio;

     int [string]  bmBc;
     immutable string pattern = "GCAGAGAG";
     const int size = to!int(pattern.length);

      struct king {

             void  calculatebmBc(int i)()
             {
                     static if ( i < size -1 )
                            
bmBc[to!string(pattern[i])]=to!int(size-i-1);

                   //        bmBc[pattern[i]] ~= i-1;

                     calculatebmBc!(i+1)();
             }
             void calculatebmBc(int i: size-1)() {

             }
     }

     void main(){
       king myKing;

       const  int start = 0;
       myKing.calculatebmBc!(start)();
      //1.   enum  bmBcTable =  bmBc;

     }
Aug 13 2015
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 13 August 2015 at 19:13:55 UTC, D_Learner wrote:
 I was wondering how I could change the code below such the 
 `bmBc` is computed at compile time .
It is currently not possible to build an associative array at compile time and keep it as a runtime table due to the implementation. However, looking at your code, you don't need a full AA... the key is a single char, right? Do something like this: int[128] bmBc = calculate(); // .... And then a line like this should work to set it in the calculate function: bmBc[pattern[i]] = i-1; Adjust this code to fit you: int[128] a = calc(); enum string pattern = "abc"; int[128] calc() { int[128] a; // local copy to work on as we build a[pattern[0]] = 0; return a; // return the completed table } This works because individual characters have a numeric value. If they are all A-Z, you can easily fit them in a small array and access them even faster than an associative array (doesn't even have to be full size 128 if the only keys are the letters). And these can be built at CTFE and stored in the program's data segment.
Aug 13 2015
next sibling parent "D_Learner" <johnsjdsd gmail.com> writes:
On Thursday, 13 August 2015 at 19:26:12 UTC, Adam D. Ruppe wrote:
 On Thursday, 13 August 2015 at 19:13:55 UTC, D_Learner wrote:
 I was wondering how I could change the code below such the 
 `bmBc` is computed at compile time .
It is currently not possible to build an associative array at compile time and keep it as a runtime table due to the implementation. However, looking at your code, you don't need a full AA... the key is a single char, right? Do something like this: int[128] bmBc = calculate(); // .... And then a line like this should work to set it in the calculate function: bmBc[pattern[i]] = i-1; Adjust this code to fit you: int[128] a = calc(); enum string pattern = "abc"; int[128] calc() { int[128] a; // local copy to work on as we build a[pattern[0]] = 0; return a; // return the completed table } This works because individual characters have a numeric value. If they are all A-Z, you can easily fit them in a small array and access them even faster than an associative array (doesn't even have to be full size 128 if the only keys are the letters). And these can be built at CTFE and stored in the program's data segment.
Thanks, the 128 is fine since I was considering the whole ASCII character set . I was a bit skeptical of writing the code in that manor though since I have to still compare runtime and compiletime implementation performance(benchmarks ). That is why my code seemed to mimic templating . Maybe the question would then be, how do I force this function to be fully executed at compiletime and later make it be executed at runntime ?
Aug 13 2015
prev sibling parent reply "D_Learner" <johnsjdsd gmail.com> writes:
On Thursday, 13 August 2015 at 19:26:12 UTC, Adam D. Ruppe wrote:
 On Thursday, 13 August 2015 at 19:13:55 UTC, D_Learner wrote:
 [...]
It is currently not possible to build an associative array at compile time and keep it as a runtime table due to the implementation. [...]
Am aware you have published a book on D. Perhaps I have to get myself a copy. Am currently looking at your Dconf2015 talk . Thanks for your advice.
Aug 14 2015
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 14 August 2015 at 20:40:13 UTC, D_Learner wrote:
Perhaps I have to get myself a copy.
you should! There's a lot of little tips and tricks in there.
 Am currently looking at your Dconf2015 talk .
My blasphemous talk as I like to call it :) There's a bit in the video where i went off script and started demoing and it wasn't shown. It was just this program fyi: https://github.com/adamdruppe/inspector not that magical but kinda cool in how simple the code was able to be.
Aug 14 2015
parent "D_Learner" <johnsjdsd gmail.com> writes:
On Friday, 14 August 2015 at 20:48:43 UTC, Adam D. Ruppe wrote:
 On Friday, 14 August 2015 at 20:40:13 UTC, D_Learner wrote:
Perhaps I have to get myself a copy.
you should! There's a lot of little tips and tricks in there.
 Am currently looking at your Dconf2015 talk .
My blasphemous talk as I like to call it :) There's a bit in the video where i went off script and started demoing and it wasn't shown. It was just this program fyi: https://github.com/adamdruppe/inspector not that magical but kinda cool in how simple the code was able to be.
Just downloaded the demo, cheers!
Aug 14 2015
prev sibling parent reply "anonymous" <anonymous example.com> writes:
On Thursday, 13 August 2015 at 19:13:55 UTC, D_Learner wrote:
 I was wondering how I could change the code below such the 
 `bmBc` is computed at compile time . The one below works for 
 runtime but it is not ideal since I need to know the  `bmBc` 
 table at compile-time . I could appreciate advice on how I 
 could improve on this.



     import std.conv:to;
     import std.stdio;

     int [string]  bmBc;
     immutable string pattern = "GCAGAGAG";
     const int size = to!int(pattern.length);

      struct king {

             void  calculatebmBc(int i)()
             {
                     static if ( i < size -1 )
                            
 bmBc[to!string(pattern[i])]=to!int(size-i-1);

                   //        bmBc[pattern[i]] ~= i-1;

                     calculatebmBc!(i+1)();
             }
             void calculatebmBc(int i: size-1)() {

             }
     }

     void main(){
       king myKing;

       const  int start = 0;
       myKing.calculatebmBc!(start)();
      //1.   enum  bmBcTable =  bmBc;

     }
I think you may have some fundamental misunderstandings regarding CTFE, templates, etc. Your code seems to be half-way between a template-based and a CTFE-based solution. The simple way to do compile-time computation in D is CTFE (Compile Time Function Evaluation). That is, you write a pure function that can be evaluated both at run-time and at compile-time. CTFE doesn't need template parameters. Here's some code that should do the same as yours and is compatible with CTFE: ---- import std.conv: to; import std.stdio; int[char] calculatebmBc(string pattern) pure { const int size = to!int(pattern.length); int[char] result; foreach(i; 0 .. size - 1) { result[pattern[i]] = to!int(size - i - 1); } return result; } void main() { auto bmBc = calculatebmBc("GCAGAGAG"); enum bmBcTable = calculatebmBc("GCAGAGAG"); } ---- The key is that calculatebmBc is pure, i.e. it doesn't read or write any module-level mutables. I touched some things here and here I didn't like that are not related to purity/CTFE. Adam D. Ruppe already mentioned an issue with associative arrays: This doesn't work: ---- static foo = calculatebmBc("GCAGAGAG"); ---- It's annoying, but if you need that you have to use some other data structure. See Adam's post.
Aug 13 2015
parent "D_Learner" <johnsjdsd gmail.com> writes:
On Thursday, 13 August 2015 at 19:54:18 UTC, anonymous wrote:
 On Thursday, 13 August 2015 at 19:13:55 UTC, D_Learner wrote:
     [...]
I think you may have some fundamental misunderstandings regarding CTFE, templates, etc. Your code seems to be half-way between a template-based and a CTFE-based solution. The simple way to do compile-time computation in D is CTFE (Compile Time Function Evaluation). That is, you write a pure function that can be evaluated both at run-time and at compile-time. CTFE doesn't need template parameters. Here's some code that should do the same as yours and is compatible with CTFE: ---- import std.conv: to; import std.stdio; int[char] calculatebmBc(string pattern) pure { const int size = to!int(pattern.length); int[char] result; foreach(i; 0 .. size - 1) { result[pattern[i]] = to!int(size - i - 1); } return result; } void main() { auto bmBc = calculatebmBc("GCAGAGAG"); enum bmBcTable = calculatebmBc("GCAGAGAG"); } ---- The key is that calculatebmBc is pure, i.e. it doesn't read or write any module-level mutables. I touched some things here and here I didn't like that are not related to purity/CTFE. Adam D. Ruppe already mentioned an issue with associative arrays: This doesn't work: ---- static foo = calculatebmBc("GCAGAGAG"); ---- It's annoying, but if you need that you have to use some other data structure. See Adam's post.
Thanks so much for the advice, it works fine. Just experimented with the code . I had no idea about it. My mind had the some pre-occupation that compile-time execution is only achievable through templates. Had no idea about pure functions...awesone , code. Thanks again for the clear explanation.
Aug 14 2015