summaryrefslogtreecommitdiff
path: root/casa/covering/state/CoveringArraySubRow.C
blob: b66f5462cc13276e2098cded1212814ac07e82dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright 2008, 2009 Brady J. Garvin

// This file is part of Covering Arrays by Simulated Annealing (CASA).

// CASA is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// CASA is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with CASA.  If not, see <http://www.gnu.org/licenses/>.


#include "covering/state/CoveringArray.H"
#include "CombinadicIterator.H"

using namespace std;

void CoveringArray::SubRow::updateTracking(const Array<unsigned>values) {
  assert(values.getSize() == columns.getSize());
  const Options&options = owner.coverage.getOptions();
  unsigned strength = owner.coverage.getStrength();
  unsigned limit = options.getSize();
  unsigned changes = 0;
  Array<unsigned>oldRow(limit);
  Array<unsigned>newRow(limit);
  Array<unsigned>changedColumns(columns.getSize());
  for (unsigned i = limit; i--;) {
    oldRow[i] = owner(row, i);
  }
  for (unsigned i = limit, j = values.getSize(); i--;) {
    if (j && (columns[j - 1] == i)) {
      newRow[i] = values[--j];
    } else {
      newRow[i] = oldRow[i];
    }
  }
  for (unsigned i = 0; i < limit; ++i) {
    if (newRow[i] != oldRow[i]) {
      changedColumns[changes++] = i;
    }
  }
  changedColumns = Array<unsigned>(changedColumns, changes);
  Array<unsigned>firsts = options.getFirstSymbols();
  Array<unsigned>counts = options.getSymbolCounts();
  for (CombinadicIterator combo(limit, strength, changedColumns);
       combo;
       ++combo) {
    const Array<unsigned>updateColumns = *combo;
    Array<unsigned>oldSymbols(strength);
    Array<unsigned>newSymbols(strength);
    for (unsigned j = strength; j--;) {
      unsigned column = updateColumns[j];
      oldSymbols[j] = oldRow[column];
      newSymbols[j] = newRow[column];
    }
    Coverage<unsigned>::Entry lost =
      owner.coverage.hintGet(updateColumns, firsts, counts, oldSymbols);
    assert(lost); // Assert that what we lost is something we had to lose.
    if (--lost == 0) {
      --owner.coverageCount;
      if (owner.trackingNoncoverage) {
	Array<unsigned>separateCopyOfSymbols(oldSymbols.getSize());
	for (unsigned j = oldSymbols.getSize(); j--;) {
	  separateCopyOfSymbols[j] = oldSymbols[j];
	}
	bool successfulInsertion =
	  owner.noncoverage->insert(separateCopyOfSymbols).second;
	assert(successfulInsertion);
	(void)successfulInsertion; // This is unused without assertions.
      }
    } else {
      --owner.multipleCoverageCount;
    }
    Coverage<unsigned>::Entry gained =
      owner.coverage.hintGet(updateColumns, firsts, counts, newSymbols);
    if (++gained == 1) {
      ++owner.coverageCount;
      if (owner.trackingNoncoverage) {
	Array<unsigned>separateCopyOfSymbols(newSymbols.getSize());
	for (unsigned j = newSymbols.getSize(); j--;) {
	  separateCopyOfSymbols[j] = newSymbols[j];
	}
	bool successfulErasure =
	  (bool)owner.noncoverage->erase(separateCopyOfSymbols);
	assert(successfulErasure);
	(void)successfulErasure; // This is unused without assertions.
      }
    } else {
      ++owner.multipleCoverageCount;
    }
  }
  owner.autoFinalizeSubstitutions();
}

CoveringArray::SubRow::operator Array<unsigned>() const {
  typedef map<pair<unsigned, unsigned>, unsigned>::const_iterator Substitution;
  Substitution end = owner.substitutions->end();
  unsigned size = columns.getSize();
  Array<unsigned>result(size);
  pair<unsigned, unsigned>key(row,0);
  for (unsigned i = size; i--;) {
    key.second = columns[i];
    Substitution substitution = owner.substitutions->find(key);
    result[i] =
      (substitution == end) ?
      owner.array[row][key.second] :
      substitution->second;
  }
  return result;
}
CoveringArray::SubRow&CoveringArray::SubRow::operator =
  (const Array<unsigned>values) {
  assert(values.getSize() == columns.getSize());
  if (owner.trackingCoverage) {
    updateTracking(values);
  }
  pair<unsigned, unsigned>key(row, 0);
  for (unsigned i = columns.getSize(); i--;) {
    key.second = columns[i];
    (*owner.substitutions)[key] = values[i];
  }
  return *this;
}