4 ms·
For a higher level language, one idea would be to automatically widen the result of operations, so for example adding two 32 bit integers would have a 33 bit re
by rep_lodsb 4y ago
For a higher level language, one idea would be to automatically widen the result of operations, so for example adding two 32 bit integers would have a 33 bit result.
Since the expression will be eventually assigned to some variable or passed as a function parameter, it will have a limited range (and there should be an exception if that overflows), but intermediate results could be larger.
Is this just completely unfeasible, or just not done because "that's not how C does it"?
- flerchin 4y agoChatGPT came up with this solution when I asked it to handle the overflow, and then asked it to be more efficient. // Calculates the midpoint of two 64-bit integers // and returns the result as a 64-bit integer. int64_t midpoint(int64_t a, int64_t b) { // Use the __int128 type to calculate the sum // of the two input numbers without overflowing. __int128 sum = (__int128) a + (__int128) b; // Shift the sum to the right by 1 bit to divide it by 2 // and get the midpoint. This operation is equivalent to // sum / 2, but is more efficient because it uses a bit shift // operation instead of a division operation. int64_t midpoint = (int64_t) (sum >> 1); return midpoint; }
- rep_lodsb 4y agoYes, but that converts to 128 bits before doing the actual sum (maybe the compiler can still optimize that away?) My idea was a better language where typecasts are never needed at all, because the compiler knows how the result will be used (in this example, returned as int64_t), and can produce whatever code is most efficient and either produces the correct result or a runtime exception. edit: Also any non-toy compiler will optimize division by powers of two into a shift operation, so ChatGPT isn't being clever at all here, just repeating a common superstition.
- jlokier 4y agoChatGPT knows better! > ChatGPT isn't being clever at all here, just repeating a common superstition Source: #include <stdint.h> int64_t midpoint_ChatGPT(int64_t a, int64_t b) { __int128 sum = (__int128) a + (__int128) b; // Shift the sum to the right by 1 bit to divide it by 2 // and get the midpoint. This operation is equivalent to // sum / 2, but is more efficient because it uses a bit shift // operation instead of a division operation. int64_t midpoint = (int64_t) (sum >> 1); return midpoint; } int64_t midpoint_rep_lodsb(int64_t a, int64_t b) { __int128 sum = (__int128) a + (__int128) b; // Shifts are for the superstitious. int64_t midpoint = (int64_t) (sum / 2); return midpoint; } Clang -O2 output: _midpoint_ChatGPT: pushq %rbp movq %rsp, %rbp movq %rdi, %rcx sarq $63, %rcx movq %rsi, %rax sarq $63, %rax addq %rdi, %rsi adcq %rcx, %rax shldq $63, %rsi, %rax popq %rbp retq _midpoint_rep_lodsb: pushq %rbp movq %rsp, %rbp movq %rdi, %rcx sarq $63, %rcx movq %rsi, %rax sarq $63, %rax addq %rdi, %rsi adcq %rcx, %rax movq %rax, %rcx shrq $63, %rcx addq %rsi, %rcx adcq $0, %rax shldq $63, %rcx, %rax popq %rbp retq GCC -O2 output: midpoint_ChatGPT: endbr64 movq %rsi, %r8 movq %rdi, %rax sarq $63, %rdi sarq $63, %rsi movq %rdi, %rdx addq %r8, %rax adcq %rsi, %rdx shrdq $1, %rdx, %rax ret midpoint_rep_lodsb: endbr64 movq %rsi, %rcx movq %rdi, %rax sarq $63, %rdi sarq $63, %rcx movq %rdi, %rdx addq %rax, %rsi movq %rcx, %rdi adcq %rdx, %rdi xorl %edx, %edx movq %rdi, %rcx shrq $63, %rcx movq %rcx, %rax addq %rsi, %rax adcq %rdi, %rdx shrdq $1, %rdx, %rax ret
- rep_lodsb 4y agoBut all of these use a bit shift instead of the (I)DIV instruction. I wasn't saying compilers can't be stupid, but the AI-generated comment explicitly stated that the shift operation was more efficient than division, not that it would result in fewer instructions emitted. midpoint_rep_lodsb_handwritten: endbr64 movq $0x8000000000000000, %rax xorq %rax, %rsi ;convert two's complement to biased xorq %rax, %rdi addq %rsi, %rdi rcrq $1, %rdi xorq %rdi, %rax ;convert back ret (sorry if I got the syntax wrong, AT&T is just horrible)