graph3.c revision 1.1
11.1Sjoerg/*	$NetBSD: graph3.c,v 1.1 2009/08/15 16:21:05 joerg Exp $	*/
21.1Sjoerg/*-
31.1Sjoerg * Copyright (c) 2009 The NetBSD Foundation, Inc.
41.1Sjoerg * All rights reserved.
51.1Sjoerg *
61.1Sjoerg * This code is derived from software contributed to The NetBSD Foundation
71.1Sjoerg * by Joerg Sonnenberger.
81.1Sjoerg *
91.1Sjoerg * Redistribution and use in source and binary forms, with or without
101.1Sjoerg * modification, are permitted provided that the following conditions
111.1Sjoerg * are met:
121.1Sjoerg *
131.1Sjoerg * 1. Redistributions of source code must retain the above copyright
141.1Sjoerg *    notice, this list of conditions and the following disclaimer.
151.1Sjoerg * 2. Redistributions in binary form must reproduce the above copyright
161.1Sjoerg *    notice, this list of conditions and the following disclaimer in
171.1Sjoerg *    the documentation and/or other materials provided with the
181.1Sjoerg *    distribution.
191.1Sjoerg *
201.1Sjoerg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
211.1Sjoerg * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
221.1Sjoerg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
231.1Sjoerg * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
241.1Sjoerg * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
251.1Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
261.1Sjoerg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
271.1Sjoerg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
281.1Sjoerg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
291.1Sjoerg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
301.1Sjoerg * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311.1Sjoerg * SUCH DAMAGE.
321.1Sjoerg */
331.1Sjoerg
341.1Sjoerg#include <sys/cdefs.h>
351.1Sjoerg__RCSID("$NetBSD: graph3.c,v 1.1 2009/08/15 16:21:05 joerg Exp $");
361.1Sjoerg
371.1Sjoerg#include <err.h>
381.1Sjoerg#include <inttypes.h>
391.1Sjoerg#include <stdio.h>
401.1Sjoerg#include <stdlib.h>
411.1Sjoerg
421.1Sjoerg#include "nbperf.h"
431.1Sjoerg#include "graph3.h"
441.1Sjoerg
451.1Sjoergstatic const uint32_t unused = 0xffffffffU;
461.1Sjoerg
471.1Sjoergvoid
481.1Sjoerggraph3_setup(struct graph3 *graph, uint32_t v, uint32_t e)
491.1Sjoerg{
501.1Sjoerg	graph->v = v;
511.1Sjoerg	graph->e = e;
521.1Sjoerg
531.1Sjoerg	graph->verts = calloc(sizeof(struct vertex3), v);
541.1Sjoerg	graph->edges = calloc(sizeof(struct edge3), e);
551.1Sjoerg	graph->output_order = calloc(sizeof(uint32_t), e);
561.1Sjoerg
571.1Sjoerg	if (graph->verts == NULL || graph->edges == NULL ||
581.1Sjoerg	    graph->output_order == NULL)
591.1Sjoerg		err(1, "malloc failed");
601.1Sjoerg}
611.1Sjoerg
621.1Sjoergvoid
631.1Sjoerggraph3_free(struct graph3 *graph)
641.1Sjoerg{
651.1Sjoerg	free(graph->verts);
661.1Sjoerg	free(graph->edges);
671.1Sjoerg	free(graph->output_order);
681.1Sjoerg
691.1Sjoerg	graph->verts = NULL;
701.1Sjoerg	graph->edges = NULL;
711.1Sjoerg	graph->output_order = NULL;
721.1Sjoerg}
731.1Sjoerg
741.1Sjoergint
751.1Sjoerggraph3_hash(struct nbperf *nbperf, struct graph3 *graph)
761.1Sjoerg{
771.1Sjoerg	struct vertex3 *v;
781.1Sjoerg	uint32_t hashes[nbperf->hash_size];
791.1Sjoerg	size_t i;
801.1Sjoerg
811.1Sjoerg	for (i = 0; i < graph->e; ++i) {
821.1Sjoerg		(*nbperf->compute_hash)(nbperf,
831.1Sjoerg		    nbperf->keys[i], nbperf->keylens[i], hashes);
841.1Sjoerg		graph->edges[i].left = hashes[0] % graph->v;
851.1Sjoerg		graph->edges[i].middle = hashes[1] % graph->v;
861.1Sjoerg		graph->edges[i].right = hashes[2] % graph->v;
871.1Sjoerg		if (graph->edges[i].left == graph->edges[i].middle)
881.1Sjoerg			return -1;
891.1Sjoerg		if (graph->edges[i].left == graph->edges[i].right)
901.1Sjoerg			return -1;
911.1Sjoerg		if (graph->edges[i].middle == graph->edges[i].right)
921.1Sjoerg			return -1;
931.1Sjoerg	}
941.1Sjoerg
951.1Sjoerg	for (i = 0; i < graph->v; ++i) {
961.1Sjoerg		graph->verts[i].l_edge = unused;
971.1Sjoerg		graph->verts[i].m_edge = unused;
981.1Sjoerg		graph->verts[i].r_edge = unused;
991.1Sjoerg	}
1001.1Sjoerg
1011.1Sjoerg	for (i = 0; i < graph->e; ++i) {
1021.1Sjoerg		v = &graph->verts[graph->edges[i].left];
1031.1Sjoerg		if (v->l_edge != unused)
1041.1Sjoerg			graph->edges[v->l_edge].l_prev = i;
1051.1Sjoerg		graph->edges[i].l_next = v->l_edge;
1061.1Sjoerg		graph->edges[i].l_prev = unused;
1071.1Sjoerg		v->l_edge = i;
1081.1Sjoerg
1091.1Sjoerg		v = &graph->verts[graph->edges[i].middle];
1101.1Sjoerg		if (v->m_edge != unused)
1111.1Sjoerg			graph->edges[v->m_edge].m_prev = i;
1121.1Sjoerg		graph->edges[i].m_next = v->m_edge;
1131.1Sjoerg		graph->edges[i].m_prev = unused;
1141.1Sjoerg		v->m_edge = i;
1151.1Sjoerg
1161.1Sjoerg		v = &graph->verts[graph->edges[i].right];
1171.1Sjoerg		if (v->r_edge != unused)
1181.1Sjoerg			graph->edges[v->r_edge].r_prev = i;
1191.1Sjoerg		graph->edges[i].r_next = v->r_edge;
1201.1Sjoerg		graph->edges[i].r_prev = unused;
1211.1Sjoerg		v->r_edge = i;
1221.1Sjoerg	}
1231.1Sjoerg
1241.1Sjoerg	return 0;
1251.1Sjoerg}
1261.1Sjoerg
1271.1Sjoergstatic void
1281.1Sjoerggraph3_remove_vertex(struct graph3 *graph, struct vertex3 *v)
1291.1Sjoerg{
1301.1Sjoerg	struct edge3 *e;
1311.1Sjoerg	struct vertex3 *vl, *vm, *vr;
1321.1Sjoerg
1331.1Sjoerg	if (v->l_edge != unused && v->m_edge != unused)
1341.1Sjoerg		return;
1351.1Sjoerg	if (v->l_edge != unused && v->r_edge != unused)
1361.1Sjoerg		return;
1371.1Sjoerg	if (v->m_edge != unused && v->r_edge != unused)
1381.1Sjoerg		return;
1391.1Sjoerg	if (v->l_edge == unused && v->m_edge == unused && v->r_edge == unused)
1401.1Sjoerg		return;
1411.1Sjoerg
1421.1Sjoerg	if (v->l_edge != unused) {
1431.1Sjoerg		e = &graph->edges[v->l_edge];
1441.1Sjoerg		if (e->l_next != unused)
1451.1Sjoerg			return;
1461.1Sjoerg	} else if (v->m_edge != unused) {
1471.1Sjoerg		e = &graph->edges[v->m_edge];
1481.1Sjoerg		if (e->m_next != unused)
1491.1Sjoerg			return;
1501.1Sjoerg	} else {
1511.1Sjoerg		if (v->r_edge == unused)
1521.1Sjoerg			abort();
1531.1Sjoerg		e = &graph->edges[v->r_edge];
1541.1Sjoerg		if (e->r_next != unused)
1551.1Sjoerg			return;
1561.1Sjoerg	}
1571.1Sjoerg
1581.1Sjoerg	graph->output_order[--graph->output_index] = e - graph->edges;
1591.1Sjoerg
1601.1Sjoerg	vl = &graph->verts[e->left];
1611.1Sjoerg	vm = &graph->verts[e->middle];
1621.1Sjoerg	vr = &graph->verts[e->right];
1631.1Sjoerg
1641.1Sjoerg	if (e->l_prev == unused)
1651.1Sjoerg		vl->l_edge = e->l_next;
1661.1Sjoerg	else
1671.1Sjoerg		graph->edges[e->l_prev].l_next = e->l_next;
1681.1Sjoerg	if (e->l_next != unused)
1691.1Sjoerg		graph->edges[e->l_next].l_prev = e->l_prev;
1701.1Sjoerg
1711.1Sjoerg	if (e->m_prev == unused)
1721.1Sjoerg		vm->m_edge = e->m_next;
1731.1Sjoerg	else
1741.1Sjoerg		graph->edges[e->m_prev].m_next = e->m_next;
1751.1Sjoerg	if (e->m_next != unused)
1761.1Sjoerg		graph->edges[e->m_next].m_prev = e->m_prev;
1771.1Sjoerg
1781.1Sjoerg	if (e->r_prev == unused)
1791.1Sjoerg		vr->r_edge = e->r_next;
1801.1Sjoerg	else
1811.1Sjoerg		graph->edges[e->r_prev].r_next = e->r_next;
1821.1Sjoerg	if (e->r_next != unused)
1831.1Sjoerg		graph->edges[e->r_next].r_prev = e->r_prev;
1841.1Sjoerg}
1851.1Sjoerg
1861.1Sjoergint
1871.1Sjoerggraph3_output_order(struct graph3 *graph)
1881.1Sjoerg{
1891.1Sjoerg	struct edge3 *e;
1901.1Sjoerg	size_t i;
1911.1Sjoerg
1921.1Sjoerg	graph->output_index = graph->e;
1931.1Sjoerg
1941.1Sjoerg	for (i = 0; i < graph->v; ++i)
1951.1Sjoerg		graph3_remove_vertex(graph, &graph->verts[i]);
1961.1Sjoerg
1971.1Sjoerg	for (i = graph->e; i > 0 && i > graph->output_index;) {
1981.1Sjoerg		--i;
1991.1Sjoerg		e = &graph->edges[graph->output_order[i]];
2001.1Sjoerg
2011.1Sjoerg		graph3_remove_vertex(graph, &graph->verts[e->left]);
2021.1Sjoerg		graph3_remove_vertex(graph, &graph->verts[e->middle]);
2031.1Sjoerg		graph3_remove_vertex(graph, &graph->verts[e->right]);
2041.1Sjoerg	}
2051.1Sjoerg
2061.1Sjoerg	if (graph->output_index != 0)
2071.1Sjoerg		return -1;
2081.1Sjoerg
2091.1Sjoerg	return 0;
2101.1Sjoerg}
211