Page 1 of 2

Is there consensus on a 128-bit type?

Posted: Sat Dec 30, 2006 2:33 am
by Candy
I was trying to start implementing my time keeping code and as I've said before, I'd like it to be a 128-bit time value. For returning it from the kernel, I need some form of transportation, but afaik there's no 128-bit type that you can use/abuse for that. Is there a default name for a 128-bit type?

I thought it might be "long long long", but that's just silly.

Re: Is there consensus on a 128-bit type?

Posted: Sat Dec 30, 2006 2:50 am
by Brendan
Hi,
Candy wrote:I was trying to start implementing my time keeping code and as I've said before, I'd like it to be a 128-bit time value. For returning it from the kernel, I need some form of transportation, but afaik there's no 128-bit type that you can use/abuse for that. Is there a default name for a 128-bit type?
I'm not too sure, but could you use the "time_t" type for this?

From the manual for the GCC library:

"In the GNU C library, time_t is equivalent to long int. In other systems, time_t might be either an integer or floating-point type."

It seems "time_t" is designed as a "system specific" data type (hence functions like "difftime()"), and this could make it easier if you ever want to port software from elsewhere...


Cheers,

Brendan

Re: Is there consensus on a 128-bit type?

Posted: Sat Dec 30, 2006 2:54 am
by Candy
Brendan wrote:
Candy wrote:I was trying to start implementing my time keeping code and as I've said before, I'd like it to be a 128-bit time value. For returning it from the kernel, I need some form of transportation, but afaik there's no 128-bit type that you can use/abuse for that. Is there a default name for a 128-bit type?
I'm not too sure, but could you use the "time_t" type for this?

From the manual for the GCC library:

"In the GNU C library, time_t is equivalent to long int. In other systems, time_t might be either an integer or floating-point type."

It seems "time_t" is designed as a "system specific" data type (hence functions like "difftime()"), and this could make it easier if you ever want to port software from elsewhere...

Code: Select all

// start timer that gives indications on given key
timer_t timer_start(const time_t *start_time, const time_t *interval, bool recurring,!
// start timer like above, implicit: start_time == NOW
timer_t timer_start(const time_t *interval, bool recurring, msgkey_t key);
// stop timer that is either recurring or hasn't expired yet
void    timer_stop(timer_t timer);
I picked it already but I don't know exactly what to define it as. I've used it as a pointer to *something* now, so I can make it a struct if necessary. If not, I might change it back to stack parameters.

The time_t you're reading is in a specific design though (I think posix / ansi C), I'm aiming at a generic kind of type (language type, not library type).

It's pretty evil to document what your system does and what all the others will do. That's pretty much enforcing your will on everybody. I have seen that kind of thinking with GNU before though...

Posted: Sat Dec 30, 2006 6:43 am
by Ready4Dis
In my OS I have a types header that I can include from all my C programs, basically it defines types like this:

typedef unsigned char u8;
typedef signed char s8;
typedef unsigned char u16;
typedef signed char s16;


etc, etc until however many bits I want. That way, when I switch platforms I can change this header file and bam, I know what size every data type is without worrying about it. For a 128-bit integer, I would just make a struct that has 2 64-bit integers, low and high parts. I don't know of a pre-existing type that isn't specific to one compiler, sorry.

typedef struct
{
unsigned long long low;
unsigned long long high;
} u128;

Only problem is, now you have to create your own functions (I would use overloaded +/-,/,*, etc if your compiler supports it) to do arithmetic operations on this type if required.

Posted: Sat Dec 30, 2006 7:09 am
by Brendan
Hi,
Ready4Dis wrote:In my OS I have a types header that I can include from all my C programs, basically it defines types like this:

typedef unsigned char u8;
typedef signed char s8;
typedef unsigned char u16;
typedef signed char s16;


etc, etc until however many bits I want. That way, when I switch platforms I can change this header file and bam, I know what size every data type is without worrying about it. For a 128-bit integer, I would just make a struct that has 2 64-bit integers, low and high parts. I don't know of a pre-existing type that isn't specific to one compiler, sorry.
I tend to do the same thing, in an attempt to write half-portable code... ;)

There are standard (POSIX?) types with fixed sizes (try "#include <sys/types.h>"). Unfortunately the people who decided on these types were as short-sighted as most of the industry, and didn't define anything larger than "u_int64_t" and "int64_t".

AFAIK they also didn't bother defining anything suitable for formatted output either. Consider something like this:

Code: Select all

    u_int32_t foo = 12345678;

    printf("foo = %u\n", foo);
In this case, "printf" will expect an "int" (which isn't necessarily 32-bit). To do portable code you'd need to use the largest type (e.g. "printf("foo = %Lu\n", foo)") , which is fairly silly if an int actually is 32-bit.


Cheers,

Brendan

Posted: Sat Dec 30, 2006 7:29 am
by Ready4Dis
I know what you mean, printf is great, but not perfect, that is why C++ added streams with cout and cin, you pass it the variable and it automagically calls that types display function, you can even make your own types and be good to go with some overloaded functions. You can't really modify printf (I mean, you could and change it to things like %u16, %u32, etc), because that would/could break pre-existing code, and would make compiling other codes to your OS a pain, especially something for the console ;). Maybe another function similar to printf that is more specific, but then that's just something else for someone trying to program for your OS to learn. It's a lose lose situation really. My OS always assumes 32-bit integers with printf, because when you call a C function with a variable number of arguments, it passes each argument as a 32-bit number (or so I am under the impression, but haven't played with it all that much yet).

Posted: Sat Dec 30, 2006 7:34 am
by Candy
Ready4Dis wrote:In my OS I have a types header that I can include from all my C programs, basically it defines types like this:

typedef unsigned char u8;
typedef signed char s8;
typedef unsigned char u16;
typedef signed char s16;


etc, etc until however many bits I want. That way, when I switch platforms I can change this header file and bam, I know what size every data type is without worrying about it. For a 128-bit integer, I would just make a struct that has 2 64-bit integers, low and high parts. I don't know of a pre-existing type that isn't specific to one compiler, sorry.

typedef struct
{
unsigned long long low;
unsigned long long high;
} u128;

Only problem is, now you have to create your own functions (I would use overloaded +/-,/,*, etc if your compiler supports it) to do arithmetic operations on this type if required.
Got the same definitions, but named after the standard type of the given size, so uint32_t etc. I was wondering how to typedef uint128_t so I thought I'd ask :). Using overloaded functions isn't the best option, trying to use as little c++ as possible in the kernel (only for minor supporting things where it makes a big difference... this might become one).

Posted: Sat Dec 30, 2006 7:35 am
by Candy
Ready4Dis wrote:I know what you mean, printf is great, but not perfect, that is why C++ added streams with cout and cin, you pass it the variable and it automagically calls that types display function, you can even make your own types and be good to go with some overloaded functions. You can't really modify printf (I mean, you could and change it to things like %u16, %u32, etc), because that would/could break pre-existing code, and would make compiling other codes to your OS a pain, especially something for the console ;). Maybe another function similar to printf that is more specific, but then that's just something else for someone trying to program for your OS to learn. It's a lose lose situation really. My OS always assumes 32-bit integers with printf, because when you call a C function with a variable number of arguments, it passes each argument as a 32-bit number (or so I am under the impression, but haven't played with it all that much yet).
You can use variadic templates for printf, which does make printf aware of the actual type the parameter had. It's not in C++ yet though, but you can download a patch to add it to gcc. That allows you to use %d and %u for all integer types irrespective of their size.

Posted: Sat Dec 30, 2006 8:48 am
by Ready4Dis
Candy wrote: Got the same definitions, but named after the standard type of the given size, so uint32_t etc. I was wondering how to typedef uint128_t so I thought I'd ask :). Using overloaded functions isn't the best option, trying to use as little c++ as possible in the kernel (only for minor supporting things where it makes a big difference... this might become one).
Yeah, that'd probably make more sense to use those, lol, i can always change it with a search and replace before I get to far along in my re-write. Anyways, I don't think the C library defines any default data types for 128-bit, but you can however add them to your kernel's C library if you'd like. I know you can use MMX and other operations to perform 128-bit opertions in a single instruction, but that would make your minimum requirements a pentium 166+ mmx :P. Another option is to get the compiler sources, and recompile it with supporting 128-bit functionality, wouldn't be to hard to make a 128-bit data type, very similar to the 64-bit data type i'd presume, since there is no default 64-bit data type on an x86 CPU (without extensions that is!)

Posted: Sat Dec 30, 2006 8:56 am
by Candy
Ready4Dis wrote:
Candy wrote: Got the same definitions, but named after the standard type of the given size, so uint32_t etc. I was wondering how to typedef uint128_t so I thought I'd ask :). Using overloaded functions isn't the best option, trying to use as little c++ as possible in the kernel (only for minor supporting things where it makes a big difference... this might become one).
Yeah, that'd probably make more sense to use those, lol, i can always change it with a search and replace before I get to far along in my re-write. Anyways, I don't think the C library defines any default data types for 128-bit, but you can however add them to your kernel's C library if you'd like. I know you can use MMX and other operations to perform 128-bit opertions in a single instruction, but that would make your minimum requirements a pentium 166+ mmx :P. Another option is to get the compiler sources, and recompile it with supporting 128-bit functionality, wouldn't be to hard to make a 128-bit data type, very similar to the 64-bit data type i'd presume, since there is no default 64-bit data type on an x86 CPU (without extensions that is!)
Actually, I'm aiming at a minimum of a 64-bit machine, so that's a pretty good idea. Adding a 128-bit type is even a pretty good idea, but I'm not sure it won't be a lot of work, since you would also have to add 128-bit multiply etc. to your libcc (libgcc). I'm modifying the setup again so it's changing a lot anyway :) Patching the compiler is ok, got the compiler compile script setup to do that already (for having both concept-gcc + x86_64-pc-elf).

Posted: Sat Dec 30, 2006 9:19 am
by Ready4Dis
Candy wrote:
Ready4Dis wrote:
Candy wrote: Got the same definitions, but named after the standard type of the given size, so uint32_t etc. I was wondering how to typedef uint128_t so I thought I'd ask :). Using overloaded functions isn't the best option, trying to use as little c++ as possible in the kernel (only for minor supporting things where it makes a big difference... this might become one).
Yeah, that'd probably make more sense to use those, lol, i can always change it with a search and replace before I get to far along in my re-write. Anyways, I don't think the C library defines any default data types for 128-bit, but you can however add them to your kernel's C library if you'd like. I know you can use MMX and other operations to perform 128-bit opertions in a single instruction, but that would make your minimum requirements a pentium 166+ mmx :P. Another option is to get the compiler sources, and recompile it with supporting 128-bit functionality, wouldn't be to hard to make a 128-bit data type, very similar to the 64-bit data type i'd presume, since there is no default 64-bit data type on an x86 CPU (without extensions that is!)
Actually, I'm aiming at a minimum of a 64-bit machine, so that's a pretty good idea. Adding a 128-bit type is even a pretty good idea, but I'm not sure it won't be a lot of work, since you would also have to add 128-bit multiply etc. to your libcc (libgcc). I'm modifying the setup again so it's changing a lot anyway :) Patching the compiler is ok, got the compiler compile script setup to do that already (for having both concept-gcc + x86_64-pc-elf).
Well, that works then, lol. Look into SSE, you will notice a lot of 128-bit registers, very simple to create 128-bit functions that way. For example, the PIII has 8 128-bit SIMD registers. Older athlons use3d now, which is very similar, but if you intend to support only 64-bit cpu's, i would stick with SSE,because both amd and intel support sse ;).

Posted: Sun Dec 31, 2006 4:45 am
by Candy
Ready4Dis wrote:
Candy wrote:
Ready4Dis wrote: Yeah, that'd probably make more sense to use those, lol, i can always change it with a search and replace before I get to far along in my re-write. Anyways, I don't think the C library defines any default data types for 128-bit, but you can however add them to your kernel's C library if you'd like. I know you can use MMX and other operations to perform 128-bit opertions in a single instruction, but that would make your minimum requirements a pentium 166+ mmx :P. Another option is to get the compiler sources, and recompile it with supporting 128-bit functionality, wouldn't be to hard to make a 128-bit data type, very similar to the 64-bit data type i'd presume, since there is no default 64-bit data type on an x86 CPU (without extensions that is!)
Actually, I'm aiming at a minimum of a 64-bit machine, so that's a pretty good idea. Adding a 128-bit type is even a pretty good idea, but I'm not sure it won't be a lot of work, since you would also have to add 128-bit multiply etc. to your libcc (libgcc). I'm modifying the setup again so it's changing a lot anyway :) Patching the compiler is ok, got the compiler compile script setup to do that already (for having both concept-gcc + x86_64-pc-elf).
Well, that works then, lol. Look into SSE, you will notice a lot of 128-bit registers, very simple to create 128-bit functions that way. For example, the PIII has 8 128-bit SIMD registers. Older athlons use3d now, which is very similar, but if you intend to support only 64-bit cpu's, i would stick with SSE,because both amd and intel support sse ;).
You can't use them for a 128*128 multiply though, they're only for vector data. So yes, you can load them and with a bit of hacking you can get them to add and substract, but you can't get them to multiply and divide. For add/substract, I can tell an 8086 how to do that with 128-bit numbers.

I was going for SSE, not because I think it's better or anything, but because my 64-bit cpu is an intel one (cheapest 64-bit dualcore available at the time).

Posted: Sun Dec 31, 2006 2:43 pm
by Ready4Dis
I have not done much as far as SSE, so was not sure exactly what it had support for. You could write some functions to handle 128-bit numbers by splitting it into smaller sections, will be a tad slow i'm afraid, but how much math will be done on those types normally?

Posted: Mon Jan 01, 2007 6:24 am
by Solar
The C standard explicitly reserves int*_t and uint*_t in <stdint.h>, and all lowercase conversion specifiers / length modifiers in <stdio.h> / printf() / scanf().

Since it is very hard to imagine that int128_t or uint128_t are used for anything but a 128 bit integer type, to be really generic, I would tweak the library to accept int128_t and uint128_t, and add an uppercase length modifier to the I/O functions (like e.g. the already-existing "%zd" for integers of size size_t).

If you want that integer to be used natively (i.e., addition with + etc.), your compiler will have to support them too. Perhaps this post to [email protected] gets you on the right track; note it's already years old, so things may have changed.

Re: Is there consensus on a 128-bit type?

Posted: Thu Jan 04, 2007 2:42 am
by B.E
Candy wrote:I was trying to start implementing my time keeping code and as I've said before, I'd like it to be a 128-bit time value. For returning it from the kernel, I need some form of transportation, but afaik there's no 128-bit type that you can use/abuse for that. Is there a default name for a 128-bit type?

I thought it might be "long long long", but that's just silly.
Just a question as to y you need a 128-bit integer for time:

I mean that if you were to use it to the nearest second, it would take about

(2^128)/ 60/ 60/ 24 / 365 = 1.07902831 × 10^31

Years to overflow. you really got to think will your OS be used for that long (will the world last that long).