internal void GatherFlattened_impl()

in MPI/Communicator.cs [1532:1599]


        internal void GatherFlattened_impl<T>(bool isRoot, int size, T[] inValues, int[] counts, int root, ref T[] outValues)
        { 
            MPI_Datatype datatype = FastDatatypeCache<T>.datatype;
            if (!isRoot)
            {
                if (datatype == Unsafe.MPI_DATATYPE_NULL)
                {
                    T[][] tempOut = null;
                    Gather_impl<T[]>(isRoot, size, inValues, root, ref tempOut);
                }
                else
                {
                    // Pin the array while we are gathering out of it.
                    GCHandle inHandle = GCHandle.Alloc(inValues, GCHandleType.Pinned);
                    int errorCode = Unsafe.MPI_Gatherv(inHandle.AddrOfPinnedObject(), inValues.Length, datatype, new IntPtr(), null, null, datatype, root, comm);
                    inHandle.Free();

                    if (errorCode != Unsafe.MPI_SUCCESS)
                            throw Environment.TranslateErrorIntoException(errorCode);
                }
            }
            else
            {
                if (counts.Length != Size)
                    throw new ArgumentException($"counts.Length ({counts.Length}) != Communicator.Size ({Size})");
                int totalRecvSize = 0;
                // we must use checked addition in case the total count exceeds 2 billion.
                for (int i = 0; i < counts.Length; i++) checked
                {
                    totalRecvSize += counts[i];
                }

                if (outValues == null || outValues.Length < totalRecvSize)
                    outValues = new T[totalRecvSize];

                if (datatype == Unsafe.MPI_DATATYPE_NULL)
                {
                    T[][] tempOut = new T[counts.Length][];

                    Gather_impl<T[]>(isRoot, size, inValues, root, ref tempOut);

                    int cumulativeCount = 0;
                    for (int source = 0; source < counts.Length; ++source) checked
                    {
                        tempOut[source].CopyTo(outValues, cumulativeCount);
                        cumulativeCount += counts[source];
                    }
                }
                else
                {
                    int[] displs = new int[counts.Length];
                    displs[0] = 0;
                    for (int i = 1; i < counts.Length; i++)
                        displs[i] = checked(displs[i - 1] + counts[i - 1]);

                    // Pin the array while we are gathering into it.
                    GCHandle inHandle = GCHandle.Alloc(inValues, GCHandleType.Pinned);
                    GCHandle outHandle = GCHandle.Alloc(outValues, GCHandleType.Pinned);
                    int errorCode = Unsafe.MPI_Gatherv(inHandle.AddrOfPinnedObject(), inValues.Length, datatype,
                                          outHandle.AddrOfPinnedObject(), counts, displs, datatype, root, comm);
                    inHandle.Free();
                    outHandle.Free();

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