2

I want to create my own data type which can hold values from -2^127 to 2^127-1 and want to perform addition on two my128int data type variable. I search on stackoverflow community and found custom data type in C

What additional task is required from the above discussed thread.

void addition(my128int a, my128int b)
{
    ....
    //perform some task
    // print the result a+b
}
Community
  • 1
  • 1
Saurabh
  • 29
  • 2
  • This is only possible makeing `my128int` a string and performing arithmetic operations manually AFAIK. – Iharob Al Asimi Feb 20 '15 at 15:29
  • Your question is a bit broad to me. The signature of your function seems good but it depends on how you defined `my128int`. – n0p Feb 20 '15 at 15:30
  • How would you restrict the data range? – Saurabh Feb 20 '15 at 15:30
  • @Coconop yeah exactly the same problem I am facing to declare `my128int` data type. How to do that? – Saurabh Feb 20 '15 at 15:31
  • The post you refers to has the answer: use string representation. You basically deals with `char buffer[16]` which restrict your range to 16 bytes. – n0p Feb 20 '15 at 15:35
  • 3
    @iharob That's almost true, but requiring a string (i.e. a textual representation) is going a bit too far. – unwind Feb 20 '15 at 15:47
  • http://stackoverflow.com/questions/4757338/how-to-properly-add-subtract-to-a-128-bit-number-as-two-u-int64-t?rq=1 http://stackoverflow.com/questions/741301/how-can-i-add-and-subtract-128-bit-integers-in-c-or-c?rq=1 http://stackoverflow.com/questions/22085516/multiplying-two-128-bit-ints?rq=1 – phuclv Feb 20 '15 at 15:59
  • possible duplicate of [An efficient way to do basic 128 bit integer calculations in C++?](http://stackoverflow.com/questions/27261291/an-efficient-way-to-do-basic-128-bit-integer-calculations-in-c) – phuclv Feb 20 '15 at 15:59

1 Answers1

4

For an integer data type, I don't much care for the solution offered in the (unaccepted) answer to the question you referenced.

Myself, I would implement a type such as you describe like this:

typedef struct myint128_s {
    uint32_t bits[4];
} myint128;

Addition would then look like this:

void myint128_add(myint128 *addend1, myint128 *addend2, myint128 *sum) {
    uint32_t carry = 0;
    int i;

    for (i = 0; i < 4; i += 1) {
        uint64_t temp = (uint64_t) addend1->bits[i]
                + (uint64_t) addend2->bits[i] + carry;
        sum->bits[i] = (uint32_t) temp;
        carry = (uint32_t) (temp >> 32);
    }

    /* can detect overflow here, if desired */
}

This assumes / provides a twos complement representation of negative numbers, consistent with the bounds you specified for representable numbers. You don't then have to give any special attention to the sign bit (bit 63 of bits[3]).

In effect, this is a numeric representation in base 2^32.

John Bollinger
  • 121,924
  • 8
  • 64
  • 118
  • this will be inefficient on 64-bit architectures – phuclv Feb 20 '15 at 16:01
  • 3
    @LưuVĩnhPhúc, 64-bit machines do 32-bit arithmetic quite efficiently. You could nevertheless implement the bignum digits as type `uint64_t`, but that makes it a lot less straightforward to handle carries properly (in C, as opposed to assembly). I'm not convinced it would be a net win. – John Bollinger Feb 20 '15 at 16:04
  • No, your way is simply too complicated. The carry can be set easily with a comparison between the result of the lower addition with one of the operands. Modern compilers will recognize this and turn into a pair of add/adc. You can see the assembly output [here](http://goo.gl/dTDdGc). Probably you haven't see any question on SO regarding multiple word addtion http://stackoverflow.com/questions/27261291/an-efficient-way-to-do-basic-128-bit-integer-calculations-in-c – phuclv Feb 20 '15 at 16:16
  • 64-bit machines indeed can do 32-bit arithmetics efficiently, but doing 32-bit arithmetics will result in twice the number of operations needed and the total time will be increased. To add 128 bit values you only need `add rax, rcx; adc rbx, rdx` on x86_64 but at least 4 instructions on x86 with a lot of memory references – phuclv Feb 20 '15 at 16:18
  • compare the above simple code output with your super-long assembly output http://goo.gl/pj4Bvg – phuclv Feb 20 '15 at 16:24
  • 1
    @LưuVĩnhPhúc, yes, your approach is more efficient for addition than mine (though I still object to labeling mine "*in*efficient"). But what about multiplication? You need a full (big)digit of carry for that, and I don't think you'll easily get it when your digits are already the size of a register. – John Bollinger Feb 20 '15 at 17:36
  • You didn't mention anything about multiplication in your answer. Neither do I in my comment. And you can break the number into smaller parts easily to multiply. Using inline assembly just a single multiplication will produce the file 128-bit result. No libraries use 32-bit int limbs on 64-bit architectures nowadays – phuclv Feb 21 '15 at 00:48