As per c99 standard, size of long long should be minimum 64 bits. How is this implemented in a 32 bit machine (eg. addition or multiplication of 2 long longs). Also, What is the equivalent of long long in C++.
The equivalent in C++ is long long as well. It's not required by the standard, but most compilers support it because it's so usefull.
How is it implemented? Most computer architectures already have built-in support for multi-word additions and subtractions. They don't do 64 bit addititions directly but use the carry flag and a special add-instruction to build a 64 bit add from two 32 bit adds.
The same extension exists for subtraction as well (the carry is called borrow in these cases).
Longword multiplications and divisions can be built from smaller multiplications without the help of carry-flags. Sometimes simply doing the operations bit by bit is faster though.
There are architectures that don't have any flags at all (some DSP chips and simple micros). On these architectures the overflow has to be detected with logic operations. Multi-word arithmetic tend to be slow on these machines.
On the IA32 architecture, 64-bit integer are implemented in using two 32-bit registers (eax and edx).
There are platform specific equivalents for C++, and you can use the stdint.h header where available (boost provides you with one).
As everyone has stated, a 64-bit integer is typically implemented by simply using two 32-bit integers together. Then clever code generation is used to keep track of the carry and/or borrow bits to keep track of overflow, and adjust accordingly.
This of course makes such arithmetic more costly in terms of code space and execution time, than the same code compiled for an architecture with native support for 64-bit operations.
If you care about bit-sizes, you should use
#include <stdint.h>
int32_t n;
and friends. This works for C++ as well.
64-bit numbers on 32-bit machines are implemented as you think,
by 4 extra bytes. You could therefore implement your own 64-bit
datatype by doing something like this:
struct my_64bit_integer {
uint32_t low;
uint32_t high;
};
You would of course have to implement mathematical operators yourself.
There is an int64_t in the stdint.h that comes with my GCC version,
and in Microsoft Visual C++ you have an __int64 type as well.
The next C++ standard (due 2009, or maybe 2010), is slated to include the "long long" type. As mentioned earlier, it's already in common use.
The implementation is up to the compiler writers, although computers have always supported multiple precision operations. Some languages, like Python and Common Lisp, require support for indefinite-precision integers. Long ago, I wrote 64-bit multiplication and division routines for a computer (the Z80) that could manage 16-bit addition and subtraction, with no hardware multiplication at all.
Probably the easiest way to see how an operation is implemented on your particular compiler is to write a code sample and examine the assembler output, which is available from all the major compilers I've worked with.
Related
I intend to use half-precision floating-point in my code but I am not able to figure out how to declare them. For Example, I want to do something like the following-
fp16 a_fp16;
bfloat a_bfloat;
However, the compiler does not seem to know these types (fp16 and bfloat are just dummy types, for demonstration purposes)
I remember reading that bfloat support was added into GCC-10, but I am not able to find it in the manual.I am especially interested in bfloat floating numbers
Additional Questions -
FP16 now has hardware support on Intel / AMD support as today? I think native hardware support was added since Ivy Bridge itself. (https://scicomp.stackexchange.com/questions/35187/is-half-precision-supported-by-modern-architecture)
I wanted to confirm whether using FP16 will indeed increase FLOPs. I remember reading somewhere that all arithmetic operations on fp16 are internally converted to fp32 first, and only affect cache footprint and bandwidth.
SIMD intrinsic support for half precision float, especially bfloat(I am aware of intrinsics like _mm256_mul_ph, but not sure how to pass the 16bit FP datatype, would really appreciate if someone could highlight this too)
Are these types added to Intel Compilers as well ?
PS - Related Post - Half-precision floating-point arithmetic on Intel chips , but it does not cover on declaring half precision floating point numbers.
TIA
Neither C++ nor C language has arithmetic types for half floats.
The GCC compiler supports half floats as a language extension. Quote from the documentation:
On x86 targets with SSE2 enabled, GCC supports half-precision (16-bit) floating point via the _Float16 type. For C++, x86 provides a builtin type named _Float16 which contains same data format as C.
...
On x86 targets with SSE2 enabled, without -mavx512fp16, all operations will be emulated by software emulation and the float instructions. The default behavior for FLT_EVAL_METHOD is to keep the intermediate result of the operation as 32-bit precision. This may lead to inconsistent behavior between software emulation and AVX512-FP16 instructions. Using -fexcess-precision=16 will force round back after each operation.
Using -mavx512fp16 will generate AVX512-FP16 instructions instead of software emulation. The default behavior of FLT_EVAL_METHOD is to round after each operation. The same is true with -fexcess-precision=standard and -mfpmath=sse. If there is no -mfpmath=sse, -fexcess-precision=standard alone does the same thing as before, It is useful for code that does not have _Float16 and runs on the x87 FPU.
I'm trying to convert a byte array to and from a Boost number with the cpp_int backend. What is a portable way to do this?
The platforms I'm concerned about are all little endian, but can be 32 or 64 bit and can be compiled with different compilers. Some of the ways I've seen to do this break depending on compiler versions and such, and that's what I want to avoid.
The only real difference between x86 and x64 is the size of pointers. So unless it relies on the size of pointers somehow, there shouldn't be much of a problem. Especially since a byte is always 8bits and you already ruled out endiannes problems.
I am working on project (c++ integration with Python) which has migrated to 32 bit machine to 64 bit machine. In Python, C long is mapped with Python Integer.
SO I can not change in Python Interface(client interface) and always gets overflow error from python client. it was working fine in 32 bit machine
So I have following solution
1)convert all long to int in 64 bit machine.
2)Declare 32 bit long in 64 bit machine.
Do we have any general solution/header file which give me option to declare 32 bit
datatype always So I can handle this issue in more general way.
I know it may be small issue but I am not able to find general solution.
Do we have any general solution/header file which give me option to declare 32 bit datatype always?
Yes, there is, since C99.
#include <stdint.h>
uint32_t foo;
standard C99 (and newer) has <stdint.h> header defining int32_t for 32 bits signed integers (and many other types) and recent C++ have <cstdint>
If you care about bignums (arbitrary precision numbers), be aware that it is a difficult subject and use some existing library, like GMP.
I want to implement a hashmap into my code, so I decided to stick to murmurhash3
I currently only deliver my programs compiled for x86 and have tried to keep the code general so I've never had trouble running the programs on x64.
Now I've looked at the header files of murmurhash and the library offers following functions:
MurmurHash3_x86_32
MurmurHash3_x86_64
MurmurHash3_x86_128
MurmurHash3_x64_32
MurmurHash3_x64_64
MurmurHash3_x64_128
Does this mean I have to use the x64 functions and provide a x64 executable to be able to use this hash library on x64 systems? Or can I simply use the x86 version, and just encounter poorer performance?
Am I correct in thinking that the _32 _64 _128 bit versions only mean that more bit versions offer better distribution?
Edit: Changed everything after looking at the murmurhash3 documentation.
First, the _x86 variants are portable hash algorithms. The _32/_64/_128 indicates the width of the hash in bits. Generally _32 should be fine as long as your hash algorithm is smaller than 232 buckets.
The _x64 variants are an entirely different family of hash algorithms. All the _x64 variants are based on the _x64_128 implementation - a 128-bit hash. They then throw away part of the hash to get the _32 and _64 bit sizes. This may or may not be faster than the _x86 variant - the documentation claims some impressive speedups, though. Note, however, that it's very likely to get different hash values than the x86 variant.
x86 indicates that the algorithm is optimized for 32-bit platforms. This means it operates on 32-bit unsigned integers.
x64 is then optimized for 64-bit platforms, operating on 64-bit unsigned integers.
Also, the results between the two are not compatible. The hash values for the same input will be different depending if it is MurmurHash3_x86_128 or MurmurHash3_x64_128 for example.
Does this mean I have to use the x64 functions and provide a x64 executable to be able to use this hash library on x64 systems? Or can I simply use the x86 version, and just encounter poorer performance?
64-bit hash functions can be compiled for 32-bit systems but will end up being quite slow because the compiler splits computations into two parts. If 32-bit support is important, you should use a x86-optimized function, not a x64-optimized one. On x64 systems 32-bit code runs fine, although I would consider that to be an under-utilization. x64-optimized algorithms are much more efficient when on 64-bit CPUs.
Am I correct in thinking that the _32 _64 _128 bit versions only mean that more bit versions offer better distribution?
I suppose the answer is yes. If by distribution you mean "less likely to cause collisions". Each additional bit of memory used in a hash dramatically increases the number of possible outcomes. A 4-bit hash has 16 possible hashes, while 64 provides 18 quintillion (128 then providing 340.2 undecillion!). 256 bits provide so much that it is often enough for cryptographic security purposes.
Something else to be aware of: Lately, modern hash functions utilize new instruction sets of CPUs such as CRC32, AES, SSE2, SIMD - where the function takes advantage of specific CPU features/instructions to achieve better performance under supported hardware. This can greatly speed up hashing on CPUs that support these modern features.
It's common practice where I work to avoid directly using built-in types and instead include a standardtypes.h that has items like:
// \Common\standardtypes.h
typedef double Float64_T;
typedef int SInt32_T;
Almost all components and source files become dependent on this header, but some people argue that it's needed to abstract the size of the types (in practice this hasn't been needed).
Is this a good practice (especially in large-componentized systems)? Are there better alternatives? Or should the built-in types be used directly?
You can use the standardized versions available in modern C and C++ implementations in the header file: stdint.h
It has types of the like: uint8_t, int32_t, etc.
In general this is a good way to protect code against platform dependency. Even if you haven't experienced a need for it to date, it certainly makes the code easier to interpret since one doesn't need to guess a storage size as you would for 'int' or 'long' which will vary in size with platform.
It would probably be better to use the standard POSIX types defined in stdint.h et al, e.g. uint8_t, int32_t, etc. I'm not sure if there are part of C++ yet but they are in C99.
Since it hasn't been said yet, and even though you've already accepted an answer:
Only used concretely-sized types when you need concretely sized types. Mostly, this means when you're persisting data, if you're directly interacting with hardware, or using some other code (e.g. a network stack) that expects concretely-sized types. Most of the time, you should just use the abstractly-sized types so that your compiler can optimize more intelligently and so that future readers of your code aren't burdened with useless details (like the size and signedness of a loop counter).
(As several other responses have said, use stdint.h, not something homebrew, when writing new code and not interfacing with the old.)
The biggest problem with this approach is that so many developers do it that if you use a third-party library you are likely to end up with a symbol name conflict, or multiple names for the same types. It would be wise where necessary to stick to the standard implementation provided by C99's stdint.h.
If your compiler does not provide this header (as for example VC++), then create one that conforms to that standard. One for VC++ for example can be found at https://github.com/chemeris/msinttypes/blob/master/stdint.h
In your example I can see little point for defining size specific floating-point types, since these are usually tightly coupled to the FP hardware of the target and the representation used. Also the range and precision of a floating point value is determined by the combination of exponent width and significant width, so the overall width alone does not tell you much, or guarantee compatibility across platforms. With respect to single and double precision, there is far less variability across platforms, most of which use IEEE-754 representations. On some 8 bit compilers float and double are both 32-bit, while long double on x86 GCC is 80 bits, but only 64 bits in VC++. The x86 FPU supports 80 bits in hardware (2).
I think it's not a good practice. Good practice is to use something like uint32_t where you really need 32-bit unsigned integer and if you don't need a particular range use just unsigned.
It might matter if you are making cross-platform code, where the size of native types can vary from system to system. For example, the wchar_t type can vary from 8 bits to 32 bits, depending on the system.
Personally, however, I don't think the approach you describe is as practical as its proponents may suggest. I would not use that approach, even for a cross-platform system. For example, I'd rather build my system to use wchar_t directly, and simply write the code with an awareness that the size of wchar_t will vary depending on platform. I believe that is FAR more valuable.
As others have said, use the standard types as defined in stdint.h. I disagree with those who say to only use them in some places. That works okay when you work with a single processor. But when you have a project which uses multiple processor types (e.g. ARM, PIC, 8051, DSP) (which is not uncommon in embedded projects) keeping track of what an int means or being able to copy code from one processor to the other almost requires you to use fixed size type definitions.
At least it is required for me, since in the last six months I worked on 8051, PIC18, PIC32, ARM, and x86 code for various projects and I can't keep track of all the differences without screwing up somewhere.