2
2
3
3
#include " array.h"
4
4
#include " common.h"
5
+ #include " hash.h"
5
6
#include " printers.h"
6
7
#include " random.h"
7
- #include " random.h"
8
8
#include " repr.h"
9
9
#include " rnda.h"
10
10
@@ -129,41 +129,16 @@ struct TPoint : public ReprProxy<TPoint<T>> {
129
129
using Point = TPoint<long long >;
130
130
using Pointf = TPoint<long double >;
131
131
132
- } // namespace jngen
133
-
134
- namespace std {
135
-
136
132
template <>
137
- struct hash <jngen::Point > {
138
- // Credits to boost::hash
139
- static void hash_combine_impl (uint64_t & h, uint64_t k) {
140
- const uint64_t m = 0xc6a4a7935bd1e995 ;
141
- const int r = 47 ;
142
-
143
- k *= m;
144
- k ^= k >> r;
145
- k *= m;
146
-
147
- h ^= k;
148
- h *= m;
149
-
150
- // Completely arbitrary number, to prevent 0's
151
- // from hashing to 0.
152
- h += 0xe6546b64 ;
153
- }
154
-
155
- size_t operator ()(const jngen::Point & p) const {
133
+ struct Hash <Point > {
134
+ uint64_t operator ()(const Point & point) const {
156
135
uint64_t h = 0 ;
157
- hash_combine_impl (h, std::hash <long long >{}(p .x ));
158
- hash_combine_impl (h, std::hash <long long >{}(p .y ));
136
+ impl::hashCombine (h, Hash <long long >{}(point .x ));
137
+ impl::hashCombine (h, Hash <long long >{}(point .y ));
159
138
return h;
160
139
}
161
140
};
162
141
163
- } // namespace std
164
-
165
- namespace jngen {
166
-
167
142
template <typename T>
168
143
JNGEN_DECLARE_SIMPLE_PRINTER (TPoint<T>, 3 ) {
169
144
(void )mod;
@@ -206,8 +181,15 @@ class TPolygon : public GenericArray<TPoint<T>> {
206
181
using Polygon = TPolygon<long long >;
207
182
using Polygonf = TPolygon<long double >;
208
183
184
+ template <>
185
+ struct Hash <Polygon> {
186
+ uint64_t operator ()(const Polygon& p) const {
187
+ return Hash<TArray<Point >>{}(p);
188
+ }
189
+ };
190
+
209
191
template <typename T>
210
- JNGEN_DECLARE_SIMPLE_PRINTER (TPolygon<T >, 5 ) {
192
+ JNGEN_DECLARE_SIMPLE_PRINTER (TArray<TPoint<T> >, 5 ) {
211
193
// I should avoid copy-paste from array printer here but need to output
212
194
// points with '\n' separator. Maybe 'mod' should be made non-const?
213
195
if (mod.printN ) {
@@ -343,68 +325,7 @@ class GeometryRandom {
343
325
}
344
326
345
327
static TArray<Point > pointsInGeneralPosition (
346
- int n, long long X, long long Y)
347
- {
348
- struct Line {
349
- long long A, B, C; // Ax + By + C = 0
350
- Line () {}
351
- Line (const Point & p1, const Point & p2) {
352
- A = p1.y - p2.y ;
353
- B = p2.x - p1.x ;
354
- C = -(p1.x * A + p1.y * B);
355
-
356
- ENSURE (A != 0 || B != 0 );
357
-
358
- long long g = util::gcd (A, util::gcd (B, C));
359
- A /= g;
360
- B /= g;
361
- C /= g;
362
- if (A < 0 || (A == 0 && B < 0 )) {
363
- A = -A;
364
- B = -B;
365
- C = -C;
366
- }
367
- }
368
-
369
- bool operator <(const Line& other) const {
370
- return std::tie (A, B, C) < std::tie (other.A , other.B , other.C );
371
- }
372
- };
373
-
374
- const long long LIMIT = 2e9 ;
375
- ensure (
376
- X <= LIMIT && Y <= LIMIT,
377
- " rndg.pointsInGeneralPosition must not be called with coordinates "
378
- " larger than 2e9" );
379
-
380
- std::set<Line> lines;
381
- std::unordered_set<Point > points;
382
-
383
- TArray<Point > res;
384
-
385
- while (static_cast <int >(res.size ()) != n) {
386
- Point p = point (X, Y);
387
-
388
- if (points.count (p)) {
389
- continue ;
390
- }
391
-
392
- if (std::none_of (
393
- res.begin (),
394
- res.end (),
395
- [&lines, &p] (const Point & q) {
396
- return lines.count (Line (p, q));
397
- }))
398
- {
399
- points.insert (p);
400
- for (const auto & q: res) {
401
- lines.emplace (p, q);
402
- }
403
- res.push_back (p);
404
- }
405
- }
406
- return res;
407
- }
328
+ int n, long long X, long long Y);
408
329
409
330
static TArray<Point > pointsInGeneralPosition (int n, long long C) {
410
331
return pointsInGeneralPosition (n, C, C);
@@ -415,6 +336,9 @@ JNGEN_EXTERN GeometryRandom rndg;
415
336
416
337
} // namespace jngen
417
338
339
+ JNGEN_DEFINE_STD_HASH (jngen::Point );
340
+ JNGEN_DEFINE_STD_HASH (jngen::Polygon);
341
+
418
342
using jngen::Point ;
419
343
using jngen::Pointf;
420
344
@@ -424,3 +348,69 @@ using jngen::Polygonf;
424
348
using jngen::rndg;
425
349
426
350
using jngen::setEps;
351
+
352
+ #ifndef JNGEN_DECLARE_ONLY
353
+ TArray<Point > jngen::GeometryRandom::pointsInGeneralPosition (
354
+ int n, long long X, long long Y)
355
+ {
356
+ struct Line {
357
+ long long A, B, C; // Ax + By + C = 0
358
+ Line () {}
359
+ Line (const Point & p1, const Point & p2) {
360
+ A = p1.y - p2.y ;
361
+ B = p2.x - p1.x ;
362
+ C = -(p1.x * A + p1.y * B);
363
+
364
+ ENSURE (A != 0 || B != 0 );
365
+
366
+ long long g = util::gcd (A, util::gcd (B, C));
367
+ A /= g;
368
+ B /= g;
369
+ C /= g;
370
+ if (A < 0 || (A == 0 && B < 0 )) {
371
+ A = -A;
372
+ B = -B;
373
+ C = -C;
374
+ }
375
+ }
376
+
377
+ bool operator <(const Line& other) const {
378
+ return std::tie (A, B, C) < std::tie (other.A , other.B , other.C );
379
+ }
380
+ };
381
+
382
+ const long long LIMIT = 2e9 ;
383
+ ensure (
384
+ X <= LIMIT && Y <= LIMIT,
385
+ " rndg.pointsInGeneralPosition must not be called with coordinates "
386
+ " larger than 2e9" );
387
+
388
+ std::set<Line> lines;
389
+ std::unordered_set<Point > points;
390
+
391
+ TArray<Point > res;
392
+
393
+ while (static_cast <int >(res.size ()) != n) {
394
+ Point p = point (X, Y);
395
+
396
+ if (points.count (p)) {
397
+ continue ;
398
+ }
399
+
400
+ if (std::none_of (
401
+ res.begin (),
402
+ res.end (),
403
+ [&lines, &p] (const Point & q) {
404
+ return lines.count (Line (p, q));
405
+ }))
406
+ {
407
+ points.insert (p);
408
+ for (const auto & q: res) {
409
+ lines.emplace (p, q);
410
+ }
411
+ res.push_back (p);
412
+ }
413
+ }
414
+ return res;
415
+ }
416
+ #endif // JNGEN_DECLARE_ONLY
0 commit comments