Sorting Network Verify and Draw
Check Whether Comparator Networks Sort and Draw Them
CMain.cpp
Go to the documentation of this file.
1
3
4// MIT License
5//
6// Copyright (c) 2022 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 "CMain.h"
27
28#include "Defines.h"
29#include "Helpers.h"
30#include "WindowsHelpers.h"
31#include "DialogBox.h"
32
33#include "Bubblesort.h"
34#include "OddEven.h"
35#include "Bitonic.h"
36#include "Pairwise.h"
37
39// Constructors and destructors
40
41#pragma region Constructors and destructors
42
45
46CMain::CMain(const HWND hwnd):
47 m_hWnd(hwnd)
48{
49 CreateMenus(); //create the menu bar
50 SetDrawStyle(m_eDrawStyle); //check mark next to draw style in menu
51
52 m_gdiplusToken = InitGDIPlus(); //initialize GDI+
53} //constructor
54
56
58 delete m_pSortingNetwork;
59 Gdiplus::GdiplusShutdown(m_gdiplusToken);
60} //destructor
61
62#pragma endregion Constructors and destructors
63
65// Drawing functions
66
67#pragma region Drawing functions
68
73
75 PAINTSTRUCT ps; //paint structure
76 HDC hdc = BeginPaint(m_hWnd, &ps); //device context
77 Gdiplus::Graphics graphics(hdc); //GDI+ graphics object
78 graphics.Clear(Gdiplus::Color::White); //clear to white
79
80 Gdiplus::Bitmap* pBitmap = GetBitmap();
81
82 if(pBitmap){
83 const int w = pBitmap->GetWidth(); //bitmap width
84 const int h = pBitmap->GetHeight(); //bitmap height
85
86 //get client area width and height
87
88 RECT rectClient; //for client rectangle
89 GetClientRect(m_hWnd, &rectClient); //get client rectangle
90 const int nClientWidth = rectClient.right - rectClient.left; //client width
91 const int nClientHeight = rectClient.bottom - rectClient.top; //client height
92
93 //compute the drawing scale for the bitmap
94
95 const UINT margin = 20; //margin width
96
97 const float xscale = float(nClientWidth - 2*margin)/w; //horizontal scale
98 const float yscale = float(nClientHeight - 2*margin)/h; //vertical scale
99 const float scale = min(min(xscale, yscale), 1); //actual scale
100
101 //compute the destination rectangle
102
103 Gdiplus::Rect rectDest; //destination rectangle
104
105 rectDest.Width = (int)std::floor(scale*w);
106 rectDest.Height = (int)std::floor(scale*h);
107
108 rectDest.X = max(margin, (nClientWidth - rectDest.Width)/2);
109 rectDest.Y = max(margin, (nClientHeight - rectDest.Height)/2);
110
111 //draw the bitmap to the window
112
113 graphics.DrawImage(pBitmap, rectDest);
114 } //if
115
116 EndPaint(m_hWnd, &ps); //this must be done last
117} //OnPaint
118
119#pragma endregion Drawing functions
120
122// Menu functions
123
124#pragma region Menu functions
125
129
131 m_hMenuBar = CreateMenu(); //create menu bar
132
133 CreateFileMenu(m_hMenuBar); //attach File menu to menu bar
134 CreateGenerateMenu(m_hMenuBar); //attach Generate menu to menu bar
135 CreateViewMenu(m_hMenuBar); //attach View menu to menu bar
136 CreateHelpMenu(m_hMenuBar); //attach Help menu to menu bar
137
138 SetMenu(m_hWnd, m_hMenuBar); //attach menu bar to app window
139} //CreateMenus
140
143
145 EnableMenuItem(m_hMenuBar, IDM_FILE_EXPORT_PNG, MF_ENABLED);
146 EnableMenuItem(m_hMenuBar, IDM_FILE_EXPORT_TEX, MF_ENABLED);
147 EnableMenuItem(m_hMenuBar, IDM_FILE_EXPORT_SVG, MF_ENABLED);
148 EnableMenuItem(m_hMenuBar, IDM_FILE_VERIFY, MF_ENABLED);
149} //EnableMenus
150
151#pragma endregion Menu functions
152
154// Other functions
155
158
159Gdiplus::Bitmap* CMain::GetBitmap(){
160 return (m_pSortingNetwork? m_pSortingNetwork->GetBitmap(): nullptr);
161} //GetBitmap
162
168
170 delete m_pSortingNetwork;
172
173 if(Load(m_hWnd, m_pSortingNetwork, m_wstrName) == S_OK) //file read succeeded
174 EnableMenus();
175
176 else{ //file read failed
177 delete m_pSortingNetwork;
178 m_pSortingNetwork = nullptr;
179
180 EnableMenuItem(m_hMenuBar, IDM_FILE_EXPORT_PNG, MF_GRAYED);
181 EnableMenuItem(m_hMenuBar, IDM_FILE_EXPORT_TEX, MF_GRAYED);
182 EnableMenuItem(m_hMenuBar, IDM_FILE_EXPORT_SVG, MF_GRAYED);
183 EnableMenuItem(m_hMenuBar, IDM_FILE_VERIFY, MF_GRAYED);
184 } //else
185} //Read
186
190
191template<class t> void CMain::Generate(){
192 UINT n = 0; //for number of inputs
193
194 if(SUCCEEDED(CDialogBox().GetNumInputs(m_hWnd, n))){ //got number of inputs
195 delete m_pSortingNetwork; //delete old sorting network
196
197 t* p = new t(n); //sorting network
198 m_wstrName = p->GetName(); //get name
199 m_pSortingNetwork = p; //this is the new sorting network
200
201 EnableMenus();
202 } //if
203} //Generate
204
205template void CMain::Generate<CBubbleSortMin>();
206template void CMain::Generate<CBubbleSortMax>();
207template void CMain::Generate<CBubbleSort>();
208
214
215template<class t> void CMain::GeneratePowerOf2(){
216 UINT n = 0; //for number of inputs
217
218 if(SUCCEEDED(CDialogBox().GetNumInputs(m_hWnd, n))){ //got number of inputs
219 delete m_pSortingNetwork; //delete old sorting network
220
221 t* p = new t(CeilLog2(n)); //sorting network with inputs rounded up to next power of 2
222 if(!IsPowerOf2(n))p->Prune(n); //prune unneeded channels and comparators
223 m_wstrName = p->GetName(); //get name
224 m_pSortingNetwork = p; //this is the new sorting network
225
226 EnableMenus();
227 } //if
228} //GeneratePowerOf2
229
230template void CMain::GeneratePowerOf2<COddEvenSort>();
231template void CMain::GeneratePowerOf2<CBitonicSort>();
232template void CMain::GeneratePowerOf2<CPairwiseSort>();
233
236
238 if(m_pSortingNetwork) //safety
240} //Draw
241
245
246HRESULT CMain::Export(const eExport t){
248} //Export
249
265
267 if(m_pSortingNetwork == nullptr)return false; //bail and fail
268
269 bool result = false; //result
270
271 const std::string strInputs = std::to_string(m_pSortingNetwork->GetNumInputs());
272 const std::string strDepth = std::to_string(m_pSortingNetwork->GetDepth());
273 const std::string strSize = std::to_string(m_pSortingNetwork->GetSize());
274
275 const std::string strDetails = "of size " + strSize + " and depth " + strDepth;
276
277 UINT nIcon = 0; //for icon flag in message box
278 std::string s; //for message box text
279
280 bool bSorts = false; //true if it sorts
281 bool bUnknown = false; //true if sorting status is unknown
282
285
286 else{
287 s = "Sorting network verification is Co-NP-complete.";
288 s += " This may take a long time. Are you sure you want to proceed?";
289
290 const int id = MessageBox(nullptr, s.c_str(), "Verify", MB_ICONQUESTION | MB_YESNO);
291
292 if(id == IDYES)
294 else bUnknown = true;
295 } //else
296
297 if(bSorts){
298 s = "This is a " + strInputs + "-input sorting network " + strDetails + ".";
299 nIcon = MB_ICONINFORMATION;
300 } //if
301
302 else if(bUnknown){
303 s = "This is a " + strInputs + "-input comparator network " + strDetails + ".";
304 nIcon = MB_ICONINFORMATION;
305 } //else if
306
307 else{
308 s = "This is a " + strInputs + "-input comparator network " + strDetails +
309 " that is not a sorting network.";
310 nIcon = MB_ICONERROR;
311 } //else
312
313 //first normal form
314
316 s += " It is in First Normal Form.";
317 else s += " It is not in First Normal Form.";
318
319 //redundant comparators
320
321 if(bSorts){
322 const UINT nUnused = m_pSortingNetwork->GetUnused();
323 result = nUnused > 0;
324
325 const std::string strUnused = std::to_string(nUnused);
326
327 s += " There are " + (nUnused == 0? "no": strUnused) + " redundant comparators.";
328 } //if
329
330 //now display the message box and exit
331
332 MessageBox(nullptr, s.c_str(), "Verify", nIcon | MB_OK);
333 return result;
334} //Verify
335
338
340 m_eDrawStyle = d;
341
342 switch(d){
343 case eDrawStyle::Vertical:
344 CheckMenuItem(m_hMenuBar, IDM_VIEW_VERTICAL, MF_CHECKED);
345 CheckMenuItem(m_hMenuBar, IDM_VIEW_HORIZONTAL, MF_UNCHECKED);
346 break;
347
348 case eDrawStyle::Horizontal:
349 CheckMenuItem(m_hMenuBar, IDM_VIEW_VERTICAL, MF_UNCHECKED);
350 CheckMenuItem(m_hMenuBar, IDM_VIEW_HORIZONTAL, MF_CHECKED);
351 break;
352 } //switch
353} //SetDrawStyle
Interface for Batcher's bitonic sorting network.
Interface for the bubblesort sorting network.
Interface for the main class CMain.
Useful definitions.
eDrawStyle
Drawing style.
Definition: Defines.h:34
eExport
Export type.
Definition: Defines.h:42
Interface for CDialogBox.
UINT CeilLog2(const UINT n)
Ceiling of log base 2.
Definition: Helpers.cpp:52
bool IsPowerOf2(const UINT n)
Power of 2 test.
Definition: Helpers.cpp:40
Header for useful helper functions.
Interface for Batcher's odd-even sorting network.
Interface for the pairwise sorting network.
void CreateFileMenu(HMENU hParent)
Create File menu.
HRESULT Load(HWND hwnd, CComparatorNetwork *pNet, std::wstring &wstrName)
Load comparator network.
HRESULT ExportImage(const eExport t, HWND hwnd, CRenderableComparatorNet *pNet, std::wstring &wstrName)
Export.
void CreateGenerateMenu(HMENU hParent)
Create Generate menu.
ULONG_PTR InitGDIPlus()
Initialize GDI+.
void CreateHelpMenu(HMENU hParent)
Create Help menu.
void CreateViewMenu(HMENU hParent)
Create View menu.
Interface for some helpful Windows-specific functions.
#define IDM_FILE_EXPORT_PNG
Menu id for Export PNG.
#define IDM_FILE_VERIFY
Menu id for Verify.
#define IDM_FILE_EXPORT_TEX
Menu id for Export TeX.
#define IDM_VIEW_HORIZONTAL
Menu id for horizontal view.
#define IDM_FILE_EXPORT_SVG
Menu id for Export SVG.
#define IDM_VIEW_VERTICAL
Menu id for vertical view.
const UINT GetDepth() const
Get depth.
const bool FirstNormalForm() const
Test for first normal form.
const UINT GetSize() const
Get size.
const UINT GetNumInputs() const
Get number of inputs.
Custom dialog box.
Definition: DialogBox.h:36
void SetDrawStyle(const eDrawStyle)
Set drawing style.
Definition: CMain.cpp:339
void CreateMenus()
Create menus.
Definition: CMain.cpp:130
~CMain()
Destructor.
Definition: CMain.cpp:57
std::wstring m_wstrName
File name.
Definition: CMain.h:44
CMain(const HWND)
Constructor.
Definition: CMain.cpp:46
void Draw()
Draw comparator network to bitmap.
Definition: CMain.cpp:237
void Read()
Read comparator network from file.
Definition: CMain.cpp:169
void GeneratePowerOf2()
Generate sorting network.
Definition: CMain.cpp:215
ULONG_PTR m_gdiplusToken
GDI+ token.
Definition: CMain.h:41
HRESULT Export(const eExport)
Export image file.
Definition: CMain.cpp:246
eDrawStyle m_eDrawStyle
Drawing style.
Definition: CMain.h:46
void EnableMenus()
Enable menus.
Definition: CMain.cpp:144
HMENU m_hMenuBar
Handle to the menu bar.
Definition: CMain.h:42
Gdiplus::Bitmap * GetBitmap()
Get pointer to bitmap.
Definition: CMain.cpp:159
void Generate()
Generate sorting network.
Definition: CMain.cpp:191
void OnPaint()
Paint the client area of the window.
Definition: CMain.cpp:74
CSortingNetwork * m_pSortingNetwork
Pointer to the sorting network.
Definition: CMain.h:48
bool Verify()
Verify that comparator network sorts.
Definition: CMain.cpp:266
HWND m_hWnd
Window handle.
Definition: CMain.h:40
Gdiplus::Bitmap * GetBitmap()
Get bitmap pointer.
void Draw(const eDrawStyle)
Draw to a Gdiplus::Bitmap.
Sorting network.
const UINT GetUnused() const
Get number of unused comparators.
bool sorts()
Does it sort?