public void ScatterFromFlattened()

in MPI/Intracommunicator.cs [1949:2015]


        public void ScatterFromFlattened<T>(T[] inValues, int[] counts, int root, ref T[] outValues)
        {
            if (counts.Length != Size)
                throw new ArgumentException($"counts.Length ({counts.Length}) != Communicator.Size ({Size})");
            MPI_Datatype datatype = FastDatatypeCache<T>.datatype;
            if (datatype == Unsafe.MPI_DATATYPE_NULL)
            {
                if (Rank == root)
                {
                    T[][] tempIn = new T[Size][];
                    int inLocation = 0;
                    for (int i = 0; i < Size; i++) checked
                    {
                        tempIn[i] = new T[counts[i]];
                        Array.Copy(inValues, inLocation, tempIn[i], 0, counts[i]);
                        inLocation += counts[i];
                    }
                    outValues = Scatter<T[]>(tempIn);

                }
                else
                    outValues = Scatter<T[]>(root);
            }
            else
            {
                if (outValues == null || outValues.Length != counts[Rank])
                    outValues = new T[counts[Rank]];

                if (Rank == root)
                {
                    int[] displs = new int[counts.Length];
                    displs[0] = 0;
                    for (int i = 1; i < counts.Length; i++) checked
                    {
                        displs[i] = displs[i - 1] + counts[i - 1];
                    }
                    int lastIndex = counts.Length - 1;
                    int totalCount = checked(displs[lastIndex] + counts[lastIndex]);
                    if (totalCount > inValues.Length)
                    {
                        throw new ArgumentException($"Sum of counts ({totalCount}) > inValues.Length ({inValues.Length})");
                    }

                    // Pin the array while we are scattering it.
                    GCHandle inHandle = GCHandle.Alloc(inValues, GCHandleType.Pinned);
                    GCHandle outHandle = GCHandle.Alloc(outValues, GCHandleType.Pinned);
                    int errorCode = Unsafe.MPI_Scatterv(inHandle.AddrOfPinnedObject(), counts, displs, datatype,
                                          outHandle.AddrOfPinnedObject(), counts[Rank], datatype, root, comm);
                    inHandle.Free();
                    outHandle.Free();

                    if (errorCode != Unsafe.MPI_SUCCESS)
                        throw Environment.TranslateErrorIntoException(errorCode);
                }
                else
                {
                    // Pin the array while we are scattering it.
                    GCHandle outHandle = GCHandle.Alloc(outValues, GCHandleType.Pinned);
                    int errorCode = Unsafe.MPI_Scatterv(new IntPtr(0), counts, new int[0], datatype,
                                                        outHandle.AddrOfPinnedObject(), counts[Rank], datatype, root, comm);
                    outHandle.Free();

                    if (errorCode != Unsafe.MPI_SUCCESS)
                        throw Environment.TranslateErrorIntoException(errorCode);
                }
            }
        }