Home | History | Annotate | Line # | Download | only in nbperf
      1  1.6  joerg /*	$NetBSD: graph2.c,v 1.6 2021/01/28 18:52:43 joerg Exp $	*/
      2  1.1  joerg /*-
      3  1.1  joerg  * Copyright (c) 2009 The NetBSD Foundation, Inc.
      4  1.1  joerg  * All rights reserved.
      5  1.1  joerg  *
      6  1.1  joerg  * This code is derived from software contributed to The NetBSD Foundation
      7  1.1  joerg  * by Joerg Sonnenberger.
      8  1.1  joerg  *
      9  1.1  joerg  * Redistribution and use in source and binary forms, with or without
     10  1.1  joerg  * modification, are permitted provided that the following conditions
     11  1.1  joerg  * are met:
     12  1.1  joerg  *
     13  1.1  joerg  * 1. Redistributions of source code must retain the above copyright
     14  1.1  joerg  *    notice, this list of conditions and the following disclaimer.
     15  1.1  joerg  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  joerg  *    notice, this list of conditions and the following disclaimer in
     17  1.1  joerg  *    the documentation and/or other materials provided with the
     18  1.1  joerg  *    distribution.
     19  1.1  joerg  *
     20  1.1  joerg  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  1.1  joerg  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     22  1.1  joerg  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     23  1.1  joerg  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
     24  1.1  joerg  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  1.1  joerg  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
     26  1.1  joerg  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     27  1.1  joerg  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     28  1.1  joerg  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     29  1.1  joerg  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     30  1.1  joerg  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  1.1  joerg  * SUCH DAMAGE.
     32  1.1  joerg  */
     33  1.1  joerg 
     34  1.4  joerg #if HAVE_NBTOOL_CONFIG_H
     35  1.4  joerg #include "nbtool_config.h"
     36  1.4  joerg #endif
     37  1.4  joerg 
     38  1.1  joerg #include <sys/cdefs.h>
     39  1.6  joerg __RCSID("$NetBSD: graph2.c,v 1.6 2021/01/28 18:52:43 joerg Exp $");
     40  1.1  joerg 
     41  1.1  joerg #include <err.h>
     42  1.1  joerg #include <inttypes.h>
     43  1.1  joerg #include <stdio.h>
     44  1.1  joerg #include <stdlib.h>
     45  1.3  joerg #include <string.h>
     46  1.1  joerg 
     47  1.1  joerg #include "nbperf.h"
     48  1.1  joerg #include "graph2.h"
     49  1.1  joerg 
     50  1.1  joerg void
     51  1.5  joerg SIZED2(_setup)(struct SIZED(graph) *graph, uint32_t v, uint32_t e)
     52  1.1  joerg {
     53  1.1  joerg 	graph->v = v;
     54  1.1  joerg 	graph->e = e;
     55  1.1  joerg 
     56  1.5  joerg 	graph->verts = calloc(sizeof(*graph->verts), v);
     57  1.5  joerg 	graph->edges = calloc(sizeof(*graph->edges), e);
     58  1.1  joerg 	graph->output_order = calloc(sizeof(uint32_t), e);
     59  1.1  joerg 
     60  1.1  joerg 	if (graph->verts == NULL || graph->edges == NULL ||
     61  1.1  joerg 	    graph->output_order == NULL)
     62  1.1  joerg 		err(1, "malloc failed");
     63  1.1  joerg }
     64  1.1  joerg 
     65  1.1  joerg void
     66  1.5  joerg SIZED2(_free)(struct SIZED(graph) *graph)
     67  1.1  joerg {
     68  1.1  joerg 	free(graph->verts);
     69  1.1  joerg 	free(graph->edges);
     70  1.1  joerg 	free(graph->output_order);
     71  1.1  joerg 
     72  1.1  joerg 	graph->verts = NULL;
     73  1.1  joerg 	graph->edges = NULL;
     74  1.1  joerg 	graph->output_order = NULL;
     75  1.1  joerg }
     76  1.1  joerg 
     77  1.5  joerg static struct nbperf *sorting_nbperf;
     78  1.5  joerg static struct SIZED(graph) *sorting_graph;
     79  1.5  joerg static int sorting_found;
     80  1.5  joerg 
     81  1.5  joerg static int sorting_cmp(const void *a_, const void *b_)
     82  1.5  joerg {
     83  1.5  joerg 	const uint32_t *a = a_, *b = b_;
     84  1.5  joerg 	int i;
     85  1.5  joerg 	const struct SIZED(edge) *ea = &sorting_graph->edges[*a],
     86  1.5  joerg 	    *eb = &sorting_graph->edges[*b];
     87  1.5  joerg 	for (i = 0; i < GRAPH_SIZE; ++i) {
     88  1.5  joerg 		if (ea->vertices[i] < eb->vertices[i])
     89  1.5  joerg 			return -1;
     90  1.5  joerg 		if (ea->vertices[i] > eb->vertices[i])
     91  1.5  joerg 			return 1;
     92  1.5  joerg 	}
     93  1.5  joerg 	if (sorting_nbperf->keylens[*a] < sorting_nbperf->keylens[*b])
     94  1.5  joerg 		return -1;
     95  1.5  joerg 	if (sorting_nbperf->keylens[*a] > sorting_nbperf->keylens[*b])
     96  1.5  joerg 		return 1;
     97  1.5  joerg 	i = memcmp(sorting_nbperf->keys[*a], sorting_nbperf->keys[*b],
     98  1.5  joerg 	    sorting_nbperf->keylens[*a]);
     99  1.5  joerg 	if (i == 0)
    100  1.5  joerg 		sorting_found = 1;
    101  1.5  joerg 	return i;
    102  1.5  joerg }
    103  1.5  joerg 
    104  1.3  joerg static int
    105  1.5  joerg SIZED2(_check_duplicates)(struct nbperf *nbperf, struct SIZED(graph) *graph)
    106  1.3  joerg {
    107  1.5  joerg 	size_t i;
    108  1.5  joerg 	uint32_t *key_index = calloc(sizeof(*key_index), graph->e);
    109  1.3  joerg 
    110  1.5  joerg 	if (key_index == NULL)
    111  1.5  joerg 		err(1, "malloc failed");
    112  1.5  joerg 	for (i = 0; i < graph->e; ++i)
    113  1.5  joerg 		key_index[i] = i;
    114  1.5  joerg 
    115  1.5  joerg 	sorting_nbperf = nbperf;
    116  1.5  joerg 	sorting_graph = graph;
    117  1.5  joerg 	sorting_found = 0;
    118  1.5  joerg 	qsort(key_index, graph->e, sizeof(*key_index), sorting_cmp);
    119  1.5  joerg 	if (sorting_found)
    120  1.5  joerg 		goto found_dups;
    121  1.5  joerg 	/*
    122  1.5  joerg 	 * Any duplicate must have been found as part of the qsort,
    123  1.5  joerg 	 * as it can't sort consecutive elements in the output without
    124  1.5  joerg 	 * comparing them at least once.
    125  1.5  joerg 	 */
    126  1.5  joerg 
    127  1.5  joerg 	free(key_index);
    128  1.3  joerg 	return 0;
    129  1.5  joerg  found_dups:
    130  1.5  joerg 	nbperf->has_duplicates = 1;
    131  1.5  joerg 	return -1;
    132  1.3  joerg }
    133  1.3  joerg 
    134  1.5  joerg static inline void
    135  1.5  joerg SIZED2(_add_edge)(struct SIZED(graph) *graph, uint32_t edge)
    136  1.1  joerg {
    137  1.5  joerg 	struct SIZED(edge) *e = graph->edges + edge;
    138  1.5  joerg 	struct SIZED(vertex) *v;
    139  1.1  joerg 	size_t i;
    140  1.1  joerg 
    141  1.5  joerg 	for (i = 0; i < GRAPH_SIZE; ++i) {
    142  1.5  joerg 		v = graph->verts + e->vertices[i];
    143  1.5  joerg 		v->edges ^= edge;
    144  1.5  joerg 		++v->degree;
    145  1.1  joerg 	}
    146  1.5  joerg }
    147  1.5  joerg 
    148  1.5  joerg static inline void
    149  1.5  joerg SIZED2(_remove_edge)(struct SIZED(graph) *graph, uint32_t edge)
    150  1.5  joerg {
    151  1.5  joerg 	struct SIZED(edge) *e = graph->edges + edge;
    152  1.5  joerg 	struct SIZED(vertex) *v;
    153  1.5  joerg 	size_t i;
    154  1.1  joerg 
    155  1.5  joerg 	for (i = 0; i < GRAPH_SIZE; ++i) {
    156  1.5  joerg 		v = graph->verts + e->vertices[i];
    157  1.5  joerg 		v->edges ^= edge;
    158  1.5  joerg 		--v->degree;
    159  1.1  joerg 	}
    160  1.5  joerg }
    161  1.1  joerg 
    162  1.5  joerg static inline void
    163  1.5  joerg SIZED2(_remove_vertex)(struct SIZED(graph) *graph, uint32_t vertex)
    164  1.5  joerg {
    165  1.5  joerg 	struct SIZED(vertex) *v = graph->verts + vertex;
    166  1.5  joerg 	uint32_t e;
    167  1.5  joerg 
    168  1.5  joerg 	if (v->degree == 1) {
    169  1.5  joerg 		e = v->edges;
    170  1.5  joerg 		graph->output_order[--graph->output_index] = e;
    171  1.5  joerg 		SIZED2(_remove_edge)(graph, e);
    172  1.3  joerg 	}
    173  1.1  joerg }
    174  1.1  joerg 
    175  1.5  joerg int
    176  1.5  joerg SIZED2(_hash)(struct nbperf *nbperf, struct SIZED(graph) *graph)
    177  1.1  joerg {
    178  1.5  joerg 	struct SIZED(edge) *e;
    179  1.5  joerg 	uint32_t hashes[NBPERF_MAX_HASH_SIZE];
    180  1.5  joerg 	size_t i, j;
    181  1.1  joerg 
    182  1.5  joerg #if GRAPH_SIZE == 2
    183  1.6  joerg 	if (nbperf->allow_hash_fudging && (graph->v & 1) != 0)
    184  1.6  joerg 		errx(1, "vertex count must have lowest bit clear");
    185  1.5  joerg #else
    186  1.6  joerg 	if (nbperf->allow_hash_fudging && (graph->v & 3) != 0)
    187  1.6  joerg 		errx(1, "vertex count must have lowest 2 bits clear");
    188  1.5  joerg #endif
    189  1.5  joerg 
    190  1.5  joerg 
    191  1.5  joerg 	memset(graph->verts, 0, sizeof(*graph->verts) * graph->v);
    192  1.5  joerg 	graph->hash_fudge = 0;
    193  1.5  joerg 
    194  1.5  joerg 	for (i = 0; i < graph->e; ++i) {
    195  1.5  joerg 		(*nbperf->compute_hash)(nbperf,
    196  1.5  joerg 		    nbperf->keys[i], nbperf->keylens[i], hashes);
    197  1.5  joerg 		e = graph->edges + i;
    198  1.5  joerg 		for (j = 0; j < GRAPH_SIZE; ++j) {
    199  1.5  joerg 			e->vertices[j] = hashes[j] % graph->v;
    200  1.5  joerg 			if (j == 1 && e->vertices[0] == e->vertices[1]) {
    201  1.5  joerg 				if (!nbperf->allow_hash_fudging)
    202  1.5  joerg 					return -1;
    203  1.5  joerg 				e->vertices[1] ^= 1; /* toogle bit to differ */
    204  1.5  joerg 				graph->hash_fudge |= 1;
    205  1.5  joerg 			}
    206  1.5  joerg #if GRAPH_SIZE == 3
    207  1.5  joerg 			if (j == 2 && (e->vertices[0] == e->vertices[2] ||
    208  1.5  joerg 			    e->vertices[1] == e->vertices[2])) {
    209  1.5  joerg 				if (!nbperf->allow_hash_fudging)
    210  1.5  joerg 					return -1;
    211  1.5  joerg 				graph->hash_fudge |= 2;
    212  1.5  joerg 				e->vertices[2] ^= 1;
    213  1.5  joerg 				e->vertices[2] ^= 2 * (e->vertices[0] == e->vertices[2] ||
    214  1.5  joerg 				    e->vertices[1] == e->vertices[2]);
    215  1.5  joerg 			}
    216  1.5  joerg #endif
    217  1.1  joerg 		}
    218  1.5  joerg 	}
    219  1.5  joerg 
    220  1.5  joerg 	for (i = 0; i < graph->e; ++i)
    221  1.5  joerg 		SIZED2(_add_edge)(graph, i);
    222  1.1  joerg 
    223  1.5  joerg 	if (nbperf->check_duplicates) {
    224  1.5  joerg 		nbperf->check_duplicates = 0;
    225  1.5  joerg 		return SIZED2(_check_duplicates)(nbperf, graph);
    226  1.1  joerg 	}
    227  1.5  joerg 
    228  1.5  joerg 	return 0;
    229  1.1  joerg }
    230  1.1  joerg 
    231  1.1  joerg int
    232  1.5  joerg SIZED2(_output_order)(struct SIZED(graph) *graph)
    233  1.1  joerg {
    234  1.5  joerg 	size_t i, j;
    235  1.5  joerg 	struct SIZED(edge) *e2;
    236  1.1  joerg 
    237  1.1  joerg 	graph->output_index = graph->e;
    238  1.1  joerg 
    239  1.1  joerg 	for (i = 0; i < graph->v; ++i)
    240  1.5  joerg 		SIZED2(_remove_vertex)(graph, i);
    241  1.1  joerg 
    242  1.5  joerg 	for (i = graph->e; graph->output_index > 0 && i > graph->output_index;) {
    243  1.5  joerg 		e2 = graph->edges + graph->output_order[--i];
    244  1.5  joerg 		for (j = 0; j < GRAPH_SIZE; ++j)
    245  1.5  joerg 			SIZED2(_remove_vertex)(graph, e2->vertices[j]);
    246  1.5  joerg 	}
    247  1.5  joerg 
    248  1.5  joerg 	if (graph->output_index != 0) {
    249  1.1  joerg 		return -1;
    250  1.5  joerg 	}
    251  1.1  joerg 
    252  1.1  joerg 	return 0;
    253  1.1  joerg }
    254