Is there consensus on a 128-bit type?
Is there consensus on a 128-bit type?
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.
I thought it might be "long long long", but that's just silly.
Re: Is there consensus on a 128-bit type?
Hi,
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
I'm not too sure, but could you use the "time_t" type for this?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?
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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: Is there consensus on a 128-bit type?
Brendan wrote:I'm not too sure, but could you use the "time_t" type for this?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?
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);
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...
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.
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.
Hi,
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:
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
I tend to do the same thing, in an attempt to write half-portable code...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.
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);
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
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).
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).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.
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.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).
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 . 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!)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).
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).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 . 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!)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).
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 .Candy wrote: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).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 . 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!)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).
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.Ready4Dis wrote: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 .Candy wrote: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).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 . 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!)
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).
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.
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.
Every good solution is obvious once you've found it.
Re: Is there consensus on a 128-bit type?
Just a question as to y you need a 128-bit integer for time: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.
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).
Microsoft: "let everyone run after us. We'll just INNOV~1"