... typedef unsigned int uInt; typedef unsigned long long int uLong; #define MAX_uInt ((uInt)(-1)) #define MUL ((uLong)MAX_uInt) // MUL: Max_uInt in Unsigned Long int BigInt::WS = sizeof(uInt); BigInt & BigInt::operator+=(const BigInt &rhs) { ... // , uLong carry = 0; for ( uInt *th = (uInt*)words, *oz = (uInt*)rhs.words, *limit = oz + rhs.wc, *thl = th + wc; oz < limit || carry && th < thl; oz++, th++) { uLong t = carry + *th; t += oz < limit ? *oz : 0; if (t > MUL) { carry = 1; t &= MUL; } else carry = 0; *th = (uInt)t; } if (carry) { ... // } return *this; }
struct timespec t1, t2; BigInt *a = ..., *b = ...; // - 400 clock_gettime(CLOCK_MONOTONIC_RAW, &t1); for (int j = 0; j < 10000000; j++) { *a += *b; *a -= *b; } clock_gettime(CLOCK_MONOTONIC_RAW, &t2); printf(...); // t1 t2
-O1 | -O2 | -O3 |
7 | 6 | 6 |
// uInt int long long int BigInt & BigInt::operator+=(const BigInt &rhs) { ... // , uInt *th = (uInt*)words, *oz = (uInt*)rhs.words; asm goto ( "clc\n" "l1:\t" "mov\t(%[oz]), %[ax]\n\t" "adc\t%[ax], (%[th])\n\t" "lahf\n\t" "add\t%[ws], %[th]\n\t" "add\t%[ws], %[oz]\n\t" "sahf\n\t" "loop\tl1\n\t" "jnc\t%l[nocarry]\n" : : [th] "r" (th), [oz] "r" (oz), [ws] "I" (sizeof(uInt)), [ax] "a" ((uInt)0), "c" (wc) : : nocarry ); ... // nocarry: return *this; }
... clc lo: mov (%rbx), %rax adc %rax, (%rdx) lahf add $8, %rdx add $8, %rbx sahf loop lo jnc nocarry ...
... clc lo: mov (%rbx), %rax adc %rax, (%rdx) lahf add $8, %rdx add $8, %rbx sahf dec %rcx jnz lo jnc nocarry ...
... clc lo: mov (%rbx), %rax adc %rax, (%rdx) lea 8(%rdx), %rdx lea 8(%rbx), %rbx dec %rcx jnz lo jnc nocarry ...
lea 8 (% rdx),% rdxdoes the same thing as
add $ 8,% rdx- adds the word size to the register.
// WS = 16 ... clc lo: mov (%rbx), %rax adc %rax, (%rdx) mov 8(%rbx), %rax adc %rax, 8(%rdx) lea 16(%rbx), %rbx lea 16(%rdx), %rdx dec %rcx jnz lo jnc nocarry ...
Source: https://habr.com/ru/post/135590/
All Articles