1 /*
2 Copyright (c) 2005-2020 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 // Polygon overlay
18 //
19 // Don't want warnings about deprecated sscanf, getenv
20 #ifndef _CRT_SECURE_NO_DEPRECATE
21 #define _CRT_SECURE_NO_DEPRECATE
22 #endif
23 #define _MAIN_C_ 1
24 #include <iostream>
25 #include <iomanip>
26 #include <algorithm>
27 #include <cstring>
28
29 #include "tbb/tick_count.h"
30 #include "pover_global.h"
31 #include "polyover.h"
32 #include "pover_video.h"
33 #include "polymain.h"
34
35 using namespace std;
36
37 #if _DEBUG
38 const char *faceNames[] = { "North", "East", "South", "West" };
39 #endif
40
41 /**
42 **/
main(int argc,char ** argv)43 int main( int argc, char **argv) {
44 pover_video poly;
45 poly.threaded = true;
46 gVideo = &poly;
47
48 if(!initializeVideo(argc, argv)) {
49 return 1;
50 }
51
52 gIsGraphicalVersion = poly.graphic_display();
53 if(argc > 1) {
54 if(!ParseCmdLine(argc, argv)) {
55 if(gIsGraphicalVersion) rt_sleep(10000);
56 // if graphical, we haven't opened the console window so all the error messages we
57 // so carefully wrote out disappeared into the ether. :(
58 exit(1);
59 }
60 }
61
62 if(gCsvFilename != NULL) {
63 #define BUFLEN 1000
64 std::string fname_buf = gCsvFilename;
65 fname_buf += ".csv";
66 gCsvFile.open(fname_buf.c_str());
67 }
68
69 // we have gMapXSize and gMapYSize determining the number of "squares"
70 // we have g_xwinsize and g_ywinsize the total size of the window
71 // we also have BORDER_SIZE the size of the border between maps
72 // we need to determine
73 // g_polyBoxSize -- the number of pixels on each size of each square
74
75 if(gIsGraphicalVersion) {
76 int xpixelsPerMap = (g_xwinsize - 4*BORDER_SIZE) / 3; // three maps, with borders between and outside
77 gMapXSize = xpixelsPerMap; // make the boxes one per pixel
78 gPolyXBoxSize = xpixelsPerMap / gMapXSize;
79 int ypixelsPerMap = (g_ywinsize - 2*BORDER_SIZE); // one map vertically
80 gMapYSize = ypixelsPerMap; // one pixel per box, rather.
81
82 gPolyYBoxSize = ypixelsPerMap / gMapYSize;
83 if((gPolyXBoxSize == 0) || (gPolyYBoxSize == 0)) {
84 cout << "The display window is not large enough to show the maps" << std::endl;
85 int minxSize = 4*BORDER_SIZE + 3*gMapXSize;
86 int minySize = 2*BORDER_SIZE + gMapYSize;
87 cout << " Should be at least " << minxSize << " x " << minySize << "." << std::endl;
88 return 1;
89 }
90 map2XLoc = 2*BORDER_SIZE + gMapXSize * gPolyXBoxSize;
91 maprXLoc = 3*BORDER_SIZE + 2 * gMapXSize * gPolyXBoxSize;
92
93 }
94 else { // not gIsGraphicalVersion
95 // gMapXSize, gMapYSize, gNPolygons defined in pover_global.h
96 }
97
98 // create two polygon maps
99 SetRandomSeed(gMyRandomSeed); // for repeatability
100
101 gVideo->main_loop();
102 }
103
Usage(int argc,char ** argv)104 void Usage(int argc, char **argv) {
105 char *cmdTail = strrchr(*argv, '\\');
106 if(cmdTail == NULL) {
107 cmdTail = *argv;
108 }
109 else {
110 cmdTail++;
111 }
112 cout << cmdTail << " [threads[:threads2]] [--polys npolys] [--size nnnxnnn] [--seed nnn]" << std::endl;
113 cout << "Create polygon maps and overlay them." << std::endl << std::endl;
114 cout << "Parameters:" << std::endl;
115 cout << " threads[:threads2] - number of threads to run" << std::endl;
116 cout << " --polys npolys - number of polygons in each map" << std::endl;
117 cout << " --size nnnxnnn - size of each map (X x Y)" << std::endl;
118 cout << " --seed nnn - initial value of random number generator" << std::endl;
119 cout << " --csv filename - write timing data to CSV-format file" << std::endl;
120 cout << " --grainsize n - set grainsize to n" << std::endl;
121 cout << " --use_malloc - allocate polygons with malloc instead of scalable allocator" << std::endl;
122 cout << std::endl;
123 cout << "npolys must be smaller than the size of the map" << std::endl;
124 cout << std::endl;
125 exit(1);
126 }
127
ParseCmdLine(int argc,char ** argv)128 bool ParseCmdLine(int argc, char **argv ) {
129 bool error_found = false;
130 bool nPolysSpecified = false;
131 bool nMapSizeSpecified = false;
132 bool nSeedSpecified = false;
133 bool csvSpecified = false;
134 bool grainsizeSpecified = false;
135 bool mallocSpecified = false;
136 int origArgc = argc;
137 char** origArgv = argv;
138 unsigned int newnPolygons = gNPolygons;
139 unsigned int newSeed = gMyRandomSeed;
140 unsigned int newX = gMapXSize;
141 unsigned int newY = gMapYSize;
142 unsigned int newGrainSize = gGrainSize;
143 argc--; argv++;
144 if(argc > 0 && isdigit((*argv)[0])) {
145 // first argument is one or two numbers, specifying how mny threads to run
146 char* end; gThreadsHigh = gThreadsLow = (int)strtol(argv[0],&end,0);
147 switch( *end) {
148 case ':': gThreadsHigh = (int)strtol(end+1,0,0); break;
149 case '\0': break;
150 default: cout << "Unexpected character in thread specifier: " << *end << std::endl; break;
151 }
152 if(gThreadsLow > gThreadsHigh) {
153 int t = gThreadsLow;
154 gThreadsLow = gThreadsHigh;
155 gThreadsHigh = t;
156 }
157 argv++; argc--;
158 }
159 while(argc > 0) {
160 // format 1: --size nnnxnnn, where nnn in {0 .. 9}+ -- size of map in "squares"
161 if(!strncmp("--size", *argv, (size_t)6)) {
162 if(nMapSizeSpecified) {
163 cout << " Error: map size multiply specified" << std::endl;
164 error_found = true;
165 }
166 else {
167 argv++; argc--;
168 if(argc == 0) {
169 error_found = true;
170 cout << " Error: --size must have a value" << std::endl;
171 }
172 if(strchr(*argv, 'x') != strrchr(*argv,'x')) {
173 // more than one 'x'
174 cout << "Error: map size should be nnnxnnn (" << *argv << ")" << std::endl;
175 error_found = true;
176 }
177 else {
178 int rval;
179 rval = sscanf(*argv, "%ux%u", &newX, &newY);
180 if(rval != 2) {
181 cout << "Error parsing map size (format should be nnnxnnn (" << *argv << ")" << std::endl;
182 error_found = true;
183 }
184 if(newX == 0 || newY == 0) {
185 cout << "Error: size of map should be greater than 0 (" << *argv << ")" << std::endl;
186 error_found = true;
187 }
188 }
189 }
190 argc--; argv++;
191 }
192 // format 2: --seed nnn -- initial random number seed
193 else if(!strncmp("--seed", *argv, (size_t)6)) {
194 argv++; argc--;
195 if(nSeedSpecified) {
196 cout << "Error: new seed multiply specified" << std::endl;
197 error_found = true;
198 }
199 else {
200 nSeedSpecified = true;
201 int rtval = sscanf(*argv, "%u", &newSeed);
202 if(rtval == 0) {
203 cout << "Error: --seed should be an unsigned number (instead of " << *argv << ")" << std::endl;
204 error_found = true;
205 }
206 }
207 argv++; argc--;
208 }
209 // format 3: --polys n[n] -- number of polygons in each map
210 else if(!strncmp("--polys", *argv, (size_t)7)) {
211 //unsigned int newnPolygons;
212 argv++; argc--;
213 if(nPolysSpecified) {
214 cout << "Error: number of polygons multiply-specified" << std::endl;
215 error_found = true;
216 }else {
217 int rtval = sscanf(*argv, "%u", &newnPolygons);
218 if(newnPolygons == 0) {
219 cout << "Error: number of polygons must be greater than 0 (" << *argv << ")" << std::endl;
220 }
221 }
222 argv++; argc--;
223 }
224 // format 4: --csv <fileroot> -- name of CSV output file ("xxx" for "xxx.csv")
225 else if(!strncmp("--csv", *argv, (size_t)5)) {
226 argv++; argc--;
227 if(csvSpecified) {
228 cout << "Error: Multiple specification of CSV file" << std::endl;
229 error_found = true;
230 }
231 else {
232 gCsvFilename = *argv;
233 argv++; argc--;
234 csvSpecified = true;
235 }
236 }
237 else if(!strncmp("--grainsize", *argv, (size_t)11)) {
238 argv++; argc--;
239 if(grainsizeSpecified) {
240 cout << "Error: Multiple specification of grainsize" << std::endl;
241 error_found = true;
242 }
243 else {
244 int grval = sscanf(*argv, "%u", &newGrainSize);
245 grainsizeSpecified = true;
246 if(newGrainSize == 0) {
247 cout << "Error: grainsize must be greater than 0" << std::endl;
248 error_found = true;
249 }
250 }
251 argv++; argc--;
252 }
253 else if(!strncmp("--use_malloc", *argv, (size_t)12)) {
254 argv++; argc--;
255 if(mallocSpecified) {
256 cout << "Error: --use_malloc multiply-specified" << std::endl;
257 error_found = true;
258 }
259 else {
260 mallocSpecified = true;
261 gMBehavior = UseMalloc;
262 }
263 }
264 else {
265 cout << "Error: unrecognized argument: " << *argv << std::endl;
266 error_found = true;
267 argv++; argc--;
268 }
269 }
270 if(!error_found) {
271 if(newX * newY < newnPolygons) {
272 error_found = true;
273 cout << "Error: map size should not be smaller than the number of polygons (gNPolygons = " << newnPolygons << ", map size " << newX << "x" << newY << ")" << std::endl;
274 }
275 }
276 if(!error_found) {
277 gMapXSize = newX;
278 gMapYSize = newY;
279 gNPolygons = newnPolygons;
280 gMyRandomSeed = newSeed;
281 gGrainSize = (int)newGrainSize;
282 }
283 else {
284 Usage(origArgc, origArgv);
285 }
286 return !error_found;
287 }
288
289 // create a polygon map with at least gNPolygons polygons.
290 // Usually more than gNPolygons polygons will be generated, because the
291 // process of growing the polygons results in holes.
GenerateMap(Polygon_map_t ** newMap,int xSize,int ySize,int gNPolygons,colorcomp_t maxR,colorcomp_t maxG,colorcomp_t maxB)292 bool GenerateMap(Polygon_map_t **newMap, int xSize, int ySize, int gNPolygons, colorcomp_t maxR, colorcomp_t maxG, colorcomp_t maxB) {
293 bool error_found = false;
294 int *validPolys;
295 int *validSide;
296 int maxSides;
297 RPolygon *newPoly;
298
299 if(xSize <= 0) {
300 cout << "xSize (" << xSize << ") should be > 0." << std::endl;
301 error_found = true;
302 }
303 if(ySize <= 0) {
304 cout << "ySize (" << ySize << ") should be > 0." << std::endl;
305 error_found = true;
306 }
307 if(gNPolygons > (xSize * ySize)) {
308 cout << "gNPolygons (" << gNPolygons << ") should be less than " << (xSize * ySize) << std::endl;
309 error_found = true;
310 }
311 if(error_found) return false;
312 // the whole map is [xSize x ySize] squares
313 // the way we create the map is to
314 // 1) pick nPolygon discrete squares on an [xSize x ySize] grid
315 // 2) while there are unused squares on the grid
316 // 3) pick a polygon with a side that has unused squares on a side
317 // 4) expand the polygon by 1 to occupy the unused squares
318 //
319 // Continue until every square on the grid is occupied by a polygon
320 int *tempMap;
321 tempMap = (int *)malloc(xSize * ySize * sizeof(int));
322 for(int i=0;i < xSize; i++) {
323 for(int j=0;j < ySize; j++) {
324 tempMap[i*ySize + j] = 0;
325 }
326 }
327
328 // *newMap = new vector<RPolygon>;
329 *newMap = new Polygon_map_t;
330 (*newMap)->reserve(gNPolygons + 1); // how much bigger does this need to be on average?
331 (*newMap)->push_back(RPolygon(0,0,xSize-1, ySize-1));
332 for(int i=0; i < gNPolygons; i++) {
333 int nX;
334 int nY;
335 do { // look for an empty square.
336 nX = NextRan(xSize);
337 nY = NextRan(ySize);
338 } while(tempMap[nX * ySize + nY] != 0);
339 int nR = (maxR * NextRan(1000)) / 999;
340 int nG = (maxG * NextRan(1000)) / 999;
341 int nB = (maxB * NextRan(1000)) / 999;
342 (*newMap)->push_back(RPolygon(nX,nY,nX,nY,nR,nG,nB));
343 tempMap[nX * ySize + nY] = i+1; // index of this polygon + 1
344 }
345 // now have to grow polygons to fill the space.
346 validPolys = (int *)malloc(4*gNPolygons * sizeof(int));
347 validSide = (int *)malloc(4*gNPolygons * sizeof(int));
348 for(int i=0;i<gNPolygons;i++) {
349 validPolys[4*i] = validPolys[4*i + 1] = validPolys[4*i + 2] = validPolys[4*i + 3] = i + 1;
350 validSide[4*i] = NORTH_SIDE;
351 validSide[4*i+1] = EAST_SIDE;
352 validSide[4*i+2] = SOUTH_SIDE;
353 validSide[4*i+3] = WEST_SIDE;
354 }
355 maxSides = 4*gNPolygons;
356 while(maxSides > 0) {
357 int indx = NextRan(maxSides);
358 int polyIndx = validPolys[indx];
359 int checkSide = validSide[indx];
360 int xlow, xhigh, ylow, yhigh;
361 int xlnew, xhnew, ylnew, yhnew;
362 (**newMap)[polyIndx].get(&xlow,&ylow,&xhigh,&yhigh);
363 xlnew = xlow;
364 xhnew = xhigh;
365 ylnew = ylow;
366 yhnew = yhigh;
367 // can this polygon be expanded along the chosen side?
368 switch(checkSide) {
369 case NORTH_SIDE:
370 // y-1 from xlow to xhigh
371 ylow = yhigh = (ylow - 1);
372 ylnew--;
373 break;
374 case EAST_SIDE:
375 // x+1 from ylow to yhigh
376 xlow = xhigh = (xhigh + 1);
377 xhnew++;
378 break;
379 case SOUTH_SIDE:
380 // y+1 from xlow to xhigh
381 ylow = yhigh = (yhigh+1);
382 yhnew++;
383 break;
384 case WEST_SIDE:
385 // x-1 from ylow to yhigh
386 xlow = xhigh = (xlow - 1);
387 xlnew--;
388 break;
389 }
390 bool okay_to_extend = !(((xlow < 0) || (xlow >= xSize)) || ((ylow < 0) || (ylow >= ySize)));
391 for(int ii = xlow; (ii <= xhigh) && okay_to_extend; ii++) {
392 for(int jj=ylow; (jj <= yhigh) && okay_to_extend; jj++) {
393 okay_to_extend = tempMap[ii*ySize + jj] == 0;
394 }
395 }
396 if(okay_to_extend) {
397 (**newMap)[polyIndx].set(xlnew,ylnew,xhnew,yhnew);
398 for(int ii = xlow; ii <= xhigh; ii++) {
399 for(int jj=ylow; jj <= yhigh && okay_to_extend; jj++) {
400 tempMap[ii*ySize + jj] = polyIndx;
401 }
402 }
403 }
404 else {
405 // once we cannot expand along a side, we will never be able to; remove from the list.
406 for(int i=indx + 1; i < maxSides; i++) {
407 validPolys[i-1] = validPolys[i];
408 validSide[i-1] = validSide[i];
409 }
410 maxSides--;
411 }
412 }
413
414 // Once no polygons can be grown, look for unused squares, and fill them with polygons.
415 for(int j=0;j<ySize;j++) {
416 for(int i=0;i<xSize;i++) {
417 if(tempMap[i*ySize+j] == 0) {
418 // try to grow in the x direction, then the y direction
419 int ilen = i;
420 int jlen = j;
421 while(ilen < (xSize - 1) && tempMap[(ilen+1)*ySize + jlen] == 0) {
422 ilen++;
423 }
424 bool yok = true;
425 while(yok && jlen < (ySize - 1)) {
426 for(int ii = i; ii <= ilen && yok; ii++) {
427 yok = (tempMap[ii*ySize + jlen + 1] == 0);
428 }
429 if(yok) {
430 jlen++;
431 }
432 }
433
434 // create new polygon and push it on our list.
435 int nR = (maxR * NextRan(1000)) / 999;
436 int nG = (maxG * NextRan(1000)) / 999;
437 int nB = (maxB * NextRan(1000)) / 999;
438 (*newMap)->push_back(RPolygon(i,j,ilen,jlen,nR,nG,nB));
439 gNPolygons++;
440 for(int ii=i; ii<=ilen;ii++) {
441 for(int jj=j;jj<=jlen;jj++) {
442 tempMap[ii*ySize + jj] = gNPolygons;
443 }
444 }
445 }
446 }
447 }
448
449 #if _DEBUG
450 if(!gIsGraphicalVersion) {
451 cout << std::endl << "Final Map:" << std::endl;
452 for(int j=0; j < ySize; j++ ) {
453 cout << "Row " << setw(2) << j << ":";
454 for(int i=0;i<xSize;i++) {
455 int it = tempMap[i*ySize + j];
456 if(it<10) {
457 cout << setw(2) << it;
458 }
459 else {
460 char ct = (int)'a' + it - 10;
461 cout << " " << ct;
462 }
463 }
464 cout << std::endl;
465 }
466 }
467 #endif // _DEBUG
468 free(tempMap);
469 free(validPolys);
470 free(validSide);
471 return true;
472 }
473
CheckPolygonMap(Polygon_map_t * checkMap)474 void CheckPolygonMap(Polygon_map_t *checkMap) {
475 #define indx(i,j) (i*gMapYSize + j)
476 #define rangeCheck(str,n,limit) if(((n)<0)||((n)>=limit)) {cout << "checkMap error: " << str << " out of range (" << n << ")" << std::endl;anError=true;}
477 #define xRangeCheck(str,n) rangeCheck(str,n,gMapXSize)
478 #define yRangeCheck(str,n) rangeCheck(str,n,gMapYSize)
479 // The first polygon is the whole map.
480 bool anError = false;
481 int *cArray;
482 if(checkMap->size() <= 0) {
483 cout << "checkMap error: no polygons in map" << std::endl;
484 return;
485 }
486 // mapXhigh and mapYhigh are inclusive, that is, if the map is 5x5, those values would be 4.
487 int mapXhigh, mapYhigh, mapLowX, mapLowY;
488 int gMapXSize, gMapYSize;
489 (*checkMap)[0].get(&mapLowX, &mapLowY, &mapXhigh, &mapYhigh);
490 if((mapLowX !=0) || (mapLowY != 0)) {
491 cout << "checkMap error: map origin not (0,0) (X=" << mapLowX << ", Y=" << mapLowY << ")" << std::endl;
492 anError = true;
493 }
494 if((mapXhigh < 0) || (mapYhigh < 0)) {
495 cout << "checkMap error: no area in map (X=" << mapXhigh << ", Y=" << mapYhigh << ")" << std::endl;
496 anError = true;
497 }
498 if(anError) return;
499 // bounds for array.
500 gMapXSize = mapXhigh + 1;
501 gMapYSize = mapYhigh + 1;
502 cArray = (int *)malloc(sizeof(int)*(gMapXSize*gMapYSize));
503
504 for(int i=0; i<gMapXSize; i++) {
505 for(int j=0; j< gMapYSize; j++) {
506 cArray[indx(i,j)] = 0;
507 }
508 }
509
510 int xlow, xhigh, ylow, yhigh;
511 for(int p=1; p < int(checkMap->size()) && !anError; p++) {
512 (*checkMap)[p].get(&xlow, &ylow, &xhigh, &yhigh);
513 xRangeCheck("xlow", xlow);
514 yRangeCheck("ylow", ylow);
515 xRangeCheck("xhigh", xhigh);
516 yRangeCheck("yhigh", yhigh);
517 if(xlow>xhigh) {
518 cout << "checkMap error: xlow > xhigh (" << xlow << "," << xhigh << ")" << std::endl;
519 anError = true;
520 }
521 if(ylow>yhigh) {
522 cout << "checkMap error: ylow > yhigh (" << ylow << "," << yhigh << ")" << std::endl;
523 anError = true;
524 }
525 for(int ii = xlow; ii <= xhigh; ii++) {
526 for(int jj = ylow; jj <= yhigh; jj++) {
527 if(cArray[indx(ii,jj)] != 0) {
528 cout << "checkMap error: polygons " << cArray[indx(ii,jj)] << " and " << p << " intersect" << std::endl;
529 anError = true;
530 }
531 cArray[indx(ii,jj)] = p;
532 }
533 }
534 }
535 for(int ii=0; ii < gMapXSize; ii++) {
536 for(int jj=0; jj < gMapYSize; jj++) {
537 if(cArray[indx(ii,jj)] == 0) {
538 cout << "checkMap error: block(" << ii << ", " << jj << ") not in any polygon" << std::endl;
539 anError = true;
540 }
541 }
542 }
543 free(cArray);
544 }
545
CompOnePolygon(RPolygon & p1,RPolygon & p2)546 bool CompOnePolygon(RPolygon &p1, RPolygon &p2) {
547 int xl1, xh1, yl1, yh1;
548 int xl2, xh2, yl2, yh2;
549 p1.get(&xl1, &yl1, &xh1, &yh1);
550 p2.get(&xl2, &yl2, &xh2, &yh2);
551 if(yl1>yl2) return true;
552 if(yl1<yl2) return false;
553 return (xl1 > xl2);
554 }
555
PolygonsEqual(RPolygon * p1,RPolygon * p2)556 bool PolygonsEqual(RPolygon *p1, RPolygon *p2) {
557 int xl1, xh1, yl1, yh1;
558 int xl2, xh2, yl2, yh2;
559 p1->get(&xl1, &yl1, &xh1, &yh1);
560 p2->get(&xl2, &yl2, &xh2, &yh2);
561 return ((xl1 == xl2) && (yl1==yl2) && (xh1 == xh2) && (yh1 == yh2));
562 }
563
ComparePolygonMaps(Polygon_map_t * map1,Polygon_map_t * map2)564 bool ComparePolygonMaps(Polygon_map_t *map1, Polygon_map_t *map2) {
565 // create two new polygon maps, copy the pointers from the original to these.
566 // we have to skip the first polygon, which is the size of the whole map
567 Polygon_map_t *t1, *t2;
568 bool is_ok = true;
569 t1 = new Polygon_map_t;
570 t1->reserve(map1->size());
571 for(unsigned int i=1;i<map1->size(); i++) {
572 t1->push_back(map1->at(i));
573 }
574 t2 = new Polygon_map_t;
575 t2->reserve(map2->size());
576 for(unsigned int i=1;i<map2->size();i++) {
577 t2->push_back(map2->at(i));
578 }
579 // sort the two created maps by (xlow, ylow)
580 sort(t1->begin(), t1->end());
581 sort(t2->begin(), t2->end());
582 // compare each element of both maps.
583 if(t1->size() != t2->size()) {
584 cout << "Error: maps not the same size ( " << int(t1->size()) << " vs " << int(t2->size()) << ")." << std::endl;
585 }
586 int maxSize = (int)((t1->size() < t2->size()) ? t1->size() : t2->size());
587 for(int i=0; i < maxSize; i++) {
588 if(!PolygonsEqual(&((*t1)[i]), &((*t2)[i]))) {
589 cout << "Error: polygons unequal (" << (*t1)[i] << " vs " << (*t2)[i] << std::endl;
590 is_ok = false;
591 }
592 }
593 delete t1;
594 delete t2;
595 return is_ok;
596 }
597
SetRandomSeed(int newSeed)598 void SetRandomSeed(int newSeed) {
599 srand((unsigned)newSeed);
600 }
601
NextRan(int n)602 int NextRan(int n) {
603 // assert(n > 1);
604 // if we are given 1, we will just return 0
605 //assert(n < RAND_MAX);
606 int rrand = rand() << 15 | rand();
607 if(rrand < 0) rrand = -rrand;
608 return rrand % n;
609 }
610
operator <<(std::ostream & s,const RPolygon & p)611 std::ostream& operator<<(std::ostream& s, const RPolygon &p) {
612 int xl, yl, xh, yh;
613 p.get(&xl, &yl, &xh, &yh);
614 return s << "[(" << xl << "," << yl << ")-(" << xh << "," << yh << ")] ";
615 }
616