1 /* OpenACC parallelism dimensions clauses: num_gangs, num_workers,
4 /* See also '../libgomp.oacc-fortran/parallel-dims.f90'. */
8 #include <gomp-constants.h>
10 /* TODO: "(int) acc_device_*" casts because of the C++ acc_on_device wrapper
11 not behaving as expected for -O0. */
12 #pragma acc routine seq
13 static unsigned int __attribute__ ((optimize ("O2"))) acc_gang ()
15 if (acc_on_device ((int) acc_device_host
))
17 else if (acc_on_device ((int) acc_device_nvidia
)
18 || acc_on_device ((int) acc_device_radeon
))
19 return __builtin_goacc_parlevel_id (GOMP_DIM_GANG
);
24 #pragma acc routine seq
25 static unsigned int __attribute__ ((optimize ("O2"))) acc_worker ()
27 if (acc_on_device ((int) acc_device_host
))
29 else if (acc_on_device ((int) acc_device_nvidia
)
30 || acc_on_device ((int) acc_device_radeon
))
31 return __builtin_goacc_parlevel_id (GOMP_DIM_WORKER
);
36 #pragma acc routine seq
37 static unsigned int __attribute__ ((optimize ("O2"))) acc_vector ()
39 if (acc_on_device ((int) acc_device_host
))
41 else if (acc_on_device ((int) acc_device_nvidia
)
42 || acc_on_device ((int) acc_device_radeon
))
43 return __builtin_goacc_parlevel_id (GOMP_DIM_VECTOR
);
51 acc_init (acc_device_default
);
53 /* OpenACC parallel construct. */
55 /* Non-positive value. */
59 #define GANGS 0 /* { dg-warning "'num_gangs' value must be positive" "" { target c } } */
60 int gangs_actual
= GANGS
;
61 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
62 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
63 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
64 #pragma acc parallel copy (gangs_actual) \
65 reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max) \
66 num_gangs (GANGS) /* { dg-warning "'num_gangs' value must be positive" "" { target c++ } } */
68 /* We're actually executing with num_gangs (1). */
70 for (int i
= 100 * gangs_actual
; i
> -100 * gangs_actual
; --i
)
72 /* <https://gcc.gnu.org/PR80547>. */
74 gangs_min
= gangs_max
= acc_gang ();
75 workers_min
= workers_max
= acc_worker ();
76 vectors_min
= vectors_max
= acc_vector ();
78 int gangs
= acc_gang ();
79 gangs_min
= (gangs_min
< gangs
) ? gangs_min
: gangs
;
80 gangs_max
= (gangs_max
> gangs
) ? gangs_max
: gangs
;
81 int workers
= acc_worker ();
82 workers_min
= (workers_min
< workers
) ? workers_min
: workers
;
83 workers_max
= (workers_max
> workers
) ? workers_max
: workers
;
84 int vectors
= acc_vector ();
85 vectors_min
= (vectors_min
< vectors
) ? vectors_min
: vectors
;
86 vectors_max
= (vectors_max
> vectors
) ? vectors_max
: vectors
;
90 if (gangs_actual
!= 1)
92 if (gangs_min
!= 0 || gangs_max
!= gangs_actual
- 1
93 || workers_min
!= 0 || workers_max
!= 0
94 || vectors_min
!= 0 || vectors_max
!= 0)
101 #define GANGS 0 /* { dg-warning "'num_gangs' value must be positive" "" { target c } } */
102 int gangs_actual
= GANGS
;
103 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
104 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
105 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
106 #pragma acc parallel copy (gangs_actual) \
107 num_gangs (GANGS) /* { dg-warning "'num_gangs' value must be positive" "" { target c++ } } */
109 /* We're actually executing with num_gangs (1). */
111 #pragma acc loop gang reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
112 for (int i
= 100 * gangs_actual
; i
> -100 * gangs_actual
; --i
)
114 gangs_min
= gangs_max
= acc_gang ();
115 workers_min
= workers_max
= acc_worker ();
116 vectors_min
= vectors_max
= acc_vector ();
119 if (gangs_actual
!= 1)
121 if (gangs_min
!= 0 || gangs_max
!= gangs_actual
- 1
122 || workers_min
!= 0 || workers_max
!= 0
123 || vectors_min
!= 0 || vectors_max
!= 0)
130 #define WORKERS 0 /* { dg-warning "'num_workers' value must be positive" "" { target c } } */
131 int workers_actual
= WORKERS
;
132 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
133 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
134 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
135 #pragma acc parallel copy (workers_actual) \
136 num_workers (WORKERS) /* { dg-warning "'num_workers' value must be positive" "" { target c++ } } */
138 /* We're actually executing with num_workers (1). */
140 #pragma acc loop worker reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
141 for (int i
= 100 * workers_actual
; i
> -100 * workers_actual
; --i
)
143 gangs_min
= gangs_max
= acc_gang ();
144 workers_min
= workers_max
= acc_worker ();
145 vectors_min
= vectors_max
= acc_vector ();
148 if (workers_actual
!= 1)
150 if (gangs_min
!= 0 || gangs_max
!= 0
151 || workers_min
!= 0 || workers_max
!= workers_actual
- 1
152 || vectors_min
!= 0 || vectors_max
!= 0)
159 #define VECTORS 0 /* { dg-warning "'vector_length' value must be positive" "" { target c } } */
160 int vectors_actual
= VECTORS
;
161 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
162 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
163 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
164 #pragma acc parallel copy (vectors_actual) /* { dg-warning "using vector_length \\(32\\), ignoring 1" "" { target openacc_nvidia_accel_selected } } */ \
165 vector_length (VECTORS) /* { dg-warning "'vector_length' value must be positive" "" { target c++ } } */
167 /* We're actually executing with vector_length (1), just the GCC nvptx
168 back end enforces vector_length (32). */
169 if (acc_on_device (acc_device_nvidia
))
173 #pragma acc loop vector reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
174 for (int i
= 100 * vectors_actual
; i
> -100 * vectors_actual
; --i
)
176 gangs_min
= gangs_max
= acc_gang ();
177 workers_min
= workers_max
= acc_worker ();
178 vectors_min
= vectors_max
= acc_vector ();
181 if (acc_get_device_type () == acc_device_nvidia
)
183 if (vectors_actual
!= 32)
187 if (vectors_actual
!= 1)
189 if (gangs_min
!= 0 || gangs_max
!= 0
190 || workers_min
!= 0 || workers_max
!= 0
191 || vectors_min
!= 0 || vectors_max
!= vectors_actual
- 1)
201 /* There is no actual limit for the number of gangs, so we try with a
202 rather high value. */
204 int gangs_actual
= gangs
;
205 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
206 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
207 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
208 #pragma acc parallel copy (gangs_actual) \
209 reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max) \
212 if (acc_on_device (acc_device_host
))
214 /* We're actually executing with num_gangs (1). */
217 /* As we're executing GR not GP, don't multiply with a "gangs_actual"
219 for (int i
= 100 /* * gangs_actual */; i
> -100 /* * gangs_actual */; --i
)
221 gangs_min
= gangs_max
= acc_gang ();
222 workers_min
= workers_max
= acc_worker ();
223 vectors_min
= vectors_max
= acc_vector ();
226 if (gangs_actual
< 1)
228 if (gangs_min
!= 0 || gangs_max
!= gangs_actual
- 1
229 || workers_min
!= 0 || workers_max
!= 0
230 || vectors_min
!= 0 || vectors_max
!= 0)
236 /* There is no actual limit for the number of gangs, so we try with a
237 rather high value. */
239 int gangs_actual
= gangs
;
240 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
241 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
242 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
243 #pragma acc parallel copy (gangs_actual) \
246 if (acc_on_device (acc_device_host
))
248 /* We're actually executing with num_gangs (1). */
251 #pragma acc loop gang reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
252 for (int i
= 100 * gangs_actual
; i
> -100 * gangs_actual
; --i
)
254 gangs_min
= gangs_max
= acc_gang ();
255 workers_min
= workers_max
= acc_worker ();
256 vectors_min
= vectors_max
= acc_vector ();
259 if (gangs_actual
< 1)
261 if (gangs_min
!= 0 || gangs_max
!= gangs_actual
- 1
262 || workers_min
!= 0 || workers_max
!= 0
263 || vectors_min
!= 0 || vectors_max
!= 0)
269 /* We try with an outrageously large value. */
270 #define WORKERS 2 << 20
271 int workers_actual
= WORKERS
;
272 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
273 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
274 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
275 #pragma acc parallel copy (workers_actual) /* { dg-warning "using num_workers \\(32\\), ignoring 2097152" "" { target openacc_nvidia_accel_selected } } */ \
276 num_workers (WORKERS)
278 if (acc_on_device (acc_device_host
))
280 /* We're actually executing with num_workers (1). */
283 else if (acc_on_device (acc_device_nvidia
))
285 /* The GCC nvptx back end enforces num_workers (32). */
288 else if (acc_on_device (acc_device_radeon
))
290 /* The GCC GCN back end is limited to num_workers (16).
291 Temporarily set this to 1 until multiple workers are permitted. */
292 workers_actual
= 1; // 16;
296 #pragma acc loop worker reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
297 for (int i
= 100 * workers_actual
; i
> -100 * workers_actual
; --i
)
299 gangs_min
= gangs_max
= acc_gang ();
300 workers_min
= workers_max
= acc_worker ();
301 vectors_min
= vectors_max
= acc_vector ();
304 if (workers_actual
< 1)
306 if (gangs_min
!= 0 || gangs_max
!= 0
307 || workers_min
!= 0 || workers_max
!= workers_actual
- 1
308 || vectors_min
!= 0 || vectors_max
!= 0)
315 /* We try with an outrageously large value. */
316 int workers
= 2 << 20;
317 /* For nvptx offloading, this one will not result in "using num_workers
318 (32), ignoring runtime setting", and will in fact try to launch with
319 "num_workers (workers)", which will run into "libgomp: cuLaunchKernel
320 error: invalid argument". So, limit ourselves here. */
321 if (acc_get_device_type () == acc_device_nvidia
)
323 int workers_actual
= workers
;
324 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
325 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
326 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
327 #pragma acc parallel copy (workers_actual) \
328 num_workers (workers)
330 if (acc_on_device (acc_device_host
))
332 /* We're actually executing with num_workers (1). */
335 else if (acc_on_device (acc_device_nvidia
))
337 /* We're actually executing with num_workers (32). */
338 /* workers_actual = 32; */
340 else if (acc_on_device (acc_device_radeon
))
342 /* The GCC GCN back end is limited to num_workers (16). */
347 #pragma acc loop worker reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
348 for (int i
= 100 * workers_actual
; i
> -100 * workers_actual
; --i
)
350 gangs_min
= gangs_max
= acc_gang ();
351 workers_min
= workers_max
= acc_worker ();
352 vectors_min
= vectors_max
= acc_vector ();
355 if (workers_actual
< 1)
357 if (gangs_min
!= 0 || gangs_max
!= 0
358 || workers_min
!= 0 || workers_max
!= workers_actual
- 1
359 || vectors_min
!= 0 || vectors_max
!= 0)
365 /* We try with an outrageously large value. */
366 #define VECTORS 2 << 20
367 int vectors_actual
= VECTORS
;
368 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
369 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
370 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
371 #pragma acc parallel copy (vectors_actual) /* { dg-warning "using vector_length \\(1024\\), ignoring 2097152" "" { target openacc_nvidia_accel_selected } } */ \
372 vector_length (VECTORS)
374 if (acc_on_device (acc_device_host
))
376 /* We're actually executing with vector_length (1). */
379 else if (acc_on_device (acc_device_nvidia
))
381 /* The GCC nvptx back end enforces vector_length (32). */
382 vectors_actual
= 1024;
384 else if (acc_on_device (acc_device_radeon
))
386 /* The GCC GCN back end enforces vector_length (1): autovectorize. */
391 #pragma acc loop vector reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
392 for (int i
= 100 * vectors_actual
; i
> -100 * vectors_actual
; --i
)
394 gangs_min
= gangs_max
= acc_gang ();
395 workers_min
= workers_max
= acc_worker ();
396 vectors_min
= vectors_max
= acc_vector ();
399 if (vectors_actual
< 1)
401 if (gangs_min
!= 0 || gangs_max
!= 0
402 || workers_min
!= 0 || workers_max
!= 0
403 || vectors_min
!= 0 || vectors_max
!= vectors_actual
- 1)
410 /* We try with an outrageously large value. */
411 int vectors
= 2 << 20;
412 int vectors_actual
= vectors
;
413 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
414 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
415 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
416 #pragma acc parallel copy (vectors_actual) /* { dg-warning "using vector_length \\(32\\), ignoring runtime setting" "" { target openacc_nvidia_accel_selected } } */ \
417 vector_length (vectors)
419 if (acc_on_device (acc_device_host
))
421 /* We're actually executing with vector_length (1). */
424 else if (acc_on_device (acc_device_nvidia
))
426 /* The GCC nvptx back end enforces vector_length (32). */
429 else if (acc_on_device (acc_device_radeon
))
431 /* Because of the way vectors are implemented for GCN, a vector loop
432 containing a seq routine call will not vectorize calls to that
433 routine. Hence, we'll only get one "vector". */
438 #pragma acc loop vector reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
439 for (int i
= 100 * vectors_actual
; i
> -100 * vectors_actual
; --i
)
441 gangs_min
= gangs_max
= acc_gang ();
442 workers_min
= workers_max
= acc_worker ();
443 vectors_min
= vectors_max
= acc_vector ();
446 if (vectors_actual
< 1)
448 if (gangs_min
!= 0 || gangs_max
!= 0
449 || workers_min
!= 0 || workers_max
!= 0
450 || vectors_min
!= 0 || vectors_max
!= vectors_actual
- 1)
455 /* Composition of GP, WP, VP. */
458 /* With nvptx offloading, multi-level reductions apparently are very slow
459 in the following case. So, limit ourselves here. */
460 if (acc_get_device_type () == acc_device_nvidia
)
462 /* Similar appears to be true for GCN. */
463 if (acc_get_device_type () == acc_device_radeon
)
465 int gangs_actual
= gangs
;
467 int workers_actual
= WORKERS
;
469 int vectors_actual
= VECTORS
;
470 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
471 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
472 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
473 #pragma acc parallel copy (gangs_actual, workers_actual, vectors_actual) /* { dg-warning "using vector_length \\(32\\), ignoring 11" "" { target openacc_nvidia_accel_selected } } */ \
475 num_workers (WORKERS) \
476 vector_length (VECTORS)
478 if (acc_on_device (acc_device_host
))
480 /* We're actually executing with num_gangs (1), num_workers (1),
481 vector_length (1). */
486 else if (acc_on_device (acc_device_nvidia
))
488 /* The GCC nvptx back end enforces vector_length (32). */
491 else if (acc_on_device (acc_device_radeon
))
493 /* Temporary setting, until multiple workers are permitted. */
495 /* See above comments about GCN vectors_actual. */
500 #pragma acc loop gang reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
501 for (int i
= 100 * gangs_actual
; i
> -100 * gangs_actual
; --i
)
502 #pragma acc loop worker reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
503 for (int j
= 100 * workers_actual
; j
> -100 * workers_actual
; --j
)
504 #pragma acc loop vector reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
505 for (int k
= 100 * vectors_actual
; k
> -100 * vectors_actual
; --k
)
507 gangs_min
= gangs_max
= acc_gang ();
508 workers_min
= workers_max
= acc_worker ();
509 vectors_min
= vectors_max
= acc_vector ();
512 if (gangs_min
!= 0 || gangs_max
!= gangs_actual
- 1
513 || workers_min
!= 0 || workers_max
!= workers_actual
- 1
514 || vectors_min
!= 0 || vectors_max
!= vectors_actual
- 1)
521 /* OpenACC kernels construct. */
523 /* We can't test parallelized OpenACC kernels constructs in this way: use of
524 the acc_gang, acc_worker, acc_vector functions will make the construct
528 /* Unparallelized OpenACC kernels constructs must get launched as 1 x 1 x 1
531 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
532 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
533 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
536 /* This is to make the OpenACC kernels construct unparallelizable. */
537 asm volatile ("" : : : "memory");
539 #pragma acc loop reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
540 for (int i
= 100; i
> -100; --i
)
542 gangs_min
= gangs_max
= acc_gang ();
543 workers_min
= workers_max
= acc_worker ();
544 vectors_min
= vectors_max
= acc_vector ();
547 if (gangs_min
!= 0 || gangs_max
!= 1 - 1
548 || workers_min
!= 0 || workers_max
!= 1 - 1
549 || vectors_min
!= 0 || vectors_max
!= 1 - 1)
554 /* Unparallelized OpenACC kernels constructs must get launched as 1 x 1 x 1
555 kernels even when there are explicit num_gangs, num_workers, or
556 vector_length clauses. */
561 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
562 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
563 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
564 #pragma acc kernels \
566 num_workers (WORKERS) \
567 vector_length (VECTORS)
569 /* This is to make the OpenACC kernels construct unparallelizable. */
570 asm volatile ("" : : : "memory");
572 #pragma acc loop reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
573 for (int i
= 100; i
> -100; --i
)
575 gangs_min
= gangs_max
= acc_gang ();
576 workers_min
= workers_max
= acc_worker ();
577 vectors_min
= vectors_max
= acc_vector ();
580 if (gangs_min
!= 0 || gangs_max
!= 1 - 1
581 || workers_min
!= 0 || workers_max
!= 1 - 1
582 || vectors_min
!= 0 || vectors_max
!= 1 - 1)
589 /* OpenACC serial construct. */
593 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
594 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
595 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
596 #pragma acc serial /* { dg-warning "using vector_length \\(32\\), ignoring 1" "" { target openacc_nvidia_accel_selected } } */ \
597 reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
599 for (int i
= 100; i
> -100; i
--)
601 gangs_min
= gangs_max
= acc_gang ();
602 workers_min
= workers_max
= acc_worker ();
603 vectors_min
= vectors_max
= acc_vector ();
606 if (gangs_min
!= 0 || gangs_max
!= 1 - 1
607 || workers_min
!= 0 || workers_max
!= 1 - 1
608 || vectors_min
!= 0 || vectors_max
!= 1 - 1)
612 /* Composition of GP, WP, VP. */
614 int vectors_actual
= 1; /* Implicit 'vector_length (1)' clause. */
615 int gangs_min
, gangs_max
, workers_min
, workers_max
, vectors_min
, vectors_max
;
616 gangs_min
= workers_min
= vectors_min
= INT_MAX
;
617 gangs_max
= workers_max
= vectors_max
= INT_MIN
;
618 #pragma acc serial copy (vectors_actual) /* { dg-warning "using vector_length \\(32\\), ignoring 1" "" { target openacc_nvidia_accel_selected } } */ \
619 copy (gangs_min, gangs_max, workers_min, workers_max, vectors_min, vectors_max)
621 if (acc_on_device (acc_device_nvidia
))
623 /* The GCC nvptx back end enforces vector_length (32). */
624 /* It's unclear if that's actually permissible here;
625 <https://github.com/OpenACC/openacc-spec/issues/238> "OpenACC
626 'serial' construct might not actually be serial". */
629 #pragma acc loop gang reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
630 for (int i
= 100; i
> -100; i
--)
631 #pragma acc loop worker reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
632 for (int j
= 100; j
> -100; j
--)
633 #pragma acc loop vector reduction (min: gangs_min, workers_min, vectors_min) reduction (max: gangs_max, workers_max, vectors_max)
634 for (int k
= 100 * vectors_actual
; k
> -100 * vectors_actual
; k
--)
636 gangs_min
= gangs_max
= acc_gang ();
637 workers_min
= workers_max
= acc_worker ();
638 vectors_min
= vectors_max
= acc_vector ();
641 if (acc_get_device_type () == acc_device_nvidia
)
643 if (vectors_actual
!= 32)
647 if (vectors_actual
!= 1)
649 if (gangs_min
!= 0 || gangs_max
!= 1 - 1
650 || workers_min
!= 0 || workers_max
!= 1 - 1
651 || vectors_min
!= 0 || vectors_max
!= vectors_actual
- 1)