как это рефакторится?
Как бы это переписать по удобнее?что в результате хочешь получить? увеличение скорости выполнения? или улучшение читабельности? что-то еще?
return table[x[0], x[1] ] ( seg1, seg2 );
чтобы вместо table[ x[0], x[1] ] подставлялась нужна функция и вызывалась с параметрами (seg1, seg2)
время работы ускорить тоже не помешало бы. Но над оптимизацией пока не заморачивался вообще.
То есть хочется, чтобы эти функции задавались не в коде, а в табличке. Еще неплохо было бы, чтобы табличка сама строилась и создавалась в зависимости от заданных номеров функций.
Вот есть у нас четыре функции. пронумеруем их типа 1 2 3 4
И имеем в текстовом файлике табличку типа
1 1 1
2 3 4
2 1 3
хочу из нее получать табличку из функций, а потом ее использовать так, как написал в начале этого поста
чтобы вместо table[ x[0], x[1] ] подставлялась нужна функция и вызывалась с параметрами (seg1, seg2)а что мешает в табличке хранить функции?
public override Interval Calc(Interval seg1, Interval seg2, params Trio[] x)
{
var kind = CalcMatrix[(int)x[0], (int)x[1]);
switch (kind)
{
case CalcKind:V1:
return new Interval(seg1.a, seg1.b);
case CalcKind:V2:
return new Interval(seg2.a, seg2.b);
case CalcKind:Min:
return new Interval(Math.Min(seg1.a, seg2.a Math.Min(seg1.b, seg2.b;
case CalcKind:Max:
return new Interval(Math.Max(seg1.a, seg2.a Math.Max(seg1.b, seg2.b;
}
return null;
}
static readonly CalcKind[,] CalcMatrix = new CalcKind[3,3] {CalcKind.V1, CalcKind.V2, CalcKind.Min},...};
enum CalcKind
{
V1,
V2,
Min,
Max
}
а что мешает в табличке хранить функции?так сделать можно, но будет медленнее. будет тратиться время на передачу лишних параметров, и вызов функции. с конвеером еще могут быть проблемы.
И имеем в текстовом файлике табличку типаты уже сам себе ответил. как по русски написал, так и в коде делай.
1 1 1
2 3 4
2 1 3
хочу из нее получать табличку из функций, а потом ее использовать так, как написал в начале этого поста
public override Interval Calc(Interval seg1, Interval seg2, params Trio[] x)
{
return CalcFuncMatrix[(int)x[0], (int)x[1]seg1, seg2);
}
static readonly CalcKind[,] CalcMatrix = new CalcKind[3,3] {CalcKind.V1, CalcKind.V2, CalcKind.Min},...};
static readonly Func<Interval, Interval, Interval>[,] CalcFuncMatrix = MakeCalcFuncMatrix(CalcMatrix);
static Func<Interval, Interval, Interval>[,] MakeCalcFuncMatrix(CalcKind[,] matrix)
{
var result = new Func<Interval, Interval, Interval>[matrix.GetLength(0matrix.GetLength(1)];
for(int x = 0; x < matrix.GetLength(0); ++x)
for(int y = 0; y < matrix.GetLength(0); ++y)
{
switch (matrix[x,y])
{
case CalcKind:V1:
result[x,y] = (seg1, seg2) => new Interval(seg1.a, seg1.b);
break;
case CalcKind:V2:
result[x,y] = (seg1, seg2) => new Interval(seg2.a, seg2.b);
break;
case CalcKind:Min:
result[x,y] = (seg1, seg2) => new Interval(Math.Min(seg1.a, seg2.a Math.Min(seg1.b, seg2.b;
break;
case CalcKind:Max:
result[x,y] = (seg1, seg2) => new Interval(Math.Max(seg1.a, seg2.a Math.Max(seg1.b, seg2.b;
break;
}
}
return result;
}
enum CalcKind
{
V1,
V2,
Min,
Max
}
а если функций будет не четыре, а больше?
switch (kind)можно будет это как-нибудь ускорить? То есть при каком количестве функций на твой взгляд, вариант с созданием таблички из функций (то что говорит ) будет быстрее, чем свитч?
или "оно само по себе" все разумно и правильно (быстро) будет работать? типа слава суперкомпилятору, которые видит, что свитч идет по маленькому enum-у и невъебнно это оптимайзит, создавая табличку? или это совсем фантастика
или "оно само по себе" все разумно и правильно (быстро) будет работать? типа слава суперкомпилятору, которые видит, что свитч идет по маленькому enum-у и невъебнно это оптимайзит, создавая табличку? или это совсем фантастикада, switch компилятором оптимайзится через таблицу или аналог.
на вскидку, вариант со switch-ом будет всегда быстрее, чем функции.
но с функциями вариант красивее.
Если устраивают явные условия, то оставил бы в таком виде, тока немного подсократил (если я правильно понял, что у Trio только 3 указанные значения)
public override Interval Calc(Interval seg1, Interval seg2, params Trio[] x)
{
switch(x[0])
{
case Trio.False:
return x[1] == Trio.False
? new Interval(Math.Min(seg1.a, seg2.a Math.Min(seg1.b, seg2.b
: new Interval(seg1.a, seg1.b);
case Trio.True:
return x[1] == Trio.False
? new Interval(seg2.a, seg2.b)
: new Interval(Math.Max(seg1.a, seg2.a Math.Max(seg1.b, seg2.b;
case Trio.Indef:
return x[1] == Trio.False
? new Interval(seg2.a, seg2.b)
: new Interval(Math.Max(seg1.a, seg2.a Math.Max(seg1.b, seg2.b;
}
}
public override Interval calc(Interval seg1, Interval seg2, params Trio[] x)
{
if x[0] == Trio.False) && (x[1] == Trio.False
return new Interval(Math.Min(seg1.a, seg2.a Math.Min(seg1.b, seg2.b;
if x[0] == Trio.False) && (x[1] == Trio.True
return new Interval(seg1.a, seg1.b);
if x[0] == Trio.False) && (x[1] == Trio.Indef
return Interval.Union(calc(seg1, seg2, Trio.False, Trio.False
calc(seg1, seg2, Trio.False, Trio.True;
if x[0] == Trio.True) && (x[1] == Trio.False
return new Interval(seg2.a, seg2.b);
if x[0] == Trio.True) && (x[1] == Trio.True
return new Interval(Math.Max(seg1.a, seg2.a Math.Max(seg1.b, seg2.b;
if x[0] == Trio.True) && (x[1] == Trio.Indef
return Interval.Union(calc(seg1, seg2, Trio.True, Trio.False
calc(seg1, seg2, Trio.True, Trio.True;
if x[0] == Trio.Indef) && (x[1] == Trio.False
return Interval.Union(calc(seg1, seg2, Trio.False, Trio.False
calc(seg1, seg2, Trio.True, Trio.False;
if x[0] == Trio.Indef) && (x[1] == Trio.True
return Interval.Union(calc(seg1, seg2, Trio.False, Trio.True
calc(seg1, seg2, Trio.True, Trio.True;
if x[0] == Trio.Indef) && (x[1] == Trio.Indef
return Interval.Union(calc(seg1, seg2, Trio.False, Trio.False
calc(seg1, seg2, Trio.False, Trio.True
calc(seg1, seg2, Trio.True, Trio.False
calc(seg1, seg2, Trio.True, Trio.True;
return null;
}
Отличие от старых в том, что если один за параметров Indef, то для ответа нужно взять максимум (Union) из ответов, получаемых подставлением вместо Indef как False, так и True
Понятно, что формулы можно соптимайзить, сократить, убить повторяющиеся части. но пока для наглядности - так как есть
Это были формулы для функционального элемента AND.
Для XOR они вот такие: (вообще 1 фунция только встречается вместо 4-х)
public override Interval calc(Interval seg1, Interval seg2, params Trio[] x)
{
if x[0] == Trio.False) && (x[1] == Trio.False
return new Interval(Math.Max(seg1.a, seg2.a Math.Max(seg1.b, seg2.b;
if x[0] == Trio.False) && (x[1] == Trio.True
return new Interval(Math.Max(seg1.a, seg2.a Math.Max(seg1.b, seg2.b;
if x[0] == Trio.False) && (x[1] == Trio.Indef
return Interval.Union(calc(seg1, seg2, Trio.False, Trio.False
calc(seg1, seg2, Trio.False, Trio.True;
if x[0] == Trio.True) && (x[1] == Trio.False
return new Interval(Math.Max(seg1.a, seg2.a Math.Max(seg1.b, seg2.b;
if x[0] == Trio.True) && (x[1] == Trio.True
return new Interval(Math.Max(seg1.a, seg2.a Math.Max(seg1.b, seg2.b;
if x[0] == Trio.True) && (x[1] == Trio.Indef
return Interval.Union(calc(seg1, seg2, Trio.True, Trio.False
calc(seg1, seg2, Trio.True, Trio.True;
if x[0] == Trio.Indef) && (x[1] == Trio.False
return Interval.Union(calc(seg1, seg2, Trio.False, Trio.False
calc(seg1, seg2, Trio.True, Trio.False;
if x[0] == Trio.Indef) && (x[1] == Trio.True
return Interval.Union(calc(seg1, seg2, Trio.False, Trio.True
calc(seg1, seg2, Trio.True, Trio.True;
if x[0] == Trio.Indef) && (x[1] == Trio.Indef
return Interval.Union(calc(seg1, seg2, Trio.False, Trio.False
calc(seg1, seg2, Trio.False, Trio.True
calc(seg1, seg2, Trio.True, Trio.False
calc(seg1, seg2, Trio.True, Trio.True;
return null;
}
избыточность очевидна. нужно будет раскрыть скобки и все там посокращать. но записано так, чтобы можно было проверять правильность
после скоращения для XOR выходит такой вариант:
public override Interval calc(Interval seg1, Interval seg2, params Trio[] x)
{
return new Interval(Math.Max(seg1.a, seg2.a Math.Max(seg1.b, seg2.b;
}
Оставить комментарий
lubanj
если бы нужно было просто по табличке значения возвращать, я бы и загнал бы табличку и потом бы делал.
Но тут получается есть табличка 3х3 в клетках которой стоят не значения, а некоторые функции
в данном случае возможно четыре случая
то бишь есть четыре функции вычисления нового интервала по старым двум.
В других случаях вроде будут те же функции, но в другом порядке.
Как бы это переписать по удобнее?