[1] https://www.forth.com/starting-forth/5-fixed-point-arithmeti...
It also is a lot less of a concern on modern systems, where floating point operations aren't much slower than integer ones.
At least on x86-64, the 64x64->128 bit multiplication is a single instruction, like the 32x32->64 bit and the 16x16->32 bit multiplications. Doing the calculation with only three limbs is clearly faster than doing it with five limbs; to start with, using 3 limbs you need 9 multiplies, while with 5 limbs you have to do 25 multiplies. The carry propagation and reduction steps also take time proportional to the number of limbs.
1. I guess having bit mask operations for IPv6 addresses could be useful.
Added: I'm talking about implementing specific, optimized hash functions on 128-bit values (e.g. GUIDs, IPv6 addresses), and not generic hash functions that can take any length input (although many of them speed up linearly in the size of int that gets used internally).
Hashers provide conveniences for feeding in a u8, u16, u32, u64, etc., but most hashers just implement this as casting the value to an array of bytes and using the generic implementation. This is because most algorithms are defined in terms of bytes. Evidently there isn't any interesting optimization to do by statically knowing you have a u32 vs a u64 for these algorithms (appears to be the case for SipHash, XXHash, and Fnv).
And indeed, u128 continues this tradition in the PR: https://github.com/rust-lang/rust/pull/37900/files#diff-2327...
This is the big annoyance in Golang with it's net.IP type - it's `type IP []byte`, which means you can write ip1 == ip2 and you can't pass by value easily, nor use it as a map key.
I've ended up inventing my own type for that a lot of the time as a struct wit static fields, since those you can copy around and do 1:1 comparisons.
Though to be honest I'd be super happy if there was a drop-in varint type, or you could trivially have the compiler calculate instructions for a arbitrary fixed size ints.
Most UUID libraries I've seen and written use [16]byte as the concrete UUID type.
Sorry for the rhetorical device.
type IP []byte
That is not the same as [16]byte. // Note that in this documentation, referring to an
// IP address as an IPv4 address or an IPv6 address
// is a semantic property of the address, not just the
// length of the byte slice: a 16-byte slice can still
// be an IPv4 address.
What I believe that comment is saying is that something that is [16]byte can still be an IPv4 address, but that doesn't mean that all IPv4 addresses are stored as [16]byte. At least that would be my interpretation based on the comment above it: // An IP is a single IP address, a slice of bytes.
// Functions in this package accept either 4-byte (IPv4)
// or 16-byte (IPv6) slices as input.(Maybe you want to foreach over an array every time you want to apply one. I'd rather not.)
In my world integer is a mathematical construct with no particular representation, making things like bitmasks and or shifts nonsensical.
If you really want to work with fixed length bitstrings why not just have a type for that? Operating on a string of 128-bits should be valid on all such bitstrings no matter wether those represent a number or a string of code points.
And equally operations on integers should not care about particular bitstrings representations of the number in question.
Your world doesn't map to the reality of silicon and registers, whereas Rust does. As it happens, you can be fixed much more easily than the whole of modern computing.
> If you really want to work with fixed length bitstrings why not just have a type for that?
I don't. I want to work with integers. An IPv6 address is not the hex format that you read--it is a 128-bit integer. You can go read RFC 2460 if you don't believe me, but it's true. It is an integer that I can add and subtract from; I don't add 1 to an octet of an IP address and then do a bunch of carries if I want the next IP address in my network, I add 1 to the IP address. I don't perform some magic operation to determine what a subnet looks like, I bitand the integer. They are inescapably based on the representation used both by my computer and by my network hardware. (As is the performance of both my network hardware and yours. There's a reason that your router doesn't use BCD or whatever.)
There are programming languages that do not represent the underlying system. They are, for the most part, bad at dealing with the kinds of problems Rust is tailored to effectively represent. You can use those. It's pretty presumptuous to suggest that languages designed for lower-level problems accommodate your peculiarity.
About the only mathematical operations I can think of which are ever done to them are bitwise-anding, bitwise-inclusive-oring, and testing for zero (and, as mentioned, equality).
If you have internalized an IP address as a dotted set of octets expressed in ASCII digits, that's a problem of comprehension. When you don't, it's pretty natural to just use this stuff like any other integer.
It's like saying a pointer to RAM isn't an integer. Of course it is, and you add to them every time you de-reference an array in C. That it has additional semantic meaning doesn't mean it stops being a integer. The pedantry you're peddling doesn't fly.
That is a cool link though, I'm gonna give it a deeper read.
if ip >= IP(10.34.12.3) && ip <= IP(10.34.12.9)
//is one of our database servers
> They are never added, subtracted, if abs(atk1.ip - atk2.ip) < 16
//same source likely, modify threshold
Netmask are useful, but sometimes doing regular math is a better fit for your problem. Adding an integer to an IP, subtracting IPs or comparing IPs all yield meaningful results. ping6 42540577535212633203815888880477462122
Like you can do this: ping 2158835347
PING 2158835347 (128.173.54.147) 56(84) bytes of data.
64 bytes from 128.173.54.147: icmp_seq=1 ttl=52 time=20.4 ms
64 bytes from 128.173.54.147: icmp_seq=2 ttl=52 time=20.5 msI know fortran and Cobol code that banks use and is used for science (tm) often defines numbers this large for certain operations.
One such i can think of is a map reduce of large datasets. Let's say you want to find as a result a huge sum. 2^128 is a bit bigger then 2^64 and that difference may be big enough to provide the computation needed for getting to Mars rather then getting to the moon on 2^8 machines.
I haven't used it, but Julia lets you declare any(?) fixed size bitset. Which would probably come in handy for Go.
It would be much easier for them to just build on top of i128.
Also, you can see that one of the implementations is copied from Cairo, so it seems graphics libraries have some use for 128-bit integers too.
But I don't think rust has support for the Emotion Engine in any case.