Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-

long doubles

Name: Anonymous 2011-08-13 11:42


int main(void)
{
    long double test = 1;
    test <<= 1E1L;
    return 0;
}

test@test:~/test$ gcc -ansi -pedantic -Wall -O0 -o test test.c
test.c: In function ‘main’:
test.c:35:7: error: invalid operands to binary << (have ‘long double’ and ‘long double’)


So there is no way I can bit-shift the damn long double's?

Name: Anonymous 2011-08-13 11:46

How the fuck do you want a bitshit of a float to work?

Name: Anonymous 2011-08-13 11:53

>>2
I just want to see if it's possible to use long double as bit array. On my machine the representation of a long double is 128 bits and I have a program that uses bit arrays. So is it possible?

Enlighten me C wizards.

Name: Anonymous 2011-08-13 11:59

>>3
This is ridiculous. Most FPU don't support bitshifts and yours most likely doesn't. You can do vectorized bitshifts with SSE, though.

Name: Anonymous 2011-08-13 13:14

check out ma long doubles

Name: Anonymous 2011-08-13 13:15

Name: Anonymous 2011-08-13 13:20

If the hardware supports it, use assembly or intrinsics (if available). C only supports the things defined by the C language.

Name: Anonymous 2011-08-13 13:31

Ha ha! I thought of this.

union loldouble {
    struct{
        unsigned long int a;
        unsigned long int b;
    } c;
    long double d;
} l_dbl;
l_dbl.c.a = 12;
l_dbl.c.b = 13;

printf("the long double value is: %LG\n",l_dbl.d);


Now I can use the damn bit-shifts.

Name: Anonymous 2011-08-13 13:34

>>8
This is buggy and useless.

Name: Anonymous 2011-08-13 14:02

>>9
Elaborate.

Name: Anonymous 2011-08-13 14:03

>>8
This is useless and buggy.

Name: Anonymous 2011-08-13 14:08

>>10
What you're doing with the union is undefined behaviour, but you probably don't care. Also, there really isn't any point in writing the halves of a 128-bits float independently.

Name: (loop (print (eval (read)))) 2011-08-13 14:12

(loop (print (eval (read))))
Fuck your shit language.

Name: Anonymous 2011-08-13 14:46

>>12
So structs in unions are ill defined? Fuck. Where the fuck does it say that in the ANSI standard?

Name: Anonymous 2011-08-13 15:02

You can use an unsigned char array to do bitshifts in conformance with the standard but that does not mean you can evaluate the double variable again, because the bit representation might be undefined. Search your documentation for the macro __STDC_IEC_559__ and I hope you understand IEEE-754.

Name: Anonymous 2011-08-13 15:10

>>8
If you're trying to take advantage of your architecture's extra-long floating-point registers that's a fucking fail on so many levels. Two things you want to avoid is writing the value out to memory, and manipulating the values using the integer instructions (in integer registers).

You're a long way off from attempting any kinds of architecture-specific optimizations. You're not even ready to crawl, stuck in the shitting-your-pants phase.

Name: Anonymous 2011-08-13 15:30

>>16
I see you are not stuck in the shitting-your-pants phase :), so how would you press more juice out of this (architecture-specific of course and the architecture is AMD64):


unsigned long int *eratosthenes_sieve(const unsigned long int n)
{
    unsigned long int *sieve = NULL;
    register unsigned long int i, j, k;
    register const unsigned long int init_int = 0525252525252525252523;
    register const unsigned long int even_int = 0525252525252525252525;
    register const size_t bit_size = sizeof(*sieve)*8;
    register const size_t arr_size = (((n/bit_size)+1));
   
        sieve = malloc(sizeof(*sieve)*(((n/bit_size)+1)));
    if (sieve == NULL)
            return NULL;

    *sieve = init_int;
    for (i = 1; i < arr_size; ++i)
        *(sieve+i) |= even_int;

    for (i = 3, j = 0; pow(i,2) <= n; i += 2) {
        j = ((i%bit_size)-1 == 0? j+1 : j);
        if ((j < arr_size) && (((*(sieve+j)) & (1LU << (i%bit_size))) == 0)) {
            for (k = 2*i; k <= n; k += i)
                *(sieve+(k/bit_size)) |= (1LU << (k%bit_size));
        }
    }

    return sieve;
}

Name: Anonymous 2011-08-13 15:41

>>17
The author of this code obviously doesn't know of the array addressing operator.

Name: Anonymous 2011-08-13 15:50

>>18
From the K&R:
"5.3 Pointers and Arrays

In C, there is a strong relationship between pointers and arrays, strong enough that pointers
and arrays should be discussed simultaneously. Any operation that can be achieved by array
subscripting can also be done with pointers. The pointer version will in general be faster but,
at least to the uninitiated, somewhat harder to understand."

Name: Anonymous 2011-08-13 15:58

>>19
Try to understand that paragraph and see how it doesn't apply here.

Name: Anonymous 2011-08-13 16:02

>>19
I'm >>20 and what I'm saying is, instead of f(&p); you'd need to do q = f(p); which would double the memory use. That's what K&R mean when they say pointers are faster than arrays.

Name: n3n7i 2011-08-13 22:26

If it's a bit-shift upwards.... and your not using the top couple of bits .... X<<1 = X + X

EG 1X = 0010101011110
EG 2X = 0101010111100

...Though probably not without int precision?? =.

Name: Anonymous 2011-08-14 0:11

As >>4-san already mentioned, you want to use SSE, Altivec, NEON, or whatever SIMD instruction set you have at your disposal. It will be faster than trying to hack it using regular SISD arithmetic instructions and union casts by a factor of 4 or more. Most SIMD pipelines also support integer instructions, including bitwise operators, shifts, and basic integer arithmetic. Generally, you have 128-bit types to work with, but newer SIMD architectures are moving to 256-bit, 512-bit, and even 1024-bit SIMD types.

// Compile with $ gcc/clang -msse2 on x86/x86-64. Following code also works in MSVC++ and Intel C++.

#include <immintrin.h>

int main() {
   __m128i test = _mm_set_epi32(0, 0, 0, 1); // 128-bits, fuck my anus
   test = _mm_slli_si128(test, 1); // shift-left logical 1 bit
   return 0;
}


You can't rely on long double being 128-bits. On x86/x86-64 it's actually only 80-bits, but gets padded/aligned to 128-bits. The top 48-bits are unused and most likely get zero'd by the compiler and you wouldn't be able to use it to reliably store data. Furthermore, both Intel C++ and MSVC++ just make long double be an alias for double anyway, so it's 64-bits with those compilers, as the x87 FPU has been deprecated anyway in favor of SSE/AVX. This is fully standard compliant too, the C and C++ language standards make no guarantees as to the size or precise binary format of long double. On other platforms without double-precision, like some game consoles with custom MIPS RISC or Power processors, both double and long-double are in fact aliases for 32-bit floats.

Name: Anonymous 2011-08-14 0:25

>>23
Also, forgot to mention that GCC, Clang, MSVC++, and Intel C++ support a new __int128 type, and C1x is adding int128_t, int_least128_t, and int_fast128_t to stdint.h.

For most CPU architectures, the compiler will generate sequences of regular 32-bit or 64-bit integer instructions or possibly generate SIMD instructions depending on how good it is at optimizing stuff.

http://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html

int main() {
    __int128 test = 1;
    test <<= 1;
    return 0;
}

Name: Anonymous 2011-08-14 2:10

int128_t? What's next, bigint_t?

Don't change these.
Name: Email:
Entire Thread Thread List