Thread: Advanced math in precompiling?

  1. #1
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286

    Advanced math in precompiling?

    Hi, is there a possibility to use advanced math functions during the pre-compiling? For example, I have defined D_TYPE, currently to unsigned int, D_BITS to (sizeof(D_TYPE)*8), then I want to have a macro named BASE, which is the largest potens of 10, below 2^(D_BITS -1) - 1 (where ^ is the power function), or (the maximum value D_TYPE can accept)/2. So, using mathematical functions it would be something like 10^(floor(log(D_TYPE_MAX/2))). And the floor(log(D_TYPE_MAX/2)) part of the macro definition could be another macro called B_DIGITS, so that BASE is defined as 10^B_DIGITS (^ is not xor this time either).
    Come on, you can do it! b( ~_')

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by TriKri View Post
    Hi, is there a possibility to use advanced math functions during the pre-compiling? For example, I have defined D_TYPE, currently to unsigned int, D_BITS to (sizeof(D_TYPE)*8), then I want to have a macro named BASE, which is the largest potens of 10, below 2^(D_BITS -1) - 1 (where ^ is the power function), or (the maximum value D_TYPE can accept)/2. So, using mathematical functions it would be something like 10^(floor(log(D_TYPE_MAX/2))). And the floor(log(D_TYPE_MAX/2)) part of the macro definition could be another macro called B_DIGITS, so that BASE is defined as 10^B_DIGITS (^ is not xor this time either).
    The Boost integer library might be handy.

  3. #3
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    But how can I use a library in precompiling? :P
    Come on, you can do it! b( ~_')

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    <boost/integer/static_log2.hpp> is an example of how to compute floor(log2(N)) at compile time. There may be other tools in boost to help, I'm not sure.

    Here's a good intro to template meta-programs - check out the links at the top as well.

    http://ubiety.uwaterloo.ca/~tveldhui.../meta-art.html

    gg

  5. #5
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Thanks, I'm gonna check that out!
    Come on, you can do it! b( ~_')

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    I do enjoy a challenge
    Here's code that will essentially calculate floor(log10(N)) at compile time.
    Code:
    #include<iostream>
    using namespace std;
    
    // compile time pow()
    template<int X, int Y>
    struct ctime_pow
    {
        enum {result = X * ctime_pow<X, Y-1>::result};
    };
    
    // specialization for pow(X, 0) to stop recursion
    template<int X>
    struct ctime_pow<X, 0>
    {
        enum {result = 1};
    };
    
    // recusively calculate X^Potens where X^Potens <= MAX
    template<int X, int Potens, int MAX, bool bStop>
    struct greatest_pow_imp
    {
        enum {result = greatest_pow_imp<X, 
                                        Potens + 1, 
                                        MAX, 
                                        (ctime_pow<X, Potens + 1>::result > MAX)>::result};
    };
    
    // specialization where bStop is true, "choose" Potens - 1
    template<int X, int Potens, int MAX>
    struct greatest_pow_imp<X, Potens, MAX, true>
    {
        enum {result = Potens - 1};
    };
    
    // calculate greatest power of X that is <= MAX
    template<int X, int MAX>
    struct greatest_pow //less than or equal to MAX
    {
        enum {result = greatest_pow_imp<X, 0, MAX, false>::result};
    };
    
    #define TEST(X, MAX) \
        cout << "greatest_pow<" #X ", " #MAX ">::result = " \
             << greatest_pow<X, MAX>::result << endl
    
    int main() 
    {
        TEST(10, 0);
        TEST(10, 1);
        TEST(10, 9);
        TEST(10, 10);
        TEST(10, 99);
        TEST(10, 100);
        TEST(10, 999);
        TEST(10, 1000);
    
        return 0;
    }//main
    gg

  7. #7
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Codeplug View Post
    I do enjoy a challenge
    Here's code that will essentially calculate floor(log10(N)) at compile time.
    You seem to have caught on to that awfully quick. Welcome to the metaprogrammer's guild!

    EDIT: Haha, nevermind. I had you confused with the OP

  8. #8
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Nice Codeplug!

    So the < ... > is really just for making multiple definitions from one code snippet in compile time, whether it is unique intereger numbers or type names laying inside it? That can be quite usefull. Templates, isn't it?
    Come on, you can do it! b( ~_')

  9. #9
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    And if you would like to make
    Code:
    template<int X, int Y>
    struct ctime_pow
    {
        enum {result = X * ctime_pow<X, Y-1>::result};
    };
    valid for all types of X, not only ints, how do you write then?
    Come on, you can do it! b( ~_')

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    You can't, it has to be an integral type. I think you can use short, long or char (or probably even bool) but you can't use a floating type for this kind of template metaprogramming.

  11. #11
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Quote Originally Posted by Daved View Post
    You can't, it has to be an integral type. I think you can use short, long or char (or probably even bool) but you can't use a floating type for this kind of template metaprogramming.
    I didn't have any specific type in mind, I just thought maybe we can generalize this to cover all possible types that can be used in preprocessing. Or do you have to choose?

    I have tried
    • template<T X, int Y> //T not defined
    • template<class T, T X, int Y> //Also produces an error
    • template<class T X, int Y> //Wrong syntax
    • template<class T, int Y> POW<T X, int Y>//Wrong syntax again
      etc.

    Is there any way to do this?
    Come on, you can do it! b( ~_')

  12. #12
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I don't think so, but why would you want to? If you use long that's probably the best you can do, because any number that fits for any of the other types would fit for long as well.

  13. #13
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Quote Originally Posted by Daved View Post
    I don't think so, but why would you want to? If you use long that's probably the best you can do, because any number that fits for any of the other types would fit for long as well.
    Why does it have to be an integral type, I thought you could use any type you wanted when writing templates? I'd like to make it work for floats and doubles as well... :/
    Last edited by TriKri; 09-25-2007 at 06:10 PM.
    Come on, you can do it! b( ~_')

  14. #14
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    You can do different things with templates. You can do something where the code depends on the type like a vector<T> or something like this:
    Code:
    template <typename T>
    void outputData(std::ostream& out, T data)
    {
      out << data;
    };
    Those things don't work on any type, they only work on types that don't cause compile errors when you replace T with that type, but that's what you're thinking of.

    I different way to use templates is to use an integer value instead of a type. An example of this is Codeplug's code. The point of it is not to be generic code that can work on different types, the point is to take advantage of the compiler and the template system to do work at the compilation stage and avoid doing that work at runtime.

  15. #15
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Hmm, I se. Maybe I'll use it at the time and IFF I need the same code some other time but with some other type I'll rewrite it for that specific type ... but thank you. It can be good to know!
    Come on, you can do it! b( ~_')

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. advanced math library for linux?
    By Cobras2 in forum Linux Programming
    Replies: 5
    Last Post: 07-18-2005, 12:20 AM
  2. how to use operator+() in this code?
    By barlas in forum C++ Programming
    Replies: 10
    Last Post: 07-09-2005, 07:22 PM
  3. toughest math course
    By axon in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 10-28-2003, 10:06 PM
  4. advanced math problem
    By laasunde in forum Tech Board
    Replies: 62
    Last Post: 10-03-2003, 10:19 PM
  5. advanced math help plz
    By Geo-Fry in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 04-14-2003, 07:01 PM