1
\$\begingroup\$

I just started development on a new bignum library that can operate on numbers of any arbitrary base (up to 232). I want to get a good idea of where I can improve before taking things any further. Right now, the library supports basic addition and subtraction, comparisons, and absolute values. I will be adding division, multiplication, modulus, and bit operations soon but now seems as good a time as any to get some feedback.

The library has some typedefs for base 2, 8, 10, 16, and 32 right now, so I'll just give an example using base-10.

#include <iostream>

#include "bignum.h"

/*
 * Use with an std::ostream
 */
#define LOG_DEBUG_COMP(x, cmp, y)\
    x << BN_STRINGIFY(cmp) << y << ":\t" << (x cmp y)

#define CREATE_BN_TEST(bnType) \
void test_##bnType() { \
    std::cout \
        << "------------------------------------------------------------------\n" \
        << "\t\t\t" << BN_STRINGIFY(bnType) << '\n' \
        << "------------------------------------------------------------------\n" \
        << std::endl; \
    bnType testNum1 = {bn_desc_t::BN_NEG, {1, bnType::SINGLE_BASE_MAX, bnType::SINGLE_BASE_MAX}}; \
    bnType testNum2 = {bn_desc_t::BN_POS, {bnType::SINGLE_BASE_MIN, 1}}; \
    \
    std::cout << LOG_DEBUG_COMP(testNum1, >, testNum2) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum1, >=, testNum2) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum1, <, testNum2) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum1, <=, testNum2) << std::endl; \
    std::cout << std::endl; \
    \
    std::cout << LOG_DEBUG_COMP(testNum1, +, testNum2) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum1, -, testNum2) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum2, +, testNum1) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum2, -, testNum1) << std::endl; \
    std::cout << std::endl; \
     \
    testNum1.setDescriptor(BN_POS); \
    testNum2.setDescriptor(BN_NEG); \
     \
    std::cout << LOG_DEBUG_COMP(testNum1, >, testNum2) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum1, >=, testNum2) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum1, <, testNum2) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum1, <=, testNum2) << std::endl; \
    std::cout << std::endl; \
     \
    std::cout << LOG_DEBUG_COMP(testNum1, +, testNum2) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum1, -, testNum2) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum2, +, testNum1) << std::endl; \
    std::cout << LOG_DEBUG_COMP(testNum2, -, testNum1) << std::endl; \
    std::cout << "\n\n" << std::endl; \
}

CREATE_BN_TEST(bignum_base8)
CREATE_BN_TEST(bignum_base10)
CREATE_BN_TEST(bignum_base16)

int main() {
    try {
        test_bignum_base8();
        test_bignum_base10();
        test_bignum_base16();
    }
    catch(const std::exception& e) {
       std::cerr << "Exception caught: " << e.what() << std::endl;
    }

    return 0;
}

Here's the output:

------------------------------------------------------------------
            bignum_base8
------------------------------------------------------------------

-177>01:  0
-177>=01: 0
-177<01:  1
-177<=01: 1

-177+01:  -176
-177-01:  -200
01+-177:  -176
01--177:  200

177>-01:  1
177>=-01: 1
177<-01:  0
177<=-01: 0

177+-01:  176
177--01:  200
-01+177:  176
-01-177:  -200



------------------------------------------------------------------
            bignum_base10
------------------------------------------------------------------

-199>01:  0
-199>=01: 0
-199<01:  1
-199<=01: 1

-199+01:  -198
-199-01:  -200
01+-199:  -198
01--199:  200

199>-01:  1
199>=-01: 1
199<-01:  0
199<=-01: 0

199+-01:  198
199--01:  200
-01+199:  198
-01-199:  -200



------------------------------------------------------------------
            bignum_base16
------------------------------------------------------------------

-11515>01:    0
-11515>=01:   0
-11515<01:    1
-11515<=01:   1

-11515+01:    -11514
-11515-01:    -200
01+-11515:    -11514
01--11515:    200

11515>-01:    1
11515>=-01:   1
11515<-01:    0
11515<=-01:   0

11515+-01:    11514
11515--01:    200
-01+11515:    11514
-01-11515:    -200

Is there anything that I should improve upon regarding the API or its internals? It makes pretty heavy use of templates (which may harm readability) but I tried making the code as clean as possible, while also using external templates to reduce build times. I'd like to use this in production code but I also want it to be used publicly as well.

\$\endgroup\$
  • \$\begingroup\$ Is this all the code there is to review? \$\endgroup\$ – Jamal Jul 25 '14 at 4:00
  • \$\begingroup\$ The code is actually on github (see the link above). There's quite a bit of code and I couldn't cram it all into one post. \$\endgroup\$ – icdae Jul 25 '14 at 4:03
  • 1
    \$\begingroup\$ Keep in mind that we can only review what's embedded here. Try to include as much as you can, even if it means posting multiple questions. \$\endgroup\$ – Jamal Jul 25 '14 at 4:05
  • \$\begingroup\$ I've updated the post to include my current test of basic arithmetic from the library. \$\endgroup\$ – icdae Jul 25 '14 at 4:17
  • \$\begingroup\$ That looks better. I'm not particularly familiar enough with libraries, so someone else can take a look at it. \$\endgroup\$ – Jamal Jul 25 '14 at 4:20
3
\$\begingroup\$

Since you are using C++, kill the macros. Macros are evil and dangerous.

For example:

  CREATE_BN_TEST("Apple")
  struct Node
  {
     int value;
     struct Node * next;
  };
  CREATE_BN_TEST(Node)
  CREATE_BN_TEST(std);
  CREATE_BN_TEST(:::);

Try using inline functions or templated functions.

\$\endgroup\$
3
\$\begingroup\$

I assume the exception-handling is only for testing or and/or displaying purposes based on the lack of documentation provided. It doesn't otherwise do very much considering there's nothing in place to actually handle the exceptions. It's also flawed since you may not know which function has thrown the first exception.

For a library, this wouldn't be helpful if the client isn't made aware of the exceptions that can be thrown (if any). Applications using practical exception-handling use specific exception types in this case.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.