Okay. So we're going to do that in pure PyTorch. Let's first import torch and then define the signature of the method pack_weights. That is going to take the unsigned int8 tensor and the number of bits. So the reason why we're using unsigned int instead of int8 is that for int8 tensor, the first bit is used to determine the sign of the tensor. So, just for simplicity we're going to use unsigned int so that we don't have to deal with the sign bit. So recall also what I've said at the beginning. So for simplicity it's better to have, the shape of the input tensor being a multiple of four eight divided by number of bits. So we're just going to add a small condition here checking that if the tensor does not have the right shape, then we're going to raise a small error saying that the input shape needs to be a multiple of the expected number and print it to the users. So, now let's get the number of values expected values of the packed tensor. So if we come back to our example. So this of course depends on the number of bits that you use to encode your values. So in case of two bits we have four values. So the number of expected packed values is simply going to be the shape of your input tensor multiplied by the number of bits. So here we have two bits per value. And then we have four values. So eight bit divided by eight because our packed tensor is going to be eight bits. So number of expected value is simply going to be number of input low bits values that you're going to retrieve with dot shape of zero times the number of bits. If either you are in 2 or 4 bits, everything divided by eight. Perfect. So let's come back again to the example that we had before. So in case of two bits, each packet weight will contain four values two bit. We're processing four parameters per packed parameter. So this is going to be our number of processing steps. So we're calling this value num steps. That is simply going to be the number of bits of the pack tensor divided by number of bits. Again in our example this should be four because of a processing for two bit values for packed tensor. And we're going to declare this index because we're going to have a four loop. And then we initialize our packed tensor which should contain num values and which should be in a dtype of unsigned eight. Perfect. Let's first loop on each packed value. And then for each packed value we pack num steps, low bit values. So we need to loop again here using a new variable. And then we're going to use unpacked index in order to keep track of which values are we trying to pack in our algorithm. So, in the first iteration again if we consider the tensor that we had in our example. So I'm going to write it here. So 1,0,3,2 which should be in two bit. And then we have our so this is uint8 tensor. So it's encoded in Int8. And we only want to extract those bits. And then we have our plain packed tensor which should only contain one value in uint8. All right. For each num steps here. So for each, num step. So each two bits, we're going to retrieve the corresponding value. So here for example it should be one. And then, we're going to perform bitwise shifting on the left for this tensor but encoded in eight bits. So let me try to break it down below. So here, this value. So it's encoded in uint8. So it should give us this value. All right. And then the idea is that we're going to take this value shifted on the left by bits times J. So here since we are on the first iteration it's going to be zero. So nothing is going to be applied here. So no shifting on the left. So this value should stay like this. All right. And then we're going to perform bitwise or operation on the current packed tensor. So let me explain you that. So in the first iteration this is how the packed tensor would look like. And this is how the right side of the equation would look like. Here. And again we want to pack this here. Then this here, this here, and this here. So we're going to perform an bitwise or operation. So that zero and 0 or 1 would give us one 0 or 0 zero and so on. So here after the first iteration the packed tensor would exactly look like this. Okay. And then on the second iteration then we're going to increment our unpacked index here. All right. And then on the second iteration we're going to take this tensor but encoded in uint8. So now the packed tensor would look like this because of the bitwise or operation. And this time the shifting coefficient is going to be two. So you're going to take this tensor. It's 000. Shift it on the left by two. So again it's going to be 000. And then you're going to perform bitwise Or operation between the shifted tensor and the pack tensor. And it's still going to be 1000000. That's fine because we pack the first tensor here in two bit. We pack the second thing off here in two bits, and then we're ready to move on to the next one. And then on the next iteration we're going to have this tensor. Okay. Again so encode you in uint8. We're going to shift it on the left this time by. So J is going to be equal to two. So two times two four. So we're going to shift that by four bit. And it's going to look like this. And then you're going to perform bitwise or operation. And the new pack tensor would look like this. Perfect. And then on the last iteration you'll do the same thing but this time shifting by six on the left. So one zero would be here. And then bitwise or at the very end you would end up like this. So the final packed tensor would look theoretically like this. Perfect. Yeah. Let's try out quickly our methods and test it. And we're going to test it on our toy example. Let's say our unpacked tensor is encoded as follows: 1032. Again everything encoded in two bit. And yeah let's pack the weights to see if it works. Perfect. So 177 should be encoded exactly like this in uint8. You can try that out verifying the results. But yeah that should be the correct result. Perfect. So yeah. You can pause the video and maybe try to understand this whole logic. Try also maybe to enhance it a bit. Optimize it. You can also try out with four bits and yeah, maybe you can also try out different combinations. For example, you can also battle test the method a bit if we add these values. So three and two which should be one one. So we should have 11111 here everywhere. And the second tensor should be 255 which is the case.