What is the maximum value of Nat64, Nat32, Nat16, Nat8, Int64, Int32, Int16, and Int8?

What is the maximum value of Nat64, Nat32, Nat16, Nat8, Int64, Int32, Int16, and Int8?

1 Like

2^64-1, 2^32-1, 2^16-1, 2^8-1, 2^63-1, 2^31-1, 2^15-1, 2^7-1.

But note that there are very few reasons to use them. The main ones are algorithms requiring bit fiddling (e.g., crypto, compression), or matching an external interface or data structure using them. In almost all other cases you are better off with Nat or Int (safer, typically requiring less memory, often even faster).

7 Likes

Can you also tell me one more thing, what can be the maximum size of Trie or Hashmaps Data Structures ? Is there any limit ? or they just depend on size of Canister (limited upto 4gb?)

Oh, I didn’t know Nat may require less memory AND be faster than NatX… Why is that exactly?

Guess I need to refactor my code now.

1 Like

They just depend on the size of the canister. But actually due to serialization, garbage collection, and other considerations, the available memory is probably closer to 3 GB, I believe. Hopefully that is temporary.

1 Like

I noticed that you can’t use a Nat as a key in a TrieMap because the Hash.hash function seems to be limited to Nat32. Is there any way around that?

When I try to do it the error I get is “canister trapped explicitly, losing precision”

Use something like the following as your hash function(actually hard code the number for fewer cycles)

func(a:Nat){Nat32.fromNat(a%(2^32 -1))};

Also see: Hash Collisions

oh nice thanks, yeah I was going to use Text.hash but this solution seems better. I just hope we do get 64 bit hashes at some point.

That Hash.hash function is buggy and should be fixed (See issue Possible bug: Hash.hash(i : Nat) will trap if i >= 2^32 · Issue #345 · dfinity/motoko-base · GitHub)

You could use

  /// Conversion. Wraps on overflow/underflow.
 Nat.fromIntWrap : Int -> Nat32;

Which won’t trap but won’t hash large numbers very well either (since it ignores all but the least significant 32 bits).

Note that you can apply Nat.fromIntWrap(n) to a Nat, n, by virtue of subtyping since Nat <: Int.

1 Like

I use @quint’s crypto library and Candy to get a 256 bit crypto secure hash like the below.

import Conversion "mo:candy/conversion";
import SHA256 "mo:crypto/SHA/SHA256";

SHA256.sum(CandyConversion.valuetoBytes(#Nat(a));

You may want to add a namespace into it depending on your use case. For that I use the .write() API endpoint.

        let h = SHA256.New();
        h.write(Conversion.valueToBytes(#Nat32(Text.hash("com.yourapp"))));
        h.write(Conversion.valueToBytes(#Nat(a);
        h.sum([]);

I had one issue with the crypto library where if I wrote a strange number of bytes it would throw. I think you have to have a mod(4) bytes…it would be nice if the crypto library had a padWriteLittleEndian() that would make sure a proper number of bytes get written. :slight_smile: