2222#include <stdio.h>
2323#include <math.h>
2424#include <time.h>
25+ #include <pthread.h>
2526
2627#include "../mapcodelib/mapcoder.c"
2728#include "../mapcodelib/mapcode_countrynames_short.h"
3132extern void test_territories ();
3233
3334#define MAXLINESIZE 1024
35+ #define MAX_THREADS 16
36+
3437
3538// globals to count tests, errors and warnings
3639int nrTests = 0 ;
@@ -230,7 +233,7 @@ static void testEncodeAndDecode(const char *str, double y, double x, int localso
230233 nrTests ++ ;
231234 if (nrresults != localsolutions ) {
232235 nrErrors ++ ;
233- printf ("*** ERROR *** encode(%0.8f , %0.8f,%d) does not deliver %d local solutions\n" ,
236+ printf ("*** ERROR *** encode(%0.8f, %0.8f,%d) does not deliver %d local solutions\n" ,
234237 y , x , tc , localsolutions );
235238 printGeneratedMapcodes ("Delivered" , & mapcodes );
236239 }
@@ -246,7 +249,7 @@ static void testEncodeAndDecode(const char *str, double y, double x, int localso
246249 }
247250 if (!found ) {
248251 nrErrors ++ ;
249- printf ("*** ERROR *** encode(%0.8f , %0.8f) does not deliver \"%s\"\n" , y , x , clean );
252+ printf ("*** ERROR *** encode(%0.8f, %0.8f) does not deliver \"%s\"\n" , y , x , clean );
250253 printGeneratedMapcodes ("Delivered" , & mapcodes );
251254 }
252255 }
@@ -258,7 +261,7 @@ static void testEncodeAndDecode(const char *str, double y, double x, int localso
258261 nrresults = encodeLatLonToMapcodes (& mapcodes , y , x , 0 , precision );
259262 if (nrresults != globalsolutions ) {
260263 nrErrors ++ ;
261- printf ("*** ERROR *** encode(%0.8f , %0.8f) does not deliver %d global solutions\n" , y , x , globalsolutions );
264+ printf ("*** ERROR *** encode(%0.8f, %0.8f) does not deliver %d global solutions\n" , y , x , globalsolutions );
262265 printGeneratedMapcodes ("Delivered" , & mapcodes );
263266 }
264267 }
@@ -274,15 +277,15 @@ static void testEncodeAndDecode(const char *str, double y, double x, int localso
274277 err = decodeMapcodeToLatLon (& lat , & lon , strResult , 0 );
275278 if (err ) {
276279 nrErrors ++ ;
277- printf ("*** ERROR *** decode('%s') = no result, expected ~(%0.8f , %0.8f)\n" , strResult , y , x );
280+ printf ("*** ERROR *** decode('%s') = no result, expected ~(%0.8f, %0.8f)\n" , strResult , y , x );
278281 } else {
279282 double dm = distanceInMeters (y , x , lat , lon );
280283 double maxerror = maxErrorInMeters (precision );
281284 // check if decode is sufficiently close to the encoded coordinate
282285 nrTests ++ ;
283286 if (dm > maxerror ) {
284287 nrErrors ++ ;
285- printf ("*** ERROR *** decode('%s') = (%0.8f , %0.8f), which is %0.4f cm way (>%0.4f cm) from (%0.8f , %0.8f)\n" ,
288+ printf ("*** ERROR *** decode('%s') = (%0.8f, %0.8f), which is %0.4f cm away (>%0.4f cm) from (%0.8f, %0.8f)\n" ,
286289 strResult , lat , lon ,
287290 dm * 100.0 , maxerror * 100.0 , y , x );
288291 } else {
@@ -423,18 +426,6 @@ static void test_failing_decodes() {
423426 }
424427}
425428
426- // perform testEncodeAndDecode for all elements of encode_test[] (from decode_test.h)
427- void encode_decode_tests () {
428- int i = 0 ;
429- int nr = sizeof (encode_test ) / sizeof (encode_test_record ) - 1 ;
430- printf ("%d encodes\n" , nr );
431- for (i = 0 ; i < nr ; i ++ ) {
432- show_progress (i , nr );
433- const encode_test_record * t = & encode_test [i ];
434- testEncodeAndDecode (t -> mapcode , t -> latitude , t -> longitude , t -> nr_local_mapcodes , t -> nr_global_mapcodes );
435- }
436- }
437-
438429// perform tests on alphacodes (designed in test_territories.c)
439430void test_territory (const char * alphaCode , int tc , int isAlias , int needsParent , int tcParent ) {
440431
@@ -491,46 +482,91 @@ static void test_around(double y, double x) {
491482 testEncodeAndDecode ("" , y - 0.00001 , x - 0.00001 , 0 , 0 );
492483}
493484
485+
486+ void join_threads (pthread_t * threads , int total ) {
487+ for (int i = 0 ; i < total ; ++ i ) {
488+ if (pthread_join (threads [i ], 0 )) {
489+ nrErrors ++ ;
490+ fprintf (stderr , "*** ERROR *** Error joining thread %d of %d\n" , i , total );
491+ return ;
492+
493+ }
494+ }
495+ }
496+
497+ // perform testEncodeAndDecode for all elements of encode_test[] (from decode_test.h)
498+ void encode_decode_tests () {
499+ int i = 0 ;
500+ int nr = sizeof (encode_test ) / sizeof (encode_test_record ) - 1 ;
501+ printf ("%d encodes\n" , nr );
502+ for (i = 0 ; i < nr ; i ++ ) {
503+ show_progress (i , nr );
504+ const encode_test_record * t = & encode_test [i ];
505+ testEncodeAndDecode (t -> mapcode , t -> latitude , t -> longitude , t -> nr_local_mapcodes , t -> nr_global_mapcodes );
506+ }
507+ }
508+
509+ void * execute_test_around (void * context_mminforec ) {
510+ double y , x , midx , midy , thirdx ;
511+ const mminforec * b = (mminforec * ) context_mminforec ;
512+
513+ midy = (b -> miny + b -> maxy ) / 2000000.0 ;
514+ midx = (b -> minx + b -> maxx ) / 2000000.0 ;
515+ thirdx = (2 * b -> minx + b -> maxx ) / 3000000.0 ;
516+ test_around (midy , midx );
517+
518+ y = (b -> miny ) / 1000000.0 ;
519+ x = (b -> minx ) / 1000000.0 ;
520+ test_around (y , x );
521+ test_around (midy , x );
522+ test_around (y , midx );
523+ test_around (y , thirdx );
524+
525+ x = (b -> maxx ) / 1000000.0 ;
526+ test_around (y , x );
527+ test_around (midy , x );
528+
529+ y = (b -> maxy ) / 1000000.0 ;
530+ x = (b -> minx ) / 1000000.0 ;
531+ test_around (y , x );
532+ test_around (y , midx );
533+
534+ x = (b -> maxx ) / 1000000.0 ;
535+ test_around (y , x );
536+ test_around (midy , x );
537+ return 0 ;
538+ }
539+
494540// test around all centers and corners of all territory rectangles
495541static void re_encode_tests () {
496- int ccode , m ;
497- int nrrecords = lastrec (ccode_earth ) + 1 ;
498- printf ("%d records\n" , nrrecords );
542+ int ccode = 0 ;
543+ int m = 0 ;
544+ int nrRecords = lastrec (ccode_earth ) + 1 ;
545+ int nrThread = 0 ;
546+ pthread_t threads [MAX_THREADS ];
547+ printf ("%d records\n" , nrRecords );
499548 for (ccode = 0 ; ccode <= ccode_earth ; ccode ++ ) {
500549 show_progress (ccode , ccode_earth );
501550 for (m = firstrec (ccode ); m <= lastrec (ccode ); m ++ ) {
502- double y , x , midx , midy , thirdx ;
503551 const mminforec * b = boundaries (m );
504-
505- midy = (b -> miny + b -> maxy ) / 2000000.0 ;
506- midx = (b -> minx + b -> maxx ) / 2000000.0 ;
507- thirdx = (2 * b -> minx + b -> maxx ) / 3000000.0 ;
508- test_around (midy , midx );
509-
510- y = (b -> miny ) / 1000000.0 ;
511- x = (b -> minx ) / 1000000.0 ;
512- test_around (y , x );
513- test_around (midy , x );
514- test_around (y , midx );
515- test_around (y , thirdx );
516-
517- x = (b -> maxx ) / 1000000.0 ;
518- test_around (y , x );
519- test_around (midy , x );
520-
521- y = (b -> maxy ) / 1000000.0 ;
522- x = (b -> minx ) / 1000000.0 ;
523- test_around (y , x );
524- test_around (y , midx );
525-
526- x = (b -> maxx ) / 1000000.0 ;
527- test_around (y , x );
528- test_around (midy , x );
552+ if (nrThread < MAX_THREADS ) {
553+ // Execute the test on a new thread.
554+ if (pthread_create (& threads [nrThread ], 0 , execute_test_around , (void * ) b )) {
555+ nrErrors ++ ;
556+ fprintf (stderr , "*** ERROR *** Cannot create thread\n" );
557+ return ;
558+ }
559+ nrThread ++ ;
560+ } else {
561+ join_threads (threads , nrThread );
562+ nrThread = 0 ;
563+ }
529564 }
565+ join_threads (threads , nrThread );
566+ nrThread = 0 ;
530567 }
531568}
532569
533-
534570void distance_tests () {
535571 if (strcmp (mapcode_cversion , "2.1.3" ) >= 0 ) {
536572 int i ;
0 commit comments