Xref: utzoo comp.lang.c++:11565 comp.std.c++:586 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!microsoft!jimad From: jimad@microsoft.UUCP (Jim ADCOCK) Newsgroups: comp.lang.c++,comp.std.c++ Subject: Re: Add-with-carry operator Message-ID: <70453@microsoft.UUCP> Date: 4 Feb 91 21:56:44 GMT References: <1991Feb3.202530.14874@julius.cs.uiuc.edu> Reply-To: jimad@microsoft.UUCP (Jim ADCOCK) Organization: Microsoft Corp., Redmond WA Lines: 83 In article <1991Feb3.202530.14874@julius.cs.uiuc.edu> zweig@cs.uiuc.edu writes: | |The problem: there is not an add-with-carry operator in C++, so there isn't |any way of writing portable code to use this. I know, I know, I know, I can be |totally gross and icky and hard and use asm's and come up with a different one |for each processor/compiler combination I want to run on. But if there were a |standard way of letting the compiler know that I want to do add-with-carry |rather than vanilla add I could write portable, efficient code that people |like Van Jacobson would think was swell. I suppose that a properly inlined |function could do the trick, but it would be nice if there were an operator. | |Comments? On my machine/compiler, the following example generates code close to what one would generate by hand in assembler. Thus, one has an example showing it's not necessary for the language to add a add-plus-carry command -- good optimizers can generate such commands where implied by code. I believe compilers ought to offer built-in support for word sizes to 2X the natural bit-size of the machine. Thus, for example, 32-bit machines ought to support code generation for 64-bit integer arithmetic. Whether 64-bit arithmetic on a 32-bit machine ought to be called "long long" or just "long" remains debatable. /* assumes: 8 bits per byte two's complement sizeof(short) < sizeof(long) */ #define bitsperbyte 8 class longlong { private: unsigned short s[4]; public: longlong(long); const longlong& operator+=(const longlong& p); void print(); }; longlong::longlong(long l) { s[0] = (unsigned short)l; s[1] = (unsigned short)(l >> (bitsperbyte * sizeof(unsigned short))); s[2] = s[3] = (l >= 0) ? (unsigned short)0 : (unsigned short)-1;; } const longlong& longlong::operator+=(const longlong& p) { long accum; accum = (long) s[0] + p.s[0]; // unwrapped loop: s[0] = (unsigned short)accum; accum = ((unsigned short)(accum >> (bitsperbyte * sizeof(unsigned short)))) + (long) s[1] + p.s[1]; s[1] = (unsigned short)accum; accum = ((unsigned short)(accum >> (bitsperbyte * sizeof(unsigned short)))) + (long) s[2] + p.s[2]; s[2] = (unsigned short)accum; accum = ((unsigned short)(accum >> (bitsperbyte * sizeof(unsigned short)))) + (long) s[3] + p.s[3]; s[3] = (unsigned short)accum; return *this; } extern "C" void printf(const char*, ...); void longlong::print() { printf("%04X%04X%04X%04X\n", s[3], s[2], s[1], s[0]); } main() { longlong a(0x12345678L); a.print(); longlong b(0xEDCBA988L); b.print(); a += b; a.print(); return 0; }