# How can I pack two int16 into a single byte32?

I have a contract that makes use of cartesian coordinates. My initial thought is to map a single location (x,y) to a value/struct. I would like to define any given pair of coordinates by a single `byte32` that can be converted back into coordinates. Ex:

``````int16 x, int16 y;
byte32 key = coordinatesToBytes32(x, y);
``````

and vise-versa:

``````[x, y] = bytes32ToCoordinates(key);
``````

After jumping into `solc@^0.5.0` I discovered you can no longer explicitly convert between these types which made it difficult for me to cast, mask, shift, and run bitwise operations. For reference, here is where I made it to (note the solidity version):

``````pragma solidity ^0.4.17;

contract CoordinateUtils {
function coordinatesToBytes32(int16 x, int16 y) internal pure returns(bytes32) {
return (bytes32(x) << 16 & 0xFFFFFFFF) | bytes16(y);  // left shift extends negative so we mask out
}
function bytes32ToCoordinates(bytes32 b) internal pure returns(int16 x, int16 y) {
return (int16(b >> 16), int16(b));
}
}
``````

Also, I am open to other suggestions on the storage of cartesian related values if this seems inefficient.

First of all, `int16` is just 2 bytes wide (16 bit), not 16 bytes. Did you mean `int128`?

Second, you still may pack/unpack two `int16` values into single `bytes32` in Solidity 0.5.x, you just need a bit more type casts:

``````function pack (int16 a, int16 b) public pure returns (bytes32) {
return bytes32 (bytes2 (a)) >> 16 | bytes2 (b);
}

function unpack (bytes32 x) public pure returns (int16, int16) {
return (int16 (bytes2 (x << 16)), int16 (bytes2 (x)));
}
``````

Note, the direction of shifts. This is because, for `bytesN` widening works differently than for numbers:

``````bytes2 a = 0x0102;
bytes4 b = bytes32 (a); // 0x01020000 (padded from right)

int16 c = 0x0102;
int32 d = int32 (c); // 0x00000102 (padded from left)
``````
• Perfect! Thank you for correcting me on the `int16` byte length. So in this scenario it would make more sense to pack two `int128` into a `bytes32`, or two `int16` into a `bytes4` correct? Also good to know about the different padding behaviors, I can see why they made this change that @markus-waas pointed out. – Neil Harlow Jul 2 '19 at 18:03

The behavior changed in Solidity 0.5.x.

Conversions between bytesX and uintY of different size are now disallowed due to bytesX padding on the right and uintY padding on the left which may cause unexpected conversion results. The size must now be adjusted within the type before the conversion. For example, you can convert a bytes4 (4 bytes) to a uint64 (8 bytes) by first converting the bytes4 variable to bytes8 and then to uint64. You get the opposite padding when converting through uint32.

``````int16 x = 5;