```
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
class Program
{
static public unsafe double CalcAmix(int n, double[] XY, double[] ai, double[,] kijm, out double[,] Aij, out double[] sumAi)
{
Aij = new double[n, n];
sumAi = new double[n];
return CalcAmixInner(n, XY, ai, kijm, Aij, sumAi);
}
static public unsafe double CalcAmixInner(int n, double[] XY, double[] ai, double[,] kijm, double[,] Aij, double[] sumAi)
{
double amix = 0;
int UpperBound0 = Aij.GetUpperBound(0);
int UpperBound1 = Aij.GetUpperBound(1);
fixed (double* ptr = Aij, aiPtr = ai, kijmPtr = kijm)
{
double* element = ptr;
double* kijelement = kijmPtr;
double* aielement = aiPtr;
for (int i = 0; i <= UpperBound0; i++)
{
for (int j = 0; j <= UpperBound1; j++)
{
if (i == j)
*element = *aielement;
else
*element = Math.Sqrt(*(aiPtr + i) * *(aiPtr + j)) * (1 - *kijelement);
element++;
kijelement++;
}
aielement++;
}
}
fixed (double* ptrAij = Aij, ptrXY = XY, ptrsumAI = sumAi)
{
double* elementAij = ptrAij;
double* elementsumAI = ptrsumAI;
double* elementXy = ptrXY;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
*elementsumAI += *elementXy * *elementAij;
elementXy++;
elementAij++;
}
amix += *elementsumAI * *(ptrXY + i);
elementXy = ptrXY;
elementsumAI++;
}
}
return amix;
}
static public double CalcAmixArrays(int n, double[] XY, double[] ai, double[,] kijm, out double[,] Aij, out double[] sumAi)
{
Aij = new double[n, n];
sumAi = new double[n];
return CalcAmixArraysInner(n, XY, ai, kijm, Aij, sumAi);
}
static public double CalcAmixArraysInner(int n, double[] XY, double[] ai, double[,] kijm, double[,] Aij, double[] sumAi)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i == j)
Aij[i,j] = ai[i];
else
Aij[i,j] = Math.Sqrt(ai[i] * ai[j]) * (1 - kijm[i,j]);
}
}
double amix = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
sumAi[i] += XY[j] * Aij[i,j];
amix += sumAi[i] * XY[i];
}
return amix;
}
static public double CalcAmixArraysInner2(int n, double[] XY, double[] ai, double[,] kijm, double[,] Aij, double[] sumAi)
{
for (int i = 0; i < n; i++)
{
var aii = ai[i];
for (int j = 0; j < n; j++)
Aij[i, j] = Math.Sqrt(aii * ai[j]) * (1 - kijm[i, j]);
Aij[i, i] = aii;
}
double amix = 0;
for (int i = 0; i < n; i++)
{
double sum = 0;
for (int j = 0; j < n; j++)
sum += XY[j] * Aij[i, j];
sumAi[i] = sum;
amix += sum * XY[i];
}
return amix;
}
static public double CalcAmixArraysInner3(int n, double[] XY, double[] ai, double[,] kijm, double[,] Aij, double[] sumAi)
{
double amix = 0;
for (int i = 0; i < n; i++)
{
var aii = ai[i];
double sum = XY[i] * aii;
for (int j = 0; j < n; j++)
{
var value = Math.Sqrt(aii * ai[j]) * (1 - kijm[i, j]);
Aij[i, j] = value;
sum += XY[j] * value;
}
sum -= XY[i] * Aij[i, i];
Aij[i, i] = aii;
sumAi[i] = sum;
amix += sum * XY[i];
}
return amix;
}
static public double CalcAmixSpansInner(int n,
ReadOnlySpan<double> XY,
ReadOnlySpan<double> ai,
double[,] kijm,
double[,] Aij,
Span<double> sumAi)
{
for (int i = 0; i < n; i++)
{
var aii = ai[i];
for (int j = 0; j < n; j++)
Aij[i, j] = Math.Sqrt(aii * ai[j]) * (1 - kijm[i, j]);
Aij[i, i] = aii;
}
double amix = 0;
for (int i = 0; i < n; i++)
{
double sum = 0;
for (int j = 0; j < n; j++)
sum += XY[j] * Aij[i, j];
sumAi[i] = sum;
amix += sum * XY[i];
}
return amix;
}
static public unsafe double CalcAmixSpansInner2(int n,
ReadOnlySpan<double> XY,
ReadOnlySpan<double> ai,
double[,] kijm,
double[,] Aij,
Span<double> sumAi)
{
fixed (double * kijmPtr = kijm, AijPtr = Aij)
{
var kijmSpan = new ReadOnlySpan<double>(kijmPtr, kijm.Length);
var kijmRowISpan = kijmSpan.Slice(0);
var AijSpan = new Span<double>(AijPtr, Aij.Length);
var AijRowISpan = AijSpan.Slice(0);
for (int i = 0; i < n; i++)
{
var aii = ai[i];
for (int j = 0; j < n; j++)
AijRowISpan[j] = Math.Sqrt(aii * ai[j]) * (1 - kijmRowISpan[j]);
AijRowISpan[i] = aii;
kijmRowISpan = kijmRowISpan.Slice(n);
AijRowISpan = AijRowISpan.Slice(n);
}
double amix = 0;
AijRowISpan = AijSpan.Slice(0);
for (int i = 0; i < n; i++)
{
double sum = 0;
for (int j = 0; j < n; j++)
sum += XY[j] * AijRowISpan[j];
sumAi[i] = sum;
amix += sum * XY[i];
AijRowISpan = AijRowISpan.Slice(n);
}
return amix;
}
}
static public unsafe double CalcAmixSpansInner3(int n,
ReadOnlySpan<double> XY,
ReadOnlySpan<double> ai,
double[,] kijm,
double[,] Aij,
Span<double> sumAi)
{
fixed (double* kijmPtr = kijm, AijPtr = Aij)
{
var kijmSpan = new ReadOnlySpan<double>(kijmPtr, kijm.Length);
var kijmRowISpan = kijmSpan.Slice(0);
var AijSpan = new Span<double>(AijPtr, Aij.Length);
var AijRowISpan = AijSpan.Slice(0);
double amix = 0;
for (int i = 0; i < n; i++)
{
var aii = ai[i];
double sum = XY[i] * aii;
for (int j = 0; j < n; j++)
{
var value = Math.Sqrt(aii * ai[j]) * (1 - kijmRowISpan[j]);
AijRowISpan[j] = value;
sum += XY[j] * value;
}
sum -= XY[i] * AijRowISpan[i];
AijRowISpan[i] = aii;
sumAi[i] = sum;
amix += sum * XY[i];
kijmRowISpan = kijmRowISpan.Slice(n);
AijRowISpan = AijRowISpan.Slice(n);
}
return amix;
}
}
static Random _random = new Random(123);
static double[] MakeRandomOneDimensionalArray(int n)
=> Enumerable.Range(0, n)
.Select(i => _random.NextDouble())
.ToArray();
static double[,] MakeRandomTwoDimensionalArray(int n)
{
var arr = new double[n, n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
arr[i, j] = _random.NextDouble();
return arr;
}
static void TimeIt(string caption, Action action)
{
const int iterationCount = 5;
var stopwatch = new Stopwatch();
stopwatch.Start();
for(int i = 0; i < iterationCount; i++)
action();
stopwatch.Stop();
Console.WriteLine($"{caption}: Average: {stopwatch.ElapsedMilliseconds / iterationCount} ms");
}
static void Main()
{
int n = 10000;
var xy = MakeRandomOneDimensionalArray(n);
var ai = MakeRandomOneDimensionalArray(n);
var kijm = MakeRandomTwoDimensionalArray(n);
var aij = new double[n, n];
var sumai = new double[n];
TimeIt("Original pointers", () => CalcAmixInner(n, xy, ai, kijm, aij, sumai));
TimeIt("Back to arrays", () => CalcAmixArraysInner(n, xy, ai, kijm, aij, sumai));
TimeIt("Back to arrays 2", () => CalcAmixArraysInner2(n, xy, ai, kijm, aij, sumai));
TimeIt("Back to arrays 3", () => CalcAmixArraysInner3(n, xy, ai, kijm, aij, sumai));
TimeIt("Spans", () => CalcAmixSpansInner(n, xy, ai, kijm, aij, sumai));
TimeIt("Spans 2", () => CalcAmixSpansInner2(n, xy, ai, kijm, aij, sumai));
TimeIt("Spans 3", () => CalcAmixSpansInner3(n, xy, ai, kijm, aij, sumai));
}
}
```