Sorting Network Search
Backtracking for Small Sorting Networks
Matching.cpp
Go to the documentation of this file.
1
3
4// MIT License
5//
6// Copyright (c) 2023 Ian Parberry
7//
8// Permission is hereby granted, free of charge, to any person obtaining a copy
9// of this software and associated documentation files (the "Software"), to
10// deal in the Software without restriction, including without limitation the
11// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12// sell copies of the Software, and to permit persons to whom the Software is
13// furnished to do so, subject to the following conditions:
14//
15// The above copyright notice and this permission notice shall be included in
16// all copies or substantial portions of the Software.
17//
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24// IN THE SOFTWARE.
25
26#include <algorithm>
27
28#include "Matching.h"
29
31
33 Initialize();
34} //constructor
35
38
39CMatching::CMatching(const CMatching& m){ //copy constructor
40 for(size_t i=0; i<m_nWidth+1; i++){
41 m_nMatching[i] = m.m_nMatching[i];
42 m_nMap[i] = m.m_nMap[i];
43
44 m_nStack[i] = m.m_nStack[i];
45 } //for
46} //copy constructor
47
49
51 for(size_t i=0; i<evenceil(m_nWidth); i++){
52 m_nMatching[i] = i;
53 m_nMap[i] = i;
54
55 m_nStack[i] = (int)i - 1;
56 } //for
57} //Initialize
58
61
63 size_t s = 4;
64 size_t i = m_nStack[s - 1];
65
66 while(i < 1 && s < oddfloor(m_nWidth)){
67 size_t temp = m_nMatching[s - 2];
68
69 for(size_t j=s-1; j>=2; j--){
70 m_nMatching[j - 1] = m_nMatching[j - 2];
71 m_nMap[m_nMatching[j - 1]] = j - 1;
72 } //for
73
74 m_nMatching[0] = temp;
75 m_nMap[temp] = 0;
76
77 for(size_t j=0; j<s; j++)
78 m_nStack[j] = (int)j - 1;
79
80 s += 2;
81 i = m_nStack[s - 1];
82 } //while
83
84 if(i > 0){
85 std::swap(m_nMatching[i - 1], m_nMatching[s - 2]);
86 m_nMap[m_nMatching[i - 1]] = i - 1;
87 m_nMap[m_nMatching[s - 2]] = s - 2;
88 m_nStack[s - 1] = (int)i - 1;
89 } //if
90
91 return m_nStack[i] >= 0;
92} //Next
93
98
99void CMatching::SwapPair(int m[], size_t i, size_t j){
100 const size_t i0 = 2*i;
101 const size_t i1 = i0 + 1;
102 const size_t j0 = 2*j;
103 const size_t j1 = j0 + 1;
104
105 std::swap(m[i0], m[j0]);
106 std::swap(m[i1], m[j1]);
107
108 for(size_t k=0; k<m_nWidth; k++)
109 if(m[k] == i0) m[k] = (int)j0;
110 else if(m[k] == (int)j0) m[k] = (int)i0;
111 else if(m[k] == (int)i1) m[k] = (int)j1;
112 else if(m[k] == (int)j1) m[k] = (int)i1;
113} //SwapPair
114
116
118 const size_t n = evenceil(m_nWidth);
119
120 int nCopy[MAXINPUTS + 1] = {0};
121
122 for(size_t j=0; j<n; j++)
123 nCopy[j] = (int)m_nMatching[m_nMap[j]^1];
124
125 size_t next = 1;
126
127 for(size_t j=0; j<n; j++){
128 const size_t src = std::max(next++, j/2 + 1);
129
130 if(nCopy[j] > int(2*src + 1))
131 SwapPair(nCopy, src, nCopy[j]/2);
132 } //for
133
134 size_t top = 0;
135
136 for(size_t k=0; k<n; k++)
137 if(nCopy[k] >= 0){
138 m_nMatching[top++] = k;
139 m_nMatching[top++] = nCopy[k];
140 nCopy[nCopy[k]] = -1;
141 } //if
142} //Normalize
143
147
148void CMatching::Swap(const size_t i, const size_t j){
149 const size_t i0 = m_nMap[2*i];
150 const size_t j0 = m_nMap[2*j];
151
152 m_nMatching[i0] = 2*j;
153 m_nMatching[j0] = 2*i;
154
155 m_nMap[m_nMatching[i0]] = i0;
156 m_nMap[m_nMatching[j0]] = j0;
157
158 const size_t i1 = m_nMap[2*i + 1];
159 const size_t j1 = m_nMap[2*j + 1];
160
161 m_nMatching[i1] = 2*j + 1;
162 m_nMatching[j1] = 2*i + 1;
163
164 m_nMap[m_nMatching[i1]] = i1;
165 m_nMap[m_nMatching[j1]] = j1;
166} //swap
167
171
172CMatching::operator std::string() const{
173 std::string str; //result string
174
175 for(size_t i=0; i<m_nWidth-1; i++) //for all but last entry
176 str += std::to_string(m_nMatching[i]) + " "; //append space separated
177
178 return str + std::to_string(m_nMatching[m_nWidth - 1]); //append last entry
179} //std::string
180
184
185size_t& CMatching::operator[](const size_t i){
186 return m_nMatching[i];
187} //operator[]
188
192
193const size_t CMatching::operator[](const size_t i) const{
194 return m_nMatching[i];
195} //operator[]
#define evenceil(n)
If odd, round up to make even.
Definition: Defines.h:38
#define MAXINPUTS
Maximum width, that is, number of inputs.
Definition: Defines.h:29
#define oddfloor(n)
If even, round down to make odd.
Definition: Defines.h:35
Interface for the matching CMatching.
Perfect matching.
Definition: Matching.h:39
bool Next()
Advance to next matching.
Definition: Matching.cpp:62
void Normalize()
Normalize.
Definition: Matching.cpp:117
CMatching()
Void constructor.
Definition: Matching.cpp:32
int m_nStack[MAXINPUTS+1]
Stack to remove recursion from permutation.
Definition: Matching.h:43
void Initialize()
Initialize.
Definition: Matching.cpp:50
size_t & operator[](const size_t)
Overloaded index operator.
Definition: Matching.cpp:185
void Swap(const size_t, const size_t)
Swap.
Definition: Matching.cpp:148
size_t m_nMap[MAXINPUTS+1]
Matching index map.
Definition: Matching.h:42
size_t m_nMatching[MAXINPUTS+1]
Matching.
Definition: Matching.h:41
void SwapPair(int[], size_t, size_t)
Swap pair.
Definition: Matching.cpp:99
static size_t m_nWidth
Comparator network width.
Definition: Settings.h:39