Source

nrnr / test.c

#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include "nrnr.h"



float GetTime(void);
void RunSearch(int repear, const struct NrNrHood* hood, const float* minimum, const float* maximum);
void CheckSearch(const struct NrNrHood* hood, size_t numResults, const size_t* results, const float* minimum, const float* maximum);



int main(int _argc, char** _argv) {

    float start;

    // Create random points
    srand(1234);
    size_t numPoints = 1000000; // million
    start = GetTime();
    float* points = (float*)malloc(sizeof(float) * 3 * numPoints);
	for(size_t i=0; i<numPoints; i++) {
		float* p = points + i * 3;
		p[0] = ((float)rand() / RAND_MAX) * 200.0 - 100.0;
		p[1] = ((float)rand() / RAND_MAX) * 200.0 - 100.0;
		p[2] = ((float)rand() / RAND_MAX) * 200.0 - 100.0;
    }

    // Create neighborhood
    start = GetTime();
    struct NrNrHood* hood = NrNrCreateNeighborhood(numPoints, 3, points);
	printf("Create neighborhood: %.2f msec\n", GetTime() - start);

    // Radius 1 search
    float minPos1[3] = {-49.0f, -8.0f, 59.0f};
    float maxPos1[3] = {-47.0f, -6.0f, 61.0f};
    RunSearch(12000, hood, minPos1, maxPos1);

    // Radius 10 search
    float minPos10[3] = {-10.0f,10.0f,-30.0f};
    float maxPos10[3] = { 10.0,  30.0f, -10.0f};
    RunSearch(3000, hood, minPos10, maxPos10);

    float minPos20[3] = {-20.0f, 0.0f, -40.0f};
    float maxPos20[3] = { 20.0,  40.0f, 00.0f};
    RunSearch(1700, hood, minPos20, maxPos20);

    float minPos40[3] = {-40.0f,-20.0f,-60.0f};
    float maxPos40[3] = { 40.0,  60.0f, 20.0f};
    RunSearch(800, hood, minPos40, maxPos40);

    float minPos80[3] = {-80.0f,-60.0f,-100.0f};
    float maxPos80[3] = { 80.0,  100.0f, 60.0f};
    RunSearch(500, hood, minPos80, maxPos80);

    // Cleanup
    start = GetTime();
    free(points);
    hood = NrNrFreeNeighborhood(hood);
    printf("Cleanup: %.2f msec\n", GetTime() - start);

	return 0;
}



void RunSearch(int repeat, const struct NrNrHood* hood, const float* minimum, const float* maximum) {
    size_t count;
    size_t* results = NULL;
    float start = GetTime();
    for (int r = 0; r < repeat; ++r) {
        results = NrNrFreeResults(results);
        count = NrNrSearchBlock(hood, &results, minimum, maximum);
    }

    float radius = (maximum[0] - minimum[0]) / 2.0f;
    printf("Search found %zu: %.2f msec per search  (repeat=%d radius=%.1f)\n",
                count, (GetTime() - start) / repeat, repeat, radius);

    // Checking is too slow with big pools of matches
    if (count < 10000) {
        CheckSearch(hood, count, results, minimum, maximum);
    }
    results = NrNrFreeResults(results);
}



void CheckSearch(const struct NrNrHood* hood, size_t numResults, const size_t* results, const float* minimum, const float* maximum) {
    int foundError = 0;
    for (size_t i = 0; i < hood->numPoints; ++i) {
        const float* pos = hood->points + i * hood->dimensions;
        int inside = 1;

        for (size_t d = 0; d < hood->dimensions; ++d) {
            if (pos[d] < minimum[d] || pos[d] > maximum[d]) {
                inside = 0;
                break;
            }
        }

        int inresults = 0;
        for (size_t j = 0; j < numResults; ++j) {
            if (results[j] == i) {
                inresults = 1;
                break;
            }
        }
        if (inside && !inresults) {
            printf("Error with results, points should be inside: index=%zu, %.1f %.1f %.1f\n", i,
                        hood->points[i * hood->dimensions], hood->points[i * hood->dimensions + 1], hood->points[i * hood->dimensions + 2]);
            foundError = 1;
        } else if (!inside && inresults) {
            printf("Error with results, points should not be inside: index=%zu, %.1f %.1f %.1f\n", i,
                        hood->points[i * hood->dimensions], hood->points[i * hood->dimensions + 1], hood->points[i * hood->dimensions + 2]);
            foundError = 1;
        }
    }
    if (foundError) {
        exit(1);
    }
}



// Return time in milliseconds
float GetTime(void)
{
	static struct timeval timeval, first_timeval;
	gettimeofday(&timeval, 0);
	if(first_timeval.tv_sec == 0) {
		first_timeval = timeval;
		return 0;
	}
	float s = (timeval.tv_sec - first_timeval.tv_sec) * 1000 + (timeval.tv_usec - first_timeval.tv_usec) / 1000.0;
    return s;
}