Здравствуйте, Sinclair, Вы писали:
S>Можно всё же в студию полное тело метода FourNeighborAverage?
S>Можете, если хотите, сделать его generic с where T: Struct, IArray2d<T>.
Разумеется генерик, ради ж этого всё.
Без студии:
void FourNeighborAverage<T>(T array) where T : struct, IArray2d<int>
{
for(int y = 1, dy = array.DY - 1; y < dy; y++)
for(int x = 1, dx = array.DX - 1; x < dx; x++)
array[x, y] = array[x-1, y] + array[x+1, y] + array[x, y-1] + array[x, y+1];
}
Что здесь "так" в сравнении с твоим вариантом?
Здесь прикладное "знание" об алгоритме содержится в самом алгоритме, вот тут:
int x = 1, DX = array.dx — 1.
В твоём же алгоритме такие "знания" необходимо каким-то образом передавать в сам абстрактный индексер.
Мой индексер получается более простым и универсальным — это просто абстракция некоторой матрицы.
Учитывая новый ref-return, можно попробовать пойти еще дальше:
[cs]
interface IArray2d<T> {
...
ref T this[int x, int y] { get; } // только геттер
}
...
unsafe void FourNeighborAverage(T array) where T : struct, IArray2d<int>
{
int dx = array.DX;
for(int y = 1, dy = array.DY - 1; y < dy; y++) {
fixed(int* current = array[1, y])
fixed(int* end = array[dx, y])
fixed(int* it1 = array[0, y])
fixed(int* it2 = array[2, y])
fixed(int* it3 = array[1, y - 1])
fixed(int* it4 = array[1, y + 1]) {
int* c = current, _1 = it1, _2 = it2, _3 = it3, _4 = it4;
while(c < end)
*c++ = *_1++ + *_2++ + *_3++ + *_4++;
}
}
}
Не, знаю, стоит ли напоминать, что в алгоритмах обработки изображений почти всегда присутствует параметр stride, который задаёт "шаг" между строками в физической памяти. Этот параметр можно загнать в конкретную реализацию IArray2d, т.е. можно побить изображение на области в том числе вертикально, т.е. распараллелить работу произвольных алгоритмов.
S>Меня интересует не "индексер" (предоставленный, потенциально, библиотекой), а полный код, который должен писать прикладной программист.
А другой программист должен будет еще этот код читать, верно?