473,320 Members | 1,572 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Need help mixing computed goto and loop unrolling via template metaprogramming

3
My parser project calls for a computed goto (see code below).
The C preprocessor delivers the desired result, but is ugly.
Template metaprogramming delivers results I do not understand.

Can anyone explain why loop unrolling doesn't play well with templates?
Or better, can someone submit a code fragment to get desired results?

Here are the command-lines I use to generate code:
"g++ -DTEMPLATE=0 -o gotofun0 gotofun.cpp" works exactly as desired.
"g++ -DTEMPLATE=1 -o gotofun1 gotofun.cpp" fails to output properly.
"g++ -DTEMPLATE=2 -o gotofun2 gotofun.cpp" fails to output properly.

When correct, the program should generate a countdown sequence.
For instance, running the program gotofun0, the output is 3 2 1.
The programs gotofun1 and gotofun2 countdown past 0, down to -252.
It is as if the "end:" label only applies to the first line from the unrolling.
I have tried various uses of brace-blocking, parens, and whatnot.

Any help would be appreciated.

Expand|Select|Wrap|Line Numbers
  1. /// gotofun.cpp
  2. /// goto considered fun
  3. /// @date 12/31/2007
  4. /// @brief This code counts down from a specified number using computed gotos.
  5. #include <iostream>
  6.  
  7. using namespace std;
  8.  
  9. #ifndef TEMPLATE
  10. #define TEMPLATE 0
  11. #endif
  12.  
  13. #if ( 0 == TEMPLATE )
  14. /// C preprocessor version works fine.
  15. #define go1 cout << count-- << endl
  16. #define go2     ((go1),(go1))
  17. #define go4     ((go2),(go2))
  18. #define go8     ((go4),(go4))
  19. #define go16    ((go8),(go8))
  20. #define go32   ((go16),(go16))
  21. #define go64   ((go32),(go32))
  22. #define go128  ((go64),(go64))
  23. #define go256 ((go128),(go128))
  24. #endif
  25.  
  26. #if ( 1 == TEMPLATE ) /// Don't yet know how to make template metaprogramming version work.
  27. template<int N>
  28.   static inline void GO   ( int &n ) { cout << n-- << endl; GO<N-1>( n ); }
  29. template<     >
  30.   static inline void GO<1>( int &n ) { cout << n-- << endl;               }
  31. #define go1   GO<  1>( count );
  32. #define go256 GO<256>( count );
  33. #endif
  34.  
  35. #if ( 2 == TEMPLATE ) /// Don't yet know how to make template metaprogramming version work.
  36. template<int N>
  37.   struct Q     { static inline void q( int &n ) { cout << n-- << endl; Q< N-1 >::q( n ); } };
  38. template<     >
  39.   struct Q< 1 >{ static inline void q( int &n ) { cout << n-- << endl; } };
  40. #define go1   Q<  1>::q( count )
  41. #define go256 Q<256>::q( count )
  42. #endif
  43.  
  44. int main( int argc, char **argv ) {
  45.     try {
  46.         char *u = (char *) &&unused, *b = (char *) &&begin, *e = (char *) &&end;
  47.         int d = ( b - u );                   ///< Code size between labels
  48.         int n = ( e - b ) / d;
  49.         void *jump[ n + 1 ];                 ///< Make a jump table
  50.         for( int i = 0; i < ( n + 1 ); ++i ) /// Generate jump table contents.
  51.             jump[ i ] = (void *)( b + ( i * d ) );
  52.         if( jump[ n ] != &&end ) throw( "Failed to generate jump table" );
  53.         cout << n << " table entries of width " << d << endl;
  54.         cout << &&unused << ", " << &&begin << ", " << &&end << endl;
  55.         cout << (void *)u << ", " << (void *)b << ", " << (void *)e << endl;
  56.  
  57.         int count;                           ///< Number to count-down
  58.         if( argc == 2 ) count = atoi( argv[ 1 ] );
  59.         if( argc != 2 || count < 0 )
  60.             throw( "Please provide exactly one positive integer arg." );
  61.  
  62.         goto *( jump[ n - ( count % n ) ] ); /// partway through table.
  63. unused: go1;
  64. begin:  go256;
  65. end:    if( count > 0 ) goto begin;          ///< If more, go back and do it.
  66.     }
  67.     catch( const char *s) {
  68.         cerr << "Error: " << s << endl;
  69.     }
  70.     catch( ... ) {
  71.         cerr << "Error: unknown" << endl;
  72.     }
  73.     return 0;
  74. }
Jan 1 '08 #1
5 3589
weaknessforcats
9,208 Expert Mod 8TB
This is the worst C++ that I have seen in several years.

Re-post when you have removed all #define, goto, casts to void*, etc.

You might compare your code to the examples in any C++ textbook.
Jan 2 '08 #2
RedSon
5,000 Expert 4TB
This is the worst C++ that I have seen in several years.

Re-post when you have removed all #define, goto, casts to void*, etc.

You might compare your code to the examples in any C++ textbook.
I think this is a good example of trying to make you c/c++ code work like assembly. You might want to reconsider your software design to either a) be in assembly or b) be more object oriented.
Jan 2 '08 #3
iapx86
3
I do appreciate the obvious departure of my code from standard practice. I welcome your criticism. I agree that one ought not to adopt this practice in general. However, I have not done this without reason.

There are important problems to be solved that are best done with a combination of generic, object-oriented, procedural, and spaghetti-code programming. Extreme performance lexers are one case where this style is necessary.

I have written an XML Unicode lexer that executes 8 instructions for every codepoint translated into internal UTF32 form, including determining all possible error conditions and the character class. The code submitted above was intended to increase performance on yet another lexer that hand-unrolls stream iteration rather than operating on a fully in-memory XML file as the older one does.

I am more than a little competent at both C++ and Intel iapx86 Assembly. The C preprocessor macro version in the code submitted delivers dramatic performance gains over anything that might be done with inline, -O4, or any compiler optimizing.

Comparing lex and boost::spirit performance with my own code, my lexer generally outperforms these by factors of over 1000 times. Comparing the performance with best-of-breed lexers, this factor drops to between 10 and 100 times better.

Please understand that I am happy to be criticized, but I would still like an answer on how to perform template metaprogramming loop unrolling while maintaining label address integrity. Such loop unrolling is well-documented in a variety of good web-pages, and I still wish to use it.

Sometimes one must take the road less travelled by. Sometimes it makes all the difference.
Jan 2 '08 #4
RedSon
5,000 Expert 4TB
I do appreciate the obvious departure of my code from standard practice. I welcome your criticism. I agree that one ought not to adopt this practice in general. However, I have not done this without reason.

There are important problems to be solved that are best done with a combination of generic, object-oriented, procedural, and spaghetti-code programming. Extreme performance lexers are one case where this style is necessary.

I have written an XML Unicode lexer that executes 8 instructions for every codepoint translated into internal UTF32 form, including determining all possible error conditions and the character class. The code submitted above was intended to increase performance on yet another lexer that hand-unrolls stream iteration rather than operating on a fully in-memory XML file as the older one does.

I am more than a little competent at both C++ and Intel iapx86 Assembly. The C preprocessor macro version in the code submitted delivers dramatic performance gains over anything that might be done with inline, -O4, or any compiler optimizing.

Comparing lex and boost::spirit performance with my own code, my lexer generally outperforms these by factors of over 1000 times. Comparing the performance with best-of-breed lexers, this factor drops to between 10 and 100 times better.

Please understand that I am happy to be criticized, but I would still like an answer on how to perform template metaprogramming loop unrolling while maintaining label address integrity. Such loop unrolling is well-documented in a variety of good web-pages, and I still wish to use it.

Sometimes one must take the road less travelled by. Sometimes it makes all the difference.
If you say so...but in the future lets try to at least put them in code tags (i.e. [CODE=<lang>] Your code here... [/code] ) renders as
Expand|Select|Wrap|Line Numbers
  1.  Your code here... 
Thanks
Jan 2 '08 #5
iapx86
3
I successfully unrolled my loop in a clear maintainable style.
I hope my future inquiries are considered less controversial.

If you say so...but in the future lets try to at least put them in code tags (i.e.
Expand|Select|Wrap|Line Numbers
  1.  Your code here... 
) renders as
Expand|Select|Wrap|Line Numbers
  1.  Your code here... 
Thanks
Jan 6 '08 #6

Sign in to post your reply or Sign up for a free account.

Similar topics

12
by: Dave | last post by:
Would people agree with the statement that to a large degree, using template metaprogramming techniques turns a C++ compiler into a C++ interpreter (but just for the metaprogrammed portions of the...
5
by: Mohammad | last post by:
Hi, Is it possible to disable a method of a template class depending on the typename at compile time? thanks!
15
by: Robin Eidissen | last post by:
What I try to do is to iterate over two variables using template metaprogramming. I've specialized it such that when it reaches the end of a row ot starts on the next and when it reaches the last...
3
by: Richard Cavell | last post by:
I have a recursive function like this: void MyFunction(int i) { i++; // do something with i if (we're not finished) MyFunction(i); } I keep count of how far nested we are with i. Now, it...
22
by: Jan Richter | last post by:
Hi there, the Code below shows DJBs own implementation of strlen (str_len): unsigned int str_len(char *s) { register char *t; t = s; for (;;) { if (!*t) return t - s; ++t;
9
by: PengYu.UT | last post by:
Hi, I have the code below this email. I want to replace the last 4 lines with a Metaprogramming loop to get something like the following (I don't know the syntax). Is it possible? for type in...
33
by: Nikhil Bokare | last post by:
I wanted a C++ compiler which would follow the ANSI C++ standards. If you could tell me an IDE also, it would be more helpful. Thanks.
7
by: Joe | last post by:
Hi, I found a concept named template metaprogramming that can be used in C+ + code at compile-time. I am a beginner at C++. But I am a programmer on the .NET platform. Do you know if template...
12
by: nooneinparticular314159 | last post by:
Hello. If I declare the following: template<int a, int b, int SomeArray> class DoSomething{ public: .. .. ..
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.