-1

I got a programm in C , that uses MPI in order to send coordinates of a specific point in (x,y,z) axis' between processes.Because the points sent,are in contiguous type (Rows of a 2d array) i want to encode the coordinates that are stored in a struct

  Struct pnts{

    int x;
    int y;
    int z;
  }pnt;

In one number (INTEGER/FLOAT) I need to encode these three coordinates Coordinates are integer numbers in the interval [0, 28] For example : x = 16, y = 2, z = 4 with respect to x < y < z

Any ideas?

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
BillG
  • 31
  • 9
  • `N=x*Max^2 + y*Max + z` – Eugene Sh. Jul 20 '16 at 13:32
  • You could just bitshift them like : `int coordinates = x<<16 | y << 8 | z` – rtur Jul 20 '16 at 13:32
  • @Eugene Sh. Perhaps `N=x*(Max+1)^2 + y*(Max+1) + z` or `N=(x*(Max+1) + y)*(Max+1) + z` – chux - Reinstate Monica Jul 20 '16 at 13:32
  • @chux Yes, you are right – Eugene Sh. Jul 20 '16 at 13:33
  • 1
    There are already many similar questions like this on SO e.g.: [bit-packing-of-array-of-integers](http://stackoverflow.com/q/2397655/3426025) or [using-1-int-to-send-2-numbers](http://stackoverflow.com/q/5291267/3426025) – BeyelerStudios Jul 20 '16 at 13:39
  • @rtur - As 2^8 is a legal value, the shift should be with 18 and 9 instead of 16 and 8 – Support Ukraine Jul 20 '16 at 13:40
  • @4386427 I assumed the OP meant one byte, not one byte + 1, not sure why :). You are right, if 2^8 supposed to be valid then the shifting needs to be one bit further to the left. – rtur Jul 20 '16 at 13:44
  • @4386427 exactly, that's how I fixed my asnwer. – Iharob Al Asimi Jul 20 '16 at 13:50
  • 1
    As is, this is a duplicate as highlighted by @BeyelerStudios. However I strongly need to emphasize that you do not need or even want do resort to bit manipulations for this particular use case. As said in your other question, MPI is perfectly capable of sending a struct, or array thereof, and there are existing answers that explain how to do that. – Zulan Jul 20 '16 at 19:04

1 Answers1

0

It's a very simple thing to do, you need to encode 3 bytes in a 32bit integer which allows 4. So what you need is

int32_t coordinates;

coordinates = x | (y << 8) | (z << 16);

and then you can access the coordinates with masks of bit flags.

Test program:

#include <stdint.h>
#include <stdio.h>

int
main(void)
{
    int x = 16;
    int y = 2;
    int z = 4;
    int32_t coordinates = x | (y << 8) | (z << 16);

    fprintf(stdout, "x = %d\n", (coordinates & 0xFF));
    fprintf(stdout, "y = %d\n", ((coordinates >> 8) & 0xFF));
    fprintf(stdout, "z = %d\n", ((coordinates >> 16) & 0xFF));
    return 0;
}

But then you can't encode 256 because it requires one more bit, remember that you start at 20 so you can only represent 255 with 8 bits, so here is an idea

#include <stdint.h>
#include <stdio.h>

#define XSHIFT 0
#define YSHIFT 9
#define ZSHIFT 18

#define GET_X(x) (((x) >> XSHIFT) & 0x1FF)
#define GET_Y(y) (((y) >> YSHIFT) & 0x1FF)
#define GET_Z(z) (((z) >> ZSHIFT) & 0x1FF)
#define ENCODE(x, y, z) (((x) << XSHIFT) | ((y) << YSHIFT) | ((z) << ZSHIFT))

int
main(void)
{
    int32_t coordinates = ENCODE(256, 0, 1);

    fprintf(stdout, "x = %d\n", GET_X(coordinates));
    fprintf(stdout, "y = %d\n", GET_Y(coordinates));
    fprintf(stdout, "z = %d\n", GET_Z(coordinates));
    return 0;
}

Use one extra bit from the remaining 8 bits that you have in a 32 bit integer.

NOTE: perhaps you (and others) think that defining XSHIFT is superflous but I think that the expressions then make more sense and are easier to read. It's something I believe I learned from studying physics and it's hard for me to see things like x + 7 in code as it is in mathematical expressions derived from physical laws.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • 1
    The problem (which is probably in the question, but anyway) that the range given is inclusive. – Eugene Sh. Jul 20 '16 at 13:35
  • Thanks for the answer! If i want to store32 bit integers in array,this should be done with an array of chars? – BillG Jul 20 '16 at 14:00
  • Of course you can use `char`, although it's better to use `unsigned char`. You can read about it online. – Iharob Al Asimi Jul 20 '16 at 14:16
  • 2
    While this correctly and nicely answers the Y-question of the OP, this totally fails to recognize that it is completely unnecessary to do this in the first place. MPI is perfectly capable to send three integers, whether in a `struct`, array or whatever. There is no reason to resort to bit-magic, it is much better to use the appropriate abstractions. This is also [well](http://stackoverflow.com/questions/18165277/how-to-send-a-variable-of-type-struct-in-mpi-send) [documented](http://stackoverflow.com/a/9865041/620382) on SO as noted on the OPs other question about this. – Zulan Jul 20 '16 at 17:11
  • P.S. I strongly assume that the OP meant 8-bit in the first place or at least has no reason to optimize away 2 unnecessarily transferred bytes. – Zulan Jul 20 '16 at 17:14
  • Zulan i understand what you say.But as i told before i use contiguous data to send each ROW of array.So i need standard mpi type(?) in segment – BillG Jul 20 '16 at 19:16
  • MPI_Type_contiguous(row,oldtype,&newtype); – BillG Jul 20 '16 at 19:16
  • 2
    @BillG, MPI types can be nested. Just create a structure type for one point, then create a contiguous type for an array of points. Also, contiguous MPI types are simply for convenience - you do not need one in order to send an array. – Hristo Iliev Jul 20 '16 at 20:52
  • Downvoter, please read the question carefully. I think I did answer it. If you have useful information you can post a comment on the question to help the OP, but downvoting this question makes no sense unless, something is wrong or bad about it I think. And it cerainly will NOT HELP THE OP. – Iharob Al Asimi Jul 20 '16 at 23:12
  • @Hristo Iliev . My problem is that when i useMPI_Type_contiguous(oldtype=PointType,newtype=rowOfArray etc..). i get garbage in recv code.And i thought that the nested type causes that. – BillG Jul 21 '16 at 10:11