예제 #1
0
        public IEnumerable <Fix64> ParallelizedCalculateIntegerSumUpToNumbers(int[] numbers)
        {
            if (numbers.Length != MaxDegreeOfParallelism)
            {
                throw new ArgumentException(
                          "Provide as many numbers as the degree of parallelism of Fix64Calculator is (" +
                          MaxDegreeOfParallelism + ")");
            }

            var memory = new SimpleMemory(2 * MaxDegreeOfParallelism);

            for (int i = 0; i < numbers.Length; i++)
            {
                memory.WriteInt32(ParallelizedCalculateLargeIntegerSum_Int32NumbersStartIndex + i, numbers[i]);
            }

            ParallelizedCalculateIntegerSumUpToNumbers(memory);

            var results = new Fix64[MaxDegreeOfParallelism];

            for (int i = 0; i < MaxDegreeOfParallelism; i++)
            {
                var itemOutputStartIndex = ParallelizedCalculateLargeIntegerSum_OutputInt32sStartIndex + i * 2;

                results[i] = Fix64.FromRawInts(new[]
                {
                    memory.ReadInt32(itemOutputStartIndex),
                    memory.ReadInt32(itemOutputStartIndex + 1)
                });
            }

            return(results);
        }
예제 #2
0
        private void RunSimdOperation(SimpleMemory memory, SimdOperation operation)
        {
            var elementCount = memory.ReadInt32(VectorsElementCountInt32Index);

            int i = 0;

            while (i < elementCount)
            {
                var vector1      = new int[MaxDegreeOfParallelism];
                var vector2      = new int[MaxDegreeOfParallelism];
                var resultVector = new int[MaxDegreeOfParallelism];

                for (int m = 0; m < MaxDegreeOfParallelism; m++)
                {
                    vector1[m] = memory.ReadInt32(VectorElementsStartInt32Index + i + m);
                }

                for (int m = 0; m < MaxDegreeOfParallelism; m++)
                {
                    vector2[m] = memory.ReadInt32(VectorElementsStartInt32Index + i + m + elementCount);
                }

                switch (operation)
                {
                case SimdOperation.Add:
                    resultVector = SimdOperations.AddVectors(vector1, vector2, MaxDegreeOfParallelism);
                    break;

                case SimdOperation.Subtract:
                    resultVector = SimdOperations.SubtractVectors(vector1, vector2, MaxDegreeOfParallelism);
                    break;

                case SimdOperation.Multiply:
                    resultVector = SimdOperations.MultiplyVectors(vector1, vector2, MaxDegreeOfParallelism);
                    break;

                case SimdOperation.Divide:
                    resultVector = SimdOperations.DivideVectors(vector1, vector2, MaxDegreeOfParallelism);
                    break;

                default:
                    break;
                }

                for (int m = 0; m < MaxDegreeOfParallelism; m++)
                {
                    memory.WriteInt32(ResultVectorElementsStartInt32Index + i + m, resultVector[m]);
                }

                i += MaxDegreeOfParallelism;
            }
        }
예제 #3
0
        public virtual void Run(SimpleMemory memory)
        {
            var startIndex = memory.ReadInt32(Run_StartIndexInt32Index);
            var length     = memory.ReadInt32(Run_LengthInt32Index);
            var endIndex   = startIndex + length;

            for (int i = startIndex; i < endIndex; i++)
            {
                // Adding 1 to the input so it's visible whether this actually has run, not just the untouched data was
                // sent back.
                memory.WriteInt32(i, memory.ReadInt32(i) + 1);
            }
        }
예제 #4
0
        public Fix64 CalculateIntegerSumUpToNumber(int input)
        {
            var memory = new SimpleMemory(2);

            memory.WriteInt32(CalculateLargeIntegerSum_InputInt32Index, input);

            CalculateIntegerSumUpToNumber(memory);

            return(Fix64.FromRawInts(new[]
            {
                memory.ReadInt32(CalculateLargeIntegerSum_OutputInt32Index),
                memory.ReadInt32(CalculateLargeIntegerSum_OutputInt32Index + 1)
            }));
        }
예제 #5
0
        private int[] RunSimdOperation(int[] vector1, int[] vector2, Action <SimpleMemory> operation)
        {
            SimdOperations.ThrowIfVectorsNotEquallyLong(vector1, vector2);

            var originalElementCount = vector1.Length;

            vector1 = vector1.PadToMultipleOf(MaxDegreeOfParallelism);
            vector2 = vector2.PadToMultipleOf(MaxDegreeOfParallelism);

            var elementCount = vector1.Length;
            var memory       = new SimpleMemory(1 + elementCount * 2);

            memory.WriteInt32(VectorsElementCountInt32Index, elementCount);

            for (int i = 0; i < elementCount; i++)
            {
                memory.WriteInt32(VectorElementsStartInt32Index + i, vector1[i]);
                memory.WriteInt32(VectorElementsStartInt32Index + elementCount + i, vector2[i]);
            }

            operation(memory);

            var result = new int[elementCount];

            for (int i = 0; i < elementCount; i++)
            {
                result[i] = memory.ReadInt32(ResultVectorElementsStartInt32Index + i);
            }

            return(result.CutToLength(originalElementCount));
        }
예제 #6
0
        public static int Run(this Loopback loopback, int input)
        {
            var memory = new SimpleMemory(1);

            memory.WriteInt32(Loopback.Run_InputOutputInt32Index, input);
            loopback.Run(memory);
            return(memory.ReadInt32(Loopback.Run_InputOutputInt32Index));
        }
예제 #7
0
        public virtual void CalculateFactorial(SimpleMemory memory)
        {
            memory.WriteUInt32(CalculateFactorial_InvocationCounterUInt32Index, 1);

            var number = (short)memory.ReadInt32(CalculateFactorial_InputShortIndex);

            memory.WriteUInt32(CalculateFactorial_OutputUInt32Index, RecursivelyCalculateFactorial(memory, number));
        }
예제 #8
0
        public int Run(int input)
        {
            var memory = new SimpleMemory(1);

            memory.WriteInt32(Run_InputOutputInt32Index, input);
            Run(memory);
            return(memory.ReadInt32(Run_InputOutputInt32Index));
        }
예제 #9
0
        public int Run(int startIndex, int length)
        {
            var memory = new SimpleMemory(startIndex + length < 2 ? 2 : startIndex + length);

            memory.WriteInt32(Run_StartIndexInt32Index, startIndex);
            memory.WriteInt32(Run_LengthInt32Index, length);
            Run(memory);
            return(memory.ReadInt32(Run_StartIndexInt32Index));
        }
예제 #10
0
        /// <summary>
        /// Creates an image from a <see cref="SimpleMemory"/> instance.
        /// </summary>
        /// <param name="memory">The <see cref="SimpleMemory"/> instance.</param>
        /// <param name="image">The original image.</param>
        /// <returns>Returns the processed image.</returns>
        private Bitmap CreateImage(SimpleMemory memory, Bitmap image)
        {
            var newImage = new Bitmap(image);

            int r, g, b;

            for (int x = 0; x < newImage.Height; x++)
            {
                for (int y = 0; y < newImage.Width; y++)
                {
                    r = memory.ReadInt32((x * newImage.Width + y) * 3 + FilterImage_ImageStartIndex);
                    g = memory.ReadInt32((x * newImage.Width + y) * 3 + 1 + FilterImage_ImageStartIndex);
                    b = memory.ReadInt32((x * newImage.Width + y) * 3 + 2 + FilterImage_ImageStartIndex);

                    newImage.SetPixel(y, x, Color.FromArgb(r, g, b));
                }
            }

            return(newImage);
        }
예제 #11
0
        public virtual void CalculateIntegerSumUpToNumber(SimpleMemory memory)
        {
            var number = memory.ReadInt32(CalculateLargeIntegerSum_InputInt32Index);

            var a = new Fix64(1);
            var b = a;

            for (var i = 1; i < number; i++)
            {
                a += b;
            }

            var integers = a.ToIntegers();

            memory.WriteInt32(CalculateLargeIntegerSum_OutputInt32Index, integers[0]);
            memory.WriteInt32(CalculateLargeIntegerSum_OutputInt32Index + 1, integers[1]);
        }
        public double EstimatePi(uint iterationsCount)
        {
            if (iterationsCount % MaxDegreeOfParallelism != 0)
            {
                throw new Exception($"The number of iterations must be divisible by {MaxDegreeOfParallelism}.");
            }

            var memory = new SimpleMemory(2);

            memory.WriteUInt32(EstimatePi_IteractionsCountUInt32Index, iterationsCount);
            memory.WriteUInt32(EstimatePi_RandomSeedUInt32Index, (uint)_random.Next(0, int.MaxValue));

            EstimatePi(memory);

            // This single calculation takes up too much space on the FPGA, since it needs fix point arithmetic, but
            // it doesn't take much time. So doing it on the host instead.
            return((double)memory.ReadInt32(EstimatePi_InCircleCountSumUInt32Index) / iterationsCount * 4);
        }
예제 #13
0
        public virtual void ParallelizedCalculateIntegerSumUpToNumbers(SimpleMemory memory)
        {
            var numbers = new int[MaxDegreeOfParallelism];

            var tasks = new Task <TaskResult> [MaxDegreeOfParallelism];

            for (int i = 0; i < MaxDegreeOfParallelism; i++)
            {
                var upToNumber = memory.ReadInt32(ParallelizedCalculateLargeIntegerSum_Int32NumbersStartIndex + i);

                tasks[i] = Task.Factory.StartNew(
                    upToNumberObject =>
                {
                    var a = new Fix64(1);
                    var b = a;

                    for (var j = 1; j < (int)upToNumberObject; j++)
                    {
                        a += b;
                    }

                    var integers = a.ToIntegers();

                    return(new TaskResult
                    {
                        Fix64Low = integers[0],
                        Fix64High = integers[1]
                    });
                }, upToNumber);
            }

            Task.WhenAll(tasks).Wait();

            for (int i = 0; i < MaxDegreeOfParallelism; i++)
            {
                var itemOutputStartIndex = ParallelizedCalculateLargeIntegerSum_OutputInt32sStartIndex + i * 2;

                memory.WriteInt32(itemOutputStartIndex, tasks[i].Result.Fix64Low);
                memory.WriteInt32(itemOutputStartIndex + 1, tasks[i].Result.Fix64High);
            }
        }
예제 #14
0
        public virtual void ScheduleIterations(SimpleMemory memory)
        {
            int       numberOfIterations    = memory.ReadInt32(MemIndexNumberOfIterations);
            const int TasksPerIteration     = (GridSize * GridSize) / (LocalGridSize * LocalGridSize);
            const int SchedulesPerIteration = TasksPerIteration / ParallelTasks;
            int       iterationGroupSize    = numberOfIterations * ReschedulesPerTaskIteration;
            const int PokesInsideTask       = LocalGridSize * LocalGridSize / ReschedulesPerTaskIteration;
            const int LocalGridPartitions   = GridSize / LocalGridSize;
            //Note: TotalNumberOfTasks = TasksPerIteration * NumberOfIterations ==
            //  ((GridSize * GridSize) / (LocalGridSize * LocalGridSize)) * NumberOfIterations
            int  parallelTaskRandomIndex = 0;
            uint randomSeedTemp;
            var  random0 = new RandomMwc64X();

            var taskLocals = new KpzKernelsTaskState[ParallelTasks];

            for (int TaskLocalsIndex = 0; TaskLocalsIndex < ParallelTasks; TaskLocalsIndex++)
            {
                taskLocals[TaskLocalsIndex] = new KpzKernelsTaskState
                {
                    BramDx  = new bool[LocalGridSize * LocalGridSize],
                    BramDy  = new bool[LocalGridSize * LocalGridSize],
                    Random1 = new RandomMwc64X
                    {
                        State = memory.ReadUInt32(MemIndexRandomSeed + parallelTaskRandomIndex++)
                    }
                };
                randomSeedTemp = memory.ReadUInt32(MemIndexRandomSeed + parallelTaskRandomIndex++);
                taskLocals[TaskLocalsIndex].Random1.State |= ((ulong)randomSeedTemp) << 32;

                taskLocals[TaskLocalsIndex].Random2 = new RandomMwc64X
                {
                    State = memory.ReadUInt32(MemIndexRandomSeed + parallelTaskRandomIndex++)
                };
                randomSeedTemp = memory.ReadUInt32(MemIndexRandomSeed + parallelTaskRandomIndex++);
                taskLocals[TaskLocalsIndex].Random2.State |= ((ulong)randomSeedTemp) << 32;
            }

            // What is iterationGroupIndex good for?
            // IterationPerTask needs to be between 0.5 and 1 based on the e-mail of Mate.
            // If we want 10 iterations, and starting a full series of tasks makes half iteration on the full table,
            // then we need to start it 20 times (thus IterationGroupSize will be 20).

            random0.State  = memory.ReadUInt32(MemIndexRandomSeed + parallelTaskRandomIndex++);
            randomSeedTemp = memory.ReadUInt32(MemIndexRandomSeed + parallelTaskRandomIndex++);
            random0.State |= ((ulong)randomSeedTemp) << 32;

            for (int iterationGroupIndex = 0; iterationGroupIndex < iterationGroupSize; iterationGroupIndex++)
            {
                uint randomValue0 = random0.NextUInt32();
                // This assumes that LocalGridSize is 2^N:
                int randomXOffset = (int)((LocalGridSize - 1) & randomValue0);
                int randomYOffset = (int)((LocalGridSize - 1) & (randomValue0 >> 16));
                for (int scheduleIndex = 0; scheduleIndex < SchedulesPerIteration; scheduleIndex++)
                {
                    var tasks = new Task <KpzKernelsTaskState> [ParallelTasks];
                    for (int parallelTaskIndex = 0; parallelTaskIndex < ParallelTasks; parallelTaskIndex++)
                    {
                        // Decide the X and Y starting coordinates based on ScheduleIndex and ParallelTaskIndex
                        // (and the random added value)
                        int localGridIndex = parallelTaskIndex + scheduleIndex * ParallelTasks;
                        // The X and Y coordinate within the small table (local grid):
                        int partitionX = localGridIndex % LocalGridPartitions;
                        int partitionY = localGridIndex / LocalGridPartitions;
                        // The X and Y coordinate within the big table (grid):
                        int baseX = partitionX * LocalGridSize + randomXOffset;
                        int baseY = partitionY * LocalGridSize + randomYOffset;

                        // Copy to local memory
                        for (int copyDstX = 0; copyDstX < LocalGridSize; copyDstX++)
                        {
                            for (int CopyDstY = 0; CopyDstY < LocalGridSize; CopyDstY++)
                            {
                                //Prevent going out of grid memory area (e.g. reading into random seed):
                                int  copySrcX = (baseX + copyDstX) % GridSize;
                                int  copySrcY = (baseY + CopyDstY) % GridSize;
                                uint value    = memory.ReadUInt32(MemIndexGrid + copySrcX + copySrcY * GridSize);
                                taskLocals[parallelTaskIndex].BramDx[copyDstX + CopyDstY * LocalGridSize] =
                                    (value & 1) == 1;
                                taskLocals[parallelTaskIndex].BramDy[copyDstX + CopyDstY * LocalGridSize] =
                                    (value & 2) == 2;
                            }
                        }

                        tasks[parallelTaskIndex] = Task.Factory.StartNew(
                            rawTaskState =>
                        {
                            // Then do TasksPerIteration iterations
                            var taskLocal = (KpzKernelsTaskState)rawTaskState;
                            for (int pokeIndex = 0; pokeIndex < PokesInsideTask; pokeIndex++)
                            {
                                // ==== <Now randomly switch four cells> ====

                                // Generating two random numbers:
                                uint taskRandomNumber1 = taskLocal.Random1.NextUInt32();
                                uint taskRandomNumber2 = taskLocal.Random2.NextUInt32();

                                // The existence of var-1 in code is a good indicator of that it is assumed to be 2^N:
                                int pokeCenterX      = (int)(taskRandomNumber1 & (LocalGridSize - 1));
                                int pokeCenterY      = (int)((taskRandomNumber1 >> 16) & (LocalGridSize - 1));
                                int pokeCenterIndex  = pokeCenterX + pokeCenterY * LocalGridSize;
                                uint randomVariable1 = taskRandomNumber2 & ((1 << 16) - 1);
                                uint randomVariable2 = (taskRandomNumber2 >> 16) & ((1 << 16) - 1);

                                // get neighbour indexes:
                                int rightNeighbourIndex;
                                int bottomNeighbourIndex;
                                // We skip if neighbours would fall out of the local grid:
                                if (pokeCenterX >= LocalGridSize - 1 || pokeCenterY >= LocalGridSize - 1)
                                {
                                    continue;
                                }
                                int rightNeighbourX  = pokeCenterX + 1;
                                int rightNeighbourY  = pokeCenterY;
                                int bottomNeighbourX = pokeCenterX;
                                int bottomNeighbourY = pokeCenterY + 1;
                                rightNeighbourIndex  = rightNeighbourY * LocalGridSize + rightNeighbourX;
                                bottomNeighbourIndex = bottomNeighbourY * LocalGridSize + bottomNeighbourX;

                                // We check our own {dx,dy} values, and the right neighbour's dx, and bottom neighbour's dx.

                                if (
                                    // If we get the pattern {01, 01} we have a pyramid:
                                    ((taskLocal.BramDx[pokeCenterIndex] && !taskLocal.BramDx[rightNeighbourIndex]) &&
                                     (taskLocal.BramDy[pokeCenterIndex] && !taskLocal.BramDy[bottomNeighbourIndex]) &&
                                     (false || randomVariable1 < IntegerProbabilityP)) ||
                                    // If we get the pattern {10, 10} we have a hole:
                                    ((!taskLocal.BramDx[pokeCenterIndex] && taskLocal.BramDx[rightNeighbourIndex]) &&
                                     (!taskLocal.BramDy[pokeCenterIndex] && taskLocal.BramDy[bottomNeighbourIndex]) &&
                                     (false || randomVariable2 < IntegerProbabilityQ))
                                    )
                                {
                                    // We make a hole into a pyramid, and a pyramid into a hole.
                                    taskLocal.BramDx[pokeCenterIndex]      = !taskLocal.BramDx[pokeCenterIndex];
                                    taskLocal.BramDy[pokeCenterIndex]      = !taskLocal.BramDy[pokeCenterIndex];
                                    taskLocal.BramDx[rightNeighbourIndex]  = !taskLocal.BramDx[rightNeighbourIndex];
                                    taskLocal.BramDy[bottomNeighbourIndex] = !taskLocal.BramDy[bottomNeighbourIndex];
                                }

                                // ==== </Now randomly switch four cells> ====
                            }
                            return(taskLocal);
                        }, taskLocals[parallelTaskIndex]);
                    }

                    Task.WhenAll(tasks).Wait();

                    // Copy back to SimpleMemory
                    for (int parallelTaskIndex = 0; parallelTaskIndex < ParallelTasks; parallelTaskIndex++)
                    {
                        // Calculate these things again
                        int localGridIndex = parallelTaskIndex + scheduleIndex * ParallelTasks;
                        // The X and Y coordinate within the small table (local grid):
                        int partitionX = localGridIndex % LocalGridPartitions;
                        int partitionY = localGridIndex / LocalGridPartitions;
                        // The X and Y coordinate within the big table (grid):
                        int baseX = partitionX * LocalGridSize + randomXOffset;
                        int baseY = partitionY * LocalGridSize + randomYOffset;
                        //Console.WriteLine("CopyBack | Task={0}, To: {1},{2}", ParallelTaskIndex, BaseX, BaseY);

                        for (int copySrcX = 0; copySrcX < LocalGridSize; copySrcX++)
                        {
                            for (int copySrcY = 0; copySrcY < LocalGridSize; copySrcY++)
                            {
                                int  copyDstX = (baseX + copySrcX) % GridSize;
                                int  copyDstY = (baseY + copySrcY) % GridSize;
                                uint value    =
                                    (tasks[parallelTaskIndex].Result.BramDx[copySrcX + copySrcY * LocalGridSize] ? 1U : 0U) |
                                    (tasks[parallelTaskIndex].Result.BramDy[copySrcX + copySrcY * LocalGridSize] ? 2U : 0U);
                                //Note: use (tasks[parallelTaskIndex].Result), because
                                //    (TaskLocals[ParallelTaskIndex]) won't work.
                                memory.WriteUInt32(MemIndexGrid + copyDstX + copyDstY * GridSize, value);
                            }
                        }

                        // Take PRNG current state from Result to feed it to input next time
                        taskLocals[parallelTaskIndex].Random1.State = tasks[parallelTaskIndex].Result.Random1.State;
                        taskLocals[parallelTaskIndex].Random2.State = tasks[parallelTaskIndex].Result.Random2.State;
                    }
                }
            }
        }
        /// <summary>
        /// Changes the contrast of an image.
        /// </summary>
        /// <param name="memory">The <see cref="SimpleMemory"/> object representing the accessible memory space.</param>
        public virtual void ChangeContrast(SimpleMemory memory)
        {
            var imageWidth    = (ushort)memory.ReadUInt32(ChangeContrast_ImageWidthIndex);
            var imageHeight   = (ushort)memory.ReadUInt32(ChangeContrast_ImageHeightIndex);
            int contrastValue = memory.ReadInt32(ChangeContrast_ContrastValueIndex);

            if (contrastValue > 100)
            {
                contrastValue = 100;
            }
            else if (contrastValue < -100)
            {
                contrastValue = -100;
            }

            contrastValue = (100 + contrastValue * Multiplier) / 100;

            var tasks = new Task <PixelProcessingTaskOutput> [MaxDegreeOfParallelism];

            // Since we only need to compute the loop condition's right side once, not on each loop execution, it's an
            // optimization to put it in a separate variable. This way it's indeed computed only once.
            var pixelCount = imageHeight * imageWidth;
            var stepCount  = pixelCount / MaxDegreeOfParallelism;

            if (pixelCount % MaxDegreeOfParallelism != 0)
            {
                // This will take care of the rest of the pixels. This is wasteful as on the last step not all Tasks
                // will work on something but it's a way to keep the number of Tasks constant.
                stepCount += 1;
            }

            for (int i = 0; i < stepCount; i++)
            {
                for (int t = 0; t < MaxDegreeOfParallelism; t++)
                {
                    var pixelBytes = memory.Read4Bytes(i * MaxDegreeOfParallelism + t + ChangeContrast_ImageStartIndex);

                    // Using an input class to also pass contrastValue because it's currently not supported to access
                    // variables from the parent scope from inside Tasks (you need to explicitly pass in all inputs).
                    // Using an output class to pass the pixel values back because returning an array from Tasks is not
                    // supported at the time either.
                    tasks[t] = Task.Factory.StartNew(
                        inputObject =>
                    {
                        var input = (PixelProcessingTaskInput)inputObject;

                        return(new PixelProcessingTaskOutput
                        {
                            R = ChangePixelValue(input.PixelBytes[0], input.ContrastValue),
                            G = ChangePixelValue(input.PixelBytes[1], input.ContrastValue),
                            B = ChangePixelValue(input.PixelBytes[2], input.ContrastValue)
                        });
                    },
                        new PixelProcessingTaskInput {
                        PixelBytes = pixelBytes, ContrastValue = contrastValue
                    });
                }

                Task.WhenAll(tasks).Wait();

                for (int t = 0; t < MaxDegreeOfParallelism; t++)
                {
                    // It's no problem that we write just 3 bytes to a 4-byte slot.
                    memory.Write4Bytes(
                        i * MaxDegreeOfParallelism + t + ChangeContrast_ImageStartIndex,
                        new[] { tasks[t].Result.R, tasks[t].Result.G, tasks[t].Result.B });
                }
            }
        }
예제 #16
0
        public virtual void CalculateTorusSectionValues(SimpleMemory memory)
        {
            int w, x, y, s, z, dw, dx, dy, dz, sw, swx, swy, swz, varw, varx, vary, varz, ss, volume;

            w = x = y = s = z = dw = dx = dy = dz = sw = swx = swy = swz = varw = varx = vary = varz = 0;

            // Rounded constant value instead of "0.2 * (Math.Exp(5.0) - Math.Exp(-5.0))".
            // This is the interval of s to be random sampled.
            ss     = 29;
            volume = 3 * 7 * ss; // Volume of the sampled region in x,y,s space.

            int iterationsCount = memory.ReadInt32(MonteCarloAlgorithm_IterationsCountIndex);

            int sumsw    = 0;
            int sumswx   = 0;
            int sumswy   = 0;
            int sumswz   = 0;
            int sumvarw  = 0;
            int sumvarwx = 0;
            int sumvarwy = 0;
            int sumvarwz = 0;

            uint randomX = 0;
            uint randomY = 0;
            uint randomZ = 0;

            for (int i = 1; i <= iterationsCount; i++)
            {
                randomX = memory.ReadUInt32(MonteCarloAlgorithm_RandomNumbersStartIndex + i);
                randomY = memory.ReadUInt32(MonteCarloAlgorithm_RandomNumbersStartIndex + i + 1);
                randomZ = memory.ReadUInt32(MonteCarloAlgorithm_RandomNumbersStartIndex + i + 2);

                // Pick points randomly from the sampled region.
                x = checked ((int)(Multiplier + randomX * 3 * Multiplier / 100));

                // The constant can't be specified properly inline as (since it can't be specified as a short, see:
                // http://stackoverflow.com/questions/8670511/how-to-specify-a-short-int-constant-without-casting)
                // it would cause an underflow and be casted to an ulong.
                short minusThree = -3;
                y = checked ((int)(minusThree * Multiplier + randomY * 7 * Multiplier / 100));
                short thirteen = 13;
                s = checked ((int)(thirteen + ss * (short)randomZ * Multiplier / 100));
                short two = 2;
                z = checked ((int)(two * Multiplier * Log(5 * s / Multiplier) / 10));

                int b = checked ((int)(Sqrt((x * x) + (y * y)) - 3 * Multiplier));
                int a = checked ((int)(((z * z) + (b * b)) / Multiplier));

                // Check if the selected points are inside the torus.
                // If they are inside, add to the various cumulants.
                if (a < Multiplier)
                {
                    sw    = checked (sw + Multiplier);
                    swx   = checked (swx + x);
                    swy   = checked (swy + y);
                    swz   = checked (swz + z);
                    varw  = Multiplier;
                    varx += (x * x) / Multiplier;
                    vary += (y * y) / Multiplier;
                    varz += (z * z) / Multiplier;
                }

                // Divide the values with the multiplier to return to the original numbers in every 1000th iteration.
                // This way we can avoid overflows at the final computations, but we still get more precise values.
                if (i % 1000 == 0 || i == iterationsCount)
                {
                    sumsw     = checked (sumsw + sw / Multiplier);
                    sumswx    = checked (sumswx + swx / Multiplier);
                    sumswy    = checked (sumswy + swy / Multiplier);
                    sumswz    = checked (sumswz + swz / Multiplier);
                    sumvarw   = Multiplier;
                    sumvarwx += varx / Multiplier;
                    sumvarwy += vary / Multiplier;
                    sumvarwz += varz / Multiplier;

                    sw = swx = swy = swz = varw = varx = vary = varz = 0;
                }
            }

            // Values of the integrals.
            memory.WriteUInt32(MonteCarloAlgorithm_WIndex, checked ((uint)((uint)volume * (uint)sumsw / iterationsCount)));
            memory.WriteUInt32(MonteCarloAlgorithm_XIndex, checked ((uint)((uint)volume * (uint)sumswx / iterationsCount)));
            memory.WriteUInt32(MonteCarloAlgorithm_YIndex, checked ((uint)((uint)volume * (uint)sumswy / iterationsCount)));
            memory.WriteUInt32(MonteCarloAlgorithm_ZIndex, checked ((uint)((uint)volume * (uint)sumswz / iterationsCount)));

            // Values of the error estimates.
            memory.WriteUInt32(MonteCarloAlgorithm_DWIndex,
                               checked ((uint)(volume * Sqrt((int)((sumvarw / iterationsCount - Pow((sumsw / iterationsCount), 2)) / iterationsCount)))));
            memory.WriteUInt32(MonteCarloAlgorithm_DXIndex,
                               checked ((uint)(volume * Sqrt((int)((sumvarwx / iterationsCount - Pow((sumswx / iterationsCount), 2)) / iterationsCount)))));
            memory.WriteUInt32(MonteCarloAlgorithm_DYIndex,
                               checked ((uint)(volume * Sqrt((int)((sumvarwy / iterationsCount - Pow((sumswy / iterationsCount), 2)) / iterationsCount)))));
            memory.WriteUInt32(MonteCarloAlgorithm_DZIndex,
                               checked ((uint)(volume * Sqrt((int)((sumvarwz / iterationsCount - Pow((sumswz / iterationsCount), 2)) / iterationsCount)))));
        }
예제 #17
0
 public virtual void Run(SimpleMemory memory)
 {
     // Adding 1 to the input so it's visible whether this actually has run, not just the untouched data was
     // sent back.
     memory.WriteInt32(Run_InputOutputInt32Index, memory.ReadInt32(Run_InputOutputInt32Index) + 1);
 }
예제 #18
0
        /// <summary>
        /// Makes the changes according to the matrix on the image.
        /// </summary>
        /// <param name="memory">The <see cref="SimpleMemory"/> object representing the accessible memory space.</param>
        public virtual void FilterImage(SimpleMemory memory)
        {
            ushort imageWidth  = (ushort)memory.ReadUInt32(FilterImage_ImageWidthIndex);
            ushort imageHeight = (ushort)memory.ReadUInt32(FilterImage_ImageHeightIndex);

            int factor            = memory.ReadInt32(FilterImage_FactorIndex);
            int offset            = memory.ReadInt32(FilterImage_OffsetIndex);
            int topLeftValue      = memory.ReadInt32(FilterImage_TopLeftIndex);
            int topMiddleValue    = memory.ReadInt32(FilterImage_TopMiddleIndex);
            int topRightValue     = memory.ReadInt32(FilterImage_TopRightIndex);
            int middleLeftValue   = memory.ReadInt32(FilterImage_MiddleLeftIndex);
            int pixelValue        = memory.ReadInt32(FilterImage_PixelIndex);
            int middleRightValue  = memory.ReadInt32(FilterImage_MiddleRightIndex);
            int bottomLeftValue   = memory.ReadInt32(FilterImage_BottomLeftIndex);
            int bottomMiddleValue = memory.ReadInt32(FilterImage_BottomMiddleIndex);
            int bottomRightValue  = memory.ReadInt32(FilterImage_BottomRightIndex);

            ushort topLeft      = 0;
            ushort topMiddle    = 0;
            ushort topRight     = 0;
            ushort middleLeft   = 0;
            ushort pixel        = 0;
            ushort middleRight  = 0;
            ushort bottomLeft   = 0;
            ushort bottomMiddle = 0;
            ushort bottomRight  = 0;

            int    pixelCountHelper = imageHeight * imageWidth * 3;
            ushort imageWidthHelper = (ushort)(imageWidth * 3);

            for (int x = 1; x < imageHeight - 1; x++)
            {
                for (int y = 3; y < imageWidthHelper - 3; y++)
                {
                    topLeft      = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper - imageWidthHelper - 3 + FilterImage_ImageStartIndex);
                    topMiddle    = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper - imageWidthHelper + FilterImage_ImageStartIndex);
                    topRight     = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper - imageWidthHelper + 3 + FilterImage_ImageStartIndex);
                    middleLeft   = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper - 3 + FilterImage_ImageStartIndex);
                    pixel        = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper + FilterImage_ImageStartIndex);
                    middleRight  = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper + 3 + FilterImage_ImageStartIndex);
                    bottomLeft   = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper + imageWidthHelper - 3 + FilterImage_ImageStartIndex);
                    bottomMiddle = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper + imageWidthHelper + FilterImage_ImageStartIndex);
                    bottomRight  = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper + imageWidthHelper + 3 + FilterImage_ImageStartIndex);

                    memory.WriteUInt32(x * imageWidthHelper + y + FilterImage_ImageStartIndex, CalculatePixelValue(
                                           topLeft, topMiddle, topRight,
                                           middleLeft, pixel, middleRight,
                                           bottomLeft, bottomMiddle, bottomRight,
                                           topLeftValue, topMiddleValue, topRightValue,
                                           middleLeftValue, pixelValue, middleRightValue,
                                           bottomLeftValue, bottomMiddleValue, bottomRightValue,
                                           factor, offset));
                }
            }
        }